summaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
Diffstat (limited to 'gas')
-rw-r--r--gas/config/tc-i386.c42
-rw-r--r--gas/config/tc-i386.h6
-rw-r--r--gas/testsuite/gas/i386/i386.exp3
-rw-r--r--gas/testsuite/gas/i386/x86-64-gprel.d10
-rw-r--r--gas/testsuite/gas/i386/x86-64-gprel.s3
-rw-r--r--gas/testsuite/gas/i386/x86-64-inval-gprel.l34
-rw-r--r--gas/testsuite/gas/i386/x86-64-inval-gprel.s8
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