aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShinichiro Hamaji <shinichiro.hamaji _at_ gmail.com>2009-03-31 22:17:36 +0900
committergrischka <grischka>2009-04-18 15:07:09 +0200
commit040ef000e486ac1e47cde85698878cb06ad34973 (patch)
tree0cb8232d9b58e191052b0dc4be15facabd25c7e5
parentfe8f230ab6bc26ab0a9a61412594111d8df5971d (diff)
downloadtinycc-040ef000e486ac1e47cde85698878cb06ad34973.tar.gz
tinycc-040ef000e486ac1e47cde85698878cb06ad34973.tar.bz2
Better DLL support on x86-64.
- Add a macro TCC_OUTPUT_DLL_WITH_PLT. -- Now, the DLL with PLT support works only on x86-64, but we may be able to support it on all architectures eventually. - Define TCC_OUTPUT_DLL_WITH_PLT when target architecture is x86-64. - Current status (x86-64): -- Main program should be able to call functions in shared objects. -- Main program should be able to use global variables in shared objects. -- Shared objects should be able to call functions in main program. -- Shared objects can NOT use global variables in main program. - To fix the last issue, we may need to add support of -fPIC option in our code generator.
-rw-r--r--tccelf.c47
1 files changed, 39 insertions, 8 deletions
diff --git a/tccelf.c b/tccelf.c
index 0bc4bca..926a9ff 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -22,12 +22,17 @@
#define ElfW_Rel ElfW(Rela)
#define SHT_RELX SHT_RELA
#define REL_SECTION_FMT ".rela%s"
+/* x86-64 requires PLT for DLLs */
+#define TCC_OUTPUT_DLL_WITH_PLT
#else
#define ElfW_Rel ElfW(Rel)
#define SHT_RELX SHT_REL
#define REL_SECTION_FMT ".rel%s"
#endif
+/* XXX: DLL with PLT would only work with x86-64 for now */
+//#define TCC_OUTPUT_DLL_WITH_PLT
+
static int put_elf_str(Section *s, const char *sym)
{
int offset, len;
@@ -902,11 +907,15 @@ static void put_got_entry(TCCState *s1,
uint8_t *p;
int modrm;
+#if defined(TCC_OUTPUT_DLL_WITH_PLT)
+ modrm = 0x25;
+#else
/* if we build a DLL, we add a %ebx offset */
if (s1->output_type == TCC_OUTPUT_DLL)
modrm = 0xa3;
else
modrm = 0x25;
+#endif
/* add a PLT entry */
plt = s1->plt;
@@ -932,7 +941,9 @@ static void put_got_entry(TCCState *s1,
/* the symbol is modified so that it will be relocated to
the PLT */
+#if !defined(TCC_OUTPUT_DLL_WITH_PLT)
if (s1->output_type == TCC_OUTPUT_EXE)
+#endif
offset = plt->data_offset - 16;
}
#elif defined(TCC_TARGET_ARM)
@@ -1468,13 +1479,29 @@ int elf_output_file(TCCState *s1, const char *filename)
sym < sym_end;
sym++) {
if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
- name = symtab_section->link->data + sym->st_name;
- index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
- sym->st_info, 0,
- sym->st_shndx, name);
- s1->symtab_to_dynsym[sym -
- (ElfW(Sym) *)symtab_section->data] =
- index;
+#if defined(TCC_OUTPUT_DLL_WITH_PLT)
+ if (ELFW(ST_TYPE)(sym->st_info) == STT_FUNC &&
+ sym->st_shndx == SHN_UNDEF) {
+ put_got_entry(s1, R_JMP_SLOT, sym->st_size,
+ sym->st_info,
+ sym - (ElfW(Sym) *)symtab_section->data);
+ }
+ else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
+ put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
+ sym->st_info,
+ sym - (ElfW(Sym) *)symtab_section->data);
+ }
+ else
+#endif
+ {
+ name = symtab_section->link->data + sym->st_name;
+ index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
+ sym->st_info, 0,
+ sym->st_shndx, name);
+ s1->symtab_to_dynsym[sym -
+ (ElfW(Sym) *)symtab_section->data] =
+ index;
+ }
}
}
}
@@ -1727,7 +1754,11 @@ int elf_output_file(TCCState *s1, const char *filename)
put32(s1->got->data, dynamic->sh_addr);
/* relocate the PLT */
- if (file_type == TCC_OUTPUT_EXE) {
+ if (file_type == TCC_OUTPUT_EXE
+#if defined(TCC_OUTPUT_DLL_WITH_PLT)
+ || file_type == TCC_OUTPUT_DLL
+#endif
+ ) {
uint8_t *p, *p_end;
p = s1->plt->data;