diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2013-01-17 04:28:48 +0000 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2013-01-17 04:28:48 +0000 |
commit | 8fd4256dd0a856d3a1320598f063d4d593d84e67 (patch) | |
tree | b614ee9174f36ec9976ca8081f9224ce33953767 /gas/config/tc-i386.c | |
parent | c32d6f7bd43c74fbe950858502e6e9ba6eaca2af (diff) | |
download | gdb-8fd4256dd0a856d3a1320598f063d4d593d84e67.zip gdb-8fd4256dd0a856d3a1320598f063d4d593d84e67.tar.gz gdb-8fd4256dd0a856d3a1320598f063d4d593d84e67.tar.bz2 |
Add x86 size relocation support to gas
gas/
* config/tc-i386.c (reloc): Support BFD_RELOC_SIZE32.
(tc_i386_fix_adjustable): Keep symbol for BFD_RELOC_32_SIZE and
BFD_RELOC_64_SIZE relocations.
(lex_got): Support "symbol@SIZE" and don't create GOT symbol
for it.
(tc_gen_reloc): Resolve BFD_RELOC_SIZE32 and BFD_RELOC_SIZE64
relocations against local symbols.
gas/testsuite/
* gas/i386/i386.exp: Run size-1, size-2, size-3, size-4,
x86-64-size-1, x86-64-size-2, x86-64-size-3, x86-64-size-4,
x86-64-size-5 and x86-64-size-inval-1.
* gas/i386/size-1.d: New file.
* gas/i386/size-1.s: Likewise.
* gas/i386/size-2.d: Likewise.
* gas/i386/size-2.s: Likewise.
* gas/i386/size-3.d: Likewise.
* gas/i386/size-3.s: Likewise.
* gas/i386/size-4.d: Likewise.
* gas/i386/size-4.s: Likewise.
* gas/i386/x86-64-size-1.d: Likewise.
* gas/i386/x86-64-size-2.d: Likewise.
* gas/i386/x86-64-size-3.d: Likewise.
* gas/i386/x86-64-size-4.d: Likewise.
* gas/i386/x86-64-size-5.d: Likewise.
* gas/i386/x86-64-size-5.s: Likewise.
* gas/i386/x86-64-size-inval-1.l: Likewise.
* gas/i386/x86-64-size-inval-1.s: Likewise.
* gas/i386/ilp32/x86-64-size-1.d: Likewise.
* gas/i386/ilp32/x86-64-size-2.d: Likewise.
* gas/i386/ilp32/x86-64-size-3.d: Likewise.
* gas/i386/ilp32/x86-64-size-4.d: Likewise.
* gas/i386/ilp32/x86-64-size-5.d: Likewise.
ld/testsuite/
* ld-size/size.exp: New file.
* ld-size/size32-1-i386.d: Likewise.
* ld-size/size32-1-x32.d: Likewise.
* ld-size/size32-1-x86-64.d: Likewise.
* ld-size/size32-1.s: Likewise.
* ld-size/size32-2-i386.d: Likewise.
* ld-size/size32-2-x32.d: Likewise.
* ld-size/size32-2-x86-64.d: Likewise.
* ld-size/size32-2.s: Likewise.
* ld-size/size64-1-x32.d: Likewise.
* ld-size/size64-1-x86-64.d: Likewise.
* ld-size/size64-1.s: Likewise.
* ld-size/size64-2-x32.d: Likewise.
* ld-size/size64-2-x86-64.d: Likewise.
* ld-size/size64-2.s: Likewise.
* ld-size/size-3.c: Likewise.
* ld-size/size-3.out: Likewise.
* ld-size/size-3a.c: Likewise.
* ld-size/size-3b.c: Likewise.
* ld-size/size-3c.c: Likewise.
* ld-size/size-4.out: Likewise.
* ld-size/size-4a.c: Likewise.
* ld-size/size-4b.c: Likewise.
* ld-size/size-5.out: Likewise.
* ld-size/size-5a.c: Likewise.
* ld-size/size-5b.c: Likewise.
* ld-size/size-6.out: Likewise.
* ld-size/size-6a.c: Likewise.
* ld-size/size-6b.c: Likewise.
* ld-size/size-7.rd: Likewise.
* ld-size/size-7a.c: Likewise.
* ld-size/size-7b.c: Likewise.
* ld-size/size-8.rd: Likewise.
* ld-size/size-8a.c: Likewise.
* ld-size/size-8b.c: Likewise.
Diffstat (limited to 'gas/config/tc-i386.c')
-rw-r--r-- | gas/config/tc-i386.c | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 641af39..c96229e 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -2686,6 +2686,14 @@ reloc (unsigned int size, break; } + if (other == BFD_RELOC_SIZE32) + { + if (size == 8) + return BFD_RELOC_SIZE64; + if (pcrel) + as_bad (_("there are no pc-relative size relocations")); + } + /* Sign-checking 4-byte relocations in 16-/32-bit code is pointless. */ if (size == 4 && (flag_code != CODE_64BIT || disallow_64bit_reloc)) sign = -1; @@ -2769,8 +2777,11 @@ tc_i386_fix_adjustable (fixS *fixP ATTRIBUTE_UNUSED) && fixP->fx_r_type == BFD_RELOC_32_PCREL) return 0; - /* adjust_reloc_syms doesn't know about the GOT. */ - if (fixP->fx_r_type == BFD_RELOC_386_GOTOFF + /* Adjust_reloc_syms doesn't know about the GOT. Need to keep symbol + for size relocations. */ + if (fixP->fx_r_type == BFD_RELOC_SIZE32 + || fixP->fx_r_type == BFD_RELOC_SIZE64 + || fixP->fx_r_type == BFD_RELOC_386_GOTOFF || fixP->fx_r_type == BFD_RELOC_386_PLT32 || fixP->fx_r_type == BFD_RELOC_386_GOT32 || fixP->fx_r_type == BFD_RELOC_386_TLS_GD @@ -6708,6 +6719,9 @@ lex_got (enum bfd_reloc_code_real *rel, const enum bfd_reloc_code_real rel[2]; const i386_operand_type types64; } gotrel[] = { + { STRING_COMMA_LEN ("SIZE"), { BFD_RELOC_SIZE32, + BFD_RELOC_SIZE32 }, + OPERAND_TYPE_IMM32_64 }, { STRING_COMMA_LEN ("PLTOFF"), { _dummy_first_bfd_reloc_code_real, BFD_RELOC_X86_64_PLTOFF64 }, OPERAND_TYPE_IMM64 }, @@ -6795,7 +6809,7 @@ lex_got (enum bfd_reloc_code_real *rel, *types = gotrel[j].types64; } - if (GOT_symbol == NULL) + if (j != 0 && GOT_symbol == NULL) GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME); /* The length of the first part of our input line. */ @@ -9231,6 +9245,24 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) switch (fixp->fx_r_type) { + case BFD_RELOC_SIZE32: + case BFD_RELOC_SIZE64: + if (S_IS_DEFINED (fixp->fx_addsy) + && !S_IS_EXTERNAL (fixp->fx_addsy)) + { + /* Resolve size relocation against local symbol to size of + the symbol plus addend. */ + valueT value = S_GET_SIZE (fixp->fx_addsy) + fixp->fx_offset; + if (fixp->fx_r_type == BFD_RELOC_SIZE32 + && !fits_in_unsigned_long (value)) + as_bad_where (fixp->fx_file, fixp->fx_line, + _("symbol size computation overflow")); + fixp->fx_addsy = NULL; + fixp->fx_subsy = NULL; + md_apply_fix (fixp, (valueT *) &value, NULL); + return NULL; + } + case BFD_RELOC_X86_64_PLT32: case BFD_RELOC_X86_64_GOT32: case BFD_RELOC_X86_64_GOTPCREL: |