forked from Imagelibrary/binutils-gdb
Reformat experimental header for compatibility with old DWARF consumers.
Old consumers will now see a DWARF-4 header, with new fields added at the end of the header. The new fields and the entire logicals and actuals tables are wrapped in a single extended opcode so that old consumers will see just the single opcode. 2015-01-28 Cary Coutant <ccoutant@google.com> gas/ * dwarf2dbg.c (line_base): New variable. (line_range): New variable. (DWARF2_EXPERIMENTAL_LINE_OPCODE_BASE): Rename. (DWARF2_LINE_BASE): Restore to original value. (DWARF2_LINE_RANGE): Likewise. (DWARF5_EXPERIMENTAL_LINE_BASE): New macro. (DWARF5_EXPERIMENTAL_LINE_RANGE): New macro. (SPECIAL_LINE): Use line_base, line_range. (size_inc_line_addr): Likewise. (emit_inc_line_addr): Likewise. (out_debug_line): Reformat header for compatibility with old DWARF consumers.
This commit is contained in:
120
gas/dwarf2dbg.c
120
gas/dwarf2dbg.c
@@ -132,21 +132,27 @@
|
||||
"standard_opcode_lengths" table that is emitted below in
|
||||
out_debug_line(). */
|
||||
#define DWARF2_LINE_OPCODE_BASE 13
|
||||
#define DWARF2_EXPERIMENTAL_LINE_OPCODE_BASE 16
|
||||
#define DWARF5_EXPERIMENTAL_LINE_OPCODE_BASE 16
|
||||
|
||||
static int opcode_base;
|
||||
static int line_base;
|
||||
static unsigned int line_range;
|
||||
|
||||
#ifndef DWARF2_LINE_BASE
|
||||
/* Minimum line offset in a special line info. opcode. This value
|
||||
was chosen to give a reasonable range of values. */
|
||||
# define DWARF2_LINE_BASE -3
|
||||
# define DWARF2_LINE_BASE -5
|
||||
#endif
|
||||
|
||||
/* Range of line offsets in a special line info. opcode. */
|
||||
#ifndef DWARF2_LINE_RANGE
|
||||
# define DWARF2_LINE_RANGE 10
|
||||
# define DWARF2_LINE_RANGE 14
|
||||
#endif
|
||||
|
||||
/* For two-level line tables, these values work a bit better. */
|
||||
#define DWARF5_EXPERIMENTAL_LINE_BASE -3
|
||||
#define DWARF5_EXPERIMENTAL_LINE_RANGE 10
|
||||
|
||||
#ifndef DWARF2_LINE_MIN_INSN_LENGTH
|
||||
/* Define the architecture-dependent minimum instruction length (in
|
||||
bytes). This value should be rather too small than too big. */
|
||||
@@ -162,11 +168,11 @@ static int opcode_base;
|
||||
|
||||
/* Given a special op, return the line skip amount. */
|
||||
#define SPECIAL_LINE(op) \
|
||||
(((op) - opcode_base) % DWARF2_LINE_RANGE + DWARF2_LINE_BASE)
|
||||
(((op) - opcode_base) % line_range + line_base)
|
||||
|
||||
/* Given a special op, return the address skip amount (in units of
|
||||
DWARF2_LINE_MIN_INSN_LENGTH. */
|
||||
#define SPECIAL_ADDR(op) (((op) - opcode_base) / DWARF2_LINE_RANGE)
|
||||
#define SPECIAL_ADDR(op) (((op) - opcode_base) / line_range)
|
||||
|
||||
/* The maximum address skip amount that can be encoded with a special op. */
|
||||
#define MAX_SPECIAL_ADDR_DELTA SPECIAL_ADDR(255)
|
||||
@@ -1170,15 +1176,15 @@ size_inc_line_addr (int line_delta, addressT addr_delta)
|
||||
}
|
||||
|
||||
/* Bias the line delta by the base. */
|
||||
tmp = line_delta - DWARF2_LINE_BASE;
|
||||
tmp = line_delta - line_base;
|
||||
|
||||
/* If the line increment is out of range of a special opcode, we
|
||||
must encode it with DW_LNS_advance_line. */
|
||||
if (tmp >= DWARF2_LINE_RANGE)
|
||||
if (tmp >= line_range)
|
||||
{
|
||||
len = 1 + sizeof_leb128 (line_delta, 1);
|
||||
line_delta = 0;
|
||||
tmp = 0 - DWARF2_LINE_BASE;
|
||||
tmp = 0 - line_base;
|
||||
}
|
||||
|
||||
/* Bias the opcode by the special opcode base. */
|
||||
@@ -1188,12 +1194,12 @@ size_inc_line_addr (int line_delta, addressT addr_delta)
|
||||
if (addr_delta < (unsigned int) (256 + MAX_SPECIAL_ADDR_DELTA))
|
||||
{
|
||||
/* Try using a special opcode. */
|
||||
opcode = tmp + addr_delta * DWARF2_LINE_RANGE;
|
||||
opcode = tmp + addr_delta * line_range;
|
||||
if (opcode <= 255)
|
||||
return len + 1;
|
||||
|
||||
/* Try using DW_LNS_const_add_pc followed by special op. */
|
||||
opcode = tmp + (addr_delta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE;
|
||||
opcode = tmp + (addr_delta - MAX_SPECIAL_ADDR_DELTA) * line_range;
|
||||
if (opcode <= 255)
|
||||
return len + 2;
|
||||
}
|
||||
@@ -1241,17 +1247,17 @@ emit_inc_line_addr (int line_delta, addressT addr_delta, char *p, int len)
|
||||
}
|
||||
|
||||
/* Bias the line delta by the base. */
|
||||
tmp = line_delta - DWARF2_LINE_BASE;
|
||||
tmp = line_delta - line_base;
|
||||
|
||||
/* If the line increment is out of range of a special opcode, we
|
||||
must encode it with DW_LNS_advance_line. */
|
||||
if (tmp >= DWARF2_LINE_RANGE)
|
||||
if (tmp >= line_range)
|
||||
{
|
||||
*p++ = DW_LNS_advance_line;
|
||||
p += output_leb128 (p, line_delta, 1);
|
||||
|
||||
line_delta = 0;
|
||||
tmp = 0 - DWARF2_LINE_BASE;
|
||||
tmp = 0 - line_base;
|
||||
need_copy = 1;
|
||||
}
|
||||
|
||||
@@ -1270,7 +1276,7 @@ emit_inc_line_addr (int line_delta, addressT addr_delta, char *p, int len)
|
||||
if (addr_delta < (unsigned int) (256 + MAX_SPECIAL_ADDR_DELTA))
|
||||
{
|
||||
/* Try using a special opcode. */
|
||||
opcode = tmp + addr_delta * DWARF2_LINE_RANGE;
|
||||
opcode = tmp + addr_delta * line_range;
|
||||
if (opcode <= 255)
|
||||
{
|
||||
*p++ = opcode;
|
||||
@@ -1278,7 +1284,7 @@ emit_inc_line_addr (int line_delta, addressT addr_delta, char *p, int len)
|
||||
}
|
||||
|
||||
/* Try using DW_LNS_const_add_pc followed by special op. */
|
||||
opcode = tmp + (addr_delta - MAX_SPECIAL_ADDR_DELTA) * DWARF2_LINE_RANGE;
|
||||
opcode = tmp + (addr_delta - MAX_SPECIAL_ADDR_DELTA) * line_range;
|
||||
if (opcode <= 255)
|
||||
{
|
||||
*p++ = DW_LNS_const_add_pc;
|
||||
@@ -2060,7 +2066,7 @@ static void
|
||||
out_debug_line (segT line_seg, segT str_seg)
|
||||
{
|
||||
expressionS exp;
|
||||
symbolS *prologue_start, *prologue_end, *actuals_start;
|
||||
symbolS *prologue_start, *prologue_end, *logicals_start, *actuals_start;
|
||||
symbolS *line_end;
|
||||
struct line_seg *s;
|
||||
int sizeof_offset;
|
||||
@@ -2070,11 +2076,15 @@ out_debug_line (segT line_seg, segT str_seg)
|
||||
{
|
||||
version = DWARF2_LINE_VERSION;
|
||||
opcode_base = DWARF2_LINE_OPCODE_BASE;
|
||||
line_base = DWARF2_LINE_BASE;
|
||||
line_range = DWARF2_LINE_RANGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
version = DWARF2_LINE_EXPERIMENTAL_VERSION;
|
||||
opcode_base = DWARF2_EXPERIMENTAL_LINE_OPCODE_BASE;
|
||||
opcode_base = DWARF5_EXPERIMENTAL_LINE_OPCODE_BASE;
|
||||
line_base = DWARF5_EXPERIMENTAL_LINE_BASE;
|
||||
line_range = DWARF5_EXPERIMENTAL_LINE_RANGE;
|
||||
}
|
||||
|
||||
sizeof_offset = out_header (line_seg, &exp);
|
||||
@@ -2083,13 +2093,6 @@ out_debug_line (segT line_seg, segT str_seg)
|
||||
/* Version. */
|
||||
out_two (version);
|
||||
|
||||
/* Version 5 adds address_size and segment_size. */
|
||||
if (version >= 5)
|
||||
{
|
||||
out_byte (sizeof_address);
|
||||
out_byte (0);
|
||||
}
|
||||
|
||||
/* Length of the prologue following this length. */
|
||||
prologue_start = symbol_temp_make ();
|
||||
prologue_end = symbol_temp_make ();
|
||||
@@ -2100,21 +2103,13 @@ out_debug_line (segT line_seg, segT str_seg)
|
||||
emit_expr (&exp, sizeof_offset);
|
||||
symbol_set_value_now (prologue_start);
|
||||
|
||||
/* Actuals table offset. */
|
||||
if (version == DWARF2_LINE_EXPERIMENTAL_VERSION)
|
||||
{
|
||||
actuals_start = symbol_temp_make ();
|
||||
exp.X_add_symbol = actuals_start;
|
||||
emit_expr (&exp, sizeof_offset);
|
||||
}
|
||||
|
||||
/* Parameters of the state machine. */
|
||||
out_byte (DWARF2_LINE_MIN_INSN_LENGTH);
|
||||
if (version >= 4)
|
||||
out_byte (DWARF2_LINE_MAX_OPS_PER_INSN);
|
||||
out_byte (DWARF2_LINE_DEFAULT_IS_STMT);
|
||||
out_byte (DWARF2_LINE_BASE);
|
||||
out_byte (DWARF2_LINE_RANGE);
|
||||
out_byte (line_base);
|
||||
out_byte (line_range);
|
||||
out_byte (opcode_base);
|
||||
|
||||
/* Standard opcode lengths. */
|
||||
@@ -2130,28 +2125,63 @@ out_debug_line (segT line_seg, segT str_seg)
|
||||
out_byte (0); /* DW_LNS_set_prologue_end */
|
||||
out_byte (0); /* DW_LNS_set_epilogue_begin */
|
||||
out_byte (1); /* DW_LNS_set_isa */
|
||||
if (opcode_base == DWARF2_EXPERIMENTAL_LINE_OPCODE_BASE)
|
||||
if (opcode_base == DWARF5_EXPERIMENTAL_LINE_OPCODE_BASE)
|
||||
{
|
||||
out_byte (1); /* DW_LNS_set_subprogram/DW_LNS_set_address_from_logical */
|
||||
out_byte (2); /* DW_LNS_inlined_call */
|
||||
out_byte (0); /* DW_LNS_pop_context */
|
||||
}
|
||||
|
||||
if (version >= 5)
|
||||
out_dwarf5_file_list (str_seg, sizeof_offset);
|
||||
else
|
||||
out_file_list ();
|
||||
|
||||
if (version == DWARF2_LINE_EXPERIMENTAL_VERSION)
|
||||
out_subprog_list (str_seg, sizeof_offset);
|
||||
|
||||
symbol_set_value_now (prologue_end);
|
||||
|
||||
if (version == DWARF2_LINE_EXPERIMENTAL_VERSION)
|
||||
{
|
||||
/* Fake empty version 4 directory and filename lists, to fool
|
||||
old consumers who don't check the version number. */
|
||||
out_byte (0);
|
||||
out_byte (0);
|
||||
|
||||
symbol_set_value_now (prologue_end);
|
||||
|
||||
/* Now wrap the remainder of the section inside a fake
|
||||
extended opcode, so old consumers will see just the single
|
||||
extended opcode, and will not try to read anything else.
|
||||
For simplicity, we simply output a very large number for
|
||||
the size of the extended op. */
|
||||
out_opcode (DW_LNS_extended_op);
|
||||
out_byte (255); /* 3-byte LEB128 for 0x1fffff. */
|
||||
out_byte (255);
|
||||
out_byte (127);
|
||||
out_byte (127); /* Fake extended opcode. */
|
||||
|
||||
/* Logicals table offset. */
|
||||
logicals_start = symbol_temp_make ();
|
||||
exp.X_add_symbol = logicals_start;
|
||||
emit_expr (&exp, sizeof_offset);
|
||||
|
||||
/* Actuals table offset. */
|
||||
actuals_start = symbol_temp_make ();
|
||||
exp.X_add_symbol = actuals_start;
|
||||
emit_expr (&exp, sizeof_offset);
|
||||
|
||||
/* Directory and filename lists. */
|
||||
out_dwarf5_file_list (str_seg, sizeof_offset);
|
||||
|
||||
/* Subprogram list. */
|
||||
out_subprog_list (str_seg, sizeof_offset);
|
||||
|
||||
symbol_set_value_now (logicals_start);
|
||||
emit_logicals ();
|
||||
symbol_set_value_now (actuals_start);
|
||||
}
|
||||
else if (version >= 5)
|
||||
{
|
||||
out_dwarf5_file_list (str_seg, sizeof_offset);
|
||||
symbol_set_value_now (prologue_end);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_file_list ();
|
||||
symbol_set_value_now (prologue_end);
|
||||
}
|
||||
|
||||
/* For each section, emit a statement program. */
|
||||
for (s = all_segs; s; s = s->next)
|
||||
|
||||
Reference in New Issue
Block a user