Remove gaps between RELX sections
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 R_...NONE reloc. This does work on most targets but on OpenBSD/arm64 this is illegal.
This commit is contained in:
parent
cd91ea658a
commit
c9bdfcedb4
1 changed files with 33 additions and 14 deletions
47
tccelf.c
47
tccelf.c
|
@ -1863,8 +1863,7 @@ struct ro_inf {
|
||||||
static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr,
|
static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr,
|
||||||
int phnum, int phfill,
|
int phnum, int phfill,
|
||||||
Section *interp, Section* strsec,
|
Section *interp, Section* strsec,
|
||||||
struct dyn_inf *dyninf, struct ro_inf *roinf,
|
struct ro_inf *roinf, int *sec_order)
|
||||||
int *sec_order)
|
|
||||||
{
|
{
|
||||||
int i, sh_order_index, file_offset;
|
int i, sh_order_index, file_offset;
|
||||||
Section *s;
|
Section *s;
|
||||||
|
@ -1912,9 +1911,6 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr,
|
||||||
if (interp)
|
if (interp)
|
||||||
ph += 2;
|
ph += 2;
|
||||||
|
|
||||||
/* dynamic relocation table information, for .dynamic section */
|
|
||||||
dyninf->rel_addr = dyninf->rel_size = 0;
|
|
||||||
|
|
||||||
/* read only segment mapping for GNU_RELRO */
|
/* read only segment mapping for GNU_RELRO */
|
||||||
roinf->sh_offset = roinf->sh_addr = roinf->sh_size = 0;
|
roinf->sh_offset = roinf->sh_addr = roinf->sh_size = 0;
|
||||||
|
|
||||||
|
@ -2001,12 +1997,6 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr,
|
||||||
ph->p_vaddr = addr;
|
ph->p_vaddr = addr;
|
||||||
ph->p_paddr = ph->p_vaddr;
|
ph->p_paddr = ph->p_vaddr;
|
||||||
}
|
}
|
||||||
/* update dynamic relocation infos */
|
|
||||||
if (s->sh_type == SHT_RELX && s != relocplt) {
|
|
||||||
if (dyninf->rel_size == 0)
|
|
||||||
dyninf->rel_addr = addr;
|
|
||||||
dyninf->rel_size = (addr - dyninf->rel_addr) + s->sh_size;
|
|
||||||
}
|
|
||||||
if (s == data_ro_section ||
|
if (s == data_ro_section ||
|
||||||
#ifdef CONFIG_TCC_BCHECK
|
#ifdef CONFIG_TCC_BCHECK
|
||||||
s == bounds_section ||
|
s == bounds_section ||
|
||||||
|
@ -2248,6 +2238,32 @@ static int final_sections_reloc(TCCState *s1)
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remove gaps between RELX sections.
|
||||||
|
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
|
||||||
|
R_...NONE reloc. This does work on most targets but on OpenBSD/arm64 this
|
||||||
|
is illegal. */
|
||||||
|
static void update_reloc_sections(TCCState *s1, struct dyn_inf *dyninf)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
Section *s;
|
||||||
|
Section *relocplt = s1->got ? s1->got->relocplt : NULL;
|
||||||
|
|
||||||
|
/* dynamic relocation table information, for .dynamic section */
|
||||||
|
dyninf->rel_addr = dyninf->rel_size = 0;
|
||||||
|
|
||||||
|
for(i = 1; i < s1->nb_sections; i++) {
|
||||||
|
s = s1->sections[i];
|
||||||
|
if (s->sh_type == SHT_RELX && s != relocplt) {
|
||||||
|
if (dyninf->rel_size == 0)
|
||||||
|
dyninf->rel_addr = s->sh_addr;
|
||||||
|
else
|
||||||
|
s->sh_addr = dyninf->rel_addr + dyninf->rel_size;
|
||||||
|
dyninf->rel_size += s->sh_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Create an ELF file on disk.
|
/* Create an ELF file on disk.
|
||||||
|
@ -2671,7 +2687,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||||
|
|
||||||
/* compute section to program header mapping */
|
/* compute section to program header mapping */
|
||||||
file_offset = layout_sections(s1, phdr, phnum, phfill, interp, strsec,
|
file_offset = layout_sections(s1, phdr, phnum, phfill, interp, strsec,
|
||||||
&dyninf, &roinf, sec_order);
|
&roinf, sec_order);
|
||||||
|
|
||||||
#ifndef ELF_OBJ_ONLY
|
#ifndef ELF_OBJ_ONLY
|
||||||
/* Fill remaining program header and finalize relocation related to dynamic
|
/* Fill remaining program header and finalize relocation related to dynamic
|
||||||
|
@ -2680,8 +2696,6 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||||
fill_unloadable_phdr(phdr, phnum, interp, dynamic, note, roinf_use);
|
fill_unloadable_phdr(phdr, phnum, interp, dynamic, note, roinf_use);
|
||||||
if (dynamic) {
|
if (dynamic) {
|
||||||
ElfW(Sym) *sym;
|
ElfW(Sym) *sym;
|
||||||
dynamic->data_offset = dyninf.data_offset;
|
|
||||||
fill_dynamic(s1, &dyninf);
|
|
||||||
|
|
||||||
/* put in GOT the dynamic section address and relocate PLT */
|
/* put in GOT the dynamic section address and relocate PLT */
|
||||||
write32le(s1->got->data, dynamic->sh_addr);
|
write32le(s1->got->data, dynamic->sh_addr);
|
||||||
|
@ -2703,6 +2717,11 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||||
ret = final_sections_reloc(s1);
|
ret = final_sections_reloc(s1);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto the_end;
|
goto the_end;
|
||||||
|
if (dynamic) {
|
||||||
|
update_reloc_sections (s1, &dyninf);
|
||||||
|
dynamic->data_offset = dyninf.data_offset;
|
||||||
|
fill_dynamic(s1, &dyninf);
|
||||||
|
}
|
||||||
tidy_section_headers(s1, sec_order);
|
tidy_section_headers(s1, sec_order);
|
||||||
|
|
||||||
/* Perform relocation to GOT or PLT entries */
|
/* Perform relocation to GOT or PLT entries */
|
||||||
|
|
Loading…
Add table
Reference in a new issue