From 0bf262864c95e555fbd077b8f30e64652d9113a6 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Sat, 10 Dec 2016 09:14:29 +0000 Subject: [PATCH] Fix PLT creation for i386 i386 target does not have PC relative loads. Its ABI therefore require ebx register to points to the GOT when executing a PLT entry. This means that PLT entry cannot be used transparently, the compiler needs to expect execution of a PLT entry to be able to use one, that is a PLT entry should only be created if the relocation explicitely asks for it (eg. R_386_PLT32). This patch creates a new target macro PCRELATIVE_DLLPLT to indicate whether a target can do a PC relative load in PLT entry when building a dynamic library. Executable do not normally pose a problem because they are loaded at a fixed address and thus the absolute address of GOT can be used. Note that in such a case, if the compiler does not use a PLT aware relocation for external access then the code relocation will fall on the dynamic loader since there is no PLT entry to relocate too. --- arm-link.c | 1 + arm64-link.c | 1 + c67-link.c | 1 + i386-link.c | 1 + tccelf.c | 12 +++++++++++- x86_64-link.c | 1 + 6 files changed, 16 insertions(+), 1 deletion(-) diff --git a/arm-link.c b/arm-link.c index 02f8196a..7462a57f 100644 --- a/arm-link.c +++ b/arm-link.c @@ -15,6 +15,7 @@ #define ELF_PAGE_SIZE 0x1000 #define HAVE_SECTION_RELOC +#define PCRELATIVE_DLLPLT 1 enum float_abi { ARM_SOFTFP_FLOAT, diff --git a/arm64-link.c b/arm64-link.c index 9e5a8732..c22c20ab 100644 --- a/arm64-link.c +++ b/arm64-link.c @@ -14,6 +14,7 @@ #define ELF_PAGE_SIZE 0x1000 #define HAVE_SECTION_RELOC +#define PCRELATIVE_DLLPLT 1 #else /* !TARGET_DEFS_ONLY */ diff --git a/c67-link.c b/c67-link.c index d0ed2428..0bc08d6d 100644 --- a/c67-link.c +++ b/c67-link.c @@ -15,6 +15,7 @@ #define ELF_PAGE_SIZE 0x1000 #define HAVE_SECTION_RELOC +#define PCRELATIVE_DLLPLT 0 #else /* !TARGET_DEFS_ONLY */ diff --git a/i386-link.c b/i386-link.c index c9724816..a7ef73f2 100644 --- a/i386-link.c +++ b/i386-link.c @@ -15,6 +15,7 @@ #define ELF_PAGE_SIZE 0x1000 #define HAVE_SECTION_RELOC +#define PCRELATIVE_DLLPLT 0 #else /* !TARGET_DEFS_ONLY */ diff --git a/tccelf.c b/tccelf.c index 7f1679dc..df7375c8 100644 --- a/tccelf.c +++ b/tccelf.c @@ -1052,7 +1052,8 @@ ST_FUNC void build_got_entries(TCCState *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) + - symbol is absolute (probably created by tcc_add_symbol and + thus might be too far from application code) - relocation requires a PLT/GOT (BUILD_GOTPLT_ENTRY or ALWAYS_GOTPLT_ENTRY). */ if (sym->st_shndx != SHN_UNDEF && @@ -1060,6 +1061,15 @@ ST_FUNC void build_got_entries(TCCState *s1) relocs_info[type].gotplt_entry == AUTO_GOTPLT_ENTRY) continue; + /* Building a dynamic library but target is not capable of PC + relative PLT entries. It can thus only use PLT entries if + it expects one to be used (ALWAYS_GOTPLT_ENTRY). */ + if (sym->st_shndx == SHN_UNDEF && + s1->output_type == TCC_OUTPUT_DLL && + !PCRELATIVE_DLLPLT && + relocs_info[type].gotplt_entry == AUTO_GOTPLT_ENTRY) + continue; + #ifdef TCC_TARGET_X86_64 if (type == R_X86_64_PLT32 && ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT) { diff --git a/x86_64-link.c b/x86_64-link.c index 8769b3a7..25ae29cd 100644 --- a/x86_64-link.c +++ b/x86_64-link.c @@ -15,6 +15,7 @@ #define ELF_PAGE_SIZE 0x200000 #define HAVE_SECTION_RELOC +#define PCRELATIVE_DLLPLT 1 #else /* !TARGET_DEFS_ONLY */