mirror of
https://github.com/JakeHillion/drgn.git
synced 2024-12-22 09:13:06 +00:00
libdrgn: dwarf_info: fix segfault on anonymous DIEs during scope search
Jakub Kicinski reported that prog.crashed_thread().stack_trace()[1]['does not exist'] segfaulted on a vmcore he encountered. The segfault was a NULL pointer dereference of dwarf_diename() of a DW_TAG_subprogram DIE in drgn_find_in_dwarf_scopes(). The fix is to ignore DIEs without a name. I was curious what this anonymous DW_TAG_subprogram was. It turned out to be some dubious DWARF generated by Clang when a local variable is defined via a macro. One such example comes from the following code in arch/x86/events/intel/uncore.h: static inline bool uncore_mmio_is_valid_offset(struct intel_uncore_box *box, unsigned long offset) { if (offset < box->pmu->type->mmio_map_size) return true; pr_warn_once("perf uncore: Invalid offset 0x%lx exceeds mapped area of %s.\n", offset, box->pmu->type->name); return false; } pr_warn_once() expands to: #define pr_warn_once(fmt, ...) \ printk_once(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__) #define printk_once(fmt, ...) \ ({ \ static bool __section(".data.once") __print_once; \ bool __ret_print_once = !__print_once; \ \ if (!__print_once) { \ __print_once = true; \ printk(fmt, ##__VA_ARGS__); \ } \ unlikely(__ret_print_once); \ }) For some reason, Clang generates an anonymous, top-level DW_TAG_subprogram DIE to contain the __print_once variable: <1><1cf86e>: Abbrev Number: 62 (DW_TAG_subprogram) <2><1cf86f>: Abbrev Number: 61 (DW_TAG_variable) <1cf870> DW_AT_name : (indirect string, offset: 0x34fb2e): __print_once <1cf874> DW_AT_type : <0x1c574c> <1cf878> DW_AT_decl_file : 1 <1cf879> DW_AT_decl_line : 229 <1cf87a> DW_AT_location : 16 byte block: 3 2c 84 66 83 ff ff ff ff 94 1 31 1e 30 22 9f (DW_OP_addr: ffffffff8366842c; DW_OP_deref_size: 1; DW_OP_lit1; DW_OP_mul; DW_OP_lit0; DW_OP_plus; DW_OP_stack_value) Whereas GCC puts it in a DW_TAG_lexical block DIE inside of the DW_TAG_subprogram DIE for uncore_mmio_is_valid_offset(): <1><3110b2>: Abbrev Number: 45 (DW_TAG_subprogram) <3110b3> DW_AT_name : (indirect string, offset: 0x2e13e): uncore_mmio_is_valid_offset <3110b7> DW_AT_decl_file : 4 <3110b8> DW_AT_decl_line : 223 <3110b9> DW_AT_decl_column : 20 <3110ba> DW_AT_prototyped : 1 <3110ba> DW_AT_type : <0x2f416b> <3110be> DW_AT_inline : 3 (declared as inline and inlined) <3110bf> DW_AT_sibling : <0x311142> <2><3110ef>: Abbrev Number: 66 (DW_TAG_lexical_block) <3><3110f0>: Abbrev Number: 120 (DW_TAG_variable) <3110f1> DW_AT_name : (indirect string, offset: 0x2da3f): __print_once <3110f5> DW_AT_decl_file : 4 <3110f6> DW_AT_decl_line : 229 <3110f7> DW_AT_decl_column : 2 <3110f8> DW_AT_type : <0x2f416b> <3110fc> DW_AT_location : 9 byte block: 3 2c 28 48 83 ff ff ff ff (DW_OP_addr: ffffffff8348282c) Regardless, we shouldn't crash on this input. Reported-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Omar Sandoval <osandov@osandov.com>
This commit is contained in:
parent
0825dda116
commit
330c71b5b5
@ -5373,8 +5373,9 @@ struct drgn_error *drgn_find_in_dwarf_scopes(Dwarf_Die *scopes,
|
||||
switch (dwarf_tag(&die)) {
|
||||
case DW_TAG_variable:
|
||||
case DW_TAG_formal_parameter:
|
||||
case DW_TAG_subprogram:
|
||||
if (strcmp(dwarf_diename(&die), name) == 0) {
|
||||
case DW_TAG_subprogram: {
|
||||
const char *die_name = dwarf_diename(&die);
|
||||
if (die_name && strcmp(die_name, name) == 0) {
|
||||
*die_ret = die;
|
||||
bool declaration;
|
||||
if (dwarf_flag(&die, DW_AT_declaration,
|
||||
@ -5386,6 +5387,7 @@ struct drgn_error *drgn_find_in_dwarf_scopes(Dwarf_Die *scopes,
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DW_TAG_enumeration_type: {
|
||||
bool enum_class;
|
||||
if (dwarf_flag_integrate(&die, DW_AT_enum_class,
|
||||
|
Loading…
Reference in New Issue
Block a user