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)
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);
}
/* 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;
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);
}
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);
}
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);
}
}
--- /dev/null
+#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
--- /dev/null
+ .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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
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"