dwarf2: Align relocation within .debug_line section
authorChristian Eggers <ceggers@gmx.de>
Sun, 10 Mar 2019 18:21:58 +0000 (19:21 +0100)
committerAlan Modra <amodra@gmail.com>
Wed, 13 Mar 2019 02:59:35 +0000 (13:29 +1030)
All relocations specify a byte address.  As dwarf debug information is
organized in octets, some relocations may not be aligned.  While it
might be possible to define special relocations that operate at an
octet offset from their address, it's easier to ensure the relocations
are aligned by padding with "nop" statements.

In most dwarf sections this requirement is already fulfilled, only
relocations for symbol address within the .debug_line section can be
misaligned.

* dwarf2dbg.c (out_set_addr): Align relocation within .debug_line.

gas/ChangeLog
gas/dwarf2dbg.c

index 5b209741f1579ec96ef07e9767556e7eb4256551..d08c09647c626b702e49c41d11c8c5593c763882 100644 (file)
@@ -1,3 +1,7 @@
+2019-03-13  Christian Eggers  <ceggers@gmx.de>
+
+       * dwarf2dbg.c (out_set_addr): Align relocation within .debug_line.
+
 2019-03-13  Christian Eggers  <ceggers@gmx.de>
 
        * dwarf2dbg.c (out_debug_line): Pad size of .debug_line section.
index 0b7b78c8c3acbd23d3dadebb0ff2a3d7a3f7152c..2d316ddcb9ca18da799302d28ca2c42f36dce80d 100644 (file)
@@ -1108,16 +1108,28 @@ get_frag_fix (fragS *frag, segT seg)
 
 /* Set an absolute address (may result in a relocation entry).  */
 
+static void
+out_inc_line_addr (int line_delta, addressT addr_delta);
+
 static void
 out_set_addr (symbolS *sym)
 {
   expressionS exp;
+  addressT expr_addr, expr_addr_aligned;
 
   memset (&exp, 0, sizeof exp);
-  out_opcode (DW_LNS_extended_op);
-  out_uleb128 (sizeof_address + 1);
 
-  out_opcode (DW_LNE_set_address);
+  /* The expression at the bottom must be aligned to OCTETS_PER_BYTE.  The
+     statements after the for loop will contribute 3 more octets.  */
+  expr_addr = frag_now_fix_octets () + 3;
+  expr_addr_aligned = (expr_addr + OCTETS_PER_BYTE - 1) & -OCTETS_PER_BYTE;
+  for ( ; expr_addr != expr_addr_aligned; expr_addr++)
+    out_inc_line_addr (0, 0);  /* NOP */
+
+  out_opcode (DW_LNS_extended_op);   /* 1 octet */
+  out_uleb128 (sizeof_address + 1);  /* 1 octet */
+
+  out_opcode (DW_LNE_set_address);   /* 1 octet */
   exp.X_op = O_symbol;
   exp.X_add_symbol = sym;
   exp.X_add_number = 0;