summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbrad <brad@openbsd.org>2013-02-13 03:46:46 +0000
committerbrad <brad@openbsd.org>2013-02-13 03:46:46 +0000
commit2b94ee3955bd3eba70cdf4e7f43e8bd4779eb603 (patch)
treed365ef1d04046b3a6d6a7f0c5e14afc187e1dfa4
parentReflect the -f option in last's output. Original diff from Jacob L. Leifman. (diff)
downloadwireguard-openbsd-2b94ee3955bd3eba70cdf4e7f43e8bd4779eb603.tar.xz
wireguard-openbsd-2b94ee3955bd3eba70cdf4e7f43e8bd4779eb603.zip
Add support for .loc directive options basic_block, prologue_end, and epilogue_begin.
Backported from binutils 2.17. ok miod@
-rw-r--r--gnu/usr.bin/binutils/gas/doc/as.texinfo51
-rw-r--r--gnu/usr.bin/binutils/gas/dwarf2dbg.c172
-rw-r--r--gnu/usr.bin/binutils/gas/dwarf2dbg.h11
3 files changed, 199 insertions, 35 deletions
diff --git a/gnu/usr.bin/binutils/gas/doc/as.texinfo b/gnu/usr.bin/binutils/gas/doc/as.texinfo
index d9d23dff59f..c6110c5a06c 100644
--- a/gnu/usr.bin/binutils/gas/doc/as.texinfo
+++ b/gnu/usr.bin/binutils/gas/doc/as.texinfo
@@ -3732,9 +3732,12 @@ Some machine configurations provide additional directives.
* Line:: @code{.line @var{line-number}}
@end ifclear
-* Ln:: @code{.ln @var{line-number}}
* Linkonce:: @code{.linkonce [@var{type}]}
* List:: @code{.list}
+* Ln:: @code{.ln @var{line-number}}
+
+* LNS directives:: @code{.file}, @code{.loc}, etc.
+
* Long:: @code{.long @var{expressions}}
@ignore
* Lsym:: @code{.lsym @var{symbol}, @var{expression}}
@@ -4034,6 +4037,52 @@ Allows the user to add arbitrary bytes to the unwind info. One
might use this to add OS-specific CFI opcodes, or generic CFI
opcodes that GAS does not yet support.
+@node LNS directives
+@section @code{.file @var{fileno} @var{filename}}
+@cindex @code{file} directive
+When emitting dwarf2 line number information @code{.file} assigns filenames
+to the @code{.debug_line} file name table. The @var{fileno} operand should
+be a unique positive integer to use as the index of the entry in the table.
+The @var{filename} operand is a C string literal.
+
+The detail of filename indicies is exposed to the user because the filename
+table is shared with the @code{.debug_info} section of the dwarf2 debugging
+information, and thus the user must know the exact indicies that table
+entries will have.
+
+@section @code{.loc @var{fileno} @var{lineno} [@var{column}] [@var{options}]}
+@cindex @code{loc} directive
+The @code{.loc} directive will add row to the @code{.debug_line} line
+number matrix corresponding to the immediately following assembly
+instruction. The @var{fileno}, @var{lineno}, and optional @var{column}
+arguments will be applied to the @code{.debug_line} state machine before
+the row is added.
+
+The @var{options} are a sequence of the following tokens in any order:
+
+@table @code
+@item basic_block
+This option will set the @code{basic_block} register in the
+@code{.debug_line} state machine to @code{true}.
+
+@item prologue_end
+This option will set the @code{prologue_end} register in the
+@code{.debug_line} state machine to @code{true}.
+
+@item epilogue_begin
+This option will set the @code{epilogue_begin} register in the
+@code{.debug_line} state machine to @code{true}.
+
+@item is_stmt @var{value}
+This option will set the @code{is_stmt} register in the
+@code{.debug_line} state machine to @code{value}, which must be
+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.
+@end table
+
@node Data
@section @code{.data @var{subsection}}
diff --git a/gnu/usr.bin/binutils/gas/dwarf2dbg.c b/gnu/usr.bin/binutils/gas/dwarf2dbg.c
index 3336453a4ee..4f41a6d7b24 100644
--- a/gnu/usr.bin/binutils/gas/dwarf2dbg.c
+++ b/gnu/usr.bin/binutils/gas/dwarf2dbg.c
@@ -20,15 +20,16 @@
02111-1307, USA. */
/* Logical line numbers can be controlled by the compiler via the
- following two directives:
+ following directives:
.file FILENO "file.c"
- .loc FILENO LINENO [COLUMN]
-
- FILENO is the filenumber. */
+ .loc FILENO LINENO [COLUMN] [basic_block] [prologue_end] \
+ [epilogue_begin] [is_stmt VALUE] [isa VALUE]
+*/
#include "ansidecl.h"
#include "as.h"
+#include "safe-ctype.h"
#ifdef HAVE_LIMITS_H
#include <limits.h>
@@ -69,8 +70,8 @@
/* First special line opcde - leave room for the standard opcodes.
Note: If you want to change this, you'll have to update the
"standard_opcode_lengths" table that is emitted below in
- dwarf2_finish(). */
-#define DWARF2_LINE_OPCODE_BASE 10
+ out_debug_line(). */
+#define DWARF2_LINE_OPCODE_BASE 13
#ifndef DWARF2_LINE_BASE
/* Minimum line offset in a special line info. opcode. This value
@@ -89,10 +90,7 @@
# define DWARF2_LINE_MIN_INSN_LENGTH 1
#endif
-/* Flag that indicates the initial value of the is_stmt_start flag.
- In the present implementation, we do not mark any lines as
- the beginning of a source statement, because that information
- is not made available by the GCC front-end. */
+/* Flag that indicates the initial value of the is_stmt_start flag. */
#define DWARF2_LINE_DEFAULT_IS_STMT 1
/* Given a special op, return the line skip amount. */
@@ -151,7 +149,10 @@ static unsigned int dirs_allocated;
static bfd_boolean loc_directive_seen;
/* 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,
+ DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0
+};
/* The size of an address on the target. */
static unsigned int sizeof_address;
@@ -283,6 +284,11 @@ dwarf2_gen_line_info (addressT ofs, struct dwarf2_line_info *loc)
ss->ptail = &e->next;
}
+/* 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
+ returned. */
+
void
dwarf2_where (struct dwarf2_line_info *line)
{
@@ -292,12 +298,22 @@ dwarf2_where (struct dwarf2_line_info *line)
as_where (&filename, &line->line);
line->filenum = get_filenum (filename, 0);
line->column = 0;
- line->flags = DWARF2_FLAG_BEGIN_STMT;
+ line->flags = DWARF2_FLAG_IS_STMT;
+ line->isa = current.isa;
}
else
*line = current;
}
+/* A hook to allow the target backend to inform the line number state
+ machine of isa changes when assembler debug info is enabled. */
+
+void
+dwarf2_set_isa (unsigned int isa)
+{
+ current.isa = isa;
+}
+
/* Called for each machine instruction, or relatively atomic group of
machine instructions (ie built-in macro). The instruction or group
is SIZE bytes in length. If dwarf2 line number generation is called
@@ -325,9 +341,13 @@ dwarf2_emit_insn (int size)
else if (debug_type != DEBUG_DWARF2)
return;
else
- dwarf2_where (& loc);
+ dwarf2_where (&loc);
dwarf2_gen_line_info (frag_now_fix () - size, &loc);
+
+ current.flags &= ~(DWARF2_FLAG_BASIC_BLOCK
+ | DWARF2_FLAG_PROLOGUE_END
+ | DWARF2_FLAG_EPILOGUE_BEGIN);
}
/* Get a .debug_line file number for FILENAME. If NUM is nonzero,
@@ -450,6 +470,8 @@ dwarf2_directive_file (int dummy ATTRIBUTE_UNUSED)
num = get_absolute_expression ();
filename = demand_copy_C_string (&filename_len);
+ if (filename == NULL)
+ return NULL;
demand_empty_rest_of_line ();
if (num < 1)
@@ -472,14 +494,11 @@ dwarf2_directive_file (int dummy ATTRIBUTE_UNUSED)
void
dwarf2_directive_loc (int dummy ATTRIBUTE_UNUSED)
{
- offsetT filenum, line, column;
+ offsetT filenum, line;
filenum = get_absolute_expression ();
SKIP_WHITESPACE ();
line = get_absolute_expression ();
- SKIP_WHITESPACE ();
- column = get_absolute_expression ();
- demand_empty_rest_of_line ();
if (filenum < 1)
{
@@ -494,10 +513,6 @@ dwarf2_directive_loc (int dummy ATTRIBUTE_UNUSED)
current.filenum = filenum;
current.line = line;
- current.column = column;
- current.flags = DWARF2_FLAG_BEGIN_STMT;
-
- loc_directive_seen = TRUE;
#ifndef NO_LISTING
if (listing)
@@ -519,6 +534,75 @@ dwarf2_directive_loc (int dummy ATTRIBUTE_UNUSED)
listing_source_line (line);
}
#endif
+
+ SKIP_WHITESPACE ();
+ if (ISDIGIT (*input_line_pointer))
+ {
+ current.column = get_absolute_expression ();
+ SKIP_WHITESPACE ();
+ }
+
+ while (ISALPHA (*input_line_pointer))
+ {
+ char *p, c;
+ offsetT value;
+
+ p = input_line_pointer;
+ c = get_symbol_end ();
+
+ if (strcmp (p, "basic_block") == 0)
+ {
+ current.flags |= DWARF2_FLAG_BASIC_BLOCK;
+ *input_line_pointer = c;
+ }
+ else if (strcmp (p, "prologue_end") == 0)
+ {
+ current.flags |= DWARF2_FLAG_PROLOGUE_END;
+ *input_line_pointer = c;
+ }
+ else if (strcmp (p, "epilogue_begin") == 0)
+ {
+ current.flags |= DWARF2_FLAG_EPILOGUE_BEGIN;
+ *input_line_pointer = c;
+ }
+ else if (strcmp (p, "is_stmt") == 0)
+ {
+ *input_line_pointer = c;
+ value = get_absolute_expression ();
+ if (value == 0)
+ current.flags &= ~DWARF2_FLAG_IS_STMT;
+ else if (value == 1)
+ current.flags |= DWARF2_FLAG_IS_STMT;
+ else
+ {
+ as_bad (_("is_stmt value not 0 or 1"));
+ return;
+ }
+ }
+ else if (strcmp (p, "isa") == 0)
+ {
+ *input_line_pointer = c;
+ value = get_absolute_expression ();
+ if (value >= 0)
+ current.isa = value;
+ else
+ {
+ as_bad (_("isa number less than zero"));
+ return;
+ }
+ }
+ else
+ {
+ as_bad (_("unknown .loc sub-directive `%s'"), p);
+ *input_line_pointer = c;
+ return;
+ }
+
+ SKIP_WHITESPACE ();
+ }
+
+ demand_empty_rest_of_line ();
+ loc_directive_seen = TRUE;
}
static struct frag *
@@ -760,19 +844,19 @@ emit_inc_line_addr (int line_delta, addressT addr_delta, char *p, int len)
*p++ = DW_LNS_advance_line;
p += output_leb128 (p, line_delta, 1);
- /* Prettier, I think, to use DW_LNS_copy instead of a
- "line +0, addr +0" special opcode. */
- if (addr_delta == 0)
- {
- *p++ = DW_LNS_copy;
- goto done;
- }
-
line_delta = 0;
tmp = 0 - DWARF2_LINE_BASE;
need_copy = 1;
}
+ /* Prettier, I think, to use DW_LNS_copy instead of a "line +0, addr +0"
+ special opcode. */
+ if (line_delta == 0 && addr_delta == 0)
+ {
+ *p++ = DW_LNS_copy;
+ goto done;
+ }
+
/* Bias the opcode by the special opcode base. */
tmp += DWARF2_LINE_OPCODE_BASE;
@@ -914,7 +998,8 @@ process_entries (segT seg, struct line_entry *e)
unsigned filenum = 1;
unsigned line = 1;
unsigned column = 0;
- unsigned flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_BEGIN_STMT : 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;
@@ -941,19 +1026,39 @@ process_entries (segT seg, struct line_entry *e)
changed = 1;
}
- if ((e->loc.flags ^ flags) & DWARF2_FLAG_BEGIN_STMT)
+ if (isa != e->loc.isa)
+ {
+ 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_BEGIN_BLOCK)
+ if (e->loc.flags & DWARF2_FLAG_BASIC_BLOCK)
{
out_opcode (DW_LNS_set_basic_block);
changed = 1;
}
+ if (e->loc.flags & DWARF2_FLAG_PROLOGUE_END)
+ {
+ out_opcode (DW_LNS_set_prologue_end);
+ changed = 1;
+ }
+
+ if (e->loc.flags & DWARF2_FLAG_EPILOGUE_BEGIN)
+ {
+ out_opcode (DW_LNS_set_epilogue_begin);
+ changed = 1;
+ }
+
/* 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
@@ -1116,6 +1221,9 @@ out_debug_line (segT line_seg)
out_byte (0); /* DW_LNS_set_basic_block */
out_byte (0); /* DW_LNS_const_add_pc */
out_byte (1); /* DW_LNS_fixed_advance_pc */
+ out_byte (0); /* DW_LNS_set_prologue_end */
+ out_byte (0); /* DW_LNS_set_epilogue_begin */
+ out_byte (1); /* DW_LNS_set_isa */
out_file_list ();
diff --git a/gnu/usr.bin/binutils/gas/dwarf2dbg.h b/gnu/usr.bin/binutils/gas/dwarf2dbg.h
index fe8bf277eaa..b5f440cea6a 100644
--- a/gnu/usr.bin/binutils/gas/dwarf2dbg.h
+++ b/gnu/usr.bin/binutils/gas/dwarf2dbg.h
@@ -23,13 +23,16 @@
#include "as.h"
-#define DWARF2_FLAG_BEGIN_STMT (1 << 0) /* beginning of statement */
-#define DWARF2_FLAG_BEGIN_BLOCK (1 << 1) /* beginning of basic block */
+#define DWARF2_FLAG_IS_STMT (1 << 0)
+#define DWARF2_FLAG_BASIC_BLOCK (1 << 1)
+#define DWARF2_FLAG_PROLOGUE_END (1 << 2)
+#define DWARF2_FLAG_EPILOGUE_BEGIN (1 << 3)
struct dwarf2_line_info {
unsigned int filenum;
unsigned int line;
unsigned int column;
+ unsigned int isa;
unsigned int flags;
};
@@ -52,6 +55,10 @@ extern void dwarf2_directive_loc (int dummy);
returned. */
extern void dwarf2_where (struct dwarf2_line_info *l);
+/* A hook to allow the target backend to inform the line number state
+ machine of isa changes when assembler debug info is enabled. */
+extern void dwarf2_set_isa (unsigned int isa);
+
/* This function generates .debug_line info based on the address and
source information passed in the arguments. ADDR should be the
frag-relative offset of the instruction the information is for and