* 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.
This commit is contained in:
Richard Henderson 2005-09-20 18:24:48 +00:00
parent d5cbaa1554
commit 07a53e5cdb
20 changed files with 249 additions and 107 deletions

View file

@ -1,3 +1,37 @@
2005-09-20 Richard Henderson <rth@redhat.com>
* 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 <amodra@bigpond.net.au> 2005-09-20 Alan Modra <amodra@bigpond.net.au>
* read.c (pseudo_set): Set segment of expression syms to expr_section. * read.c (pseudo_set): Set segment of expression syms to expr_section.

View file

@ -115,6 +115,7 @@ static const pseudo_typeS elf_pseudo_table[] =
/* These are used for dwarf2. */ /* These are used for dwarf2. */
{ "file", (void (*) (int)) dwarf2_directive_file, 0 }, { "file", (void (*) (int)) dwarf2_directive_file, 0 },
{ "loc", dwarf2_directive_loc, 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. */ /* We need to trap the section changing calls to handle .previous. */
{"data", obj_elf_data, 0}, {"data", obj_elf_data, 0},

View file

@ -156,6 +156,13 @@ extern void elf_frob_file_before_adjust (void);
#endif #endif
extern void elf_frob_file_after_relocs (void); 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 #ifndef obj_app_file
#define obj_app_file elf_file_symbol #define obj_app_file elf_file_symbol
#endif #endif

View file

@ -5464,6 +5464,9 @@ void
alpha_define_label (symbolS *sym) alpha_define_label (symbolS *sym)
{ {
alpha_insn_label = 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 /* Return true if we must always emit a reloc for a type and false if

View file

@ -8092,6 +8092,10 @@ arm_frob_label (symbolS * sym)
label_is_thumb_function_name = FALSE; label_is_thumb_function_name = FALSE;
} }
#ifdef OBJ_ELF
dwarf2_emit_label (sym);
#endif
} }
int int

View file

@ -1287,6 +1287,10 @@ pa_define_label (symbol)
label_symbols_rootp = label_chain; label_symbols_rootp = label_chain;
} }
#ifdef OBJ_ELF
dwarf2_emit_label (symbol);
#endif
} }
/* Removes a label definition for the current space. /* Removes a label definition for the current space.

View file

@ -469,10 +469,12 @@ const pseudo_typeS md_pseudo_table[] =
{"code64", set_code_flag, CODE_64BIT}, {"code64", set_code_flag, CODE_64BIT},
{"intel_syntax", set_intel_syntax, 1}, {"intel_syntax", set_intel_syntax, 1},
{"att_syntax", set_intel_syntax, 0}, {"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) #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
{"largecomm", handle_large_common, 0}, {"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 #endif
#ifdef TE_PE #ifdef TE_PE
{"secrel32", pe_directive_secrel, 0}, {"secrel32", pe_directive_secrel, 0},

View file

@ -159,6 +159,7 @@ struct label_fix
{ {
struct label_fix *next; struct label_fix *next;
struct symbol *sym; struct symbol *sym;
bfd_boolean dw2_mark_labels;
}; };
/* This is the endianness of the current section. */ /* This is the endianness of the current section. */
@ -1083,6 +1084,7 @@ ia64_flush_insns ()
segT saved_seg; segT saved_seg;
subsegT saved_subseg; subsegT saved_subseg;
unw_rec_list *ptr; unw_rec_list *ptr;
bfd_boolean mark;
if (!md.last_text_seg) if (!md.last_text_seg)
return; return;
@ -1096,18 +1098,23 @@ ia64_flush_insns ()
emit_one_bundle (); /* force out queued instructions */ emit_one_bundle (); /* force out queued instructions */
/* In case there are labels following the last instruction, resolve /* 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) for (lfix = CURR_SLOT.label_fixups; lfix; lfix = lfix->next)
{ {
S_SET_VALUE (lfix->sym, frag_now_fix ()); symbol_set_value_now (lfix->sym);
symbol_set_frag (lfix->sym, frag_now); mark |= lfix->dw2_mark_labels;
}
if (mark)
{
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; CURR_SLOT.label_fixups = 0;
for (lfix = CURR_SLOT.tag_fixups; lfix; lfix = lfix->next) for (lfix = CURR_SLOT.tag_fixups; lfix; lfix = lfix->next)
{ symbol_set_value_now (lfix->sym);
S_SET_VALUE (lfix->sym, frag_now_fix ());
symbol_set_frag (lfix->sym, frag_now);
}
CURR_SLOT.tag_fixups = 0; CURR_SLOT.tag_fixups = 0;
/* In case there are unwind directives following the last instruction, /* 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; int n, i, j, first, curr, last_slot;
bfd_vma t0 = 0, t1 = 0; bfd_vma t0 = 0, t1 = 0;
struct label_fix *lfix; struct label_fix *lfix;
bfd_boolean mark_label;
struct insn_fix *ifix; struct insn_fix *ifix;
char mnemonic[16]; char mnemonic[16];
fixS *fix; fixS *fix;
@ -6967,11 +6975,30 @@ emit_one_bundle ()
if (insn_unit != required_unit) if (insn_unit != required_unit)
continue; /* Try next slot. */ 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; bfd_vma addr = frag_now->fr_address + frag_now_fix () - 16 + i;
md.slot[curr].loc_directive_seen = 0; 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); dwarf2_gen_line_info (addr, &md.slot[curr].debug_line);
} }
@ -7000,19 +7027,6 @@ emit_one_bundle ()
--md.num_slots_in_use; --md.num_slots_in_use;
last_slot = i; 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) for (j = 0; j < md.slot[curr].num_fixups; ++j)
{ {
ifix = md.slot[curr].fixup + j; ifix = md.slot[curr].fixup + j;
@ -7904,6 +7918,7 @@ ia64_frob_label (sym)
fix = obstack_alloc (&notes, sizeof (*fix)); fix = obstack_alloc (&notes, sizeof (*fix));
fix->sym = sym; fix->sym = sym;
fix->next = CURR_SLOT.tag_fixups; fix->next = CURR_SLOT.tag_fixups;
fix->dw2_mark_labels = FALSE;
CURR_SLOT.tag_fixups = fix; CURR_SLOT.tag_fixups = fix;
return; return;
@ -7915,6 +7930,7 @@ ia64_frob_label (sym)
fix = obstack_alloc (&notes, sizeof (*fix)); fix = obstack_alloc (&notes, sizeof (*fix));
fix->sym = sym; fix->sym = sym;
fix->next = CURR_SLOT.label_fixups; fix->next = CURR_SLOT.label_fixups;
fix->dw2_mark_labels = dwarf2_loc_mark_labels;
CURR_SLOT.label_fixups = fix; CURR_SLOT.label_fixups = fix;
/* Keep track of how many code entry points we've seen. */ /* Keep track of how many code entry points we've seen. */

View file

@ -101,9 +101,6 @@ extern int tc_m68hc11_force_relocation (struct fix *);
extern int tc_m68hc11_fix_adjustable (struct fix *); extern int tc_m68hc11_fix_adjustable (struct fix *);
#define md_operand(x) #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 #define elf_tc_final_processing m68hc11_elf_final_processing
extern void m68hc11_elf_final_processing (void); extern void m68hc11_elf_final_processing (void);

View file

@ -4394,6 +4394,10 @@ m68k_frob_label (symbolS *sym)
n->text = 0; n->text = 0;
labels = n; labels = n;
current_label = 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. */ /* This is called when a value that is not an instruction is emitted. */

View file

@ -13594,6 +13594,10 @@ mips_define_label (symbolS *sym)
l->label = sym; l->label = sym;
l->next = insn_labels; l->next = insn_labels;
insn_labels = l; insn_labels = l;
#ifdef OBJ_ELF
dwarf2_emit_label (sym);
#endif
} }
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)

View file

@ -63,8 +63,6 @@ const char FLT_CHARS[] = "dD";
const pseudo_typeS md_pseudo_table[] = const pseudo_typeS md_pseudo_table[] =
{ {
{ "word", cons, 4 }, { "word", cons, 4 },
{ "file", (void (*) (int)) dwarf2_directive_file, 0 },
{ "loc", dwarf2_directive_loc, 0 },
{ NULL, NULL, 0 } { NULL, NULL, 0 }
}; };

View file

@ -4840,6 +4840,10 @@ ppc_frob_label (sym)
&symbol_rootP, &symbol_lastP); &symbol_rootP, &symbol_lastP);
symbol_get_tc (ppc_current_csect)->within = sym; 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 /* This variable is set by ppc_frob_symbol if any absolute symbols are

View file

@ -2876,7 +2876,7 @@ md_assemble (char *str)
emits a BFD_RELOC_SH_LABEL reloc if necessary. */ emits a BFD_RELOC_SH_LABEL reloc if necessary. */
void void
sh_frob_label (void) sh_frob_label (symbolS *sym)
{ {
static fragS *last_label_frag; static fragS *last_label_frag;
static int last_label_offset; static int last_label_offset;
@ -2895,6 +2895,8 @@ sh_frob_label (void)
last_label_offset = offset; last_label_offset = offset;
} }
} }
dwarf2_emit_label (sym);
} }
/* This routine is called when the assembler is about to output some /* This routine is called when the assembler is about to output some

View file

@ -103,8 +103,8 @@ struct sh_segment_info_type
/* We call a routine to emit a reloc for a label, so that the linker /* We call a routine to emit a reloc for a label, so that the linker
can align loads and stores without crossing a label. */ can align loads and stores without crossing a label. */
extern void sh_frob_label (void); extern void sh_frob_label (symbolS *);
#define tc_frob_label(sym) sh_frob_label () #define tc_frob_label(sym) sh_frob_label (sym)
/* We call a routine to flush pending output in order to output a DATA /* We call a routine to flush pending output in order to output a DATA
reloc when required. */ reloc when required. */

View file

@ -144,7 +144,7 @@ extern void sh64_frob_label (symbolS *);
#undef tc_frob_label #undef tc_frob_label
#define tc_frob_label(sym) \ #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) #define tc_symbol_new_hook(s) sh64_frob_label (s)

View file

@ -5054,7 +5054,7 @@ xtensa_frob_label (symbolS *sym)
xtensa_set_frag_assembly_state (frag_now); xtensa_set_frag_assembly_state (frag_now);
xtensa_move_labels (frag_now, 0, TRUE); xtensa_move_labels (frag_now, 0, TRUE);
} }
/* No target aligning in the absolute section. */ /* No target aligning in the absolute section. */
if (now_seg != 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. */ /* Loops only go forward, so they can be identified here. */
if (symbol_get_tc (sym)->is_loop_target) if (symbol_get_tc (sym)->is_loop_target)
symbol_get_frag (sym)->tc_frag_data.is_loop_target = TRUE; symbol_get_frag (sym)->tc_frag_data.is_loop_target = TRUE;
dwarf2_emit_label (sym);
} }

View file

@ -4103,6 +4103,15 @@ either 0 or 1.
@item isa @var{value} @item isa @var{value}
This directive will set the @code{isa} register in the @code{.debug_line} This directive will set the @code{isa} register in the @code{.debug_line}
state machine to @var{value}, which must be an unsigned integer. 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 @end table
@node Data @node Data

View file

@ -105,8 +105,7 @@
struct line_entry { struct line_entry {
struct line_entry *next; struct line_entry *next;
fragS *frag; symbolS *label;
addressT frag_ofs;
struct dwarf2_line_info loc; struct dwarf2_line_info loc;
}; };
@ -147,6 +146,10 @@ static unsigned int dirs_allocated;
doing work when there's nothing to do. */ doing work when there's nothing to do. */
static bfd_boolean loc_directive_seen; 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. */ /* Current location as indicated by the most recent .loc directive. */
static struct dwarf2_line_info current = { static struct dwarf2_line_info current = {
1, 1, 0, 0, 1, 1, 0, 0,
@ -167,12 +170,11 @@ static void out_four (int);
static void out_abbrev (int, int); static void out_abbrev (int, int);
static void out_uleb128 (addressT); static void out_uleb128 (addressT);
static offsetT get_frag_fix (fragS *); 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 int size_inc_line_addr (int, addressT);
static void emit_inc_line_addr (int, addressT, char *, int); static void emit_inc_line_addr (int, addressT, char *, int);
static void out_inc_line_addr (int, addressT); static void out_inc_line_addr (int, addressT);
static void relax_inc_line_addr (int, segT, fragS *, addressT, static void relax_inc_line_addr (int, symbolS *, symbolS *);
fragS *, addressT);
static void process_entries (segT, struct line_entry *); static void process_entries (segT, struct line_entry *);
static void out_file_list (void); static void out_file_list (void);
static void out_debug_line (segT); static void out_debug_line (segT);
@ -247,16 +249,34 @@ get_line_subseg (segT seg, subsegT subseg)
return ss; 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. */ /* Record an entry for LOC occurring at OFS within the current fragment. */
void void
dwarf2_gen_line_info (addressT ofs, struct dwarf2_line_info *loc) 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 line = -1;
static unsigned int filenum = -1; static unsigned int filenum = -1;
symbolS *sym;
/* Early out for as-yet incomplete location information. */ /* Early out for as-yet incomplete location information. */
if (loc->filenum == 0 || loc->line == 0) if (loc->filenum == 0 || loc->line == 0)
return; return;
@ -272,15 +292,8 @@ dwarf2_gen_line_info (addressT ofs, struct dwarf2_line_info *loc)
line = loc->line; line = loc->line;
filenum = loc->filenum; filenum = loc->filenum;
e = (struct line_entry *) xmalloc (sizeof (*e)); sym = symbol_temp_new (now_seg, ofs, frag_now);
e->next = NULL; dwarf2_gen_line_info_1 (sym, loc);
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;
} }
/* Returns the current source information. If .file directives have /* Returns the current source information. If .file directives have
@ -349,6 +362,38 @@ dwarf2_emit_insn (int size)
| DWARF2_FLAG_EPILOGUE_BEGIN); | 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, /* Get a .debug_line file number for FILENAME. If NUM is nonzero,
allocate it on that file table slot, otherwise return the first allocate it on that file table slot, otherwise return the first
empty one. */ empty one. */
@ -603,6 +648,23 @@ dwarf2_directive_loc (int dummy ATTRIBUTE_UNUSED)
demand_empty_rest_of_line (); demand_empty_rest_of_line ();
loc_directive_seen = TRUE; 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 * static struct frag *
first_frag_for_seg (segT seg) 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). */ /* Set an absolute address (may result in a relocation entry). */
static void static void
out_set_addr (segT seg, fragS *frag, addressT ofs) out_set_addr (symbolS *sym)
{ {
expressionS expr; expressionS expr;
symbolS *sym;
sym = symbol_temp_new (seg, ofs, frag);
out_opcode (DW_LNS_extended_op); out_opcode (DW_LNS_extended_op);
out_uleb128 (sizeof_address + 1); 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; int need_copy = 0;
char *end = p + len; 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 the address delta by the minimum instruction length. */
scale_addr_delta (&addr_delta); 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. */ increments between fragments of the target segment. */
static void static void
relax_inc_line_addr (int line_delta, segT seg, relax_inc_line_addr (int line_delta, symbolS *to_sym, symbolS *from_sym)
fragS *to_frag, addressT to_ofs,
fragS *from_frag, addressT from_ofs)
{ {
symbolS *to_sym, *from_sym;
expressionS expr; expressionS expr;
int max_chars; 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_op = O_subtract;
expr.X_add_symbol = to_sym; expr.X_add_symbol = to_sym;
expr.X_op_symbol = from_sym; expr.X_op_symbol = from_sym;
@ -999,22 +1056,20 @@ process_entries (segT seg, struct line_entry *e)
unsigned column = 0; unsigned column = 0;
unsigned isa = 0; unsigned isa = 0;
unsigned flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0; unsigned flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
fragS *frag = NULL; fragS *last_frag = NULL, *frag;
fragS *last_frag; addressT last_frag_ofs = 0, frag_ofs;
addressT frag_ofs = 0; symbolS *last_lab, *lab;
addressT last_frag_ofs;
struct line_entry *next; struct line_entry *next;
while (e) while (e)
{ {
int changed = 0; int line_delta;
if (filenum != e->loc.filenum) if (filenum != e->loc.filenum)
{ {
filenum = e->loc.filenum; filenum = e->loc.filenum;
out_opcode (DW_LNS_set_file); out_opcode (DW_LNS_set_file);
out_uleb128 (filenum); out_uleb128 (filenum);
changed = 1;
} }
if (column != e->loc.column) if (column != e->loc.column)
@ -1022,7 +1077,6 @@ process_entries (segT seg, struct line_entry *e)
column = e->loc.column; column = e->loc.column;
out_opcode (DW_LNS_set_column); out_opcode (DW_LNS_set_column);
out_uleb128 (column); out_uleb128 (column);
changed = 1;
} }
if (isa != e->loc.isa) if (isa != e->loc.isa)
@ -1030,62 +1084,46 @@ process_entries (segT seg, struct line_entry *e)
isa = e->loc.isa; isa = e->loc.isa;
out_opcode (DW_LNS_set_isa); out_opcode (DW_LNS_set_isa);
out_uleb128 (isa); out_uleb128 (isa);
changed = 1;
} }
if ((e->loc.flags ^ flags) & DWARF2_FLAG_IS_STMT) if ((e->loc.flags ^ flags) & DWARF2_FLAG_IS_STMT)
{ {
flags = e->loc.flags; flags = e->loc.flags;
out_opcode (DW_LNS_negate_stmt); out_opcode (DW_LNS_negate_stmt);
changed = 1;
} }
if (e->loc.flags & DWARF2_FLAG_BASIC_BLOCK) if (e->loc.flags & DWARF2_FLAG_BASIC_BLOCK)
{ out_opcode (DW_LNS_set_basic_block);
out_opcode (DW_LNS_set_basic_block);
changed = 1;
}
if (e->loc.flags & DWARF2_FLAG_PROLOGUE_END) if (e->loc.flags & DWARF2_FLAG_PROLOGUE_END)
{ out_opcode (DW_LNS_set_prologue_end);
out_opcode (DW_LNS_set_prologue_end);
changed = 1;
}
if (e->loc.flags & DWARF2_FLAG_EPILOGUE_BEGIN) if (e->loc.flags & DWARF2_FLAG_EPILOGUE_BEGIN)
{ out_opcode (DW_LNS_set_epilogue_begin);
out_opcode (DW_LNS_set_epilogue_begin);
changed = 1;
}
/* Don't try to optimize away redundant entries; gdb wants two /* Don't try to optimize away redundant entries; gdb wants two
entries for a function where the code starts on the same line as 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 the {, and there's no way to identify that case here. Trust gcc
to optimize appropriately. */ to optimize appropriately. */
if (1 /* line != e->loc.line || changed */) line_delta = e->loc.line - line;
{ lab = e->label;
int line_delta = e->loc.line - line; frag = symbol_get_frag (lab);
if (frag == NULL) frag_ofs = S_GET_VALUE (lab);
{
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);
frag = e->frag; if (last_frag == NULL)
frag_ofs = e->frag_ofs;
line = e->loc.line;
}
else if (frag == NULL)
{ {
out_set_addr (seg, e->frag, e->frag_ofs); out_set_addr (lab);
frag = e->frag; out_inc_line_addr (line_delta, 0);
frag_ofs = e->frag_ofs;
} }
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; next = e->next;
free (e); 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. */ /* Emit a DW_LNE_end_sequence for the end of the section. */
last_frag = last_frag_for_seg (seg); frag = last_frag_for_seg (seg);
last_frag_ofs = get_frag_fix (last_frag); frag_ofs = get_frag_fix (frag);
if (frag == last_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 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. */ /* Emit the directory and file tables for .debug_line. */

View file

@ -49,6 +49,9 @@ extern char *dwarf2_directive_file (int dummy);
used. */ used. */
extern void dwarf2_directive_loc (int dummy); 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 /* Returns the current source information. If .file directives have
been encountered, the info for the corresponding source file is been encountered, the info for the corresponding source file is
returned. Otherwise, the info for the assembly 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. */ /* Must be called for each generated instruction. */
extern void dwarf2_emit_insn (int); 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 void dwarf2_finish (void);
extern int dwarf2dbg_estimate_size_before_relax (fragS *); extern int dwarf2dbg_estimate_size_before_relax (fragS *);