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.
Unified · Split
| @@ -1863,8 +1863,7 @@ struct ro_inf { · 1862 unmodified lines | ||
| 1863 | 1863 | static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, |
| 1864 | 1864 | int phnum, int phfill, |
| 1865 | 1865 | Section *interp, Section* strsec, |
| 1866 | − struct dyn_inf *dyninf, struct ro_inf *roinf, | |
| 1867 | − int *sec_order) | |
| 1866 | + struct ro_inf *roinf, int *sec_order) | |
| 1868 | 1867 | { |
| 1869 | 1868 | int i, sh_order_index, file_offset; |
| 1870 | 1869 | Section *s; |
| @@ -1912,9 +1911,6 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, · 41 unmodified lines | ||
| 1912 | 1911 | if (interp) |
| 1913 | 1912 | ph += 2; |
| 1914 | 1913 | |
| 1915 | − /* dynamic relocation table information, for .dynamic section */ | |
| 1916 | − dyninf->rel_addr = dyninf->rel_size = 0; | |
| 1917 | − | |
| 1918 | 1914 | /* read only segment mapping for GNU_RELRO */ |
| 1919 | 1915 | roinf->sh_offset = roinf->sh_addr = roinf->sh_size = 0; |
| 1920 | 1916 | |
| @@ -2001,12 +1997,6 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, · 80 unmodified lines | ||
| 2001 | 1997 | ph->p_vaddr = addr; |
| 2002 | 1998 | ph->p_paddr = ph->p_vaddr; |
| 2003 | 1999 | } |
| 2004 | − /* update dynamic relocation infos */ | |
| 2005 | − if (s->sh_type == SHT_RELX && s != relocplt) { | |
| 2006 | − if (dyninf->rel_size == 0) | |
| 2007 | − dyninf->rel_addr = addr; | |
| 2008 | − dyninf->rel_size = (addr - dyninf->rel_addr) + s->sh_size; | |
| 2009 | − } | |
| 2010 | 2000 | if (s == data_ro_section || |
| 2011 | 2001 | #ifdef CONFIG_TCC_BCHECK |
| 2012 | 2002 | s == bounds_section || |
| @@ -2248,6 +2238,32 @@ static int final_sections_reloc(TCCState *s1) · 235 unmodified lines | ||
| 2248 | 2238 | } |
| 2249 | 2239 | return 0; |
| 2250 | 2240 | } |
| 2241 | + | |
| 2242 | +/* Remove gaps between RELX sections. | |
| 2243 | + These gaps are a result of final_sections_reloc. Here some relocs are removed. | |
| 2244 | + The gaps are then filled with 0 in tcc_output_elf. The 0 is intepreted as | |
| 2245 | + R_...NONE reloc. This does work on most targets but on OpenBSD/arm64 this | |
| 2246 | + is illegal. */ | |
| 2247 | +static void update_reloc_sections(TCCState *s1, struct dyn_inf *dyninf) | |
| 2248 | +{ | |
| 2249 | + int i; | |
| 2250 | + Section *s; | |
| 2251 | + Section *relocplt = s1->got ? s1->got->relocplt : NULL; | |
| 2252 | + | |
| 2253 | + /* dynamic relocation table information, for .dynamic section */ | |
| 2254 | + dyninf->rel_addr = dyninf->rel_size = 0; | |
| 2255 | + | |
| 2256 | + for(i = 1; i < s1->nb_sections; i++) { | |
| 2257 | + s = s1->sections[i]; | |
| 2258 | + if (s->sh_type == SHT_RELX && s != relocplt) { | |
| 2259 | + if (dyninf->rel_size == 0) | |
| 2260 | + dyninf->rel_addr = s->sh_addr; | |
| 2261 | + else | |
| 2262 | + s->sh_addr = dyninf->rel_addr + dyninf->rel_size; | |
| 2263 | + dyninf->rel_size += s->sh_size; | |
| 2264 | + } | |
| 2265 | + } | |
| 2266 | +} | |
| 2251 | 2267 | #endif |
| 2252 | 2268 | |
| 2253 | 2269 | /* Create an ELF file on disk. |
| @@ -2671,7 +2687,7 @@ static int elf_output_file(TCCState *s1, const char *filename) · 417 unmodified lines | ||
| 2671 | 2687 | |
| 2672 | 2688 | /* compute section to program header mapping */ |
| 2673 | 2689 | file_offset = layout_sections(s1, phdr, phnum, phfill, interp, strsec, |
| 2674 | − &dyninf, &roinf, sec_order); | |
| 2690 | + &roinf, sec_order); | |
| 2675 | 2691 | |
| 2676 | 2692 | #ifndef ELF_OBJ_ONLY |
| 2677 | 2693 | /* Fill remaining program header and finalize relocation related to dynamic |
| @@ -2680,8 +2696,6 @@ static int elf_output_file(TCCState *s1, const char *filename) · 2 unmodified lines | ||
| 2680 | 2696 | fill_unloadable_phdr(phdr, phnum, interp, dynamic, note, roinf_use); |
| 2681 | 2697 | if (dynamic) { |
| 2682 | 2698 | ElfW(Sym) *sym; |
| 2683 | − dynamic->data_offset = dyninf.data_offset; | |
| 2684 | − fill_dynamic(s1, &dyninf); | |
| 2685 | 2699 | |
| 2686 | 2700 | /* put in GOT the dynamic section address and relocate PLT */ |
| 2687 | 2701 | write32le(s1->got->data, dynamic->sh_addr); |
| @@ -2703,6 +2717,11 @@ static int elf_output_file(TCCState *s1, const char *filename) · 15 unmodified lines | ||
| 2703 | 2717 | ret = final_sections_reloc(s1); |
| 2704 | 2718 | if (ret) |
| 2705 | 2719 | goto the_end; |
| 2720 | + if (dynamic) { | |
| 2721 | + update_reloc_sections (s1, &dyninf); | |
| 2722 | + dynamic->data_offset = dyninf.data_offset; | |
| 2723 | + fill_dynamic(s1, &dyninf); | |
| 2724 | + } | |
| 2706 | 2725 | tidy_section_headers(s1, sec_order); |
| 2707 | 2726 | |
| 2708 | 2727 | /* Perform relocation to GOT or PLT entries */ |