From: Ali Gholami Rudi <address@hidden>
Subject: [PATCH] fill got table for static linking
libtcc.c | 9 +++++++++
tcc.h | 1 +
tccelf.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 54 insertions(+), 0 deletions(-)
diff --git a/libtcc.c b/libtcc.c
index 520abfd..7fb245d 100644
--- a/libtcc.c
+++ b/libtcc.c
@@ -372,6 +372,15 @@ ST_FUNC void *section_ptr_add(Section *sec, unsigned long
size)
return sec->data + offset;
}
+/* reserve at least 'size' bytes from section start */
+ST_FUNC void section_reserve(Section *sec, unsigned long size)
+{
+ if (size > sec->data_allocated)
+ section_realloc(sec, size);
+ if (size > sec->data_offset)
+ sec->data_offset = size;
+}
+
/* return a reference to a section, and create it if it does not
exists */
ST_FUNC Section *find_section(TCCState *s1, const char *name)
diff --git a/tcc.h b/tcc.h
index 3481f64..4b8111c 100644
--- a/tcc.h
+++ b/tcc.h
@@ -891,6 +891,7 @@ ST_FUNC void add_char(CString *cstr, int c);
ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int
sh_flags);
ST_FUNC void section_realloc(Section *sec, unsigned long new_size);
ST_FUNC void *section_ptr_add(Section *sec, unsigned long size);
+ST_FUNC void section_reserve(Section *sec, unsigned long size);
ST_FUNC Section *find_section(TCCState *s1, const char *name);
ST_FUNC void put_extern_sym2(Sym *sym, Section *section, unsigned long value, unsigned long size, int can_add_underscore);
diff --git a/tccelf.c b/tccelf.c
index a5385b1..2323a6b 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -1361,6 +1361,48 @@ void patch_dynsym_undef(TCCState *s1, Section *s)
#define EXTRA_RELITEMS 9
#endif
+ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
+{
+ int sym_index = ELFW(R_SYM) (rel->r_info);
+ ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
+ unsigned long offset;
+
+ if (sym_index >= s1->nb_got_offsets)
+ return;
+ offset = s1->got_offsets[sym_index];
+ section_reserve(s1->got, offset + PTR_SIZE);
+ /* only works for x86-64 */
+ put32(s1->got->data + offset, sym->st_value >> 32);
+ put32(s1->got->data + offset, sym->st_value & 0xffffffff);
+}
+
+ST_FUNC void fill_got(TCCState *s1)
+{
+ Section *s;
+ ElfW_Rel *rel, *rel_end;
+ int i;
+
+ for(i = 1; i < s1->nb_sections; i++) {
+ s = s1->sections[i];
+ if (s->sh_type != SHT_RELX)
+ continue;
+ /* no need to handle got relocations */
+ if (s->link != symtab_section)
+ continue;
+ rel_end = (ElfW_Rel *) (s->data + s->data_offset);
+ for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
+ switch (ELFW(R_TYPE) (rel->r_info)) {
+ case R_X86_64_GOT32:
+ case R_X86_64_GOTPCREL:
+ case R_X86_64_PLT32:
+ fill_got_entry(s1, rel);
+ break;
+ }
+ }
+ }
+}
+
+
/* output an ELF file */
/* XXX: suppress unneeded sections */
static int elf_output_file(TCCState *s1, const char *filename)
@@ -1977,6 +2019,8 @@ static int elf_output_file(TCCState *s1, const char
*filename)
else
ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
}
+ if (file_type == TCC_OUTPUT_EXE && s1->static_link)
+ fill_got(s1);
/* write elf file */
if (file_type == TCC_OUTPUT_OBJ)