tccelf: use plt-reloc instead of relocplt
This commit is contained in:
parent
e4f151c4cd
commit
02795106e1
10 changed files with 108 additions and 163 deletions
10
arm-link.c
10
arm-link.c
|
@ -167,15 +167,11 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s1->got->relocplt) {
|
if (s1->plt->reloc) {
|
||||||
int mem = s1->output_type == TCC_OUTPUT_MEMORY;
|
|
||||||
ElfW_Rel *rel;
|
ElfW_Rel *rel;
|
||||||
|
|
||||||
p = s1->got->data;
|
p = s1->got->data;
|
||||||
for_each_elem(s1->got->relocplt, 0, rel, ElfW_Rel) {
|
for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
|
||||||
int sym_index = ELFW(R_SYM)(rel->r_info);
|
write32le(p + rel->r_offset, s1->plt->sh_addr);
|
||||||
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
|
||||||
write32le(p + rel->r_offset, mem ? sym->st_value : s1->plt->sh_addr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
10
arm64-link.c
10
arm64-link.c
|
@ -155,15 +155,11 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s1->got->relocplt) {
|
if (s1->plt->reloc) {
|
||||||
int mem = s1->output_type == TCC_OUTPUT_MEMORY;
|
|
||||||
ElfW_Rel *rel;
|
ElfW_Rel *rel;
|
||||||
|
|
||||||
p = s1->got->data;
|
p = s1->got->data;
|
||||||
for_each_elem(s1->got->relocplt, 0, rel, ElfW_Rel) {
|
for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
|
||||||
int sym_index = ELFW(R_SYM)(rel->r_info);
|
write64le(p + rel->r_offset, s1->plt->sh_addr);
|
||||||
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
|
||||||
write64le(p + rel->r_offset, mem ? sym->st_value : s1->plt->sh_addr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
12
i386-link.c
12
i386-link.c
|
@ -121,7 +121,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
|
||||||
/* The PLT slot refers to the relocation entry it needs via offset.
|
/* The PLT slot refers to the relocation entry it needs via offset.
|
||||||
The reloc entry is created below, so its offset is the current
|
The reloc entry is created below, so its offset is the current
|
||||||
data_offset */
|
data_offset */
|
||||||
relofs = s1->got->relocplt ? s1->got->relocplt->data_offset : 0;
|
relofs = s1->plt->reloc ? s1->plt->reloc->data_offset : 0;
|
||||||
|
|
||||||
/* Jump to GOT entry where ld.so initially put the address of ip + 4 */
|
/* Jump to GOT entry where ld.so initially put the address of ip + 4 */
|
||||||
p = section_ptr_add(plt, 16);
|
p = section_ptr_add(plt, 16);
|
||||||
|
@ -157,16 +157,12 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s1->got->relocplt) {
|
if (s1->plt->reloc) {
|
||||||
int mem = s1->output_type == TCC_OUTPUT_MEMORY;
|
|
||||||
ElfW_Rel *rel;
|
ElfW_Rel *rel;
|
||||||
int x = s1->plt->sh_addr + 16 + 6;
|
int x = s1->plt->sh_addr + 16 + 6;
|
||||||
|
|
||||||
p = s1->got->data;
|
p = s1->got->data;
|
||||||
for_each_elem(s1->got->relocplt, 0, rel, ElfW_Rel) {
|
for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
|
||||||
int sym_index = ELFW(R_SYM)(rel->r_info);
|
write32le(p + rel->r_offset, x);
|
||||||
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
|
||||||
write32le(p + rel->r_offset, mem ? sym->st_value : x);
|
|
||||||
x += 16;
|
x += 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,15 +154,11 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s1->got->relocplt) {
|
if (s1->plt->reloc) {
|
||||||
int mem = s1->output_type == TCC_OUTPUT_MEMORY;
|
|
||||||
ElfW_Rel *rel;
|
ElfW_Rel *rel;
|
||||||
|
|
||||||
p = s1->got->data;
|
p = s1->got->data;
|
||||||
for_each_elem(s1->got->relocplt, 0, rel, ElfW_Rel) {
|
for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
|
||||||
int sym_index = ELFW(R_SYM)(rel->r_info);
|
write64le(p + rel->r_offset, s1->plt->sh_addr);
|
||||||
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
|
||||||
write64le(p + rel->r_offset, mem ? sym->st_value + rel->r_addend : s1->plt->sh_addr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
5
tcc.h
5
tcc.h
|
@ -423,7 +423,6 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
||||||
# define ElfW_Rel ElfW(Rela)
|
# define ElfW_Rel ElfW(Rela)
|
||||||
# define SHT_RELX SHT_RELA
|
# define SHT_RELX SHT_RELA
|
||||||
# define REL_SECTION_FMT ".rela%s"
|
# define REL_SECTION_FMT ".rela%s"
|
||||||
# define RELPLT_SECTION_FMT ".rela.plt"
|
|
||||||
#else
|
#else
|
||||||
# define ELFCLASSW ELFCLASS32
|
# define ELFCLASSW ELFCLASS32
|
||||||
# define ElfW(type) Elf##32##_##type
|
# define ElfW(type) Elf##32##_##type
|
||||||
|
@ -431,7 +430,6 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
||||||
# define ElfW_Rel ElfW(Rel)
|
# define ElfW_Rel ElfW(Rel)
|
||||||
# define SHT_RELX SHT_REL
|
# define SHT_RELX SHT_REL
|
||||||
# define REL_SECTION_FMT ".rel%s"
|
# define REL_SECTION_FMT ".rel%s"
|
||||||
# define RELPLT_SECTION_FMT ".rel.plt"
|
|
||||||
#endif
|
#endif
|
||||||
/* target address type */
|
/* target address type */
|
||||||
#define addr_t ElfW(Addr)
|
#define addr_t ElfW(Addr)
|
||||||
|
@ -593,7 +591,6 @@ typedef struct Section {
|
||||||
struct Section *reloc; /* corresponding section for relocation, if any */
|
struct Section *reloc; /* corresponding section for relocation, if any */
|
||||||
struct Section *hash; /* hash table for symbols */
|
struct Section *hash; /* hash table for symbols */
|
||||||
struct Section *prev; /* previous section on section stack */
|
struct Section *prev; /* previous section on section stack */
|
||||||
struct Section *relocplt;/* reloc with JMP_SLOTs */
|
|
||||||
char name[1]; /* section name */
|
char name[1]; /* section name */
|
||||||
} Section;
|
} Section;
|
||||||
|
|
||||||
|
@ -1588,7 +1585,7 @@ ST_FUNC void put_stabn(TCCState *s1, int type, int other, int desc, int value);
|
||||||
|
|
||||||
ST_FUNC void resolve_common_syms(TCCState *s1);
|
ST_FUNC void resolve_common_syms(TCCState *s1);
|
||||||
ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve);
|
ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve);
|
||||||
ST_FUNC void relocate_section(TCCState *s1, Section *s);
|
ST_FUNC void relocate_sections(TCCState *s1);
|
||||||
|
|
||||||
ST_FUNC ssize_t full_read(int fd, void *buf, size_t count);
|
ST_FUNC ssize_t full_read(int fd, void *buf, size_t count);
|
||||||
ST_FUNC void *load_data(int fd, unsigned long file_offset, unsigned long size);
|
ST_FUNC void *load_data(int fd, unsigned long file_offset, unsigned long size);
|
||||||
|
|
180
tccelf.c
180
tccelf.c
|
@ -737,25 +737,18 @@ ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset,
|
||||||
char buf[256];
|
char buf[256];
|
||||||
Section *sr;
|
Section *sr;
|
||||||
ElfW_Rel *rel;
|
ElfW_Rel *rel;
|
||||||
int jmp_slot = type == R_JMP_SLOT;
|
|
||||||
|
|
||||||
sr = jmp_slot ? s->relocplt : s->reloc;
|
sr = s->reloc;
|
||||||
if (!sr) {
|
if (!sr) {
|
||||||
/* if no relocation section, create it */
|
/* if no relocation section, create it */
|
||||||
if (jmp_slot)
|
snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
|
||||||
snprintf(buf, sizeof(buf), RELPLT_SECTION_FMT);
|
|
||||||
else
|
|
||||||
snprintf(buf, sizeof(buf), REL_SECTION_FMT, 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(s->s1, buf, SHT_RELX, symtab->sh_flags);
|
sr = new_section(s->s1, buf, SHT_RELX, symtab->sh_flags);
|
||||||
sr->sh_entsize = sizeof(ElfW_Rel);
|
sr->sh_entsize = sizeof(ElfW_Rel);
|
||||||
sr->link = symtab;
|
sr->link = symtab;
|
||||||
sr->sh_info = s->sh_num;
|
sr->sh_info = s->sh_num;
|
||||||
if (jmp_slot)
|
s->reloc = sr;
|
||||||
s->relocplt = sr;
|
|
||||||
else
|
|
||||||
s->reloc = sr;
|
|
||||||
}
|
}
|
||||||
rel = section_ptr_add(sr, sizeof(ElfW_Rel));
|
rel = section_ptr_add(sr, sizeof(ElfW_Rel));
|
||||||
rel->r_offset = offset;
|
rel->r_offset = offset;
|
||||||
|
@ -957,9 +950,8 @@ ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve)
|
||||||
|
|
||||||
/* relocate a given section (CPU dependent) by applying the relocations
|
/* relocate a given section (CPU dependent) by applying the relocations
|
||||||
in the associated relocation section */
|
in the associated relocation section */
|
||||||
ST_FUNC void relocate_section(TCCState *s1, Section *s)
|
static void relocate_section(TCCState *s1, Section *s, Section *sr)
|
||||||
{
|
{
|
||||||
Section *sr = s->reloc;
|
|
||||||
ElfW_Rel *rel;
|
ElfW_Rel *rel;
|
||||||
ElfW(Sym) *sym;
|
ElfW(Sym) *sym;
|
||||||
int type, sym_index;
|
int type, sym_index;
|
||||||
|
@ -967,7 +959,6 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
|
||||||
addr_t tgt, addr;
|
addr_t tgt, addr;
|
||||||
|
|
||||||
qrel = (ElfW_Rel *)sr->data;
|
qrel = (ElfW_Rel *)sr->data;
|
||||||
|
|
||||||
for_each_elem(sr, 0, rel, ElfW_Rel) {
|
for_each_elem(sr, 0, rel, ElfW_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);
|
||||||
|
@ -980,6 +971,7 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
|
||||||
addr = s->sh_addr + rel->r_offset;
|
addr = s->sh_addr + rel->r_offset;
|
||||||
relocate(s1, rel, type, ptr, addr, tgt);
|
relocate(s1, rel, type, ptr, addr, tgt);
|
||||||
}
|
}
|
||||||
|
#ifndef ELF_OBJ_ONLY
|
||||||
/* 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 = s1->dynsym;
|
sr->link = s1->dynsym;
|
||||||
|
@ -991,20 +983,37 @@ ST_FUNC void relocate_section(TCCState *s1, Section *s)
|
||||||
sr->data_offset = sr->sh_size = r;
|
sr->data_offset = sr->sh_size = r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* relocate all sections */
|
||||||
|
ST_FUNC void relocate_sections(TCCState *s1)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
Section *s, *sr;
|
||||||
|
|
||||||
|
for (i = 1; i < s1->nb_sections; ++i) {
|
||||||
|
sr = s1->sections[i];
|
||||||
|
if (sr->sh_type != SHT_RELX)
|
||||||
|
continue;
|
||||||
|
s = s1->sections[sr->sh_info];
|
||||||
|
if (s != s1->got
|
||||||
|
|| s1->static_link
|
||||||
|
|| s1->output_type == TCC_OUTPUT_MEMORY) {
|
||||||
|
relocate_section(s1, s, sr);
|
||||||
|
}
|
||||||
|
#ifndef ELF_OBJ_ONLY
|
||||||
|
if (sr->sh_flags & SHF_ALLOC) {
|
||||||
|
ElfW_Rel *rel;
|
||||||
|
/* relocate relocation table in 'sr' */
|
||||||
|
for_each_elem(sr, 0, rel, ElfW_Rel)
|
||||||
|
rel->r_offset += s->sh_addr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ELF_OBJ_ONLY
|
#ifndef ELF_OBJ_ONLY
|
||||||
/* relocate relocation table in 'sr' */
|
|
||||||
static void relocate_rel(TCCState *s1, Section *sr)
|
|
||||||
{
|
|
||||||
Section *s;
|
|
||||||
ElfW_Rel *rel;
|
|
||||||
|
|
||||||
s = s1->sections[sr->sh_info];
|
|
||||||
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
|
/* 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)
|
||||||
|
@ -1099,6 +1108,7 @@ static struct sym_attr * put_got_entry(TCCState *s1, int dyn_reloc_type,
|
||||||
unsigned got_offset;
|
unsigned got_offset;
|
||||||
char plt_name[100];
|
char plt_name[100];
|
||||||
int len;
|
int len;
|
||||||
|
Section *s_rel;
|
||||||
|
|
||||||
need_plt_entry = (dyn_reloc_type == R_JMP_SLOT);
|
need_plt_entry = (dyn_reloc_type == R_JMP_SLOT);
|
||||||
attr = get_sym_attr(s1, sym_index, 1);
|
attr = get_sym_attr(s1, sym_index, 1);
|
||||||
|
@ -1109,6 +1119,15 @@ static struct sym_attr * put_got_entry(TCCState *s1, int dyn_reloc_type,
|
||||||
if (need_plt_entry ? attr->plt_offset : attr->got_offset)
|
if (need_plt_entry ? attr->plt_offset : attr->got_offset)
|
||||||
return attr;
|
return attr;
|
||||||
|
|
||||||
|
s_rel = s1->got;
|
||||||
|
if (need_plt_entry) {
|
||||||
|
if (!s1->plt) {
|
||||||
|
s1->plt = new_section(s1, ".plt", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
|
||||||
|
s1->plt->sh_entsize = 4;
|
||||||
|
}
|
||||||
|
s_rel = s1->plt;
|
||||||
|
}
|
||||||
|
|
||||||
/* create the GOT entry */
|
/* create the GOT entry */
|
||||||
got_offset = s1->got->data_offset;
|
got_offset = s1->got->data_offset;
|
||||||
section_ptr_add(s1->got, PTR_SIZE);
|
section_ptr_add(s1->got, PTR_SIZE);
|
||||||
|
@ -1123,6 +1142,7 @@ static struct sym_attr * put_got_entry(TCCState *s1, int dyn_reloc_type,
|
||||||
|
|
||||||
sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
|
sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
|
||||||
name = (char *) symtab_section->link->data + sym->st_name;
|
name = (char *) symtab_section->link->data + sym->st_name;
|
||||||
|
//printf("sym %d %s\n", need_plt_entry, name);
|
||||||
|
|
||||||
if (s1->dynsym) {
|
if (s1->dynsym) {
|
||||||
if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) {
|
if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) {
|
||||||
|
@ -1147,7 +1167,7 @@ static struct sym_attr * put_got_entry(TCCState *s1, int dyn_reloc_type,
|
||||||
attr->dyn_index = set_elf_sym(s1->dynsym, sym->st_value,
|
attr->dyn_index = set_elf_sym(s1->dynsym, sym->st_value,
|
||||||
sym->st_size, sym->st_info, 0,
|
sym->st_size, sym->st_info, 0,
|
||||||
sym->st_shndx, name);
|
sym->st_shndx, name);
|
||||||
put_elf_reloc(s1->dynsym, s1->got, got_offset, dyn_reloc_type,
|
put_elf_reloc(s1->dynsym, s_rel, got_offset, dyn_reloc_type,
|
||||||
attr->dyn_index);
|
attr->dyn_index);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1156,12 +1176,6 @@ static struct sym_attr * put_got_entry(TCCState *s1, int dyn_reloc_type,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (need_plt_entry) {
|
if (need_plt_entry) {
|
||||||
if (!s1->plt) {
|
|
||||||
s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
|
|
||||||
SHF_ALLOC | SHF_EXECINSTR);
|
|
||||||
s1->plt->sh_entsize = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
attr->plt_offset = create_plt_entry(s1, got_offset, attr);
|
attr->plt_offset = create_plt_entry(s1, got_offset, attr);
|
||||||
|
|
||||||
/* create a symbol 'sym@plt' for the PLT jump vector */
|
/* create a symbol 'sym@plt' for the PLT jump vector */
|
||||||
|
@ -1172,7 +1186,6 @@ static struct sym_attr * put_got_entry(TCCState *s1, int dyn_reloc_type,
|
||||||
strcpy(plt_name + len, "@plt");
|
strcpy(plt_name + len, "@plt");
|
||||||
attr->plt_sym = put_elf_sym(s1->symtab, attr->plt_offset, sym->st_size,
|
attr->plt_sym = put_elf_sym(s1->symtab, attr->plt_offset, sym->st_size,
|
||||||
ELFW(ST_INFO)(STB_GLOBAL, STT_FUNC), 0, s1->plt->sh_num, plt_name);
|
ELFW(ST_INFO)(STB_GLOBAL, STT_FUNC), 0, s1->plt->sh_num, plt_name);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
attr->got_offset = got_offset;
|
attr->got_offset = got_offset;
|
||||||
}
|
}
|
||||||
|
@ -1181,14 +1194,18 @@ static struct sym_attr * put_got_entry(TCCState *s1, int dyn_reloc_type,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* build GOT and PLT entries */
|
/* build GOT and PLT entries */
|
||||||
static void build_got_entries_pass(TCCState *s1, int pass)
|
/* Two passes because R_JMP_SLOT should become first. Some targets
|
||||||
|
(arm, arm64) do not allow mixing R_JMP_SLOT and R_GLOB_DAT. */
|
||||||
|
ST_FUNC void build_got_entries(TCCState *s1)
|
||||||
{
|
{
|
||||||
Section *s;
|
Section *s;
|
||||||
ElfW_Rel *rel;
|
ElfW_Rel *rel;
|
||||||
ElfW(Sym) *sym;
|
ElfW(Sym) *sym;
|
||||||
int i, type, gotplt_entry, reloc_type, sym_index;
|
int i, type, gotplt_entry, reloc_type, sym_index;
|
||||||
struct sym_attr *attr;
|
struct sym_attr *attr;
|
||||||
|
int pass = 0;
|
||||||
|
|
||||||
|
redo:
|
||||||
for(i = 1; i < s1->nb_sections; i++) {
|
for(i = 1; i < s1->nb_sections; i++) {
|
||||||
s = s1->sections[i];
|
s = s1->sections[i];
|
||||||
if (s->sh_type != SHT_RELX)
|
if (s->sh_type != SHT_RELX)
|
||||||
|
@ -1252,7 +1269,7 @@ static void build_got_entries_pass(TCCState *s1, int pass)
|
||||||
(ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT ||
|
(ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT ||
|
||||||
ELFW(ST_BIND)(sym->st_info) == STB_LOCAL ||
|
ELFW(ST_BIND)(sym->st_info) == STB_LOCAL ||
|
||||||
s1->output_type == TCC_OUTPUT_EXE)) {
|
s1->output_type == TCC_OUTPUT_EXE)) {
|
||||||
if (pass == 0)
|
if (pass != 0)
|
||||||
continue;
|
continue;
|
||||||
rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32);
|
rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32);
|
||||||
continue;
|
continue;
|
||||||
|
@ -1261,16 +1278,17 @@ static void build_got_entries_pass(TCCState *s1, int pass)
|
||||||
reloc_type = code_reloc(type);
|
reloc_type = code_reloc(type);
|
||||||
if (reloc_type == -1)
|
if (reloc_type == -1)
|
||||||
tcc_error ("Unknown relocation type: %d", type);
|
tcc_error ("Unknown relocation type: %d", type);
|
||||||
else if (reloc_type != 0) {
|
|
||||||
jmp_slot:
|
if (reloc_type != 0) {
|
||||||
|
jmp_slot:
|
||||||
|
if (pass != 0)
|
||||||
|
continue;
|
||||||
reloc_type = R_JMP_SLOT;
|
reloc_type = R_JMP_SLOT;
|
||||||
} else
|
} else {
|
||||||
|
if (pass != 1)
|
||||||
|
continue;
|
||||||
reloc_type = R_GLOB_DAT;
|
reloc_type = R_GLOB_DAT;
|
||||||
|
}
|
||||||
|
|
||||||
if ((pass == 0 && reloc_type == R_GLOB_DAT) ||
|
|
||||||
(pass == 1 && reloc_type == R_JMP_SLOT))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!s1->got)
|
if (!s1->got)
|
||||||
build_got(s1);
|
build_got(s1);
|
||||||
|
@ -1284,16 +1302,13 @@ static void build_got_entries_pass(TCCState *s1, int pass)
|
||||||
rel->r_info = ELFW(R_INFO)(attr->plt_sym, type);
|
rel->r_info = ELFW(R_INFO)(attr->plt_sym, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (++pass < 2)
|
||||||
|
goto redo;
|
||||||
|
|
||||||
ST_FUNC void build_got_entries(TCCState *s1)
|
/* .rel.plt refers to .got actually */
|
||||||
{
|
if (s1->plt && s1->plt->reloc)
|
||||||
int i;
|
s1->plt->reloc->sh_info = s1->got->sh_num;
|
||||||
|
|
||||||
/* Two passes because R_JMP_SLOT should become first.
|
|
||||||
Some targets (arm, arm64) do not allow mixing R_JMP_SLOT and R_GLOB_DAT. */
|
|
||||||
for (i = 0; i < 2; i++)
|
|
||||||
build_got_entries_pass(s1, i);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1931,8 +1946,6 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr,
|
||||||
roinf->sh_offset = roinf->sh_addr = roinf->sh_size = 0;
|
roinf->sh_offset = roinf->sh_addr = roinf->sh_size = 0;
|
||||||
|
|
||||||
for(j = 0; j < phfill; j++) {
|
for(j = 0; j < phfill; j++) {
|
||||||
Section *relocplt = s1->got ? s1->got->relocplt : NULL;
|
|
||||||
|
|
||||||
ph->p_type = j == 2 ? PT_TLS : PT_LOAD;
|
ph->p_type = j == 2 ? PT_TLS : PT_LOAD;
|
||||||
if (j == 0)
|
if (j == 0)
|
||||||
ph->p_flags = PF_R | PF_X;
|
ph->p_flags = PF_R | PF_X;
|
||||||
|
@ -1973,10 +1986,13 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr,
|
||||||
if (k != 1)
|
if (k != 1)
|
||||||
continue;
|
continue;
|
||||||
} else if (s->sh_type == SHT_RELX) {
|
} else if (s->sh_type == SHT_RELX) {
|
||||||
if (k != 2 && s != relocplt)
|
if (s1->plt && s == s1->plt->reloc) {
|
||||||
continue;
|
if (k != 3)
|
||||||
else if (k != 3 && s == relocplt)
|
continue;
|
||||||
continue;
|
} else {
|
||||||
|
if (k != 2)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
} else if (s->sh_type == SHT_NOBITS) {
|
} else if (s->sh_type == SHT_NOBITS) {
|
||||||
if (k != 6)
|
if (k != 6)
|
||||||
continue;
|
continue;
|
||||||
|
@ -2155,10 +2171,10 @@ static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
|
||||||
put_dt(dynamic, DT_RELA, dyninf->rel_addr);
|
put_dt(dynamic, DT_RELA, dyninf->rel_addr);
|
||||||
put_dt(dynamic, DT_RELASZ, dyninf->rel_size);
|
put_dt(dynamic, DT_RELASZ, dyninf->rel_size);
|
||||||
put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
|
put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
|
||||||
if (s1->got && s1->got->relocplt) {
|
if (s1->plt && s1->plt->reloc) {
|
||||||
put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
|
put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
|
||||||
put_dt(dynamic, DT_PLTRELSZ, s1->got->relocplt->data_offset);
|
put_dt(dynamic, DT_PLTRELSZ, s1->plt->reloc->data_offset);
|
||||||
put_dt(dynamic, DT_JMPREL, s1->got->relocplt->sh_addr);
|
put_dt(dynamic, DT_JMPREL, s1->plt->reloc->sh_addr);
|
||||||
put_dt(dynamic, DT_PLTREL, DT_RELA);
|
put_dt(dynamic, DT_PLTREL, DT_RELA);
|
||||||
}
|
}
|
||||||
put_dt(dynamic, DT_RELACOUNT, 0);
|
put_dt(dynamic, DT_RELACOUNT, 0);
|
||||||
|
@ -2166,10 +2182,10 @@ static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
|
||||||
put_dt(dynamic, DT_REL, dyninf->rel_addr);
|
put_dt(dynamic, DT_REL, dyninf->rel_addr);
|
||||||
put_dt(dynamic, DT_RELSZ, dyninf->rel_size);
|
put_dt(dynamic, DT_RELSZ, dyninf->rel_size);
|
||||||
put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
|
put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
|
||||||
if (s1->got && s1->got->relocplt) {
|
if (s1->plt && s1->plt->reloc) {
|
||||||
put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
|
put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
|
||||||
put_dt(dynamic, DT_PLTRELSZ, s1->got->relocplt->data_offset);
|
put_dt(dynamic, DT_PLTRELSZ, s1->plt->reloc->data_offset);
|
||||||
put_dt(dynamic, DT_JMPREL, s1->got->relocplt->sh_addr);
|
put_dt(dynamic, DT_JMPREL, s1->plt->reloc->sh_addr);
|
||||||
put_dt(dynamic, DT_PLTREL, DT_REL);
|
put_dt(dynamic, DT_PLTREL, DT_REL);
|
||||||
}
|
}
|
||||||
put_dt(dynamic, DT_RELCOUNT, 0);
|
put_dt(dynamic, DT_RELCOUNT, 0);
|
||||||
|
@ -2208,38 +2224,6 @@ static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
|
||||||
put_dt(dynamic, DT_NULL, 0);
|
put_dt(dynamic, DT_NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Relocate remaining sections and symbols (that is those not related to
|
|
||||||
dynamic linking) */
|
|
||||||
static int final_sections_reloc(TCCState *s1)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
Section *s;
|
|
||||||
|
|
||||||
relocate_syms(s1, s1->symtab, 0);
|
|
||||||
|
|
||||||
if (s1->nb_errors != 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* relocate sections */
|
|
||||||
/* XXX: ignore sections with allocated relocations ? */
|
|
||||||
for(i = 1; i < s1->nb_sections; i++) {
|
|
||||||
s = s1->sections[i];
|
|
||||||
if (s->reloc && (s != s1->got || s1->static_link))
|
|
||||||
relocate_section(s1, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* relocate relocation entries if the relocation tables are
|
|
||||||
allocated in the executable */
|
|
||||||
for(i = 1; i < s1->nb_sections; i++) {
|
|
||||||
s = s1->sections[i];
|
|
||||||
if ((s->sh_flags & SHF_ALLOC) &&
|
|
||||||
s->sh_type == SHT_RELX) {
|
|
||||||
relocate_rel(s1, s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove gaps between RELX sections.
|
/* Remove gaps between RELX sections.
|
||||||
These gaps are a result of final_sections_reloc. Here some relocs are removed.
|
These gaps are a result of final_sections_reloc. Here some relocs are removed.
|
||||||
The gaps are then filled with 0 in tcc_output_elf. The 0 is intepreted as
|
The gaps are then filled with 0 in tcc_output_elf. The 0 is intepreted as
|
||||||
|
@ -2250,7 +2234,7 @@ static void update_reloc_sections(TCCState *s1, struct dyn_inf *dyninf)
|
||||||
int i;
|
int i;
|
||||||
unsigned long file_offset = 0;
|
unsigned long file_offset = 0;
|
||||||
Section *s;
|
Section *s;
|
||||||
Section *relocplt = s1->got ? s1->got->relocplt : NULL;
|
Section *relocplt = s1->plt ? s1->plt->reloc : NULL;
|
||||||
|
|
||||||
/* dynamic relocation table information, for .dynamic section */
|
/* dynamic relocation table information, for .dynamic section */
|
||||||
dyninf->rel_addr = dyninf->rel_size = 0;
|
dyninf->rel_addr = dyninf->rel_size = 0;
|
||||||
|
@ -2724,9 +2708,11 @@ static int elf_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 */
|
||||||
ret = final_sections_reloc(s1);
|
relocate_syms(s1, s1->symtab, 0);
|
||||||
if (ret)
|
ret = -1;
|
||||||
|
if (s1->nb_errors != 0)
|
||||||
goto the_end;
|
goto the_end;
|
||||||
|
relocate_sections(s1);
|
||||||
if (dynamic) {
|
if (dynamic) {
|
||||||
update_reloc_sections (s1, &dyninf);
|
update_reloc_sections (s1, &dyninf);
|
||||||
dynamic->data_offset = dyninf.data_offset;
|
dynamic->data_offset = dyninf.data_offset;
|
||||||
|
|
10
tccmacho.c
10
tccmacho.c
|
@ -809,22 +809,14 @@ ST_FUNC int macho_output_file(TCCState *s1, const char *filename)
|
||||||
check_relocs(s1, &mo);
|
check_relocs(s1, &mo);
|
||||||
ret = check_symbols(s1, &mo);
|
ret = check_symbols(s1, &mo);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
int i;
|
|
||||||
Section *s;
|
|
||||||
collect_sections(s1, &mo);
|
collect_sections(s1, &mo);
|
||||||
relocate_syms(s1, s1->symtab, 0);
|
relocate_syms(s1, s1->symtab, 0);
|
||||||
mo.ep->entryoff = get_sym_addr(s1, "main", 1, 1)
|
mo.ep->entryoff = get_sym_addr(s1, "main", 1, 1)
|
||||||
- get_segment(&mo, 1)->vmaddr;
|
- get_segment(&mo, 1)->vmaddr;
|
||||||
if (s1->nb_errors)
|
if (s1->nb_errors)
|
||||||
goto do_ret;
|
goto do_ret;
|
||||||
|
relocate_sections(s1);
|
||||||
for(i = 1; i < s1->nb_sections; i++) {
|
|
||||||
s = s1->sections[i];
|
|
||||||
if (s->reloc)
|
|
||||||
relocate_section(s1, s);
|
|
||||||
}
|
|
||||||
convert_symbols(s1, &mo);
|
convert_symbols(s1, &mo);
|
||||||
|
|
||||||
macho_write(s1, &mo, fp);
|
macho_write(s1, &mo, fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
12
tccpe.c
12
tccpe.c
|
@ -982,7 +982,7 @@ static void pe_build_exports(struct pe_info *pe)
|
||||||
for (ord = 0; ord < sym_count; ++ord)
|
for (ord = 0; ord < sym_count; ++ord)
|
||||||
{
|
{
|
||||||
p = sorted[ord], sym_index = p->index, name = p->name;
|
p = sorted[ord], sym_index = p->index, name = p->name;
|
||||||
/* insert actual address later in relocate_section() */
|
/* insert actual address later in relocate_sections() */
|
||||||
put_elf_reloc(symtab_section, pe->thunk,
|
put_elf_reloc(symtab_section, pe->thunk,
|
||||||
func_o, R_XXX_RELATIVE, sym_index);
|
func_o, R_XXX_RELATIVE, sym_index);
|
||||||
*(DWORD*)(pe->thunk->data + name_o)
|
*(DWORD*)(pe->thunk->data + name_o)
|
||||||
|
@ -1937,7 +1937,7 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* need this for 'tccelf.c:relocate_section()' */
|
/* need this for 'tccelf.c:relocate_sections()' */
|
||||||
if (TCC_OUTPUT_DLL == s1->output_type)
|
if (TCC_OUTPUT_DLL == s1->output_type)
|
||||||
s1->output_type = TCC_OUTPUT_EXE;
|
s1->output_type = TCC_OUTPUT_EXE;
|
||||||
if (TCC_OUTPUT_MEMORY == s1->output_type)
|
if (TCC_OUTPUT_MEMORY == s1->output_type)
|
||||||
|
@ -1996,7 +1996,6 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct pe_info pe;
|
struct pe_info pe;
|
||||||
int i;
|
|
||||||
|
|
||||||
memset(&pe, 0, sizeof pe);
|
memset(&pe, 0, sizeof pe);
|
||||||
pe.filename = filename;
|
pe.filename = filename;
|
||||||
|
@ -2018,12 +2017,7 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
|
||||||
pe_assign_addresses(&pe);
|
pe_assign_addresses(&pe);
|
||||||
relocate_syms(s1, s1->symtab, 0);
|
relocate_syms(s1, s1->symtab, 0);
|
||||||
s1->pe_imagebase = pe.imagebase;
|
s1->pe_imagebase = pe.imagebase;
|
||||||
for (i = 1; i < s1->nb_sections; ++i) {
|
relocate_sections(s1);
|
||||||
Section *s = s1->sections[i];
|
|
||||||
if (s->reloc) {
|
|
||||||
relocate_section(s1, s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pe.start_addr = (DWORD)
|
pe.start_addr = (DWORD)
|
||||||
(get_sym_addr(s1, pe.start_symbol, 1, 1) - pe.imagebase);
|
(get_sym_addr(s1, pe.start_symbol, 1, 1) - pe.imagebase);
|
||||||
if (s1->nb_errors)
|
if (s1->nb_errors)
|
||||||
|
|
10
tccrun.c
10
tccrun.c
|
@ -277,15 +277,11 @@ static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff)
|
||||||
s1->pe_imagebase = mem;
|
s1->pe_imagebase = mem;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* relocate each section */
|
/* relocate sections */
|
||||||
for(i = 1; i < s1->nb_sections; i++) {
|
#ifndef TCC_TARGET_PE
|
||||||
s = s1->sections[i];
|
|
||||||
if (s->reloc)
|
|
||||||
relocate_section(s1, s);
|
|
||||||
}
|
|
||||||
#if !defined(TCC_TARGET_PE) || defined(TCC_TARGET_MACHO)
|
|
||||||
relocate_plt(s1);
|
relocate_plt(s1);
|
||||||
#endif
|
#endif
|
||||||
|
relocate_sections(s1);
|
||||||
|
|
||||||
for(i = 1; i < s1->nb_sections; i++) {
|
for(i = 1; i < s1->nb_sections; i++) {
|
||||||
s = s1->sections[i];
|
s = s1->sections[i];
|
||||||
|
|
|
@ -131,7 +131,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
|
||||||
/* The PLT slot refers to the relocation entry it needs via offset.
|
/* The PLT slot refers to the relocation entry it needs via offset.
|
||||||
The reloc entry is created below, so its offset is the current
|
The reloc entry is created below, so its offset is the current
|
||||||
data_offset */
|
data_offset */
|
||||||
relofs = s1->got->relocplt ? s1->got->relocplt->data_offset : 0;
|
relofs = s1->plt->reloc ? s1->plt->reloc->data_offset : 0;
|
||||||
|
|
||||||
/* Jump to GOT entry where ld.so initially put the address of ip + 4 */
|
/* Jump to GOT entry where ld.so initially put the address of ip + 4 */
|
||||||
p = section_ptr_add(plt, 16);
|
p = section_ptr_add(plt, 16);
|
||||||
|
@ -169,16 +169,12 @@ ST_FUNC void relocate_plt(TCCState *s1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s1->got->relocplt) {
|
if (s1->plt->reloc) {
|
||||||
int mem = s1->output_type == TCC_OUTPUT_MEMORY;
|
|
||||||
ElfW_Rel *rel;
|
ElfW_Rel *rel;
|
||||||
int x = s1->plt->sh_addr + 16 + 6;
|
int x = s1->plt->sh_addr + 16 + 6;
|
||||||
|
|
||||||
p = s1->got->data;
|
p = s1->got->data;
|
||||||
for_each_elem(s1->got->relocplt, 0, rel, ElfW_Rel) {
|
for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
|
||||||
int sym_index = ELFW(R_SYM)(rel->r_info);
|
write64le(p + rel->r_offset, x);
|
||||||
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
|
||||||
write64le(p + rel->r_offset, mem ? sym->st_value : x);
|
|
||||||
x += 16;
|
x += 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue