Add macro to browse reloc and sym entries

Introduce for_each_elem to browse relocation entries and symbols of a
section.
This commit is contained in:
Thomas Preud'homme 2013-12-17 21:02:51 +08:00
parent 88c9f1bb4e
commit 55f751ac6d

118
tccelf.c
View File

@ -330,6 +330,12 @@ ST_FUNC void put_stabd(int type, int other, int desc)
put_stabs(NULL, type, other, desc, 0);
}
/* Browse each elem of type <type> in section <sec> starting at elem <startoff>
using variable <elem> */
#define for_each_elem(sec, startoff, elem, type) \
for (elem = (type *) sec->data + startoff; \
elem < (type *) (sec->data + sec->data_offset); elem++)
/* In an ELF file symbol table, the local symbols must appear below
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
@ -340,7 +346,7 @@ static void sort_syms(TCCState *s1, Section *s)
ElfW(Sym) *new_syms;
int nb_syms, i;
ElfW(Sym) *p, *q;
ElfW_Rel *rel, *rel_end;
ElfW_Rel *rel;
Section *sr;
int type, sym_index;
@ -379,10 +385,7 @@ static void sort_syms(TCCState *s1, Section *s)
for(i = 1; i < s1->nb_sections; i++) {
sr = s1->sections[i];
if (sr->sh_type == SHT_RELX && sr->link == s) {
rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
for(rel = (ElfW_Rel *)sr->data;
rel < rel_end;
rel++) {
for_each_elem(sr, 0, rel, ElfW_Rel) {
sym_index = ELFW(R_SYM)(rel->r_info);
type = ELFW(R_TYPE)(rel->r_info);
sym_index = old_to_new_syms[sym_index];
@ -397,13 +400,10 @@ static void sort_syms(TCCState *s1, Section *s)
/* relocate common symbols in the .bss section */
ST_FUNC void relocate_common_syms(void)
{
ElfW(Sym) *sym, *sym_end;
ElfW(Sym) *sym;
unsigned long offset, align;
sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
for(sym = (ElfW(Sym) *)symtab_section->data + 1;
sym < sym_end;
sym++) {
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
if (sym->st_shndx == SHN_COMMON) {
/* align symbol */
align = sym->st_value;
@ -421,14 +421,11 @@ ST_FUNC void relocate_common_syms(void)
true and output error if undefined symbol. */
ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
{
ElfW(Sym) *sym, *esym, *sym_end;
ElfW(Sym) *sym, *esym;
int sym_bind, sh_num, sym_index;
const char *name;
sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
for(sym = (ElfW(Sym) *)symtab_section->data + 1;
sym < sym_end;
sym++) {
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
sh_num = sym->st_shndx;
if (sh_num == SHN_UNDEF) {
name = strtab_section->data + sym->st_name;
@ -510,22 +507,18 @@ static addr_t add_jmp_table(TCCState *s1, int val)
/* relocate a given section (CPU dependent) */
ST_FUNC void relocate_section(TCCState *s1, Section *s)
{
Section *sr;
ElfW_Rel *rel, *rel_end, *qrel;
Section *sr = s->reloc;
ElfW_Rel *rel;
ElfW(Sym) *sym;
int type, sym_index;
unsigned char *ptr;
addr_t val, addr;
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
ElfW_Rel *qrel = (ElfW_Rel *) sr->data; /* ptr to next reloc entry reused */
int esym_index;
#endif
sr = s->reloc;
rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
qrel = (ElfW_Rel *)sr->data;
for(rel = qrel;
rel < rel_end;
rel++) {
for_each_elem(sr, 0, rel, ElfW_Rel) {
ptr = s->data + rel->r_offset;
sym_index = ELFW(R_SYM)(rel->r_info);
@ -893,27 +886,22 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
static void relocate_rel(TCCState *s1, Section *sr)
{
Section *s;
ElfW_Rel *rel, *rel_end;
ElfW_Rel *rel;
s = s1->sections[sr->sh_info];
rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
for(rel = (ElfW_Rel *)sr->data;
rel < rel_end;
rel++) {
for_each_elem(sr, 0, rel, ElfW_Rel)
rel->r_offset += s->sh_addr;
}
}
/* count the number of dynamic relocations so that we can reserve
their space */
static int prepare_dynamic_rel(TCCState *s1, Section *sr)
{
ElfW_Rel *rel, *rel_end;
ElfW_Rel *rel;
int sym_index, esym_index, type, count;
count = 0;
rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
for_each_elem(sr, 0, rel, ElfW_Rel) {
sym_index = ELFW(R_SYM)(rel->r_info);
type = ELFW(R_TYPE)(rel->r_info);
switch(type) {
@ -1145,7 +1133,7 @@ static void put_got_entry(TCCState *s1,
ST_FUNC void build_got_entries(TCCState *s1)
{
Section *s;
ElfW_Rel *rel, *rel_end;
ElfW_Rel *rel;
ElfW(Sym) *sym;
int i, type, reloc_type, sym_index;
@ -1156,10 +1144,7 @@ ST_FUNC void build_got_entries(TCCState *s1)
/* 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++) {
for_each_elem(s, 0, rel, ElfW_Rel) {
type = ELFW(R_TYPE)(rel->r_info);
switch(type) {
#if defined(TCC_TARGET_I386)
@ -1466,12 +1451,11 @@ static void tcc_output_binary(TCCState *s1, FILE *f,
void patch_dynsym_undef(TCCState *s1, Section *s)
{
uint32_t *gotd = (void *)s1->got->data;
ElfW(Sym) *sym, *sym_end;
ElfW(Sym) *sym;
gotd += 3; /* dummy entries in .got */
/* relocate symbols in .dynsym */
sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
for_each_elem(s, 1, sym, ElfW(Sym)) {
if (sym->st_shndx == SHN_UNDEF) {
*gotd++ = sym->st_value + 6; /* XXX 6 is magic ? */
sym->st_value = 0;
@ -1485,10 +1469,9 @@ void patch_dynsym_undef(TCCState *s1, Section *s)
/* zero plt offsets of weak symbols in .dynsym */
void patch_dynsym_undef(TCCState *s1, Section *s)
{
ElfW(Sym) *sym, *sym_end;
ElfW(Sym) *sym;
sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++)
for_each_elem(s, 1, sym, ElfW(Sym))
if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
sym->st_value = 0;
}
@ -1514,7 +1497,7 @@ ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
ST_FUNC void fill_got(TCCState *s1)
{
Section *s;
ElfW_Rel *rel, *rel_end;
ElfW_Rel *rel;
int i;
for(i = 1; i < s1->nb_sections; i++) {
@ -1524,8 +1507,7 @@ ST_FUNC void fill_got(TCCState *s1)
/* 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++) {
for_each_elem(s, 0, rel, ElfW_Rel) {
switch (ELFW(R_TYPE) (rel->r_info)) {
case R_X86_64_GOT32:
case R_X86_64_GOTPCREL:
@ -1583,7 +1565,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
if (!s1->static_link) {
const char *name;
int sym_index, index;
ElfW(Sym) *esym, *sym_end;
ElfW(Sym) *esym;
if (file_type == TCC_OUTPUT_EXE) {
char *ptr;
@ -1622,12 +1604,8 @@ static int elf_output_file(TCCState *s1, const char *filename)
is found, then we add it in the PLT. If a symbol
STT_OBJECT is found, we add it in the .bss section with
a suitable relocation */
sym_end = (ElfW(Sym) *)(symtab_section->data +
symtab_section->data_offset);
if (file_type == TCC_OUTPUT_EXE) {
for(sym = (ElfW(Sym) *)symtab_section->data + 1;
sym < sym_end;
sym++) {
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
if (sym->st_shndx == SHN_UNDEF) {
name = symtab_section->link->data + sym->st_name;
sym_index = find_elf_sym(s1->dynsymtab_section, name);
@ -1648,7 +1626,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
sym - (ElfW(Sym) *)symtab_section->data);
} else if (type == STT_OBJECT) {
unsigned long offset;
ElfW(Sym) *dynsym, *dynsym_end;
ElfW(Sym) *dynsym;
offset = bss_section->data_offset;
/* XXX: which alignment ? */
offset = (offset + 16 - 1) & -16;
@ -1657,11 +1635,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
bss_section->sh_num, name);
/* Ensure R_COPY works for weak symbol aliases */
if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
dynsym_end = (ElfW(Sym) *)
(s1->dynsymtab_section->data +
s1->dynsymtab_section->data_offset);
for(dynsym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
dynsym < dynsym_end; dynsym++) {
for_each_elem(s1->dynsymtab_section, 1, dynsym, ElfW(Sym)) {
if ((dynsym->st_value == esym->st_value)
&& (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
char *dynname;
@ -1707,11 +1681,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
/* now look at unresolved dynamic symbols and export
corresponding symbol */
sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
s1->dynsymtab_section->data_offset);
for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
esym < sym_end;
esym++) {
for_each_elem(s1->dynsymtab_section, 1, esym, ElfW(Sym)) {
if (esym->st_shndx == SHN_UNDEF) {
name = s1->dynsymtab_section->link->data + esym->st_name;
sym_index = find_elf_sym(symtab_section, name);
@ -1736,9 +1706,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
/* shared library case : we simply export all the global symbols */
nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
for(sym = (ElfW(Sym) *)symtab_section->data + 1;
sym < sym_end;
sym++) {
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
#if defined(TCC_OUTPUT_DLL_WITH_PLT)
if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
@ -2027,8 +1995,6 @@ static int elf_output_file(TCCState *s1, const char *filename)
/* if dynamic section, then add corresponing program header */
if (dynamic) {
ElfW(Sym) *sym_end;
ph = &phdr[phnum - 1];
ph->p_type = PT_DYNAMIC;
@ -2090,10 +2056,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
}
/* relocate symbols in .dynsym */
sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
sym < sym_end;
sym++) {
for_each_elem(s1->dynsym, 1, sym, ElfW(Sym)) {
if (sym->st_shndx == SHN_UNDEF) {
/* relocate to the PLT if the symbol corresponds
to a PLT entry */
@ -2365,7 +2328,7 @@ ST_FUNC int tcc_load_object_file(TCCState *s1,
char *sh_name, *name;
SectionMergeInfo *sm_table, *sm;
ElfW(Sym) *sym, *symtab;
ElfW_Rel *rel, *rel_end;
ElfW_Rel *rel;
Section *s;
int stab_index;
@ -2585,10 +2548,7 @@ ST_FUNC int tcc_load_object_file(TCCState *s1,
case SHT_RELX:
/* take relocation offset information */
offseti = sm_table[sh->sh_info].offset;
rel_end = (ElfW_Rel *)(s->data + s->data_offset);
for(rel = (ElfW_Rel *)(s->data + offset);
rel < rel_end;
rel++) {
for_each_elem(s, (offset / sizeof(*rel)), rel, ElfW_Rel) {
int type;
unsigned sym_index;
/* convert symbol index */