aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arm-gen.c1
-rw-r--r--arm-link.c54
-rw-r--r--arm64-gen.c1
-rw-r--r--arm64-link.c19
-rw-r--r--c67-gen.c1
-rw-r--r--i386-gen.c1
-rw-r--r--i386-link.c13
-rw-r--r--tcc.h20
-rw-r--r--tccelf.c263
-rw-r--r--x86_64-gen.c1
-rw-r--r--x86_64-link.c14
11 files changed, 178 insertions, 210 deletions
diff --git a/arm-gen.c b/arm-gen.c
index cb2b19a..2c30dae 100644
--- a/arm-gen.c
+++ b/arm-gen.c
@@ -138,6 +138,7 @@ enum {
#define R_DATA_32 R_ARM_ABS32
#define R_DATA_PTR R_ARM_ABS32
#define R_JMP_SLOT R_ARM_JUMP_SLOT
+#define R_GLOB_DAT R_ARM_GLOB_DAT
#define R_COPY R_ARM_COPY
#define ELF_START_ADDR 0x00008000
diff --git a/arm-link.c b/arm-link.c
index 00332e0..ec989bb 100644
--- a/arm-link.c
+++ b/arm-link.c
@@ -1,6 +1,30 @@
#include "tcc.h"
#define HAVE_SECTION_RELOC
+ST_DATA struct reloc_info relocs_info[] = {
+ INIT_RELOC_INFO (R_ARM_PC24, 1, AUTO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_ARM_CALL, 1, AUTO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_ARM_JUMP24, 1, AUTO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_ARM_PLT32, 1, ALWAYS_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_ARM_THM_PC22, 1, AUTO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_ARM_THM_JUMP24, 1, AUTO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_ARM_MOVT_ABS, 0, AUTO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_ARM_MOVW_ABS_NC, 0, AUTO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_ARM_THM_MOVT_ABS, 0, AUTO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_ARM_THM_MOVW_ABS_NC, 0, AUTO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_ARM_PREL31, 1, AUTO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_ARM_ABS32, 0, NO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_ARM_REL32, 0, AUTO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_ARM_GOTPC, 0, BUILD_GOT_ONLY, 0)
+ INIT_RELOC_INFO (R_ARM_GOTOFF, 0, BUILD_GOT_ONLY, 0)
+ INIT_RELOC_INFO (R_ARM_GOT32, 0, ALWAYS_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_ARM_COPY, 0, NO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_ARM_V4BX, 1, AUTO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_ARM_GLOB_DAT, 0, NO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_ARM_JUMP_SLOT, 1, NO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_ARM_NONE, 0, NO_GOTPLT_ENTRY, 0)
+};
+
void relocate_init(Section *sr) {}
void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, addr_t val)
@@ -19,8 +43,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, add
{
int x, is_thumb, is_call, h, blx_avail, is_bl, th_ko;
x = (*(int *) ptr) & 0xffffff;
- if (sym->st_shndx == SHN_UNDEF ||
- s1->output_type == TCC_OUTPUT_MEMORY)
+ if (sym->st_shndx == SHN_UNDEF || sym->st_shndx == SHN_ABS)
val = s1->plt->sh_addr;
#ifdef DEBUG_RELOC
printf ("reloc %d: x=0x%x val=0x%x ", type, x, val);
@@ -89,6 +112,33 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, add
(val < plt->sh_addr + plt->data_offset);
is_call = (type == R_ARM_THM_PC22);
+ if (!to_thumb && !to_plt && !is_call) {
+ int index;
+ uint8_t *p;
+ char *name, buf[1024];
+ Section *text_section;
+
+ name = (char *) symtab_section->link->data + sym->st_name;
+ text_section = s1->sections[sym->st_shndx];
+ /* Modify reloc to target a thumb stub to switch to ARM */
+ snprintf(buf, sizeof(buf), "%s_from_thumb", name);
+ index = put_elf_sym(symtab_section,
+ text_section->data_offset + 1,
+ sym->st_size, sym->st_info, 0,
+ sym->st_shndx, buf);
+ to_thumb = 1;
+ val = text_section->data_offset + 1;
+ rel->r_info = ELFW(R_INFO)(index, type);
+ /* Create a thumb stub function to switch to ARM mode */
+ put_elf_reloc(symtab_section, text_section,
+ text_section->data_offset + 4, R_ARM_JUMP24,
+ sym_index);
+ p = section_ptr_add(text_section, 8);
+ write32le(p, 0x4778); /* bx pc */
+ write32le(p+2, 0x46c0); /* nop */
+ write32le(p+4, 0xeafffffe); /* b $sym */
+ }
+
/* Compute final offset */
if (to_plt && !is_call) /* Point to 1st instr of Thumb stub */
x -= 4;
diff --git a/arm64-gen.c b/arm64-gen.c
index cd6faac..c4e83e1 100644
--- a/arm64-gen.c
+++ b/arm64-gen.c
@@ -48,6 +48,7 @@
#define R_DATA_32 R_AARCH64_ABS32
#define R_DATA_PTR R_AARCH64_ABS64
#define R_JMP_SLOT R_AARCH64_JUMP_SLOT
+#define R_GLOB_DAT R_AARCH64_GLOB_DAT
#define R_COPY R_AARCH64_COPY
#define ELF_START_ADDR 0x00400000
diff --git a/arm64-link.c b/arm64-link.c
index 0364ba0..9122eff 100644
--- a/arm64-link.c
+++ b/arm64-link.c
@@ -1,6 +1,23 @@
#include "tcc.h"
#define HAVE_SECTION_RELOC
+ST_DATA struct reloc_info relocs_info[] = {
+ INIT_RELOC_INFO (R_AARCH64_ABS32, 0, NO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_AARCH64_ABS64, 0, NO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_AARCH64_MOVW_UABS_G0_NC, 0, NO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_AARCH64_MOVW_UABS_G1_NC, 0, NO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_AARCH64_MOVW_UABS_G2_NC, 0, NO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_AARCH64_MOVW_UABS_G3, 0, NO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_AARCH64_ADR_PREL_PG_HI21, 0, NO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_AARCH64_ADD_ABS_LO12_NC, 0, NO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_AARCH64_JUMP26, 1, AUTO_GOTPLT_ENTRY, 1)
+ INIT_RELOC_INFO (R_AARCH64_CALL26, 1, AUTO_GOTPLT_ENTRY, 1)
+ INIT_RELOC_INFO (R_AARCH64_ADR_GOT_PAGE, 0, ALWAYS_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_AARCH64_LD64_GOT_LO12_NC, 0, ALWAYS_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_AARCH64_GLOB_DAT, 0, NO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_AARCH64_JUMP_SLOT, 1, NO_GOTPLT_ENTRY, 0)
+};
+
void relocate_init(Section *sr) {}
void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, addr_t val)
@@ -51,7 +68,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, char *ptr, addr_t addr, add
/* This check must match the one in build_got_entries, testing
if we really need a PLT slot. */
if (sym->st_shndx == SHN_UNDEF ||
- s1->output_type == TCC_OUTPUT_MEMORY)
+ sym->st_shndx == SHN_ABS)
/* We've put the PLT slot offset into r_addend when generating
it, and that's what we must use as relocation value (adjusted
by section offset of course). */
diff --git a/c67-gen.c b/c67-gen.c
index 5ea9666..fcfc23c 100644
--- a/c67-gen.c
+++ b/c67-gen.c
@@ -117,6 +117,7 @@ enum {
#define R_DATA_32 R_C60_32
#define R_DATA_PTR R_C60_32
#define R_JMP_SLOT R_C60_JMP_SLOT
+#define R_GLOB_DAT R_C60_GLOB_DAT
#define R_COPY R_C60_COPY
#define ELF_START_ADDR 0x00000400
diff --git a/i386-gen.c b/i386-gen.c
index d9c4dde..1d8ff19 100644
--- a/i386-gen.c
+++ b/i386-gen.c
@@ -82,6 +82,7 @@ enum {
#define R_DATA_32 R_386_32
#define R_DATA_PTR R_386_32
#define R_JMP_SLOT R_386_JMP_SLOT
+#define R_GLOB_DAT R_386_GLOB_DAT
#define R_COPY R_386_COPY
#define ELF_START_ADDR 0x08048000
diff --git a/i386-link.c b/i386-link.c
index b33882f..019b53f 100644
--- a/i386-link.c
+++ b/i386-link.c
@@ -2,6 +2,19 @@
#define HAVE_SECTION_RELOC
static ElfW_Rel *qrel; /* ptr to next reloc entry reused */
+ST_DATA struct reloc_info relocs_info[] = {
+ INIT_RELOC_INFO (R_386_32, 0, NO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_386_PC32, 1, AUTO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_386_PLT32, 1, ALWAYS_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_386_GLOB_DAT, 0, NO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_386_JMP_SLOT, 1, NO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_386_GOTPC, 0, BUILD_GOT_ONLY, 0)
+ INIT_RELOC_INFO (R_386_GOTOFF, 0, BUILD_GOT_ONLY, 0)
+ INIT_RELOC_INFO (R_386_GOT32, 0, ALWAYS_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_386_GOT32X, 0, ALWAYS_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_386_16, 0, NO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_386_PC16, 1, AUTO_GOTPLT_ENTRY, 0)
+};
void relocate_init(Section *sr)
{
diff --git a/tcc.h b/tcc.h
index 147cbac..f0cad40 100644
--- a/tcc.h
+++ b/tcc.h
@@ -1305,6 +1305,26 @@ typedef struct {
unsigned int n_value; /* value of symbol */
} Stab_Sym;
+/* Wether to generate a GOT/PLT entry and when. NO_GOTPLT_ENTRY is first so
+ that unknown relocation don't create a GOT or PLT entry */
+enum gotplt_entry {
+ NO_GOTPLT_ENTRY, /* never generate (eg. GLOB_DAT & JMP_SLOT relocs) */
+ BUILD_GOT_ONLY, /* only build GOT (eg. TPOFF relocs) */
+ AUTO_GOTPLT_ENTRY, /* generate if sym is UNDEF */
+ ALWAYS_GOTPLT_ENTRY /* always generate (eg. PLTOFF relocs) */
+};
+
+/* what kind of relocation is it */
+struct reloc_info {
+ int code_reloc; /* if false, that's a data reloc */
+ int gotplt_entry; /* wether and when to create a GOT/PLT entry */
+ int pltoff_addend; /* wether to store the PLT offset in addend */
+};
+
+#define INIT_RELOC_INFO(rtype, code_reloc, gotplt_entry, pltoff_addend) \
+ [rtype] = {code_reloc, gotplt_entry, pltoff_addend},
+ST_DATA struct reloc_info relocs_info[];
+
ST_DATA Section *text_section, *data_section, *bss_section; /* predefined sections */
ST_DATA Section *cur_text_section; /* current section where function code is generated */
#ifdef CONFIG_TCC_ASM
diff --git a/tccelf.c b/tccelf.c
index 63e8111..8bab121 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -1022,6 +1022,7 @@ ST_FUNC void build_got_entries(TCCState *s1)
ElfW_Rel *rel;
ElfW(Sym) *sym;
int i, type, reloc_type, sym_index;
+ unsigned long ofs;
for(i = 1; i < s1->nb_sections; i++) {
s = s1->sections[i];
@@ -1034,222 +1035,70 @@ ST_FUNC void build_got_entries(TCCState *s1)
type = ELFW(R_TYPE)(rel->r_info);
sym_index = ELFW(R_SYM)(rel->r_info);
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
- switch(type) {
-#if defined(TCC_TARGET_I386)
- case R_386_PC16:
- case R_386_PC32:
- case R_386_GOT32:
- case R_386_GOT32X:
- case R_386_GOTOFF:
- case R_386_GOTPC:
- case R_386_PLT32:
- if (sym->st_shndx != SHN_UNDEF && type != R_386_GOT32 &&
- type != R_386_GOT32X && type != R_386_GOTOFF &&
- type != R_386_GOTPC && type != R_386_PLT32)
- break;
-
- if (!s1->got)
- build_got(s1);
+ if (relocs_info[type].gotplt_entry == NO_GOTPLT_ENTRY)
+ continue;
- if (type != R_386_GOTOFF && type != R_386_GOTPC) {
- /* look at the symbol got offset. If none, then add one */
- if (type == R_386_GOT32 || type == R_386_GOT32X)
- reloc_type = R_386_GLOB_DAT;
- else
- reloc_type = R_386_JMP_SLOT;
- put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
- sym_index);
- }
- break;
-#elif defined(TCC_TARGET_ARM)
- case R_ARM_PC24:
- case R_ARM_CALL:
- case R_ARM_JUMP24:
- case R_ARM_PLT32:
- case R_ARM_THM_PC22:
- case R_ARM_MOVT_ABS:
- case R_ARM_MOVW_ABS_NC:
- case R_ARM_THM_MOVT_ABS:
- case R_ARM_THM_MOVW_ABS_NC:
- case R_ARM_PREL31:
- case R_ARM_REL32:
- case R_ARM_GOTPC:
- case R_ARM_GOTOFF:
- case R_ARM_GOT32:
- case R_ARM_V4BX:
- if (sym->st_shndx != SHN_UNDEF && type != R_ARM_GOT32 &&
- type != R_ARM_GOTOFF && type != R_ARM_GOTPC &&
- type != R_ARM_PLT32)
- break;
+ /* Proceed with PLT/GOT [entry] creation if any of the following
+ condition is met:
+ - it is an undefined reference (dynamic relocation needed)
+ - symbol is absolute (probably created by tcc_add_symbol)
+ - relocation requires a PLT/GOT (BUILD_GOTPLT_ENTRY or
+ ALWAYS_GOTPLT_ENTRY). */
+ if (sym->st_shndx != SHN_UNDEF &&
+ sym->st_shndx != SHN_ABS &&
+ relocs_info[type].gotplt_entry == AUTO_GOTPLT_ENTRY)
+ continue;
- if (!s1->got)
- build_got(s1);
- if (type != R_ARM_GOTOFF && type != R_ARM_GOTPC
- && (sym->st_shndx == SHN_UNDEF
- || s1->output_type == TCC_OUTPUT_MEMORY)) {
- unsigned long ofs;
- /* look at the symbol got offset. If none, then add one */
- if (type == R_ARM_GOT32 || type == R_ARM_MOVT_ABS ||
- type == R_ARM_MOVW_ABS_NC ||
- type == R_ARM_THM_MOVT_ABS ||
- type == R_ARM_THM_MOVW_ABS_NC || type == R_ARM_ABS32 ||
- type == R_ARM_REL32)
- reloc_type = R_ARM_GLOB_DAT;
- else
- reloc_type = R_ARM_JUMP_SLOT;
- ofs = put_got_entry(s1, reloc_type, sym->st_size,
- sym->st_info, sym_index);
-#ifdef DEBUG_RELOC
- printf ("maybegot: %s, %d, %d --> ofs=0x%x\n",
- (char *) symtab_section->link->data + sym->st_name,
- type, sym->st_shndx, ofs);
-#endif
- if (type == R_ARM_PC24 || type == R_ARM_CALL ||
- type == R_ARM_JUMP24 || type == R_ARM_PLT32) {
- addr_t *ptr = (addr_t*)(s1->sections[s->sh_info]->data
- + rel->r_offset);
- /* x must be signed! */
- int x = *ptr & 0xffffff;
- x = (x << 8) >> 8;
- x <<= 2;
- x += ofs;
- x >>= 2;
-#ifdef DEBUG_RELOC
- printf ("insn=0x%x --> 0x%x (x==0x%x)\n", *ptr,
- (*ptr & 0xff000000) | x, x);
+#ifdef TCC_TARGET_X86_64
+ if (type == R_X86_64_PLT32 &&
+ ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT) {
+ rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32);
+ continue;
+ }
#endif
- *ptr = (*ptr & 0xff000000) | x;
- }
- }
- break;
- case R_ARM_THM_JUMP24:
- sym_index = ELFW(R_SYM)(rel->r_info);
- sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
- /* We are relocating a jump from thumb code to arm code */
- if (sym->st_shndx != SHN_UNDEF && !(sym->st_value & 1)) {
- int index;
- uint8_t *p;
- char *name, buf[1024];
- Section *text_section;
- name = (char *) symtab_section->link->data + sym->st_name;
- text_section = s1->sections[sym->st_shndx];
- /* Modify reloc to target a thumb stub to switch to ARM */
- snprintf(buf, sizeof(buf), "%s_from_thumb", name);
- index = put_elf_sym(symtab_section,
- text_section->data_offset + 1,
- sym->st_size, sym->st_info, 0,
- sym->st_shndx, buf);
- rel->r_info = ELFW(R_INFO)(index, type);
- /* Create a thumb stub fonction to switch to ARM mode */
- put_elf_reloc(symtab_section, text_section,
- text_section->data_offset + 4, R_ARM_JUMP24,
- sym_index);
- p = section_ptr_add(text_section, 8);
- write32le(p, 0x4778); /* bx pc */
- write32le(p+2, 0x46c0); /* nop */
- write32le(p+4, 0xeafffffe); /* b $sym */
- }
-#elif defined(TCC_TARGET_ARM64)
- //xx Other cases may be required here:
- case R_AARCH64_ADR_GOT_PAGE:
- case R_AARCH64_LD64_GOT_LO12_NC:
- if (!s1->got)
- build_got(s1);
- sym_index = ELFW(R_SYM)(rel->r_info);
- sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
- reloc_type = R_AARCH64_GLOB_DAT;
- put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
- sym_index);
- break;
+ if (!s1->got)
+ build_got(s1);
- case R_AARCH64_JUMP26:
- case R_AARCH64_CALL26:
- if (!s1->got)
- build_got(s1);
- sym_index = ELFW(R_SYM)(rel->r_info);
- sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
- if (sym->st_shndx == SHN_UNDEF ||
- s1->output_type == TCC_OUTPUT_MEMORY) {
- unsigned long ofs;
- reloc_type = R_AARCH64_JUMP_SLOT;
- ofs = put_got_entry(s1, reloc_type, sym->st_size,
- sym->st_info, sym_index);
- /* We store the place of the generated PLT slot
- in our addend. */
- rel->r_addend += ofs;
- }
- break;
-#elif defined(TCC_TARGET_C67)
- case R_C60_GOT32:
- case R_C60_GOTOFF:
- case R_C60_GOTPC:
- case R_C60_PLT32:
- if (!s1->got)
- build_got(s1);
- if (type == R_C60_GOT32 || type == R_C60_PLT32) {
- sym_index = ELFW(R_SYM)(rel->r_info);
- sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
- /* look at the symbol got offset. If none, then add one */
- if (type == R_C60_GOT32)
- reloc_type = R_C60_GLOB_DAT;
- else
- reloc_type = R_C60_JMP_SLOT;
- put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
- sym_index);
- }
- break;
-#elif defined(TCC_TARGET_X86_64)
- case R_X86_64_32:
- case R_X86_64_32S:
- case R_X86_64_64:
- case R_X86_64_PC32:
- case R_X86_64_GOT32:
- case R_X86_64_GOTTPOFF:
- case R_X86_64_GOTPCREL:
- case R_X86_64_GOTPCRELX:
- case R_X86_64_REX_GOTPCRELX:
- case R_X86_64_PLT32:
- sym_index = ELFW(R_SYM)(rel->r_info);
- sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
- if ((type == R_X86_64_32 || type == R_X86_64_32S ||
- type == R_X86_64_64 || type == R_X86_64_PC32) &&
- sym->st_shndx != SHN_UNDEF)
- break;
+ if (relocs_info[type].gotplt_entry == BUILD_GOT_ONLY)
+ continue;
- if (type == R_X86_64_PLT32 &&
- ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT) {
- rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32);
- break;
- }
+ if (relocs_info[type].code_reloc)
+ reloc_type = R_JMP_SLOT;
+ else
+ reloc_type = R_GLOB_DAT;
+ ofs = put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
+ sym_index);
- if (!s1->got)
- build_got(s1);
- if (type != R_X86_64_GOTTPOFF) {
- unsigned long ofs;
- /* look at the symbol got offset. If none, then add one */
- if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
- type == R_X86_64_GOTPCRELX ||
- type == R_X86_64_REX_GOTPCRELX ||
- type == R_X86_64_32 || type == R_X86_64_32S ||
- type == R_X86_64_64)
- reloc_type = R_X86_64_GLOB_DAT;
- else
- reloc_type = R_X86_64_JUMP_SLOT;
- ofs = put_got_entry(s1, reloc_type, sym->st_size,
- sym->st_info, sym_index);
- if (type == R_X86_64_PLT32)
- /* We store the place of the generated PLT slot
- in our addend. */
- rel->r_addend += ofs;
- }
- break;
-#else
-#error unsupported CPU
+#ifdef DEBUG_RELOC
+ printf ("maybegot: %s, %d, %d --> ofs=0x%x\n",
+ (char *) symtab_section->link->data + sym->st_name, type,
+ sym->st_shndx, ofs);
#endif
- default:
- break;
+
+#if defined (TCC_TARGET_X86_64) || defined(TCC_TARGET_ARM64)
+ /* We store the place of the generated PLT slot in our addend. */
+ if (relocs_info[type].pltoff_addend)
+ rel->r_addend += ofs;
+
+#elif defined (TCC_TARGET_ARM)
+ if (type == R_ARM_PC24 || type == R_ARM_CALL ||
+ type == R_ARM_JUMP24 || type == R_ARM_PLT32) {
+ addr_t *ptr = (addr_t*)(s1->sections[s->sh_info]->data
+ + rel->r_offset);
+ /* x must be signed! */
+ int x = *ptr & 0xffffff;
+ x = (x << 8) >> 8;
+ x <<= 2;
+ x += ofs;
+ x >>= 2;
+#ifdef DEBUG_RELOC
+ printf ("insn=0x%x --> 0x%x (x==0x%x)\n", *ptr,
+ (*ptr & 0xff000000) | x, x);
+#endif
+ *ptr = (*ptr & 0xff000000) | x;
}
+#endif
}
}
}
diff --git a/x86_64-gen.c b/x86_64-gen.c
index a33bb48..f183b77 100644
--- a/x86_64-gen.c
+++ b/x86_64-gen.c
@@ -110,6 +110,7 @@ enum {
#define R_DATA_32 R_X86_64_32
#define R_DATA_PTR R_X86_64_64
#define R_JMP_SLOT R_X86_64_JUMP_SLOT
+#define R_GLOB_DAT R_X86_64_GLOB_DAT
#define R_COPY R_X86_64_COPY
#define ELF_START_ADDR 0x400000
diff --git a/x86_64-link.c b/x86_64-link.c
index 2a9e9b0..5f8c504 100644
--- a/x86_64-link.c
+++ b/x86_64-link.c
@@ -2,6 +2,20 @@
#define HAVE_SECTION_RELOC
static ElfW_Rel *qrel; /* ptr to next reloc entry reused */
+ST_DATA struct reloc_info relocs_info[] = {
+ INIT_RELOC_INFO (R_X86_64_64, 0, AUTO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_X86_64_32, 0, AUTO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_X86_64_32S, 0, AUTO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_X86_64_PC32, 1, AUTO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_X86_64_PLT32, 1, ALWAYS_GOTPLT_ENTRY, 1)
+ INIT_RELOC_INFO (R_X86_64_GLOB_DAT, 0, NO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_X86_64_JUMP_SLOT, 1, NO_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_X86_64_GOTPCREL, 0, ALWAYS_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_X86_64_GOTPCRELX, 0, ALWAYS_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_X86_64_REX_GOTPCRELX, 0, ALWAYS_GOTPLT_ENTRY, 0)
+ INIT_RELOC_INFO (R_X86_64_GOTTPOFF, 0, BUILD_GOT_ONLY, 0)
+ INIT_RELOC_INFO (R_X86_64_GOT32, 0, ALWAYS_GOTPLT_ENTRY, 0)
+};
void relocate_init(Section *sr)
{