From 1c811a4d1db56e4ed4fefa99ea39c679aa0c29f0 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Sat, 12 Nov 2016 23:16:07 +0800 Subject: [PATCH] Make build_got_entries more target independent Factor most of common logic between targets in build_got_entries by defining target specific info into structures in the backends. --- arm-gen.c | 1 + arm-link.c | 54 +++++++++- arm64-gen.c | 1 + arm64-link.c | 19 +++- c67-gen.c | 1 + i386-gen.c | 1 + i386-link.c | 13 +++ tcc.h | 20 ++++ tccelf.c | 275 ++++++++++++-------------------------------------- x86_64-gen.c | 1 + x86_64-link.c | 14 +++ 11 files changed, 184 insertions(+), 216 deletions(-) diff --git a/arm-gen.c b/arm-gen.c index cb2b19ae..2c30daee 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 00332e08..ec989bb8 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 cd6faac5..c4e83e15 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 0364ba01..9122eff5 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 5ea96665..fcfc23c1 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 d9c4dde0..1d8ff197 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 b33882fa..019b53f3 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 147cbac1..f0cad400 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 63e81116..8bab121c 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 (relocs_info[type].gotplt_entry == NO_GOTPLT_ENTRY) + continue; - if (!s1->got) - build_got(s1); + /* 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 (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; - - 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); -#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; - - 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 (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 (!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 -#endif - default: - break; +#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 + + if (!s1->got) + build_got(s1); + + if (relocs_info[type].gotplt_entry == BUILD_GOT_ONLY) + continue; + + 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); + +#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 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 a33bb480..f183b771 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 2a9e9b03..5f8c5045 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) {