From 7423731691e898b0581532cf277b1e08a510323a Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 26 Jan 2021 09:20:23 +0100 Subject: [PATCH] dwarf2asm: Fix up -gdwarf-64 for 32-bit targets For the 32-bit targets the limitations of the object file format (e.g. 32-bit ELF) will not allow > 2GiB debug info anyway, and as I've just tested, e.g. on x86_64 with -m32 -gdwarf64 will not work even on tiny testcases: as: pr64716.o: unsupported relocation type: 0x1 pr64716.s: Assembler messages: pr64716.s:6013: Error: cannot represent relocation type BFD_RELOC_64 as: pr64716.o: unsupported relocation type: 0x1 pr64716.s:6015: Error: cannot represent relocation type BFD_RELOC_64 as: pr64716.o: unsupported relocation type: 0x1 pr64716.s:6017: Error: cannot represent relocation type BFD_RELOC_64 So yes, we can either do a sorry, error, or could just avoid 64-bit relocations (depending on endianity instead of emitting .quad expression_that_needs_relocation emit .long expression_that_needs_relocation, 0 or .long 0, expression_that_needs_relocation This patch implements that last option, dunno if we need also configure tests for that or not, maybe some 32-bit targets use 64-bit ELF and can handle such relocations. > 64bit relocs are not required here? That is, can one with > dwarf64 choose 32bit forms for select offsets (like could > dwz exploit this?)? I guess it depends on whether for 32-bit target and -gdwarf64, when calling dw2_assemble_integer with non-CONST_INT argument we only need positive values or might need negative ones too. Because positive ones can be easily emulated through that .long expression, 0 or .long 0, expression depending on endianity, but I'm afraid there is no way to emit 0 or -1 depending on the sign of expression, when it needs relocations. Looking through dw2_asm_output_delta calls, at least the vast majority of the calls seem to guarantee being positive, not 100% sure about one case in .debug_line views, but I'd hope it is ok too. In most cases, the deltas are between two labels where the first one in the arguments is later in the same section than the other one, or where the second argument is the start of a section or another section base. 2021-01-26 Jakub Jelinek * dwarf2asm.c (dw2_assemble_integer): Handle size twice as large as DWARF2_ADDR_SIZE if x is not a scalar int by emitting it as two halves, one with x and the other with const0_rtx, ordered depending on endianity. --- gcc/dwarf2asm.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/gcc/dwarf2asm.c b/gcc/dwarf2asm.c index ecc33d957c4..8e08d4d24d8 100644 --- a/gcc/dwarf2asm.c +++ b/gcc/dwarf2asm.c @@ -46,6 +46,52 @@ along with GCC; see the file COPYING3. If not see void dw2_assemble_integer (int size, rtx x) { + if (size == 2 * DWARF2_ADDR_SIZE && !CONST_SCALAR_INT_P (x)) + { + /* On 32-bit targets with -gdwarf64, DImode values with + relocations usually result in assembler errors. Assume + all such values are positive and emit the relocation only + in the least significant half. */ + const char *op = integer_asm_op (DWARF2_ADDR_SIZE, FALSE); + if (BYTES_BIG_ENDIAN) + { + if (op) + { + fputs (op, asm_out_file); + fprint_whex (asm_out_file, 0); + fputs (", ", asm_out_file); + output_addr_const (asm_out_file, x); + } + else + { + assemble_integer (const0_rtx, DWARF2_ADDR_SIZE, + BITS_PER_UNIT, 1); + putc ('\n', asm_out_file); + assemble_integer (x, DWARF2_ADDR_SIZE, + BITS_PER_UNIT, 1); + } + } + else + { + if (op) + { + fputs (op, asm_out_file); + output_addr_const (asm_out_file, x); + fputs (", ", asm_out_file); + fprint_whex (asm_out_file, 0); + } + else + { + assemble_integer (x, DWARF2_ADDR_SIZE, + BITS_PER_UNIT, 1); + putc ('\n', asm_out_file); + assemble_integer (const0_rtx, DWARF2_ADDR_SIZE, + BITS_PER_UNIT, 1); + } + } + return; + } + const char *op = integer_asm_op (size, FALSE); if (op) -- 2.30.2