From 07a53e5cdb3d786ea59bdce443b307c04f691d17 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 20 Sep 2005 18:24:48 +0000 Subject: [PATCH] * dwarf2dbg.c (struct line_entry): Replace frag and frag_ofs with label. (dwarf2_loc_mark_labels): New. (dwarf2_gen_line_info_1): Split out of ... (dwarf2_gen_line_info): ... here. Create the temp symbol here. (dwarf2_emit_label): New. (dwarf2_directive_loc_mark_labels): New. (out_set_addr): Take a symbol instead of frag+ofs. (relax_inc_line_addr): Likewise. (emit_inc_line_addr): Assert delta non-negative. (process_entries): Remove dead code. Update to work with temp symbols instead of frag+ofs. * dwarf2dbg.h (dwarf2_directive_loc_mark_labels): Declare. (dwarf2_emit_label, dwarf2_loc_mark_labels): Declare. * config/obj-elf.c (elf_pseudo_tab): Add loc_mark_labels. * config/obj-elf.h (obj_frob_label): New. * config/tc-alpha.c (alpha_define_label): Call dwarf2_emit_label. * config/tc-arm.c, config/tc-hppa.c, config/tc-m68k.c, config/tc-mips.c, config/tc-ppc.c, config/tc-sh.c, config/tc-xtensa.c: Similarly in the respective tc_frob_label implementation functions. * config/tc-i386.c (md_pseudo_table): Move file and loc to non-elf section; add loc_mark_labels. * config/tc-ia64.c (struct label_fix): Add dw2_mark_labels. (ia64_flush_insns): Check for marked labels; emit line entry if so. (emit_one_bundle): Similarly. (ia64_frob_label): Record marked labels. * config/tc-m68hc11.h (tc_frob_label): Remove. * config/tc-ms1.c (md_pseudo_table): Remove file and loc. * config/tc-sh.h (tc_frob_label): Pass sym to sh_frob_label. * config/tc-sh64.h (tc_frob_label): Likewise. * doc/as.texinfo (LNS directives): Docuement .loc_mark_blocks. --- gas/ChangeLog | 34 ++++++++ gas/config/obj-elf.c | 1 + gas/config/obj-elf.h | 7 ++ gas/config/tc-alpha.c | 3 + gas/config/tc-arm.c | 4 + gas/config/tc-hppa.c | 4 + gas/config/tc-i386.c | 6 +- gas/config/tc-ia64.c | 58 ++++++++----- gas/config/tc-m68hc11.h | 3 - gas/config/tc-m68k.c | 4 + gas/config/tc-mips.c | 4 + gas/config/tc-ms1.c | 2 - gas/config/tc-ppc.c | 4 + gas/config/tc-sh.c | 4 +- gas/config/tc-sh.h | 4 +- gas/config/tc-sh64.h | 2 +- gas/config/tc-xtensa.c | 4 +- gas/doc/as.texinfo | 9 ++ gas/dwarf2dbg.c | 188 ++++++++++++++++++++++++---------------- gas/dwarf2dbg.h | 11 +++ 20 files changed, 249 insertions(+), 107 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 2018e20bfc2..c4848424930 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,37 @@ +2005-09-20 Richard Henderson + + * dwarf2dbg.c (struct line_entry): Replace frag and frag_ofs + with label. + (dwarf2_loc_mark_labels): New. + (dwarf2_gen_line_info_1): Split out of ... + (dwarf2_gen_line_info): ... here. Create the temp symbol here. + (dwarf2_emit_label): New. + (dwarf2_directive_loc_mark_labels): New. + (out_set_addr): Take a symbol instead of frag+ofs. + (relax_inc_line_addr): Likewise. + (emit_inc_line_addr): Assert delta non-negative. + (process_entries): Remove dead code. Update to work with temp + symbols instead of frag+ofs. + * dwarf2dbg.h (dwarf2_directive_loc_mark_labels): Declare. + (dwarf2_emit_label, dwarf2_loc_mark_labels): Declare. + * config/obj-elf.c (elf_pseudo_tab): Add loc_mark_labels. + * config/obj-elf.h (obj_frob_label): New. + * config/tc-alpha.c (alpha_define_label): Call dwarf2_emit_label. + * config/tc-arm.c, config/tc-hppa.c, config/tc-m68k.c, + config/tc-mips.c, config/tc-ppc.c, config/tc-sh.c, config/tc-xtensa.c: + Similarly in the respective tc_frob_label implementation functions. + * config/tc-i386.c (md_pseudo_table): Move file and loc to + non-elf section; add loc_mark_labels. + * config/tc-ia64.c (struct label_fix): Add dw2_mark_labels. + (ia64_flush_insns): Check for marked labels; emit line entry if so. + (emit_one_bundle): Similarly. + (ia64_frob_label): Record marked labels. + * config/tc-m68hc11.h (tc_frob_label): Remove. + * config/tc-ms1.c (md_pseudo_table): Remove file and loc. + * config/tc-sh.h (tc_frob_label): Pass sym to sh_frob_label. + * config/tc-sh64.h (tc_frob_label): Likewise. + * doc/as.texinfo (LNS directives): Docuement .loc_mark_blocks. + 2005-09-20 Alan Modra * read.c (pseudo_set): Set segment of expression syms to expr_section. diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index 43e0c97a0d2..f922149cae0 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -115,6 +115,7 @@ static const pseudo_typeS elf_pseudo_table[] = /* These are used for dwarf2. */ { "file", (void (*) (int)) dwarf2_directive_file, 0 }, { "loc", dwarf2_directive_loc, 0 }, + { "loc_mark_labels", dwarf2_directive_loc_mark_labels, 0 }, /* We need to trap the section changing calls to handle .previous. */ {"data", obj_elf_data, 0}, diff --git a/gas/config/obj-elf.h b/gas/config/obj-elf.h index 629fc00fcff..7ff9ef09aa3 100644 --- a/gas/config/obj-elf.h +++ b/gas/config/obj-elf.h @@ -156,6 +156,13 @@ extern void elf_frob_file_before_adjust (void); #endif extern void elf_frob_file_after_relocs (void); +/* If the target doesn't have special processing for labels, take care of + dwarf2 output at the object file level. */ +#ifndef tc_frob_label +#include "dwarf2dbg.h" +#define obj_frob_label dwarf2_emit_label +#endif + #ifndef obj_app_file #define obj_app_file elf_file_symbol #endif diff --git a/gas/config/tc-alpha.c b/gas/config/tc-alpha.c index 2eb0adfd3b1..8d923529c1d 100644 --- a/gas/config/tc-alpha.c +++ b/gas/config/tc-alpha.c @@ -5464,6 +5464,9 @@ void alpha_define_label (symbolS *sym) { alpha_insn_label = sym; +#ifdef OBJ_ELF + dwarf2_emit_label (sym); +#endif } /* Return true if we must always emit a reloc for a type and false if diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index c11e149b459..8d327eb0cf2 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -8092,6 +8092,10 @@ arm_frob_label (symbolS * sym) label_is_thumb_function_name = FALSE; } + +#ifdef OBJ_ELF + dwarf2_emit_label (sym); +#endif } int diff --git a/gas/config/tc-hppa.c b/gas/config/tc-hppa.c index 75f6dbb361e..1c1b4e45eba 100644 --- a/gas/config/tc-hppa.c +++ b/gas/config/tc-hppa.c @@ -1287,6 +1287,10 @@ pa_define_label (symbol) label_symbols_rootp = label_chain; } + +#ifdef OBJ_ELF + dwarf2_emit_label (symbol); +#endif } /* Removes a label definition for the current space. diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index b562b765e3f..3820b19abec 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -469,10 +469,12 @@ const pseudo_typeS md_pseudo_table[] = {"code64", set_code_flag, CODE_64BIT}, {"intel_syntax", set_intel_syntax, 1}, {"att_syntax", set_intel_syntax, 0}, - {"file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0}, - {"loc", dwarf2_directive_loc, 0}, #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) {"largecomm", handle_large_common, 0}, +#else + {"file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0}, + {"loc", dwarf2_directive_loc, 0}, + {"loc_mark_labels", dwarf2_directive_loc_mark_labels, 0}, #endif #ifdef TE_PE {"secrel32", pe_directive_secrel, 0}, diff --git a/gas/config/tc-ia64.c b/gas/config/tc-ia64.c index 81e5cd56a0a..5875551c78d 100644 --- a/gas/config/tc-ia64.c +++ b/gas/config/tc-ia64.c @@ -159,6 +159,7 @@ struct label_fix { struct label_fix *next; struct symbol *sym; + bfd_boolean dw2_mark_labels; }; /* This is the endianness of the current section. */ @@ -1083,6 +1084,7 @@ ia64_flush_insns () segT saved_seg; subsegT saved_subseg; unw_rec_list *ptr; + bfd_boolean mark; if (!md.last_text_seg) return; @@ -1096,18 +1098,23 @@ ia64_flush_insns () emit_one_bundle (); /* force out queued instructions */ /* In case there are labels following the last instruction, resolve - those now: */ + those now. */ + mark = FALSE; for (lfix = CURR_SLOT.label_fixups; lfix; lfix = lfix->next) { - S_SET_VALUE (lfix->sym, frag_now_fix ()); - symbol_set_frag (lfix->sym, frag_now); + symbol_set_value_now (lfix->sym); + mark |= lfix->dw2_mark_labels; } - CURR_SLOT.label_fixups = 0; - for (lfix = CURR_SLOT.tag_fixups; lfix; lfix = lfix->next) + if (mark) { - S_SET_VALUE (lfix->sym, frag_now_fix ()); - symbol_set_frag (lfix->sym, frag_now); + dwarf2_where (&CURR_SLOT.debug_line); + CURR_SLOT.debug_line.flags |= DWARF2_FLAG_BASIC_BLOCK; + dwarf2_gen_line_info (frag_now_fix (), &CURR_SLOT.debug_line); } + CURR_SLOT.label_fixups = 0; + + for (lfix = CURR_SLOT.tag_fixups; lfix; lfix = lfix->next) + symbol_set_value_now (lfix->sym); CURR_SLOT.tag_fixups = 0; /* In case there are unwind directives following the last instruction, @@ -6647,6 +6654,7 @@ emit_one_bundle () int n, i, j, first, curr, last_slot; bfd_vma t0 = 0, t1 = 0; struct label_fix *lfix; + bfd_boolean mark_label; struct insn_fix *ifix; char mnemonic[16]; fixS *fix; @@ -6967,11 +6975,30 @@ emit_one_bundle () if (insn_unit != required_unit) continue; /* Try next slot. */ - if (debug_type == DEBUG_DWARF2 || md.slot[curr].loc_directive_seen) + /* Now is a good time to fix up the labels for this insn. */ + mark_label = FALSE; + for (lfix = md.slot[curr].label_fixups; lfix; lfix = lfix->next) + { + S_SET_VALUE (lfix->sym, frag_now_fix () - 16); + symbol_set_frag (lfix->sym, frag_now); + mark_label |= lfix->dw2_mark_labels; + } + for (lfix = md.slot[curr].tag_fixups; lfix; lfix = lfix->next) + { + S_SET_VALUE (lfix->sym, frag_now_fix () - 16 + i); + symbol_set_frag (lfix->sym, frag_now); + } + + if (debug_type == DEBUG_DWARF2 + || md.slot[curr].loc_directive_seen + || mark_label) { bfd_vma addr = frag_now->fr_address + frag_now_fix () - 16 + i; md.slot[curr].loc_directive_seen = 0; + if (mark_label) + md.slot[curr].debug_line.flags |= DWARF2_FLAG_BASIC_BLOCK; + dwarf2_gen_line_info (addr, &md.slot[curr].debug_line); } @@ -7000,19 +7027,6 @@ emit_one_bundle () --md.num_slots_in_use; last_slot = i; - /* now is a good time to fix up the labels for this insn: */ - for (lfix = md.slot[curr].label_fixups; lfix; lfix = lfix->next) - { - S_SET_VALUE (lfix->sym, frag_now_fix () - 16); - symbol_set_frag (lfix->sym, frag_now); - } - /* and fix up the tags also. */ - for (lfix = md.slot[curr].tag_fixups; lfix; lfix = lfix->next) - { - S_SET_VALUE (lfix->sym, frag_now_fix () - 16 + i); - symbol_set_frag (lfix->sym, frag_now); - } - for (j = 0; j < md.slot[curr].num_fixups; ++j) { ifix = md.slot[curr].fixup + j; @@ -7904,6 +7918,7 @@ ia64_frob_label (sym) fix = obstack_alloc (¬es, sizeof (*fix)); fix->sym = sym; fix->next = CURR_SLOT.tag_fixups; + fix->dw2_mark_labels = FALSE; CURR_SLOT.tag_fixups = fix; return; @@ -7915,6 +7930,7 @@ ia64_frob_label (sym) fix = obstack_alloc (¬es, sizeof (*fix)); fix->sym = sym; fix->next = CURR_SLOT.label_fixups; + fix->dw2_mark_labels = dwarf2_loc_mark_labels; CURR_SLOT.label_fixups = fix; /* Keep track of how many code entry points we've seen. */ diff --git a/gas/config/tc-m68hc11.h b/gas/config/tc-m68hc11.h index a1a42b80f67..70d7d9e7f21 100644 --- a/gas/config/tc-m68hc11.h +++ b/gas/config/tc-m68hc11.h @@ -101,9 +101,6 @@ extern int tc_m68hc11_force_relocation (struct fix *); extern int tc_m68hc11_fix_adjustable (struct fix *); #define md_operand(x) -#define tc_frob_label(sym) do {\ - S_SET_VALUE (sym, (valueT) frag_now_fix ()); \ -} while (0) #define elf_tc_final_processing m68hc11_elf_final_processing extern void m68hc11_elf_final_processing (void); diff --git a/gas/config/tc-m68k.c b/gas/config/tc-m68k.c index 8862a7fadbe..761cdd458a3 100644 --- a/gas/config/tc-m68k.c +++ b/gas/config/tc-m68k.c @@ -4394,6 +4394,10 @@ m68k_frob_label (symbolS *sym) n->text = 0; labels = n; current_label = n; + +#ifdef OBJ_ELF + dwarf2_emit_label (sym); +#endif } /* This is called when a value that is not an instruction is emitted. */ diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index b4b76f018b5..2ce3415073b 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -13594,6 +13594,10 @@ mips_define_label (symbolS *sym) l->label = sym; l->next = insn_labels; insn_labels = l; + +#ifdef OBJ_ELF + dwarf2_emit_label (sym); +#endif } #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) diff --git a/gas/config/tc-ms1.c b/gas/config/tc-ms1.c index 3c604740be9..e459bc84319 100644 --- a/gas/config/tc-ms1.c +++ b/gas/config/tc-ms1.c @@ -63,8 +63,6 @@ const char FLT_CHARS[] = "dD"; const pseudo_typeS md_pseudo_table[] = { { "word", cons, 4 }, - { "file", (void (*) (int)) dwarf2_directive_file, 0 }, - { "loc", dwarf2_directive_loc, 0 }, { NULL, NULL, 0 } }; diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index c7ad9706724..2de8a8b85cb 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -4840,6 +4840,10 @@ ppc_frob_label (sym) &symbol_rootP, &symbol_lastP); symbol_get_tc (ppc_current_csect)->within = sym; } + +#ifdef OBJ_ELF + dwarf2_emit_label (sym); +#endif } /* This variable is set by ppc_frob_symbol if any absolute symbols are diff --git a/gas/config/tc-sh.c b/gas/config/tc-sh.c index b61793ded5d..555842b5fbd 100644 --- a/gas/config/tc-sh.c +++ b/gas/config/tc-sh.c @@ -2876,7 +2876,7 @@ md_assemble (char *str) emits a BFD_RELOC_SH_LABEL reloc if necessary. */ void -sh_frob_label (void) +sh_frob_label (symbolS *sym) { static fragS *last_label_frag; static int last_label_offset; @@ -2895,6 +2895,8 @@ sh_frob_label (void) last_label_offset = offset; } } + + dwarf2_emit_label (sym); } /* This routine is called when the assembler is about to output some diff --git a/gas/config/tc-sh.h b/gas/config/tc-sh.h index c0adaa1dace..69b82b229db 100644 --- a/gas/config/tc-sh.h +++ b/gas/config/tc-sh.h @@ -103,8 +103,8 @@ struct sh_segment_info_type /* We call a routine to emit a reloc for a label, so that the linker can align loads and stores without crossing a label. */ -extern void sh_frob_label (void); -#define tc_frob_label(sym) sh_frob_label () +extern void sh_frob_label (symbolS *); +#define tc_frob_label(sym) sh_frob_label (sym) /* We call a routine to flush pending output in order to output a DATA reloc when required. */ diff --git a/gas/config/tc-sh64.h b/gas/config/tc-sh64.h index cbb37791c9b..8af9b95fe94 100644 --- a/gas/config/tc-sh64.h +++ b/gas/config/tc-sh64.h @@ -144,7 +144,7 @@ extern void sh64_frob_label (symbolS *); #undef tc_frob_label #define tc_frob_label(sym) \ - do { sh_frob_label (); sh64_frob_label (sym); } while (0) + do { sh_frob_label (sym); sh64_frob_label (sym); } while (0) #define tc_symbol_new_hook(s) sh64_frob_label (s) diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c index a93f57eaf8e..c93a4dfafe9 100644 --- a/gas/config/tc-xtensa.c +++ b/gas/config/tc-xtensa.c @@ -5054,7 +5054,7 @@ xtensa_frob_label (symbolS *sym) xtensa_set_frag_assembly_state (frag_now); xtensa_move_labels (frag_now, 0, TRUE); - } + } /* No target aligning in the absolute section. */ if (now_seg != absolute_section @@ -5083,6 +5083,8 @@ xtensa_frob_label (symbolS *sym) /* Loops only go forward, so they can be identified here. */ if (symbol_get_tc (sym)->is_loop_target) symbol_get_frag (sym)->tc_frag_data.is_loop_target = TRUE; + + dwarf2_emit_label (sym); } diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo index 86827d5116e..63cc5d135fa 100644 --- a/gas/doc/as.texinfo +++ b/gas/doc/as.texinfo @@ -4103,6 +4103,15 @@ either 0 or 1. @item isa @var{value} This directive will set the @code{isa} register in the @code{.debug_line} state machine to @var{value}, which must be an unsigned integer. + +@section @code{.loc_mark_blocks @var{enable}} +@cindex @code{loc_mark_blocks} directive +The @code{.loc_mark_blocks} directive makes the assembler emit an entry +to the @code{.debug_line} line number matrix with the @code{basic_block} +register in the state machine set whenever a code label is seen. +The @var{enable} argument should be either 1 or 0, to enable or disable +this function respectively. + @end table @node Data diff --git a/gas/dwarf2dbg.c b/gas/dwarf2dbg.c index 43600803bec..be59eba5db7 100644 --- a/gas/dwarf2dbg.c +++ b/gas/dwarf2dbg.c @@ -105,8 +105,7 @@ struct line_entry { struct line_entry *next; - fragS *frag; - addressT frag_ofs; + symbolS *label; struct dwarf2_line_info loc; }; @@ -147,6 +146,10 @@ static unsigned int dirs_allocated; doing work when there's nothing to do. */ static bfd_boolean loc_directive_seen; +/* TRUE when we're supposed to set the basic block mark whenever a + label is seen. */ +bfd_boolean dwarf2_loc_mark_labels; + /* Current location as indicated by the most recent .loc directive. */ static struct dwarf2_line_info current = { 1, 1, 0, 0, @@ -167,12 +170,11 @@ static void out_four (int); static void out_abbrev (int, int); static void out_uleb128 (addressT); static offsetT get_frag_fix (fragS *); -static void out_set_addr (segT, fragS *, addressT); +static void out_set_addr (symbolS *); static int size_inc_line_addr (int, addressT); static void emit_inc_line_addr (int, addressT, char *, int); static void out_inc_line_addr (int, addressT); -static void relax_inc_line_addr (int, segT, fragS *, addressT, - fragS *, addressT); +static void relax_inc_line_addr (int, symbolS *, symbolS *); static void process_entries (segT, struct line_entry *); static void out_file_list (void); static void out_debug_line (segT); @@ -247,16 +249,34 @@ get_line_subseg (segT seg, subsegT subseg) return ss; } +/* Record an entry for LOC occurring at LABEL. */ + +static void +dwarf2_gen_line_info_1 (symbolS *label, struct dwarf2_line_info *loc) +{ + struct line_subseg *ss; + struct line_entry *e; + + e = (struct line_entry *) xmalloc (sizeof (*e)); + e->next = NULL; + e->label = label; + e->loc = *loc; + + ss = get_line_subseg (now_seg, now_subseg); + *ss->ptail = e; + ss->ptail = &e->next; +} + /* Record an entry for LOC occurring at OFS within the current fragment. */ void dwarf2_gen_line_info (addressT ofs, struct dwarf2_line_info *loc) { - struct line_subseg *ss; - struct line_entry *e; static unsigned int line = -1; static unsigned int filenum = -1; + symbolS *sym; + /* Early out for as-yet incomplete location information. */ if (loc->filenum == 0 || loc->line == 0) return; @@ -272,15 +292,8 @@ dwarf2_gen_line_info (addressT ofs, struct dwarf2_line_info *loc) line = loc->line; filenum = loc->filenum; - e = (struct line_entry *) xmalloc (sizeof (*e)); - e->next = NULL; - e->frag = frag_now; - e->frag_ofs = ofs; - e->loc = *loc; - - ss = get_line_subseg (now_seg, now_subseg); - *ss->ptail = e; - ss->ptail = &e->next; + sym = symbol_temp_new (now_seg, ofs, frag_now); + dwarf2_gen_line_info_1 (sym, loc); } /* Returns the current source information. If .file directives have @@ -349,6 +362,38 @@ dwarf2_emit_insn (int size) | DWARF2_FLAG_EPILOGUE_BEGIN); } +/* Called for each (preferably code) label. If dwarf2_loc_mark_labels + is enabled, emit a basic block marker. */ + +void +dwarf2_emit_label (symbolS *label) +{ + struct dwarf2_line_info loc; + + if (!dwarf2_loc_mark_labels) + return; + if (S_GET_SEGMENT (label) != now_seg) + return; + if (!(bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE)) + return; + + if (debug_type == DEBUG_DWARF2) + dwarf2_where (&loc); + else + { + loc = current; + loc_directive_seen = FALSE; + } + + loc.flags |= DWARF2_FLAG_BASIC_BLOCK; + + current.flags &= ~(DWARF2_FLAG_BASIC_BLOCK + | DWARF2_FLAG_PROLOGUE_END + | DWARF2_FLAG_EPILOGUE_BEGIN); + + dwarf2_gen_line_info_1 (label, &loc); +} + /* Get a .debug_line file number for FILENAME. If NUM is nonzero, allocate it on that file table slot, otherwise return the first empty one. */ @@ -603,6 +648,23 @@ dwarf2_directive_loc (int dummy ATTRIBUTE_UNUSED) demand_empty_rest_of_line (); loc_directive_seen = TRUE; } + +void +dwarf2_directive_loc_mark_labels (int dummy ATTRIBUTE_UNUSED) +{ + offsetT value = get_absolute_expression (); + + if (value != 0 && value != 1) + { + as_bad (_("expected 0 or 1")); + ignore_rest_of_line (); + } + else + { + dwarf2_loc_mark_labels = value != 0; + demand_empty_rest_of_line (); + } +} static struct frag * first_frag_for_seg (segT seg) @@ -702,12 +764,9 @@ get_frag_fix (fragS *frag) /* Set an absolute address (may result in a relocation entry). */ static void -out_set_addr (segT seg, fragS *frag, addressT ofs) +out_set_addr (symbolS *sym) { expressionS expr; - symbolS *sym; - - sym = symbol_temp_new (seg, ofs, frag); out_opcode (DW_LNS_extended_op); out_uleb128 (sizeof_address + 1); @@ -811,6 +870,10 @@ emit_inc_line_addr (int line_delta, addressT addr_delta, char *p, int len) int need_copy = 0; char *end = p + len; + /* Line number sequences cannot go backward in addresses. This means + we've incorrectly ordered the statements in the sequence. */ + assert ((offsetT) addr_delta >= 0); + /* Scale the address delta by the minimum instruction length. */ scale_addr_delta (&addr_delta); @@ -906,17 +969,11 @@ out_inc_line_addr (int line_delta, addressT addr_delta) increments between fragments of the target segment. */ static void -relax_inc_line_addr (int line_delta, segT seg, - fragS *to_frag, addressT to_ofs, - fragS *from_frag, addressT from_ofs) +relax_inc_line_addr (int line_delta, symbolS *to_sym, symbolS *from_sym) { - symbolS *to_sym, *from_sym; expressionS expr; int max_chars; - to_sym = symbol_temp_new (seg, to_ofs, to_frag); - from_sym = symbol_temp_new (seg, from_ofs, from_frag); - expr.X_op = O_subtract; expr.X_add_symbol = to_sym; expr.X_op_symbol = from_sym; @@ -999,22 +1056,20 @@ process_entries (segT seg, struct line_entry *e) unsigned column = 0; unsigned isa = 0; unsigned flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; - fragS *frag = NULL; - fragS *last_frag; - addressT frag_ofs = 0; - addressT last_frag_ofs; + fragS *last_frag = NULL, *frag; + addressT last_frag_ofs = 0, frag_ofs; + symbolS *last_lab, *lab; struct line_entry *next; while (e) { - int changed = 0; + int line_delta; if (filenum != e->loc.filenum) { filenum = e->loc.filenum; out_opcode (DW_LNS_set_file); out_uleb128 (filenum); - changed = 1; } if (column != e->loc.column) @@ -1022,7 +1077,6 @@ process_entries (segT seg, struct line_entry *e) column = e->loc.column; out_opcode (DW_LNS_set_column); out_uleb128 (column); - changed = 1; } if (isa != e->loc.isa) @@ -1030,62 +1084,46 @@ process_entries (segT seg, struct line_entry *e) isa = e->loc.isa; out_opcode (DW_LNS_set_isa); out_uleb128 (isa); - changed = 1; } if ((e->loc.flags ^ flags) & DWARF2_FLAG_IS_STMT) { flags = e->loc.flags; out_opcode (DW_LNS_negate_stmt); - changed = 1; } if (e->loc.flags & DWARF2_FLAG_BASIC_BLOCK) - { - out_opcode (DW_LNS_set_basic_block); - changed = 1; - } + out_opcode (DW_LNS_set_basic_block); if (e->loc.flags & DWARF2_FLAG_PROLOGUE_END) - { - out_opcode (DW_LNS_set_prologue_end); - changed = 1; - } + out_opcode (DW_LNS_set_prologue_end); if (e->loc.flags & DWARF2_FLAG_EPILOGUE_BEGIN) - { - out_opcode (DW_LNS_set_epilogue_begin); - changed = 1; - } + out_opcode (DW_LNS_set_epilogue_begin); /* Don't try to optimize away redundant entries; gdb wants two entries for a function where the code starts on the same line as the {, and there's no way to identify that case here. Trust gcc to optimize appropriately. */ - if (1 /* line != e->loc.line || changed */) - { - int line_delta = e->loc.line - line; - if (frag == NULL) - { - out_set_addr (seg, e->frag, e->frag_ofs); - out_inc_line_addr (line_delta, 0); - } - else if (frag == e->frag) - out_inc_line_addr (line_delta, e->frag_ofs - frag_ofs); - else - relax_inc_line_addr (line_delta, seg, e->frag, e->frag_ofs, - frag, frag_ofs); + line_delta = e->loc.line - line; + lab = e->label; + frag = symbol_get_frag (lab); + frag_ofs = S_GET_VALUE (lab); - frag = e->frag; - frag_ofs = e->frag_ofs; - line = e->loc.line; - } - else if (frag == NULL) + if (last_frag == NULL) { - out_set_addr (seg, e->frag, e->frag_ofs); - frag = e->frag; - frag_ofs = e->frag_ofs; + out_set_addr (lab); + out_inc_line_addr (line_delta, 0); } + else if (frag == last_frag) + out_inc_line_addr (line_delta, frag_ofs - last_frag_ofs); + else + relax_inc_line_addr (line_delta, lab, last_lab); + + line = e->loc.line; + last_lab = lab; + last_frag = frag; + last_frag_ofs = frag_ofs; next = e->next; free (e); @@ -1093,13 +1131,15 @@ process_entries (segT seg, struct line_entry *e) } /* Emit a DW_LNE_end_sequence for the end of the section. */ - last_frag = last_frag_for_seg (seg); - last_frag_ofs = get_frag_fix (last_frag); + frag = last_frag_for_seg (seg); + frag_ofs = get_frag_fix (frag); if (frag == last_frag) - out_inc_line_addr (INT_MAX, last_frag_ofs - frag_ofs); + out_inc_line_addr (INT_MAX, frag_ofs - last_frag_ofs); else - relax_inc_line_addr (INT_MAX, seg, last_frag, last_frag_ofs, - frag, frag_ofs); + { + lab = symbol_temp_new (seg, frag_ofs, frag); + relax_inc_line_addr (INT_MAX, lab, last_lab); + } } /* Emit the directory and file tables for .debug_line. */ diff --git a/gas/dwarf2dbg.h b/gas/dwarf2dbg.h index 6e80021927d..cd1d17b2031 100644 --- a/gas/dwarf2dbg.h +++ b/gas/dwarf2dbg.h @@ -49,6 +49,9 @@ extern char *dwarf2_directive_file (int dummy); used. */ extern void dwarf2_directive_loc (int dummy); +/* Implements the .loc_mark_labels {0,1} directive. */ +extern void dwarf2_directive_loc_mark_labels (int dummy); + /* Returns the current source information. If .file directives have been encountered, the info for the corresponding source file is returned. Otherwise, the info for the assembly source file is @@ -69,6 +72,14 @@ extern void dwarf2_gen_line_info (addressT addr, struct dwarf2_line_info *l); /* Must be called for each generated instruction. */ extern void dwarf2_emit_insn (int); +/* Should be called for each code label. */ +extern void dwarf2_emit_label (symbolS *); + +/* True when we're supposed to set the basic block mark whenever a label + is seen. Unless the target is doing Something Weird, just call + dwarf2_emit_label. */ +bfd_boolean dwarf2_loc_mark_labels; + extern void dwarf2_finish (void); extern int dwarf2dbg_estimate_size_before_relax (fragS *); -- 2.30.2