mirror of
https://github.com/mirror/tinycc.git
synced 2025-03-02 08:20:06 +08: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
599677a5e2
commit
3cbc7a2dcc
114
tccelf.c
114
tccelf.c
@ -330,6 +330,12 @@ ST_FUNC void put_stabd(int type, int other, int desc)
|
|||||||
put_stabs(NULL, type, other, desc, 0);
|
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
|
/* 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 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
|
||||||
@ -340,7 +346,7 @@ static void sort_syms(TCCState *s1, Section *s)
|
|||||||
ElfW(Sym) *new_syms;
|
ElfW(Sym) *new_syms;
|
||||||
int nb_syms, i;
|
int nb_syms, i;
|
||||||
ElfW(Sym) *p, *q;
|
ElfW(Sym) *p, *q;
|
||||||
ElfW_Rel *rel, *rel_end;
|
ElfW_Rel *rel;
|
||||||
Section *sr;
|
Section *sr;
|
||||||
int type, sym_index;
|
int type, sym_index;
|
||||||
|
|
||||||
@ -379,10 +385,7 @@ static void sort_syms(TCCState *s1, Section *s)
|
|||||||
for(i = 1; i < s1->nb_sections; i++) {
|
for(i = 1; i < s1->nb_sections; i++) {
|
||||||
sr = s1->sections[i];
|
sr = s1->sections[i];
|
||||||
if (sr->sh_type == SHT_RELX && sr->link == s) {
|
if (sr->sh_type == SHT_RELX && sr->link == s) {
|
||||||
rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
|
for_each_elem(sr, 0, rel, ElfW_Rel) {
|
||||||
for(rel = (ElfW_Rel *)sr->data;
|
|
||||||
rel < rel_end;
|
|
||||||
rel++) {
|
|
||||||
sym_index = ELFW(R_SYM)(rel->r_info);
|
sym_index = ELFW(R_SYM)(rel->r_info);
|
||||||
type = ELFW(R_TYPE)(rel->r_info);
|
type = ELFW(R_TYPE)(rel->r_info);
|
||||||
sym_index = old_to_new_syms[sym_index];
|
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 */
|
/* relocate common symbols in the .bss section */
|
||||||
ST_FUNC void relocate_common_syms(void)
|
ST_FUNC void relocate_common_syms(void)
|
||||||
{
|
{
|
||||||
ElfW(Sym) *sym, *sym_end;
|
ElfW(Sym) *sym;
|
||||||
unsigned long offset, align;
|
unsigned long offset, align;
|
||||||
|
|
||||||
sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
|
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
|
||||||
for(sym = (ElfW(Sym) *)symtab_section->data + 1;
|
|
||||||
sym < sym_end;
|
|
||||||
sym++) {
|
|
||||||
if (sym->st_shndx == SHN_COMMON) {
|
if (sym->st_shndx == SHN_COMMON) {
|
||||||
/* align symbol */
|
/* align symbol */
|
||||||
align = sym->st_value;
|
align = sym->st_value;
|
||||||
@ -421,14 +421,11 @@ ST_FUNC void relocate_common_syms(void)
|
|||||||
true and output error if undefined symbol. */
|
true and output error if undefined symbol. */
|
||||||
ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
|
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;
|
int sym_bind, sh_num, sym_index;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
|
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
|
||||||
for(sym = (ElfW(Sym) *)symtab_section->data + 1;
|
|
||||||
sym < sym_end;
|
|
||||||
sym++) {
|
|
||||||
sh_num = sym->st_shndx;
|
sh_num = sym->st_shndx;
|
||||||
if (sh_num == SHN_UNDEF) {
|
if (sh_num == SHN_UNDEF) {
|
||||||
name = strtab_section->data + sym->st_name;
|
name = strtab_section->data + sym->st_name;
|
||||||
@ -511,7 +508,7 @@ static addr_t add_jmp_table(TCCState *s1, int val)
|
|||||||
ST_FUNC void relocate_section(TCCState *s1, Section *s)
|
ST_FUNC void relocate_section(TCCState *s1, Section *s)
|
||||||
{
|
{
|
||||||
Section *sr;
|
Section *sr;
|
||||||
ElfW_Rel *rel, *rel_end, *qrel;
|
ElfW_Rel *rel;
|
||||||
ElfW(Sym) *sym;
|
ElfW(Sym) *sym;
|
||||||
int type, sym_index;
|
int type, sym_index;
|
||||||
unsigned char *ptr;
|
unsigned char *ptr;
|
||||||
@ -521,11 +518,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
sr = s->reloc;
|
sr = s->reloc;
|
||||||
rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
|
for_each_elem(sr, 0, rel, ElfW_Rel) {
|
||||||
qrel = (ElfW_Rel *)sr->data;
|
|
||||||
for(rel = qrel;
|
|
||||||
rel < rel_end;
|
|
||||||
rel++) {
|
|
||||||
ptr = s->data + rel->r_offset;
|
ptr = s->data + rel->r_offset;
|
||||||
|
|
||||||
sym_index = ELFW(R_SYM)(rel->r_info);
|
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)
|
static void relocate_rel(TCCState *s1, Section *sr)
|
||||||
{
|
{
|
||||||
Section *s;
|
Section *s;
|
||||||
ElfW_Rel *rel, *rel_end;
|
ElfW_Rel *rel;
|
||||||
|
|
||||||
s = s1->sections[sr->sh_info];
|
s = s1->sections[sr->sh_info];
|
||||||
rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
|
for_each_elem(sr, 0, rel, ElfW_Rel)
|
||||||
for(rel = (ElfW_Rel *)sr->data;
|
|
||||||
rel < rel_end;
|
|
||||||
rel++) {
|
|
||||||
rel->r_offset += s->sh_addr;
|
rel->r_offset += s->sh_addr;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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(TCCState *s1, Section *sr)
|
static int prepare_dynamic_rel(TCCState *s1, Section *sr)
|
||||||
{
|
{
|
||||||
ElfW_Rel *rel, *rel_end;
|
ElfW_Rel *rel;
|
||||||
int sym_index, esym_index, type, count;
|
int sym_index, esym_index, type, count;
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
|
for_each_elem(sr, 0, rel, ElfW_Rel) {
|
||||||
for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
|
|
||||||
sym_index = ELFW(R_SYM)(rel->r_info);
|
sym_index = ELFW(R_SYM)(rel->r_info);
|
||||||
type = ELFW(R_TYPE)(rel->r_info);
|
type = ELFW(R_TYPE)(rel->r_info);
|
||||||
switch(type) {
|
switch(type) {
|
||||||
@ -1145,7 +1133,7 @@ static void put_got_entry(TCCState *s1,
|
|||||||
ST_FUNC void build_got_entries(TCCState *s1)
|
ST_FUNC void build_got_entries(TCCState *s1)
|
||||||
{
|
{
|
||||||
Section *s;
|
Section *s;
|
||||||
ElfW_Rel *rel, *rel_end;
|
ElfW_Rel *rel;
|
||||||
ElfW(Sym) *sym;
|
ElfW(Sym) *sym;
|
||||||
int i, type, reloc_type, sym_index;
|
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 */
|
/* no need to handle got relocations */
|
||||||
if (s->link != symtab_section)
|
if (s->link != symtab_section)
|
||||||
continue;
|
continue;
|
||||||
rel_end = (ElfW_Rel *)(s->data + s->data_offset);
|
for_each_elem(s, 0, rel, ElfW_Rel) {
|
||||||
for(rel = (ElfW_Rel *)s->data;
|
|
||||||
rel < rel_end;
|
|
||||||
rel++) {
|
|
||||||
type = ELFW(R_TYPE)(rel->r_info);
|
type = ELFW(R_TYPE)(rel->r_info);
|
||||||
switch(type) {
|
switch(type) {
|
||||||
#if defined(TCC_TARGET_I386)
|
#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)
|
void patch_dynsym_undef(TCCState *s1, Section *s)
|
||||||
{
|
{
|
||||||
uint32_t *gotd = (void *)s1->got->data;
|
uint32_t *gotd = (void *)s1->got->data;
|
||||||
ElfW(Sym) *sym, *sym_end;
|
ElfW(Sym) *sym;
|
||||||
|
|
||||||
gotd += 3; /* dummy entries in .got */
|
gotd += 3; /* dummy entries in .got */
|
||||||
/* relocate symbols in .dynsym */
|
/* relocate symbols in .dynsym */
|
||||||
sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
|
for_each_elem(s, 1, sym, ElfW(Sym)) {
|
||||||
for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
|
|
||||||
if (sym->st_shndx == SHN_UNDEF) {
|
if (sym->st_shndx == SHN_UNDEF) {
|
||||||
*gotd++ = sym->st_value + 6; /* XXX 6 is magic ? */
|
*gotd++ = sym->st_value + 6; /* XXX 6 is magic ? */
|
||||||
sym->st_value = 0;
|
sym->st_value = 0;
|
||||||
@ -1485,10 +1469,9 @@ void patch_dynsym_undef(TCCState *s1, Section *s)
|
|||||||
/* zero plt offsets of weak symbols in .dynsym */
|
/* zero plt offsets of weak symbols in .dynsym */
|
||||||
void patch_dynsym_undef(TCCState *s1, Section *s)
|
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_each_elem(s, 1, sym, ElfW(Sym))
|
||||||
for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++)
|
|
||||||
if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
|
if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
|
||||||
sym->st_value = 0;
|
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)
|
ST_FUNC void fill_got(TCCState *s1)
|
||||||
{
|
{
|
||||||
Section *s;
|
Section *s;
|
||||||
ElfW_Rel *rel, *rel_end;
|
ElfW_Rel *rel;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for(i = 1; i < s1->nb_sections; 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 */
|
/* no need to handle got relocations */
|
||||||
if (s->link != symtab_section)
|
if (s->link != symtab_section)
|
||||||
continue;
|
continue;
|
||||||
rel_end = (ElfW_Rel *) (s->data + s->data_offset);
|
for_each_elem(s, 0, rel, ElfW_Rel) {
|
||||||
for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
|
|
||||||
switch (ELFW(R_TYPE) (rel->r_info)) {
|
switch (ELFW(R_TYPE) (rel->r_info)) {
|
||||||
case R_X86_64_GOT32:
|
case R_X86_64_GOT32:
|
||||||
case R_X86_64_GOTPCREL:
|
case R_X86_64_GOTPCREL:
|
||||||
@ -1583,7 +1565,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
|||||||
if (!s1->static_link) {
|
if (!s1->static_link) {
|
||||||
const char *name;
|
const char *name;
|
||||||
int sym_index, index;
|
int sym_index, index;
|
||||||
ElfW(Sym) *esym, *sym_end;
|
ElfW(Sym) *esym;
|
||||||
|
|
||||||
if (file_type == TCC_OUTPUT_EXE) {
|
if (file_type == TCC_OUTPUT_EXE) {
|
||||||
char *ptr;
|
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
|
is found, then we add it in the PLT. If a symbol
|
||||||
STT_OBJECT is found, we add it in the .bss section with
|
STT_OBJECT is found, we add it in the .bss section with
|
||||||
a suitable relocation */
|
a suitable relocation */
|
||||||
sym_end = (ElfW(Sym) *)(symtab_section->data +
|
|
||||||
symtab_section->data_offset);
|
|
||||||
if (file_type == TCC_OUTPUT_EXE) {
|
if (file_type == TCC_OUTPUT_EXE) {
|
||||||
for(sym = (ElfW(Sym) *)symtab_section->data + 1;
|
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
|
||||||
sym < sym_end;
|
|
||||||
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(s1->dynsymtab_section, 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);
|
sym - (ElfW(Sym) *)symtab_section->data);
|
||||||
} else if (type == STT_OBJECT) {
|
} else if (type == STT_OBJECT) {
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
ElfW(Sym) *dynsym, *dynsym_end;
|
ElfW(Sym) *dynsym;
|
||||||
offset = bss_section->data_offset;
|
offset = bss_section->data_offset;
|
||||||
/* XXX: which alignment ? */
|
/* XXX: which alignment ? */
|
||||||
offset = (offset + 16 - 1) & -16;
|
offset = (offset + 16 - 1) & -16;
|
||||||
@ -1657,11 +1635,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
|||||||
bss_section->sh_num, name);
|
bss_section->sh_num, name);
|
||||||
/* Ensure R_COPY works for weak symbol aliases */
|
/* Ensure R_COPY works for weak symbol aliases */
|
||||||
if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
|
if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
|
||||||
dynsym_end = (ElfW(Sym) *)
|
for_each_elem(s1->dynsymtab_section, 1, dynsym, ElfW(Sym)) {
|
||||||
(s1->dynsymtab_section->data +
|
|
||||||
s1->dynsymtab_section->data_offset);
|
|
||||||
for(dynsym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
|
|
||||||
dynsym < dynsym_end; dynsym++) {
|
|
||||||
if ((dynsym->st_value == esym->st_value)
|
if ((dynsym->st_value == esym->st_value)
|
||||||
&& (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
|
&& (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
|
||||||
char *dynname;
|
char *dynname;
|
||||||
@ -1707,11 +1681,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
|||||||
|
|
||||||
/* now look at unresolved dynamic symbols and export
|
/* now look at unresolved dynamic symbols and export
|
||||||
corresponding symbol */
|
corresponding symbol */
|
||||||
sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
|
for_each_elem(s1->dynsymtab_section, 1, esym, ElfW(Sym)) {
|
||||||
s1->dynsymtab_section->data_offset);
|
|
||||||
for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
|
|
||||||
esym < sym_end;
|
|
||||||
esym++) {
|
|
||||||
if (esym->st_shndx == SHN_UNDEF) {
|
if (esym->st_shndx == SHN_UNDEF) {
|
||||||
name = s1->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);
|
||||||
@ -1736,9 +1706,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
|||||||
/* 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(ElfW(Sym));
|
nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
|
||||||
s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
|
s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
|
||||||
for(sym = (ElfW(Sym) *)symtab_section->data + 1;
|
for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
|
||||||
sym < sym_end;
|
|
||||||
sym++) {
|
|
||||||
if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
|
if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
|
||||||
#if defined(TCC_OUTPUT_DLL_WITH_PLT)
|
#if defined(TCC_OUTPUT_DLL_WITH_PLT)
|
||||||
if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
|
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 section, then add corresponing program header */
|
||||||
if (dynamic) {
|
if (dynamic) {
|
||||||
ElfW(Sym) *sym_end;
|
|
||||||
|
|
||||||
ph = &phdr[phnum - 1];
|
ph = &phdr[phnum - 1];
|
||||||
|
|
||||||
ph->p_type = PT_DYNAMIC;
|
ph->p_type = PT_DYNAMIC;
|
||||||
@ -2090,10 +2056,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* relocate symbols in .dynsym */
|
/* relocate symbols in .dynsym */
|
||||||
sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
|
for_each_elem(s1->dynsym, 1, sym, ElfW(Sym)) {
|
||||||
for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
|
|
||||||
sym < sym_end;
|
|
||||||
sym++) {
|
|
||||||
if (sym->st_shndx == SHN_UNDEF) {
|
if (sym->st_shndx == SHN_UNDEF) {
|
||||||
/* relocate to the PLT if the symbol corresponds
|
/* relocate to the PLT if the symbol corresponds
|
||||||
to a PLT entry */
|
to a PLT entry */
|
||||||
@ -2365,7 +2328,7 @@ ST_FUNC int tcc_load_object_file(TCCState *s1,
|
|||||||
char *sh_name, *name;
|
char *sh_name, *name;
|
||||||
SectionMergeInfo *sm_table, *sm;
|
SectionMergeInfo *sm_table, *sm;
|
||||||
ElfW(Sym) *sym, *symtab;
|
ElfW(Sym) *sym, *symtab;
|
||||||
ElfW_Rel *rel, *rel_end;
|
ElfW_Rel *rel;
|
||||||
Section *s;
|
Section *s;
|
||||||
|
|
||||||
int stab_index;
|
int stab_index;
|
||||||
@ -2585,10 +2548,7 @@ ST_FUNC int tcc_load_object_file(TCCState *s1,
|
|||||||
case SHT_RELX:
|
case SHT_RELX:
|
||||||
/* take relocation offset information */
|
/* take relocation offset information */
|
||||||
offseti = sm_table[sh->sh_info].offset;
|
offseti = sm_table[sh->sh_info].offset;
|
||||||
rel_end = (ElfW_Rel *)(s->data + s->data_offset);
|
for_each_elem(s, (offset / sizeof(*rel)), rel, ElfW_Rel) {
|
||||||
for(rel = (ElfW_Rel *)(s->data + offset);
|
|
||||||
rel < rel_end;
|
|
||||||
rel++) {
|
|
||||||
int type;
|
int type;
|
||||||
unsigned sym_index;
|
unsigned sym_index;
|
||||||
/* convert symbol index */
|
/* convert symbol index */
|
||||||
|
Loading…
Reference in New Issue
Block a user