fill got table for static linking

master
Ali Gholami Rudi 2010-02-04 23:08:01 +03:30
parent b9aeac0a64
commit d63ec6f20d
3 changed files with 54 additions and 0 deletions

View File

@ -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)

1
tcc.h
View File

@ -900,6 +900,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);

View File

@ -1365,6 +1365,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)
@ -1985,6 +2027,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)