diff options
Diffstat (limited to 'gas')
-rw-r--r-- | gas/config/tc-i386.c | 42 | ||||
-rw-r--r-- | gas/config/tc-i386.h | 6 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/i386.exp | 3 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/x86-64-gprel.d | 10 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/x86-64-gprel.s | 3 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/x86-64-inval-gprel.l | 34 | ||||
-rw-r--r-- | gas/testsuite/gas/i386/x86-64-inval-gprel.s | 8 |
7 files changed, 104 insertions, 2 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 456be9e07cf..c15742b1c12 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -672,6 +672,9 @@ static enum rc_type evexrcig = rne; /* Pre-defined "_GLOBAL_OFFSET_TABLE_". */ static symbolS *GOT_symbol; +/* Pre-defined "__gp". */ +static symbolS *GP_symbol; + /* The dwarf2 return column, adjusted for 32 or 64 bit. */ unsigned int x86_dwarf2_return_column; @@ -7776,6 +7779,9 @@ lex_got (enum bfd_reloc_code_real *rel, { STRING_COMMA_LEN ("GOTPCREL"), { _dummy_first_bfd_reloc_code_real, BFD_RELOC_X86_64_GOTPCREL }, OPERAND_TYPE_IMM32_32S_DISP32 }, + { STRING_COMMA_LEN ("GPREL"), { _dummy_first_bfd_reloc_code_real, + BFD_RELOC_GPREL32 }, + OPERAND_TYPE_IMM32_32S_DISP32 }, { STRING_COMMA_LEN ("TLSGD"), { BFD_RELOC_386_TLS_GD, BFD_RELOC_X86_64_TLSGD }, OPERAND_TYPE_IMM32_32S_DISP32 }, @@ -7848,8 +7854,19 @@ lex_got (enum bfd_reloc_code_real *rel, *types = gotrel[j].types64; } - if (j != 0 && GOT_symbol == NULL) - GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME); + if (j != 0) + { + if (gotrel[j].rel[1] == BFD_RELOC_GPREL32) + { + if (GP_symbol == NULL) + GP_symbol = symbol_find_or_make (GLOBAL_POINTER_NAME); + } + else + { + if (GOT_symbol == NULL) + GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME); + } + } /* The length of the first part of our input line. */ first = cp - input_line_pointer; @@ -8506,6 +8523,11 @@ i386_displacement (char *disp_start, char *disp_end) if (gotfree_input_line) input_line_pointer = gotfree_input_line; + if (i.reloc[this_operand] == BFD_RELOC_GPREL32 + && (i.seg[0] == NULL + || i.types[this_operand].bitfield.baseindex)) + as_bad (_("invalid GP relocation")); + exp_seg = expression (exp); SKIP_WHITESPACE (); @@ -10740,6 +10762,21 @@ md_undefined_symbol (char *name) }; return GOT_symbol; } + else if (name[0] == GLOBAL_POINTER_NAME[0] + && name[1] == GLOBAL_POINTER_NAME[1] + && name[2] == GLOBAL_POINTER_NAME[2] + && name[3] == GLOBAL_POINTER_NAME[3] + && strcmp (name, GLOBAL_POINTER_NAME) == 0) + { + if (!GP_symbol) + { + if (symbol_find (name)) + as_bad (_("GP already in symbol table")); + GP_symbol = symbol_new (name, undefined_section, + (valueT) 0, &zero_address_frag); + }; + return GP_symbol; + } return 0; } @@ -10899,6 +10936,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) case BFD_RELOC_X86_64_PLTOFF64: case BFD_RELOC_X86_64_GOTPC32_TLSDESC: case BFD_RELOC_X86_64_TLSDESC_CALL: + case BFD_RELOC_GPREL32: case BFD_RELOC_RVA: case BFD_RELOC_VTABLE_ENTRY: case BFD_RELOC_VTABLE_INHERIT: diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h index f54924c4382..beaa4614ddc 100644 --- a/gas/config/tc-i386.h +++ b/gas/config/tc-i386.h @@ -128,6 +128,12 @@ extern const char *i386_comment_chars; #define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_" #endif +/* The name of the global pointer. Allow this to be overridden if need + be. */ +#ifndef GLOBAL_POINTER_NAME +#define GLOBAL_POINTER_NAME "__gp" +#endif + #if (defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)) && !defined (LEX_AT) #define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) x86_cons (EXP, NBYTES) #endif diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp index 67a7a13b259..427a758b35a 100644 --- a/gas/testsuite/gas/i386/i386.exp +++ b/gas/testsuite/gas/i386/i386.exp @@ -868,6 +868,9 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_64_check]] t run_dump_test "x86-64-gotpcrel-no-relax" run_dump_test "x86-64-addend" + + run_dump_test "x86-64-gprel" + run_list_test "x86-64-inval-gprel" "-al" } set ASFLAGS "$old_ASFLAGS" diff --git a/gas/testsuite/gas/i386/x86-64-gprel.d b/gas/testsuite/gas/i386/x86-64-gprel.d new file mode 100644 index 00000000000..f70624ab42e --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-gprel.d @@ -0,0 +1,10 @@ +#objdump: -drw +#name: x86-64 gprel + +.*: +file format .* + +Disassembly of section .text: + +0+ <_start>: + +[a-f0-9]+: 65 8b 04 25 00 00 00 00 mov %gs:0x0,%eax 4: R_X86_64_GPREL foo +#pass diff --git a/gas/testsuite/gas/i386/x86-64-gprel.s b/gas/testsuite/gas/i386/x86-64-gprel.s new file mode 100644 index 00000000000..96b3ce90444 --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-gprel.s @@ -0,0 +1,3 @@ + .text +_start: + movl %gs:foo@GPREL, %eax diff --git a/gas/testsuite/gas/i386/x86-64-inval-gprel.l b/gas/testsuite/gas/i386/x86-64-inval-gprel.l new file mode 100644 index 00000000000..b6683b036d1 --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-inval-gprel.l @@ -0,0 +1,34 @@ +.*: Assembler messages: +.*:3: Error: invalid GP relocation +.*:3: Error: non-pc-relative relocation for pc-relative field +.*:4: Error: invalid GP relocation +.*:5: Error: invalid GP relocation +.*:6: Error: invalid GP relocation +.*:6: Error: non-pc-relative relocation for pc-relative field +.*:7: Error: invalid GP relocation +.*:8: Error: invalid GP relocation +GAS LISTING .* + + +[ ]*1[ ]+\.text +[ ]*2[ ]+_start: +[ ]*3[ ]+\?\?\?\? 648B0500 movl %fs:foo@GPREL\(%rip\), %eax +\*\*\*\* Error: invalid GP relocation +\*\*\*\* Error: non-pc-relative relocation for pc-relative field +[ ]*3[ ]+000000 +[ ]*4[ ]+\?\?\?\? 648B8000 movl %fs:foo@GPREL\(%rax\), %eax +\*\*\*\* Error: invalid GP relocation +[ ]*4[ ]+000000 +[ ]*5[ ]+\?\?\?\? 8B844800 movl %ds:foo@GPREL\(%rax, %rcx, 2\), %eax +\*\*\*\* Error: invalid GP relocation +[ ]*5[ ]+000000 +[ ]*6[ ]+\?\?\?\? 8B050000 movl foo@GPREL\(%rip\), %eax +\*\*\*\* Error: invalid GP relocation +\*\*\*\* Error: non-pc-relative relocation for pc-relative field +[ ]*6[ ]+0000 +[ ]*7[ ]+\?\?\?\? 8B800000 movl foo@GPREL\(%rax\), %eax +\*\*\*\* Error: invalid GP relocation +[ ]*7[ ]+0000 +[ ]*8[ ]+\?\?\?\? 8B042500 movl foo@GPREL, %eax +\*\*\*\* Error: invalid GP relocation +[ ]*8[ ]+000000 diff --git a/gas/testsuite/gas/i386/x86-64-inval-gprel.s b/gas/testsuite/gas/i386/x86-64-inval-gprel.s new file mode 100644 index 00000000000..8507926860d --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-inval-gprel.s @@ -0,0 +1,8 @@ + .text +_start: + movl %fs:foo@GPREL(%rip), %eax + movl %fs:foo@GPREL(%rax), %eax + movl %ds:foo@GPREL(%rax, %rcx, 2), %eax + movl foo@GPREL(%rip), %eax + movl foo@GPREL(%rax), %eax + movl foo@GPREL, %eax |