diff options
-rw-r--r-- | gas/dwarf2dbg.c | 156 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/dwarf-3-func.d | 48 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/dwarf-3-func.s | 40 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/dwarf-5-func-global.d | 40 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/dwarf-5-func-local.d | 37 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/dwarf-5-func.d | 50 | ||||
-rw-r--r-- | gas/testsuite/gas/elf/elf.exp | 4 |
7 files changed, 368 insertions, 7 deletions
diff --git a/gas/dwarf2dbg.c b/gas/dwarf2dbg.c index fee56c2..44d7d9e 100644 --- a/gas/dwarf2dbg.c +++ b/gas/dwarf2dbg.c @@ -2674,14 +2674,55 @@ out_debug_aranges (segT aranges_seg, segT info_seg) static void out_debug_abbrev (segT abbrev_seg, segT info_seg ATTRIBUTE_UNUSED, - segT line_seg ATTRIBUTE_UNUSED) + segT line_seg ATTRIBUTE_UNUSED, + unsigned char *func_formP) { int secoff_form; + bool have_efunc = false, have_lfunc = false; + + /* Check the symbol table for function symbols which also have their size + specified. */ + if (symbol_rootP) + { + symbolS *symp; + + for (symp = symbol_rootP; symp; symp = symbol_next (symp)) + { + /* A warning construct is a warning symbol followed by the + symbol warned about. Skip this and the following symbol. */ + if (symbol_get_bfdsym (symp)->flags & BSF_WARNING) + { + symp = symbol_next (symp); + if (!symp) + break; + continue; + } + + if (!S_IS_DEFINED (symp) || !S_IS_FUNCTION (symp)) + continue; + +#if defined (OBJ_ELF) /* || defined (OBJ_MAYBE_ELF) */ + if (S_GET_SIZE (symp) == 0) + { + if (!IS_ELF || symbol_get_obj (symp)->size == NULL) + continue; + } +#else + continue; +#endif + + if (S_IS_EXTERNAL (symp)) + have_efunc = true; + else + have_lfunc = true; + } + } + subseg_set (abbrev_seg, 0); out_uleb128 (1); out_uleb128 (DW_TAG_compile_unit); - out_byte (DW_CHILDREN_no); + out_byte (have_efunc || have_lfunc ? DW_CHILDREN_yes : DW_CHILDREN_no); if (DWARF2_VERSION < 4) { if (DWARF2_FORMAT (line_seg) == dwarf2_format_32bit) @@ -2708,6 +2749,29 @@ out_debug_abbrev (segT abbrev_seg, out_abbrev (DW_AT_language, DW_FORM_data2); out_abbrev (0, 0); + if (have_efunc || have_lfunc) + { + out_uleb128 (2); + out_uleb128 (DW_TAG_subprogram); + out_byte (DW_CHILDREN_no); + out_abbrev (DW_AT_name, DW_FORM_strp); + if (have_efunc) + { + if (have_lfunc || DWARF2_VERSION < 4) + *func_formP = DW_FORM_flag; + else + *func_formP = DW_FORM_flag_present; + out_abbrev (DW_AT_external, *func_formP); + } + else + /* Any non-zero value other than DW_FORM_flag will do. */ + *func_formP = DW_FORM_block; + out_abbrev (DW_AT_low_pc, DW_FORM_addr); + out_abbrev (DW_AT_high_pc, + DWARF2_VERSION < 4 ? DW_FORM_addr : DW_FORM_udata); + out_abbrev (0, 0); + } + /* Terminate the abbreviations for this compilation unit. */ out_byte (0); } @@ -2715,9 +2779,10 @@ out_debug_abbrev (segT abbrev_seg, /* Emit a description of this compilation unit for .debug_info. */ static void -out_debug_info (segT info_seg, segT abbrev_seg, segT line_seg, +out_debug_info (segT info_seg, segT abbrev_seg, segT line_seg, segT str_seg, symbolS *ranges_sym, symbolS *name_sym, - symbolS *comp_dir_sym, symbolS *producer_sym) + symbolS *comp_dir_sym, symbolS *producer_sym, + unsigned char func_form) { expressionS exp; symbolS *info_end; @@ -2799,6 +2864,81 @@ out_debug_info (segT info_seg, segT abbrev_seg, segT line_seg, dwarf2 draft has no standard code for assembler. */ out_two (DW_LANG_Mips_Assembler); + if (func_form) + { + symbolS *symp; + + for (symp = symbol_rootP; symp; symp = symbol_next (symp)) + { + const char *name; + size_t len; + + /* Skip warning constructs (see above). */ + if (symbol_get_bfdsym (symp)->flags & BSF_WARNING) + { + symp = symbol_next (symp); + if (!symp) + break; + continue; + } + + if (!S_IS_DEFINED (symp) || !S_IS_FUNCTION (symp)) + continue; + + subseg_set (str_seg, 0); + name_sym = symbol_temp_new_now_octets (); + name = S_GET_NAME (symp); + len = strlen (name) + 1; + memcpy (frag_more (len), name, len); + + subseg_set (info_seg, 0); + + /* DW_TAG_subprogram DIE abbrev */ + out_uleb128 (2); + + /* DW_AT_name */ + TC_DWARF2_EMIT_OFFSET (name_sym, sizeof_offset); + + /* DW_AT_external. */ + if (func_form == DW_FORM_flag) + out_byte (S_IS_EXTERNAL (symp)); + + /* DW_AT_low_pc */ + exp.X_op = O_symbol; + exp.X_add_symbol = symp; + exp.X_add_number = 0; + emit_expr (&exp, sizeof_address); + + /* DW_AT_high_pc */ + exp.X_op = O_constant; +#if defined (OBJ_ELF) /* || defined (OBJ_MAYBE_ELF) */ + exp.X_add_number = S_GET_SIZE (symp); + if (exp.X_add_number == 0 && IS_ELF + && symbol_get_obj (symp)->size != NULL) + { + exp.X_op = O_add; + exp.X_op_symbol = make_expr_symbol (symbol_get_obj (symp)->size); + } +#else + exp.X_add_number = 0; +#endif + if (DWARF2_VERSION < 4) + { + if (exp.X_op == O_constant) + exp.X_op = O_symbol; + exp.X_add_symbol = symp; + emit_expr (&exp, sizeof_address); + } + else if (exp.X_op == O_constant) + out_uleb128 (exp.X_add_number); + else + emit_leb128_expr (symbol_get_value_expression (exp.X_op_symbol), 0); + } + + /* End of children. */ + out_leb128 (0); + } + symbol_set_value_now (info_end); } @@ -2968,6 +3108,7 @@ dwarf2_finish (void) segT aranges_seg; segT str_seg; symbolS *name_sym, *comp_dir_sym, *producer_sym, *ranges_sym; + unsigned char func_form = 0; gas_assert (all_segs); @@ -3013,10 +3154,11 @@ dwarf2_finish (void) } out_debug_aranges (aranges_seg, info_seg); - out_debug_abbrev (abbrev_seg, info_seg, line_seg); + out_debug_abbrev (abbrev_seg, info_seg, line_seg, &func_form); out_debug_str (str_seg, &name_sym, &comp_dir_sym, &producer_sym); - out_debug_info (info_seg, abbrev_seg, line_seg, ranges_sym, - name_sym, comp_dir_sym, producer_sym); + out_debug_info (info_seg, abbrev_seg, line_seg, str_seg, + ranges_sym, name_sym, comp_dir_sym, producer_sym, + func_form); } } diff --git a/gas/testsuite/gas/elf/dwarf-3-func.d b/gas/testsuite/gas/elf/dwarf-3-func.d new file mode 100644 index 0000000..0196f69 --- /dev/null +++ b/gas/testsuite/gas/elf/dwarf-3-func.d @@ -0,0 +1,48 @@ +#as: --gdwarf-3 +#name: Dwarf3 function debug info +#readelf: -W -wai +#target: i?86-*-* x86_64-*-* + +Contents of the .debug_info section: + + +Compilation Unit @ offset (0x)?0: + +Length: .* + +Version: +3 + +Abbrev Offset: +(0x)?0 + +Pointer Size: .* + <0><[0-9a-f]+>: Abbrev Number: 1 \(DW_TAG_compile_unit\) +#... + <1><[0-9a-f]+>: Abbrev Number: 2 \(DW_TAG_subprogram\) + +<[0-9a-f]+> +DW_AT_name +: \(strp\) \(offset: (0x)?[0-9a-f]+\): efunc1 + +<[0-9a-f]+> +DW_AT_external +: \(flag\) 1 + +<[0-9a-f]+> +DW_AT_low_pc +: \(addr\) (0x)?0 + +<[0-9a-f]+> +DW_AT_high_pc +: \(addr\) (0x)?2 + <1><[0-9a-f]+>: Abbrev Number: 2 \(DW_TAG_subprogram\) + +<[0-9a-f]+> +DW_AT_name +: \(strp\) \(offset: (0x)?[0-9a-f]+\): lfunc1 + +<[0-9a-f]+> +DW_AT_external +: \(flag\) 0 + +<[0-9a-f]+> +DW_AT_low_pc +: \(addr\) (0x)?2 + +<[0-9a-f]+> +DW_AT_high_pc +: \(addr\) (0x)?13 + <1><[0-9a-f]+>: Abbrev Number: 2 \(DW_TAG_subprogram\) + +<[0-9a-f]+> +DW_AT_name +: \(strp\) \(offset: (0x)?[0-9a-f]+\): efunc2 + +<[0-9a-f]+> +DW_AT_external +: \(flag\) 1 + +<[0-9a-f]+> +DW_AT_low_pc +: \(addr\) (0x)?13 + +<[0-9a-f]+> +DW_AT_high_pc +: \(addr\) (0x)?35 + <1><[0-9a-f]+>: Abbrev Number: 2 \(DW_TAG_subprogram\) + +<[0-9a-f]+> +DW_AT_name +: \(strp\) \(offset: (0x)?[0-9a-f]+\): lfunc2 + +<[0-9a-f]+> +DW_AT_external +: \(flag\) 0 + +<[0-9a-f]+> +DW_AT_low_pc +: \(addr\) (0x)?35 + +<[0-9a-f]+> +DW_AT_high_pc +: \(addr\) (0x)?38 + <1><[0-9a-f]+>: Abbrev Number: 0 + +Contents of the .debug_abbrev section: + + +Number TAG \(0x0\) + +1 +DW_TAG_compile_unit +\[has children\] +#... + +2 +DW_TAG_subprogram +\[no children\] + +DW_AT_name +DW_FORM_strp + +DW_AT_external +DW_FORM_flag + +DW_AT_low_pc +DW_FORM_addr + +DW_AT_high_pc +DW_FORM_addr + +DW_AT value: 0 +DW_FORM value: 0 +#pass diff --git a/gas/testsuite/gas/elf/dwarf-3-func.s b/gas/testsuite/gas/elf/dwarf-3-func.s new file mode 100644 index 0000000..4610686 --- /dev/null +++ b/gas/testsuite/gas/elf/dwarf-3-func.s @@ -0,0 +1,40 @@ + .text + + .ifndef LOCAL +efunc1: + .nop + .nop + .global efunc1 + .type efunc1, %function + .size efunc1, .-efunc1 + .endif + + .ifndef GLOBAL +lfunc1: + .nops 16 + .nop + .type lfunc1, %function + .size lfunc1, .-lfunc1 + .endif + + .ifndef LOCAL +efunc2: + .nop + .nops 32 + .nop + .global efunc2 + .type efunc2, %function + .size efunc2, .-efunc2 + .endif + + .global efunc3 + .type efunc3, %function + + .ifndef GLOBAL +lfunc2: + .nop + .nop + .nop + .type lfunc2, %function + .size lfunc2, .-lfunc2 + .endif diff --git a/gas/testsuite/gas/elf/dwarf-5-func-global.d b/gas/testsuite/gas/elf/dwarf-5-func-global.d new file mode 100644 index 0000000..09b10fd --- /dev/null +++ b/gas/testsuite/gas/elf/dwarf-5-func-global.d @@ -0,0 +1,40 @@ +#as: --gdwarf-5 --defsym GLOBAL=1 +#name: Dwarf5 global function debug info +#readelf: -W -wai +#source: dwarf-3-func.s +#target: i?86-*-* x86_64-*-* + +Contents of the .debug_info section: + + +Compilation Unit @ offset (0x)?0: + +Length: .* + +Version: +5 + +Unit Type: +DW_UT_compile \(1\) + +Abbrev Offset: +(0x)?0 + +Pointer Size: .* + <0><[0-9a-f]+>: Abbrev Number: 1 \(DW_TAG_compile_unit\) +#... + <1><[0-9a-f]+>: Abbrev Number: 2 \(DW_TAG_subprogram\) + +<[0-9a-f]+> +DW_AT_name +: \(strp\) \(offset: (0x)?[0-9a-f]+\): efunc1 + +<[0-9a-f]+> +DW_AT_external +: \(flag_present\) 1 + +<[0-9a-f]+> +DW_AT_low_pc +: \(addr\) (0x)?0 + +<[0-9a-f]+> +DW_AT_high_pc +: \(udata\) 2 + <1><[0-9a-f]+>: Abbrev Number: 2 \(DW_TAG_subprogram\) + +<[0-9a-f]+> +DW_AT_name +: \(strp\) \(offset: (0x)?[0-9a-f]+\): efunc2 + +<[0-9a-f]+> +DW_AT_external +: \(flag_present\) 1 + +<[0-9a-f]+> +DW_AT_low_pc +: \(addr\) (0x)?2 + +<[0-9a-f]+> +DW_AT_high_pc +: \(udata\) 34 + <1><[0-9a-f]+>: Abbrev Number: 0 + +Contents of the .debug_abbrev section: + + +Number TAG \(0x0\) + +1 +DW_TAG_compile_unit +\[has children\] +#... + +2 +DW_TAG_subprogram +\[no children\] + +DW_AT_name +DW_FORM_strp + +DW_AT_external +DW_FORM_flag_present + +DW_AT_low_pc +DW_FORM_addr + +DW_AT_high_pc +DW_FORM_udata + +DW_AT value: 0 +DW_FORM value: 0 +#pass diff --git a/gas/testsuite/gas/elf/dwarf-5-func-local.d b/gas/testsuite/gas/elf/dwarf-5-func-local.d new file mode 100644 index 0000000..fd97841 --- /dev/null +++ b/gas/testsuite/gas/elf/dwarf-5-func-local.d @@ -0,0 +1,37 @@ +#as: --gdwarf-5 --defsym LOCAL=1 +#name: Dwarf5 local function debug info +#readelf: -W -wai +#source: dwarf-3-func.s +#target: i?86-*-* x86_64-*-* + +Contents of the .debug_info section: + + +Compilation Unit @ offset (0x)?0: + +Length: .* + +Version: +5 + +Unit Type: +DW_UT_compile \(1\) + +Abbrev Offset: +(0x)?0 + +Pointer Size: .* + <0><[0-9a-f]+>: Abbrev Number: 1 \(DW_TAG_compile_unit\) +#... + <1><[0-9a-f]+>: Abbrev Number: 2 \(DW_TAG_subprogram\) + +<[0-9a-f]+> +DW_AT_name +: \(strp\) \(offset: (0x)?[0-9a-f]+\): lfunc1 + +<[0-9a-f]+> +DW_AT_low_pc +: \(addr\) (0x)?0 + +<[0-9a-f]+> +DW_AT_high_pc +: \(udata\) 17 + <1><[0-9a-f]+>: Abbrev Number: 2 \(DW_TAG_subprogram\) + +<[0-9a-f]+> +DW_AT_name +: \(strp\) \(offset: (0x)?[0-9a-f]+\): lfunc2 + +<[0-9a-f]+> +DW_AT_low_pc +: \(addr\) (0x)?11 + +<[0-9a-f]+> +DW_AT_high_pc +: \(udata\) 3 + <1><[0-9a-f]+>: Abbrev Number: 0 + +Contents of the .debug_abbrev section: + + +Number TAG \(0x0\) + +1 +DW_TAG_compile_unit +\[has children\] +#... + +2 +DW_TAG_subprogram +\[no children\] + +DW_AT_name +DW_FORM_strp + +DW_AT_low_pc +DW_FORM_addr + +DW_AT_high_pc +DW_FORM_udata + +DW_AT value: 0 +DW_FORM value: 0 +#pass diff --git a/gas/testsuite/gas/elf/dwarf-5-func.d b/gas/testsuite/gas/elf/dwarf-5-func.d new file mode 100644 index 0000000..11a78b2 --- /dev/null +++ b/gas/testsuite/gas/elf/dwarf-5-func.d @@ -0,0 +1,50 @@ +#as: --gdwarf-5 +#name: Dwarf5 function debug info +#readelf: -W -wai +#source: dwarf-3-func.s +#target: i?86-*-* x86_64-*-* + +Contents of the .debug_info section: + + +Compilation Unit @ offset (0x)?0: + +Length: .* + +Version: +5 + +Unit Type: +DW_UT_compile \(1\) + +Abbrev Offset: +(0x)?0 + +Pointer Size: .* + <0><[0-9a-f]+>: Abbrev Number: 1 \(DW_TAG_compile_unit\) +#... + <1><[0-9a-f]+>: Abbrev Number: 2 \(DW_TAG_subprogram\) + +<[0-9a-f]+> +DW_AT_name +: \(strp\) \(offset: (0x)?[0-9a-f]+\): efunc1 + +<[0-9a-f]+> +DW_AT_external +: \(flag\) 1 + +<[0-9a-f]+> +DW_AT_low_pc +: \(addr\) (0x)?0 + +<[0-9a-f]+> +DW_AT_high_pc +: \(udata\) 2 + <1><[0-9a-f]+>: Abbrev Number: 2 \(DW_TAG_subprogram\) + +<[0-9a-f]+> +DW_AT_name +: \(strp\) \(offset: (0x)?[0-9a-f]+\): lfunc1 + +<[0-9a-f]+> +DW_AT_external +: \(flag\) 0 + +<[0-9a-f]+> +DW_AT_low_pc +: \(addr\) (0x)?2 + +<[0-9a-f]+> +DW_AT_high_pc +: \(udata\) 17 + <1><[0-9a-f]+>: Abbrev Number: 2 \(DW_TAG_subprogram\) + +<[0-9a-f]+> +DW_AT_name +: \(strp\) \(offset: (0x)?[0-9a-f]+\): efunc2 + +<[0-9a-f]+> +DW_AT_external +: \(flag\) 1 + +<[0-9a-f]+> +DW_AT_low_pc +: \(addr\) (0x)?13 + +<[0-9a-f]+> +DW_AT_high_pc +: \(udata\) 34 + <1><[0-9a-f]+>: Abbrev Number: 2 \(DW_TAG_subprogram\) + +<[0-9a-f]+> +DW_AT_name +: \(strp\) \(offset: (0x)?[0-9a-f]+\): lfunc2 + +<[0-9a-f]+> +DW_AT_external +: \(flag\) 0 + +<[0-9a-f]+> +DW_AT_low_pc +: \(addr\) (0x)?35 + +<[0-9a-f]+> +DW_AT_high_pc +: \(udata\) 3 + <1><[0-9a-f]+>: Abbrev Number: 0 + +Contents of the .debug_abbrev section: + + +Number TAG \(0x0\) + +1 +DW_TAG_compile_unit +\[has children\] +#... + +2 +DW_TAG_subprogram +\[no children\] + +DW_AT_name +DW_FORM_strp + +DW_AT_external +DW_FORM_flag + +DW_AT_low_pc +DW_FORM_addr + +DW_AT_high_pc +DW_FORM_udata + +DW_AT value: 0 +DW_FORM value: 0 +#pass diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp index 963730a..abdc288 100644 --- a/gas/testsuite/gas/elf/elf.exp +++ b/gas/testsuite/gas/elf/elf.exp @@ -308,6 +308,10 @@ if { [is_elf_format] } then { run_dump_test "dwarf-5-cu" $dump_opts run_dump_test "dwarf-5-nop-for-line-table" $dump_opts run_dump_test "dwarf-5-irp" $dump_opts + run_dump_test "dwarf-3-func" $dump_opts + run_dump_test "dwarf-5-func" $dump_opts + run_dump_test "dwarf-5-func-global" $dump_opts + run_dump_test "dwarf-5-func-local" $dump_opts run_dump_test "pr25917" run_dump_test "bss" run_dump_test "bad-bss" |