removed many memory leaks - suppressed many global variables

This commit is contained in:
bellard 2002-11-02 14:13:21 +00:00
parent c62792e6aa
commit e4c7dd5e60

361
tccelf.c
View file

@ -199,8 +199,8 @@ static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
sym_bind, sh_num, esym_bind, esym->st_shndx); sym_bind, sh_num, esym_bind, esym->st_shndx);
#endif #endif
/* NOTE: we accept that two DLL define the same symbol */ /* NOTE: we accept that two DLL define the same symbol */
if (s != dynsymtab_section) if (s != tcc_state->dynsymtab_section)
error("'%s' defined twice", name); error_noabort("'%s' defined twice", name);
} }
} else { } else {
do_patch: do_patch:
@ -232,7 +232,7 @@ static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
snprintf(buf, sizeof(buf), ".rel%s", s->name); snprintf(buf, sizeof(buf), ".rel%s", s->name);
/* if the symtab is allocated, then we consider the relocation /* if the symtab is allocated, then we consider the relocation
are also */ are also */
sr = new_section(buf, SHT_REL, symtab->sh_flags); sr = new_section(tcc_state, buf, SHT_REL, symtab->sh_flags);
sr->sh_entsize = sizeof(Elf32_Rel); sr->sh_entsize = sizeof(Elf32_Rel);
sr->link = symtab; sr->link = symtab;
sr->sh_info = s->sh_num; sr->sh_info = s->sh_num;
@ -293,7 +293,7 @@ static void put_stabd(int type, int other, int desc)
the global and weak ones. Since TCC cannot sort it while generating the global and weak ones. Since TCC cannot sort it while generating
the code, we must do it after. All the relocation tables are also the code, we must do it after. All the relocation tables are also
modified to take into account the symbol table sorting */ modified to take into account the symbol table sorting */
static void sort_syms(Section *s) static void sort_syms(TCCState *s1, Section *s)
{ {
int *old_to_new_syms; int *old_to_new_syms;
Elf32_Sym *new_syms; Elf32_Sym *new_syms;
@ -335,8 +335,8 @@ static void sort_syms(Section *s)
tcc_free(new_syms); tcc_free(new_syms);
/* now we modify all the relocations */ /* now we modify all the relocations */
for(i = 1; i < nb_sections; i++) { for(i = 1; i < s1->nb_sections; i++) {
sr = sections[i]; sr = s1->sections[i];
if (sr->sh_type == SHT_REL && sr->link == s) { if (sr->sh_type == SHT_REL && sr->link == s) {
rel_end = (Elf32_Rel *)(sr->data + sr->data_offset); rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
for(rel = (Elf32_Rel *)sr->data; for(rel = (Elf32_Rel *)sr->data;
@ -383,7 +383,7 @@ static void *resolve_sym(const char *sym)
/* relocate symbol table, resolve undefined symbols if do_resolve is /* relocate symbol table, resolve undefined symbols if do_resolve is
true and output error if undefined symbol. */ true and output error if undefined symbol. */
static void relocate_syms(int do_resolve) static void relocate_syms(TCCState *s1, int do_resolve)
{ {
Elf32_Sym *sym, *esym, *sym_end; Elf32_Sym *sym, *esym, *sym_end;
int sym_bind, sh_num, sym_index; int sym_bind, sh_num, sym_index;
@ -404,11 +404,11 @@ static void relocate_syms(int do_resolve)
sym->st_value = addr; sym->st_value = addr;
goto found; goto found;
} }
} else if (dynsym) { } else if (s1->dynsym) {
/* if dynamic symbol exist, then use it */ /* if dynamic symbol exist, then use it */
sym_index = find_elf_sym(dynsym, name); sym_index = find_elf_sym(s1->dynsym, name);
if (sym_index) { if (sym_index) {
esym = &((Elf32_Sym *)dynsym->data)[sym_index]; esym = &((Elf32_Sym *)s1->dynsym->data)[sym_index];
sym->st_value = esym->st_value; sym->st_value = esym->st_value;
goto found; goto found;
} }
@ -423,11 +423,11 @@ static void relocate_syms(int do_resolve)
if (sym_bind == STB_WEAK) { if (sym_bind == STB_WEAK) {
sym->st_value = 0; sym->st_value = 0;
} else { } else {
error("undefined symbol '%s'", name); error_noabort("undefined symbol '%s'", name);
} }
} else if (sh_num < SHN_LORESERVE) { } else if (sh_num < SHN_LORESERVE) {
/* add section base */ /* add section base */
sym->st_value += sections[sym->st_shndx]->sh_addr; sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
} }
found: ; found: ;
} }
@ -461,7 +461,7 @@ static void relocate_section(TCCState *s1, Section *s)
switch(type) { switch(type) {
case R_386_32: case R_386_32:
if (s1->output_type == TCC_OUTPUT_DLL) { if (s1->output_type == TCC_OUTPUT_DLL) {
esym_index = symtab_to_dynsym[sym_index]; esym_index = s1->symtab_to_dynsym[sym_index];
qrel->r_offset = rel->r_offset; qrel->r_offset = rel->r_offset;
if (esym_index) { if (esym_index) {
qrel->r_info = ELF32_R_INFO(esym_index, R_386_32); qrel->r_info = ELF32_R_INFO(esym_index, R_386_32);
@ -477,7 +477,7 @@ static void relocate_section(TCCState *s1, Section *s)
case R_386_PC32: case R_386_PC32:
if (s1->output_type == TCC_OUTPUT_DLL) { if (s1->output_type == TCC_OUTPUT_DLL) {
/* DLL relocation */ /* DLL relocation */
esym_index = symtab_to_dynsym[sym_index]; esym_index = s1->symtab_to_dynsym[sym_index];
if (esym_index) { if (esym_index) {
qrel->r_offset = rel->r_offset; qrel->r_offset = rel->r_offset;
qrel->r_info = ELF32_R_INFO(esym_index, R_386_PC32); qrel->r_info = ELF32_R_INFO(esym_index, R_386_PC32);
@ -495,29 +495,29 @@ static void relocate_section(TCCState *s1, Section *s)
*(int *)ptr = val; *(int *)ptr = val;
break; break;
case R_386_GOTPC: case R_386_GOTPC:
*(int *)ptr += got->sh_addr - addr; *(int *)ptr += s1->got->sh_addr - addr;
break; break;
case R_386_GOTOFF: case R_386_GOTOFF:
*(int *)ptr += val - got->sh_addr; *(int *)ptr += val - s1->got->sh_addr;
break; break;
case R_386_GOT32: case R_386_GOT32:
/* we load the got offset */ /* we load the got offset */
*(int *)ptr += got_offsets[sym_index]; *(int *)ptr += s1->got_offsets[sym_index];
break; break;
} }
} }
/* if the relocation is allocated, we change its symbol table */ /* if the relocation is allocated, we change its symbol table */
if (sr->sh_flags & SHF_ALLOC) if (sr->sh_flags & SHF_ALLOC)
sr->link = dynsym; sr->link = s1->dynsym;
} }
/* relocate relocation table in 'sr' */ /* relocate relocation table in 'sr' */
static void relocate_rel(Section *sr) static void relocate_rel(TCCState *s1, Section *sr)
{ {
Section *s; Section *s;
Elf32_Rel *rel, *rel_end; Elf32_Rel *rel, *rel_end;
s = sections[sr->sh_info]; s = s1->sections[sr->sh_info];
rel_end = (Elf32_Rel *)(sr->data + sr->data_offset); rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);
for(rel = (Elf32_Rel *)sr->data; for(rel = (Elf32_Rel *)sr->data;
rel < rel_end; rel < rel_end;
@ -528,7 +528,7 @@ static void relocate_rel(Section *sr)
/* count the number of dynamic relocations so that we can reserve /* count the number of dynamic relocations so that we can reserve
their space */ their space */
static int prepare_dynamic_rel(Section *sr) static int prepare_dynamic_rel(TCCState *s1, Section *sr)
{ {
Elf32_Rel *rel, *rel_end; Elf32_Rel *rel, *rel_end;
int sym_index, esym_index, type, count; int sym_index, esym_index, type, count;
@ -543,7 +543,7 @@ static int prepare_dynamic_rel(Section *sr)
count++; count++;
break; break;
case R_386_PC32: case R_386_PC32:
esym_index = symtab_to_dynsym[sym_index]; esym_index = s1->symtab_to_dynsym[sym_index];
if (esym_index) if (esym_index)
count++; count++;
break; break;
@ -559,25 +559,25 @@ static int prepare_dynamic_rel(Section *sr)
return count; return count;
} }
static void put_got_offset(int index, unsigned long val) static void put_got_offset(TCCState *s1, int index, unsigned long val)
{ {
int n; int n;
unsigned long *tab; unsigned long *tab;
if (index >= nb_got_offsets) { if (index >= s1->nb_got_offsets) {
/* find immediately bigger power of 2 and reallocate array */ /* find immediately bigger power of 2 and reallocate array */
n = 1; n = 1;
while (index >= n) while (index >= n)
n *= 2; n *= 2;
tab = tcc_realloc(got_offsets, n * sizeof(unsigned long)); tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));
if (!tab) if (!tab)
error("memory full"); error("memory full");
got_offsets = tab; s1->got_offsets = tab;
memset(got_offsets + nb_got_offsets, 0, memset(s1->got_offsets + s1->nb_got_offsets, 0,
(n - nb_got_offsets) * sizeof(unsigned long)); (n - s1->nb_got_offsets) * sizeof(unsigned long));
nb_got_offsets = n; s1->nb_got_offsets = n;
} }
got_offsets[index] = val; s1->got_offsets[index] = val;
} }
/* XXX: suppress that */ /* XXX: suppress that */
@ -589,16 +589,16 @@ static void put32(unsigned char *p, unsigned int val)
p[3] = val >> 24; p[3] = val >> 24;
} }
static void build_got(void) static void build_got(TCCState *s1)
{ {
unsigned char *ptr; unsigned char *ptr;
/* if no got, then create it */ /* if no got, then create it */
got = new_section(".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
got->sh_entsize = 4; s1->got->sh_entsize = 4;
add_elf_sym(symtab_section, 0, 4, ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT), add_elf_sym(symtab_section, 0, 4, ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT),
got->sh_num, "_GLOBAL_OFFSET_TABLE_"); s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
ptr = section_ptr_add(got, 3 * sizeof(int)); ptr = section_ptr_add(s1->got, 3 * sizeof(int));
/* keep space for _DYNAMIC pointer, if present */ /* keep space for _DYNAMIC pointer, if present */
put32(ptr, 0); put32(ptr, 0);
/* two dummy got entries */ /* two dummy got entries */
@ -608,7 +608,8 @@ static void build_got(void)
/* put a got entry corresponding to a symbol in symtab_section. 'size' /* put a got entry corresponding to a symbol in symtab_section. 'size'
and 'info' can be modifed if more precise info comes from the DLL */ and 'info' can be modifed if more precise info comes from the DLL */
static void put_got_entry(int reloc_type, unsigned long size, int info, static void put_got_entry(TCCState *s1,
int reloc_type, unsigned long size, int info,
int sym_index) int sym_index)
{ {
int index; int index;
@ -617,46 +618,46 @@ static void put_got_entry(int reloc_type, unsigned long size, int info,
unsigned long offset; unsigned long offset;
int *ptr; int *ptr;
if (!got) if (!s1->got)
build_got(); build_got(s1);
/* if a got entry already exists for that symbol, no need to add one */ /* if a got entry already exists for that symbol, no need to add one */
if (sym_index < nb_got_offsets && if (sym_index < s1->nb_got_offsets &&
got_offsets[sym_index] != 0) s1->got_offsets[sym_index] != 0)
return; return;
put_got_offset(sym_index, got->data_offset); put_got_offset(s1, sym_index, s1->got->data_offset);
if (dynsym) { if (s1->dynsym) {
sym = &((Elf32_Sym *)symtab_section->data)[sym_index]; sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
name = symtab_section->link->data + sym->st_name; name = symtab_section->link->data + sym->st_name;
offset = sym->st_value; offset = sym->st_value;
/* NOTE: we put temporarily the got offset */ /* NOTE: we put temporarily the got offset */
if (reloc_type == R_386_JMP_SLOT) { if (reloc_type == R_386_JMP_SLOT) {
nb_plt_entries++; s1->nb_plt_entries++;
offset = got->data_offset; offset = s1->got->data_offset;
} }
index = put_elf_sym(dynsym, offset, index = put_elf_sym(s1->dynsym, offset,
size, info, 0, sym->st_shndx, name); size, info, 0, sym->st_shndx, name);
/* put a got entry */ /* put a got entry */
put_elf_reloc(dynsym, got, put_elf_reloc(s1->dynsym, s1->got,
got->data_offset, s1->got->data_offset,
reloc_type, index); reloc_type, index);
} }
ptr = section_ptr_add(got, sizeof(int)); ptr = section_ptr_add(s1->got, sizeof(int));
*ptr = 0; *ptr = 0;
} }
/* build GOT and PLT entries */ /* build GOT and PLT entries */
static void build_got_entries(void) static void build_got_entries(TCCState *s1)
{ {
Section *s, *symtab; Section *s, *symtab;
Elf32_Rel *rel, *rel_end; Elf32_Rel *rel, *rel_end;
Elf32_Sym *sym; Elf32_Sym *sym;
int i, type, reloc_type, sym_index; int i, type, reloc_type, sym_index;
for(i = 1; i < nb_sections; i++) { for(i = 1; i < s1->nb_sections; i++) {
s = sections[i]; s = s1->sections[i];
if (s->sh_type != SHT_REL) if (s->sh_type != SHT_REL)
continue; continue;
/* no need to handle got relocations */ /* no need to handle got relocations */
@ -673,8 +674,8 @@ static void build_got_entries(void)
case R_386_GOTOFF: case R_386_GOTOFF:
case R_386_GOTPC: case R_386_GOTPC:
case R_386_PLT32: case R_386_PLT32:
if (!got) if (!s1->got)
build_got(); build_got(s1);
if (type == R_386_GOT32 || type == R_386_PLT32) { if (type == R_386_GOT32 || type == R_386_PLT32) {
sym_index = ELF32_R_SYM(rel->r_info); sym_index = ELF32_R_SYM(rel->r_info);
sym = &((Elf32_Sym *)symtab_section->data)[sym_index]; sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
@ -683,7 +684,7 @@ static void build_got_entries(void)
reloc_type = R_386_GLOB_DAT; reloc_type = R_386_GLOB_DAT;
else else
reloc_type = R_386_JMP_SLOT; reloc_type = R_386_JMP_SLOT;
put_got_entry(reloc_type, sym->st_size, sym->st_info, put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
sym_index); sym_index);
} }
break; break;
@ -694,23 +695,24 @@ static void build_got_entries(void)
} }
} }
static Section *new_symtab(const char *symtab_name, int sh_type, int sh_flags, static Section *new_symtab(TCCState *s1,
const char *symtab_name, int sh_type, int sh_flags,
const char *strtab_name, const char *strtab_name,
const char *hash_name, int hash_sh_flags) const char *hash_name, int hash_sh_flags)
{ {
Section *symtab, *strtab, *hash; Section *symtab, *strtab, *hash;
int *ptr, nb_buckets; int *ptr, nb_buckets;
symtab = new_section(symtab_name, sh_type, sh_flags); symtab = new_section(s1, symtab_name, sh_type, sh_flags);
symtab->sh_entsize = sizeof(Elf32_Sym); symtab->sh_entsize = sizeof(Elf32_Sym);
strtab = new_section(strtab_name, SHT_STRTAB, sh_flags); strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
put_elf_str(strtab, ""); put_elf_str(strtab, "");
symtab->link = strtab; symtab->link = strtab;
put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL); put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
nb_buckets = 1; nb_buckets = 1;
hash = new_section(hash_name, SHT_HASH, hash_sh_flags); hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
hash->sh_entsize = sizeof(int); hash->sh_entsize = sizeof(int);
symtab->hash = hash; symtab->hash = hash;
hash->link = symtab; hash->link = symtab;
@ -759,7 +761,7 @@ static void tcc_add_runtime(TCCState *s1)
#ifdef TCC_TARGET_I386 #ifdef TCC_TARGET_I386
if (s1->output_type != TCC_OUTPUT_MEMORY) { if (s1->output_type != TCC_OUTPUT_MEMORY) {
/* add 'call __bound_init()' in .init section */ /* add 'call __bound_init()' in .init section */
init_section = find_section(".init"); init_section = find_section(s1, ".init");
pinit = section_ptr_add(init_section, 5); pinit = section_ptr_add(init_section, 5);
pinit[0] = 0xe8; pinit[0] = 0xe8;
put32(pinit + 1, -4); put32(pinit + 1, -4);
@ -790,8 +792,8 @@ static void tcc_add_runtime(TCCState *s1)
bss_section->sh_num, "_end"); bss_section->sh_num, "_end");
/* add start and stop symbols for sections whose name can be /* add start and stop symbols for sections whose name can be
expressed in C */ expressed in C */
for(i = 1; i < nb_sections; i++) { for(i = 1; i < s1->nb_sections; i++) {
s = sections[i]; s = s1->sections[i];
if (s->sh_type == SHT_PROGBITS && if (s->sh_type == SHT_PROGBITS &&
(s->sh_flags & SHF_ALLOC)) { (s->sh_flags & SHF_ALLOC)) {
const char *p; const char *p;
@ -834,7 +836,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
{ {
Elf32_Ehdr ehdr; Elf32_Ehdr ehdr;
FILE *f; FILE *f;
int fd, mode; int fd, mode, ret;
int *section_order; int *section_order;
int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k; int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;
unsigned long addr; unsigned long addr;
@ -848,15 +850,15 @@ int tcc_output_file(TCCState *s1, const char *filename)
unsigned long rel_addr, rel_size; unsigned long rel_addr, rel_size;
file_type = s1->output_type; file_type = s1->output_type;
s1->nb_errors = 0;
if (file_type != TCC_OUTPUT_OBJ) if (file_type != TCC_OUTPUT_OBJ)
tcc_add_runtime(s1); tcc_add_runtime(s1);
phdr = NULL;
section_order = NULL;
interp = NULL; interp = NULL;
dynamic = NULL; dynamic = NULL;
dynsym = NULL;
got = NULL;
nb_plt_entries = 0;
plt = NULL; /* avoid warning */ plt = NULL; /* avoid warning */
dynstr = NULL; /* avoid warning */ dynstr = NULL; /* avoid warning */
saved_dynamic_data_offset = 0; /* avoid warning */ saved_dynamic_data_offset = 0; /* avoid warning */
@ -865,7 +867,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
relocate_common_syms(); relocate_common_syms();
if (!static_link) { if (!s1->static_link) {
const char *name; const char *name;
int sym_index, index; int sym_index, index;
Elf32_Sym *esym, *sym_end; Elf32_Sym *esym, *sym_end;
@ -873,29 +875,29 @@ int tcc_output_file(TCCState *s1, const char *filename)
if (file_type == TCC_OUTPUT_EXE) { if (file_type == TCC_OUTPUT_EXE) {
char *ptr; char *ptr;
/* add interpreter section only if executable */ /* add interpreter section only if executable */
interp = new_section(".interp", SHT_PROGBITS, SHF_ALLOC); interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
interp->sh_addralign = 1; interp->sh_addralign = 1;
ptr = section_ptr_add(interp, sizeof(elf_interp)); ptr = section_ptr_add(interp, sizeof(elf_interp));
strcpy(ptr, elf_interp); strcpy(ptr, elf_interp);
} }
/* add dynamic symbol table */ /* add dynamic symbol table */
dynsym = new_symtab(".dynsym", SHT_DYNSYM, SHF_ALLOC, s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
".dynstr", ".dynstr",
".hash", SHF_ALLOC); ".hash", SHF_ALLOC);
dynstr = dynsym->link; dynstr = s1->dynsym->link;
/* add dynamic section */ /* add dynamic section */
dynamic = new_section(".dynamic", SHT_DYNAMIC, dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
SHF_ALLOC | SHF_WRITE); SHF_ALLOC | SHF_WRITE);
dynamic->link = dynstr; dynamic->link = dynstr;
dynamic->sh_entsize = sizeof(Elf32_Dyn); dynamic->sh_entsize = sizeof(Elf32_Dyn);
/* add PLT */ /* add PLT */
plt = new_section(".plt", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); plt = new_section(s1, ".plt", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
plt->sh_entsize = 4; plt->sh_entsize = 4;
build_got(); build_got(s1);
/* scan for undefined symbols and see if they are in the /* scan for undefined symbols and see if they are in the
dynamic symbols. If a symbol STT_FUNC is found, then we dynamic symbols. If a symbol STT_FUNC is found, then we
@ -909,12 +911,12 @@ int tcc_output_file(TCCState *s1, const char *filename)
sym++) { sym++) {
if (sym->st_shndx == SHN_UNDEF) { if (sym->st_shndx == SHN_UNDEF) {
name = symtab_section->link->data + sym->st_name; name = symtab_section->link->data + sym->st_name;
sym_index = find_elf_sym(dynsymtab_section, name); sym_index = find_elf_sym(s1->dynsymtab_section, name);
if (sym_index) { if (sym_index) {
esym = &((Elf32_Sym *)dynsymtab_section->data)[sym_index]; esym = &((Elf32_Sym *)s1->dynsymtab_section->data)[sym_index];
type = ELF32_ST_TYPE(esym->st_info); type = ELF32_ST_TYPE(esym->st_info);
if (type == STT_FUNC) { if (type == STT_FUNC) {
put_got_entry(R_386_JMP_SLOT, esym->st_size, put_got_entry(s1, R_386_JMP_SLOT, esym->st_size,
esym->st_info, esym->st_info,
sym - (Elf32_Sym *)symtab_section->data); sym - (Elf32_Sym *)symtab_section->data);
} else if (type == STT_OBJECT) { } else if (type == STT_OBJECT) {
@ -922,10 +924,10 @@ int tcc_output_file(TCCState *s1, const char *filename)
offset = bss_section->data_offset; offset = bss_section->data_offset;
/* XXX: which alignment ? */ /* XXX: which alignment ? */
offset = (offset + 8 - 1) & -8; offset = (offset + 8 - 1) & -8;
index = put_elf_sym(dynsym, offset, esym->st_size, index = put_elf_sym(s1->dynsym, offset, esym->st_size,
esym->st_info, 0, esym->st_info, 0,
bss_section->sh_num, name); bss_section->sh_num, name);
put_elf_reloc(dynsym, bss_section, put_elf_reloc(s1->dynsym, bss_section,
offset, R_386_COPY, index); offset, R_386_COPY, index);
offset += esym->st_size; offset += esym->st_size;
bss_section->data_offset = offset; bss_section->data_offset = offset;
@ -937,25 +939,28 @@ int tcc_output_file(TCCState *s1, const char *filename)
if (ELF32_ST_BIND(sym->st_info) == STB_WEAK || if (ELF32_ST_BIND(sym->st_info) == STB_WEAK ||
!strcmp(name, "_fp_hw")) { !strcmp(name, "_fp_hw")) {
} else { } else {
error("undefined symbol '%s'", name); error_noabort("undefined symbol '%s'", name);
} }
} }
} }
} }
if (s1->nb_errors)
goto fail;
/* now look at unresolved dynamic symbols and export /* now look at unresolved dynamic symbols and export
corresponding symbol */ corresponding symbol */
sym_end = (Elf32_Sym *)(dynsymtab_section->data + sym_end = (Elf32_Sym *)(s1->dynsymtab_section->data +
dynsymtab_section->data_offset); s1->dynsymtab_section->data_offset);
for(esym = (Elf32_Sym *)dynsymtab_section->data + 1; for(esym = (Elf32_Sym *)s1->dynsymtab_section->data + 1;
esym < sym_end; esym < sym_end;
esym++) { esym++) {
if (esym->st_shndx == SHN_UNDEF) { if (esym->st_shndx == SHN_UNDEF) {
name = dynsymtab_section->link->data + esym->st_name; name = s1->dynsymtab_section->link->data + esym->st_name;
sym_index = find_elf_sym(symtab_section, name); sym_index = find_elf_sym(symtab_section, name);
if (sym_index) { if (sym_index) {
sym = &((Elf32_Sym *)symtab_section->data)[sym_index]; sym = &((Elf32_Sym *)symtab_section->data)[sym_index];
put_elf_sym(dynsym, sym->st_value, sym->st_size, put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
sym->st_info, 0, sym->st_info, 0,
sym->st_shndx, name); sym->st_shndx, name);
} else { } else {
@ -971,29 +976,30 @@ int tcc_output_file(TCCState *s1, const char *filename)
int nb_syms; int nb_syms;
/* shared library case : we simply export all the global symbols */ /* shared library case : we simply export all the global symbols */
nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym); nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym);
symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms); s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
for(sym = (Elf32_Sym *)symtab_section->data + 1; for(sym = (Elf32_Sym *)symtab_section->data + 1;
sym < sym_end; sym < sym_end;
sym++) { sym++) {
if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) { if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {
name = symtab_section->link->data + sym->st_name; name = symtab_section->link->data + sym->st_name;
index = put_elf_sym(dynsym, sym->st_value, sym->st_size, index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
sym->st_info, 0, sym->st_info, 0,
sym->st_shndx, name); sym->st_shndx, name);
symtab_to_dynsym[sym - (Elf32_Sym *)symtab_section->data] = s1->symtab_to_dynsym[sym -
(Elf32_Sym *)symtab_section->data] =
index; index;
} }
} }
} }
build_got_entries(); build_got_entries(s1);
/* update PLT/GOT sizes so that we can allocate their space */ /* update PLT/GOT sizes so that we can allocate their space */
plt->data_offset += 16 * (nb_plt_entries + 1); plt->data_offset += 16 * (s1->nb_plt_entries + 1);
/* add a list of needed dlls */ /* add a list of needed dlls */
for(i = 0; i < nb_loaded_dlls; i++) { for(i = 0; i < s1->nb_loaded_dlls; i++) {
DLLReference *dllref = loaded_dlls[i]; DLLReference *dllref = s1->loaded_dlls[i];
if (dllref->level == 0) if (dllref->level == 0)
put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name)); put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
} }
@ -1007,18 +1013,18 @@ int tcc_output_file(TCCState *s1, const char *filename)
dynamic->data_offset += 8 * 9; dynamic->data_offset += 8 * 9;
} else { } else {
/* still need to build got entries in case of static link */ /* still need to build got entries in case of static link */
build_got_entries(); build_got_entries(s1);
} }
} }
memset(&ehdr, 0, sizeof(ehdr)); memset(&ehdr, 0, sizeof(ehdr));
/* we add a section for symbols */ /* we add a section for symbols */
strsec = new_section(".shstrtab", SHT_STRTAB, 0); strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
put_elf_str(strsec, ""); put_elf_str(strsec, "");
/* compute number of sections */ /* compute number of sections */
shnum = nb_sections; shnum = s1->nb_sections;
/* this array is used to reorder sections in the output file */ /* this array is used to reorder sections in the output file */
section_order = tcc_malloc(sizeof(int) * shnum); section_order = tcc_malloc(sizeof(int) * shnum);
@ -1032,7 +1038,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
phnum = 0; phnum = 0;
break; break;
case TCC_OUTPUT_EXE: case TCC_OUTPUT_EXE:
if (!static_link) if (!s1->static_link)
phnum = 4; phnum = 4;
else else
phnum = 2; phnum = 2;
@ -1046,19 +1052,19 @@ int tcc_output_file(TCCState *s1, const char *filename)
section should be output */ section should be output */
/* NOTE: the strsec section comes last, so its size is also /* NOTE: the strsec section comes last, so its size is also
correct ! */ correct ! */
for(i = 1; i < nb_sections; i++) { for(i = 1; i < s1->nb_sections; i++) {
s = sections[i]; s = s1->sections[i];
s->sh_name = put_elf_str(strsec, s->name); s->sh_name = put_elf_str(strsec, s->name);
/* when generating a DLL, we include relocations but we may /* when generating a DLL, we include relocations but we may
patch them */ patch them */
if (file_type == TCC_OUTPUT_DLL && if (file_type == TCC_OUTPUT_DLL &&
s->sh_type == SHT_REL && s->sh_type == SHT_REL &&
!(s->sh_flags & SHF_ALLOC)) { !(s->sh_flags & SHF_ALLOC)) {
prepare_dynamic_rel(s); prepare_dynamic_rel(s1, s);
} else if (do_debug || } else if (do_debug ||
file_type == TCC_OUTPUT_OBJ || file_type == TCC_OUTPUT_OBJ ||
(s->sh_flags & SHF_ALLOC) || (s->sh_flags & SHF_ALLOC) ||
i == (nb_sections - 1)) { i == (s1->nb_sections - 1)) {
/* we output all sections if debug or object file */ /* we output all sections if debug or object file */
s->sh_size = s->data_offset; s->sh_size = s->data_offset;
} }
@ -1099,8 +1105,8 @@ int tcc_output_file(TCCState *s1, const char *filename)
relocations, progbits, nobits */ relocations, progbits, nobits */
/* XXX: do faster and simpler sorting */ /* XXX: do faster and simpler sorting */
for(k = 0; k < 5; k++) { for(k = 0; k < 5; k++) {
for(i = 1; i < nb_sections; i++) { for(i = 1; i < s1->nb_sections; i++) {
s = sections[i]; s = s1->sections[i];
/* compute if section should be included */ /* compute if section should be included */
if (j == 0) { if (j == 0) {
if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) != if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
@ -1193,7 +1199,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
ph->p_align = dynamic->sh_addralign; ph->p_align = dynamic->sh_addralign;
/* put GOT dynamic section address */ /* put GOT dynamic section address */
put32(got->data, dynamic->sh_addr); put32(s1->got->data, dynamic->sh_addr);
/* compute the PLT */ /* compute the PLT */
plt->data_offset = 0; plt->data_offset = 0;
@ -1202,15 +1208,15 @@ int tcc_output_file(TCCState *s1, const char *filename)
p = section_ptr_add(plt, 16); p = section_ptr_add(plt, 16);
p[0] = 0xff; /* pushl got + 4 */ p[0] = 0xff; /* pushl got + 4 */
p[1] = 0x35; p[1] = 0x35;
put32(p + 2, got->sh_addr + 4); put32(p + 2, s1->got->sh_addr + 4);
p[6] = 0xff; /* jmp *(got + 8) */ p[6] = 0xff; /* jmp *(got + 8) */
p[7] = 0x25; p[7] = 0x25;
put32(p + 8, got->sh_addr + 8); put32(p + 8, s1->got->sh_addr + 8);
/* relocation symbols in .dynsym and build PLT. */ /* relocation symbols in .dynsym and build PLT. */
plt_offset = 0; plt_offset = 0;
sym_end = (Elf32_Sym *)(dynsym->data + dynsym->data_offset); sym_end = (Elf32_Sym *)(s1->dynsym->data + s1->dynsym->data_offset);
for(sym = (Elf32_Sym *)dynsym->data + 1; for(sym = (Elf32_Sym *)s1->dynsym->data + 1;
sym < sym_end; sym < sym_end;
sym++) { sym++) {
type = ELF32_ST_TYPE(sym->st_info); type = ELF32_ST_TYPE(sym->st_info);
@ -1220,7 +1226,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
p = section_ptr_add(plt, 16); p = section_ptr_add(plt, 16);
p[0] = 0xff; /* jmp *(got + x) */ p[0] = 0xff; /* jmp *(got + x) */
p[1] = 0x25; p[1] = 0x25;
put32(p + 2, got->sh_addr + sym->st_value); put32(p + 2, s1->got->sh_addr + sym->st_value);
p[6] = 0x68; /* push $xxx */ p[6] = 0x68; /* push $xxx */
put32(p + 7, plt_offset); put32(p + 7, plt_offset);
p[11] = 0xe9; /* jmp plt_start */ p[11] = 0xe9; /* jmp plt_start */
@ -1233,15 +1239,15 @@ int tcc_output_file(TCCState *s1, const char *filename)
} }
} else if (sym->st_shndx < SHN_LORESERVE) { } else if (sym->st_shndx < SHN_LORESERVE) {
/* do symbol relocation */ /* do symbol relocation */
sym->st_value += sections[sym->st_shndx]->sh_addr; sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
} }
} }
/* put dynamic section entries */ /* put dynamic section entries */
dynamic->data_offset = saved_dynamic_data_offset; dynamic->data_offset = saved_dynamic_data_offset;
put_dt(dynamic, DT_HASH, dynsym->hash->sh_addr); put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
put_dt(dynamic, DT_STRTAB, dynstr->sh_addr); put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
put_dt(dynamic, DT_SYMTAB, dynsym->sh_addr); put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
put_dt(dynamic, DT_STRSZ, dynstr->data_offset); put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
put_dt(dynamic, DT_SYMENT, sizeof(Elf32_Sym)); put_dt(dynamic, DT_SYMENT, sizeof(Elf32_Sym));
put_dt(dynamic, DT_REL, rel_addr); put_dt(dynamic, DT_REL, rel_addr);
@ -1256,8 +1262,8 @@ int tcc_output_file(TCCState *s1, const char *filename)
} }
/* all other sections come after */ /* all other sections come after */
for(i = 1; i < nb_sections; i++) { for(i = 1; i < s1->nb_sections; i++) {
s = sections[i]; s = s1->sections[i];
if (phnum > 0 && (s->sh_flags & SHF_ALLOC)) if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
continue; continue;
section_order[sh_order_index++] = i; section_order[sh_order_index++] = i;
@ -1272,23 +1278,29 @@ int tcc_output_file(TCCState *s1, const char *filename)
/* if building executable or DLL, then relocate each section /* if building executable or DLL, then relocate each section
except the GOT which is already relocated */ except the GOT which is already relocated */
if (file_type != TCC_OUTPUT_OBJ) { if (file_type != TCC_OUTPUT_OBJ) {
relocate_syms(0); relocate_syms(s1, 0);
if (s1->nb_errors != 0) {
fail:
ret = -1;
goto the_end;
}
/* relocate sections */ /* relocate sections */
/* XXX: ignore sections with allocated relocations ? */ /* XXX: ignore sections with allocated relocations ? */
for(i = 1; i < nb_sections; i++) { for(i = 1; i < s1->nb_sections; i++) {
s = sections[i]; s = s1->sections[i];
if (s->reloc && s != got) if (s->reloc && s != s1->got)
relocate_section(s1, s); relocate_section(s1, s);
} }
/* relocate relocation entries if the relocation tables are /* relocate relocation entries if the relocation tables are
allocated in the executable */ allocated in the executable */
for(i = 1; i < nb_sections; i++) { for(i = 1; i < s1->nb_sections; i++) {
s = sections[i]; s = s1->sections[i];
if ((s->sh_flags & SHF_ALLOC) && if ((s->sh_flags & SHF_ALLOC) &&
s->sh_type == SHT_REL) { s->sh_type == SHT_REL) {
relocate_rel(s); relocate_rel(s1, s);
} }
} }
@ -1299,7 +1311,7 @@ int tcc_output_file(TCCState *s1, const char *filename)
ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */ ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
} }
sort_syms(symtab_section); sort_syms(s1, symtab_section);
/* align to 4 */ /* align to 4 */
file_offset = (file_offset + 3) & -4; file_offset = (file_offset + 3) & -4;
@ -1338,15 +1350,16 @@ int tcc_output_file(TCCState *s1, const char *filename)
else else
mode = 0777; mode = 0777;
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, mode); fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, mode);
if (fd < 0) if (fd < 0) {
error("could not write '%s'", filename); error_noabort("could not write '%s'", filename);
goto fail;
}
f = fdopen(fd, "w"); f = fdopen(fd, "w");
fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f); fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f);
fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f); fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f);
offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr); offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);
for(i=1;i<nb_sections;i++) { for(i=1;i<s1->nb_sections;i++) {
s = sections[section_order[i]]; s = s1->sections[section_order[i]];
if (s->sh_type != SHT_NOBITS) { if (s->sh_type != SHT_NOBITS) {
while (offset < s->sh_offset) { while (offset < s->sh_offset) {
fputc(0, f); fputc(0, f);
@ -1363,10 +1376,10 @@ int tcc_output_file(TCCState *s1, const char *filename)
} }
/* output section headers */ /* output section headers */
for(i=0;i<nb_sections;i++) { for(i=0;i<s1->nb_sections;i++) {
sh = &shdr; sh = &shdr;
memset(sh, 0, sizeof(Elf32_Shdr)); memset(sh, 0, sizeof(Elf32_Shdr));
s = sections[i]; s = s1->sections[i];
if (s) { if (s) {
sh->sh_name = s->sh_name; sh->sh_name = s->sh_name;
sh->sh_type = s->sh_type; sh->sh_type = s->sh_type;
@ -1384,9 +1397,13 @@ int tcc_output_file(TCCState *s1, const char *filename)
} }
fclose(f); fclose(f);
ret = 0;
the_end:
tcc_free(s1->symtab_to_dynsym);
tcc_free(section_order); tcc_free(section_order);
tcc_free(phdr); tcc_free(phdr);
return 0; tcc_free(s1->got_offsets);
return ret;
} }
static void *load_data(int fd, unsigned long file_offset, unsigned long size) static void *load_data(int fd, unsigned long file_offset, unsigned long size)
@ -1412,7 +1429,7 @@ static int tcc_load_object_file(TCCState *s1,
{ {
Elf32_Ehdr ehdr; Elf32_Ehdr ehdr;
Elf32_Shdr *shdr, *sh; Elf32_Shdr *shdr, *sh;
int size, i, j, offset, offseti, nb_syms, sym_index; int size, i, j, offset, offseti, nb_syms, sym_index, ret;
unsigned char *strsec, *strtab; unsigned char *strsec, *strtab;
int *old_to_new_syms; int *old_to_new_syms;
char *sh_name, *name; char *sh_name, *name;
@ -1422,20 +1439,21 @@ static int tcc_load_object_file(TCCState *s1,
Section *s; Section *s;
if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
goto fail; goto fail1;
if (ehdr.e_ident[0] != ELFMAG0 || if (ehdr.e_ident[0] != ELFMAG0 ||
ehdr.e_ident[1] != ELFMAG1 || ehdr.e_ident[1] != ELFMAG1 ||
ehdr.e_ident[2] != ELFMAG2 || ehdr.e_ident[2] != ELFMAG2 ||
ehdr.e_ident[3] != ELFMAG3) ehdr.e_ident[3] != ELFMAG3)
goto fail; goto fail1;
/* test if object file */ /* test if object file */
if (ehdr.e_type != ET_REL) if (ehdr.e_type != ET_REL)
goto fail; goto fail1;
/* test CPU specific stuff */ /* test CPU specific stuff */
if (ehdr.e_ident[5] != ELFDATA2LSB || if (ehdr.e_ident[5] != ELFDATA2LSB ||
ehdr.e_machine != EM_386) { ehdr.e_machine != EM_386) {
fail: fail1:
error("invalid object file"); error_noabort("invalid object file");
return -1;
} }
/* read sections */ /* read sections */
shdr = load_data(fd, file_offset + ehdr.e_shoff, shdr = load_data(fd, file_offset + ehdr.e_shoff,
@ -1447,14 +1465,19 @@ static int tcc_load_object_file(TCCState *s1,
strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size); strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
/* load symtab and strtab */ /* load symtab and strtab */
old_to_new_syms = NULL;
symtab = NULL; symtab = NULL;
strtab = NULL; strtab = NULL;
nb_syms = 0; nb_syms = 0;
for(i = 1; i < ehdr.e_shnum; i++) { for(i = 1; i < ehdr.e_shnum; i++) {
sh = &shdr[i]; sh = &shdr[i];
if (sh->sh_type == SHT_SYMTAB) { if (sh->sh_type == SHT_SYMTAB) {
if (symtab) if (symtab) {
error("object must contain only one symtab"); error_noabort("object must contain only one symtab");
fail:
ret = -1;
goto the_end;
}
nb_syms = sh->sh_size / sizeof(Elf32_Sym); nb_syms = sh->sh_size / sizeof(Elf32_Sym);
symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size); symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
sm_table[i].s = symtab_section; sm_table[i].s = symtab_section;
@ -1481,21 +1504,23 @@ static int tcc_load_object_file(TCCState *s1,
if (sh->sh_addralign < 1) if (sh->sh_addralign < 1)
sh->sh_addralign = 1; sh->sh_addralign = 1;
/* find corresponding section, if any */ /* find corresponding section, if any */
for(j = 1; j < nb_sections;j++) { for(j = 1; j < s1->nb_sections;j++) {
s = sections[j]; s = s1->sections[j];
if (!strcmp(s->name, sh_name)) if (!strcmp(s->name, sh_name))
goto found; goto found;
} }
/* not found: create new section */ /* not found: create new section */
s = new_section(sh_name, sh->sh_type, sh->sh_flags); s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
/* take as much info as possible from the section. sh_link and /* take as much info as possible from the section. sh_link and
sh_info will be updated later */ sh_info will be updated later */
s->sh_addralign = sh->sh_addralign; s->sh_addralign = sh->sh_addralign;
s->sh_entsize = sh->sh_entsize; s->sh_entsize = sh->sh_entsize;
sm_table[i].new_section = 1; sm_table[i].new_section = 1;
found: found:
if (sh->sh_type != s->sh_type) if (sh->sh_type != s->sh_type) {
error_noabort("invalid section type");
goto fail; goto fail;
}
/* align start of section */ /* align start of section */
offset = s->data_offset; offset = s->data_offset;
@ -1531,7 +1556,7 @@ static int tcc_load_object_file(TCCState *s1,
if (sh->sh_type == SHT_REL) { if (sh->sh_type == SHT_REL) {
s->sh_info = sm_table[sh->sh_info].s->sh_num; s->sh_info = sm_table[sh->sh_info].s->sh_num;
/* update backward link */ /* update backward link */
sections[s->sh_info]->reloc = s; s1->sections[s->sh_info]->reloc = s;
} }
} }
@ -1584,7 +1609,8 @@ static int tcc_load_object_file(TCCState *s1,
sym_index = old_to_new_syms[sym_index]; sym_index = old_to_new_syms[sym_index];
if (!sym_index) { if (!sym_index) {
invalid_reloc: invalid_reloc:
error("Invalid relocation entry"); error_noabort("Invalid relocation entry");
goto fail;
} }
rel->r_info = ELF32_R_INFO(sym_index, type); rel->r_info = ELF32_R_INFO(sym_index, type);
/* offset the relocation offset */ /* offset the relocation offset */
@ -1595,12 +1621,16 @@ static int tcc_load_object_file(TCCState *s1,
break; break;
} }
} }
ret = 0;
the_end:
tcc_free(symtab); tcc_free(symtab);
tcc_free(strtab); tcc_free(strtab);
tcc_free(old_to_new_syms); tcc_free(old_to_new_syms);
tcc_free(sm_table); tcc_free(sm_table);
tcc_free(strsec);
tcc_free(shdr); tcc_free(shdr);
return 0; return ret;
} }
#define ARMAG "!<arch>\012" /* For COFF and a.out archives */ #define ARMAG "!<arch>\012" /* For COFF and a.out archives */
@ -1632,8 +1662,10 @@ static int tcc_load_archive(TCCState *s1, int fd)
len = read(fd, &hdr, sizeof(hdr)); len = read(fd, &hdr, sizeof(hdr));
if (len == 0) if (len == 0)
break; break;
if (len != sizeof(hdr)) if (len != sizeof(hdr)) {
error("invalid archive"); error_noabort("invalid archive");
return -1;
}
memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size)); memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
ar_size[sizeof(hdr.ar_size)] = '\0'; ar_size[sizeof(hdr.ar_size)] = '\0';
size = strtol(ar_size, NULL, 0); size = strtol(ar_size, NULL, 0);
@ -1652,7 +1684,8 @@ static int tcc_load_archive(TCCState *s1, int fd)
!strcmp(ar_name, "ARFILENAMES/")) { !strcmp(ar_name, "ARFILENAMES/")) {
/* skip symbol table or archive names */ /* skip symbol table or archive names */
} else { } else {
tcc_load_object_file(s1, fd, file_offset); if (tcc_load_object_file(s1, fd, file_offset) < 0)
return -1;
} }
/* align to even */ /* align to even */
size = (size + 1) & ~1; size = (size + 1) & ~1;
@ -1668,7 +1701,7 @@ static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
{ {
Elf32_Ehdr ehdr; Elf32_Ehdr ehdr;
Elf32_Shdr *shdr, *sh, *sh1; Elf32_Shdr *shdr, *sh, *sh1;
int i, nb_syms, nb_dts, sym_bind; int i, nb_syms, nb_dts, sym_bind, ret;
Elf32_Sym *sym, *dynsym; Elf32_Sym *sym, *dynsym;
Elf32_Dyn *dt, *dynamic; Elf32_Dyn *dt, *dynamic;
unsigned char *dynstr; unsigned char *dynstr;
@ -1679,8 +1712,10 @@ static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
/* test CPU specific stuff */ /* test CPU specific stuff */
if (ehdr.e_ident[5] != ELFDATA2LSB || if (ehdr.e_ident[5] != ELFDATA2LSB ||
ehdr.e_machine != EM_386) ehdr.e_machine != EM_386) {
error("bad architecture"); error_noabort("bad architecture");
return -1;
}
/* read sections */ /* read sections */
shdr = load_data(fd, ehdr.e_shoff, sizeof(Elf32_Shdr) * ehdr.e_shnum); shdr = load_data(fd, ehdr.e_shoff, sizeof(Elf32_Shdr) * ehdr.e_shnum);
@ -1721,12 +1756,13 @@ static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
} }
/* if the dll is already loaded, do not load it */ /* if the dll is already loaded, do not load it */
for(i = 0; i < nb_loaded_dlls; i++) { for(i = 0; i < s1->nb_loaded_dlls; i++) {
dllref = loaded_dlls[i]; dllref = s1->loaded_dlls[i];
if (!strcmp(soname, dllref->name)) { if (!strcmp(soname, dllref->name)) {
/* but update level if needed */ /* but update level if needed */
if (level < dllref->level) if (level < dllref->level)
dllref->level = level; dllref->level = level;
ret = 0;
goto the_end; goto the_end;
} }
} }
@ -1737,7 +1773,7 @@ static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
dllref = tcc_malloc(sizeof(DLLReference) + strlen(soname)); dllref = tcc_malloc(sizeof(DLLReference) + strlen(soname));
dllref->level = level; dllref->level = level;
strcpy(dllref->name, soname); strcpy(dllref->name, soname);
dynarray_add((void ***)&loaded_dlls, &nb_loaded_dlls, dllref); dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
/* add dynamic symbols in dynsym_section */ /* add dynamic symbols in dynsym_section */
for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) { for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
@ -1745,7 +1781,7 @@ static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
if (sym_bind == STB_LOCAL) if (sym_bind == STB_LOCAL)
continue; continue;
name = dynstr + sym->st_name; name = dynstr + sym->st_name;
add_elf_sym(dynsymtab_section, sym->st_value, sym->st_size, add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
sym->st_info, sym->st_shndx, name); sym->st_info, sym->st_shndx, name);
} }
@ -1754,20 +1790,27 @@ static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
switch(dt->d_tag) { switch(dt->d_tag) {
case DT_NEEDED: case DT_NEEDED:
name = dynstr + dt->d_un.d_val; name = dynstr + dt->d_un.d_val;
for(i = 0; i < nb_loaded_dlls; i++) { for(i = 0; i < s1->nb_loaded_dlls; i++) {
dllref = loaded_dlls[i]; dllref = s1->loaded_dlls[i];
if (!strcmp(name, dllref->name)) if (!strcmp(name, dllref->name))
goto already_loaded; goto already_loaded;
} }
if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
error("referenced dll '%s' not found", name); error_noabort("referenced dll '%s' not found", name);
ret = -1;
goto the_end;
}
already_loaded: already_loaded:
break; break;
} }
} }
ret = 0;
the_end: the_end:
tcc_free(dynstr);
tcc_free(dynsym);
tcc_free(dynamic);
tcc_free(shdr); tcc_free(shdr);
return 0; return ret;
} }
/* return -2 if error and CH_EOF if eof */ /* return -2 if error and CH_EOF if eof */
@ -1833,7 +1876,8 @@ static int tcc_load_ldscript(TCCState *s1)
cinp(); cinp();
break; break;
} else if (ch == CH_EOF) { } else if (ch == CH_EOF) {
error("unexpected end of file"); error_noabort("unexpected end of file");
return -1;
} }
} }
} else { } else {
@ -1842,4 +1886,3 @@ static int tcc_load_ldscript(TCCState *s1)
} }
return 0; return 0;
} }