tccelf: use plt-reloc instead of relocplt

This commit is contained in:
grischka 2021-01-28 14:20:05 +01:00
parent e4f151c4cd
commit 02795106e1
10 changed files with 108 additions and 163 deletions

View file

@ -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);
} }
} }
} }

View file

@ -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);
} }
} }
} }

View file

@ -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;
} }
} }

View file

@ -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
View file

@ -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
View file

@ -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;

View file

@ -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
View file

@ -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)

View file

@ -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];

View file

@ -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;
} }
} }