mirror of
https://github.com/frida/tinycc
synced 2024-11-28 10:33:07 +03:00
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:
parent
88c9f1bb4e
commit
55f751ac6d
118
tccelf.c
118
tccelf.c
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user