aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2005-09-20 18:24:48 +0000
committerRichard Henderson <rth@redhat.com>2005-09-20 18:24:48 +0000
commit07a53e5cdb3d786ea59bdce443b307c04f691d17 (patch)
treec6d80f88c6b71d66e4542f13f824727056ef27b5
parentd5cbaa15541c43d4df31e60fb61e7bc9a8b766fa (diff)
downloadgdb-07a53e5cdb3d786ea59bdce443b307c04f691d17.zip
gdb-07a53e5cdb3d786ea59bdce443b307c04f691d17.tar.gz
gdb-07a53e5cdb3d786ea59bdce443b307c04f691d17.tar.bz2
* 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.
-rw-r--r--gas/ChangeLog34
-rw-r--r--gas/config/obj-elf.c1
-rw-r--r--gas/config/obj-elf.h7
-rw-r--r--gas/config/tc-alpha.c3
-rw-r--r--gas/config/tc-arm.c4
-rw-r--r--gas/config/tc-hppa.c4
-rw-r--r--gas/config/tc-i386.c6
-rw-r--r--gas/config/tc-ia64.c58
-rw-r--r--gas/config/tc-m68hc11.h3
-rw-r--r--gas/config/tc-m68k.c4
-rw-r--r--gas/config/tc-mips.c4
-rw-r--r--gas/config/tc-ms1.c2
-rw-r--r--gas/config/tc-ppc.c4
-rw-r--r--gas/config/tc-sh.c4
-rw-r--r--gas/config/tc-sh.h4
-rw-r--r--gas/config/tc-sh64.h2
-rw-r--r--gas/config/tc-xtensa.c4
-rw-r--r--gas/doc/as.texinfo9
-rw-r--r--gas/dwarf2dbg.c188
-rw-r--r--gas/dwarf2dbg.h11
20 files changed, 249 insertions, 107 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 2018e20..c484842 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -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>
* 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 43e0c97..f922149 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 629fc00..7ff9ef0 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 2eb0adf..8d92352 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 c11e149..8d327eb 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 75f6dbb..1c1b4e4 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 b562b76..3820b19 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 81e5cd5..5875551 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 (&notes, 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 (&notes, 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 a1a42b8..70d7d9e 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 8862a7f..761cdd4 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 b4b76f0..2ce3415 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 3c60474..e459bc8 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 c7ad970..2de8a8b 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 b61793d..555842b 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 c0adaa1..69b82b2 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 cbb3779..8af9b95 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 a93f57e..c93a4df 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 86827d5..63cc5d1 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 4360080..be59eba 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 6e80021..cd1d17b 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 *);