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 | static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, | 1863 | static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, |
| 1864 | int phnum, int phfill, | 1864 | int phnum, int phfill, |
| 1865 | Section *interp, Section* strsec, | 1865 | Section *interp, Section* strsec, |
| 1866 | struct dyn_inf *dyninf, struct ro_inf *roinf, | 1866 | struct ro_inf *roinf, int *sec_order) |
| 1867 | int *sec_order) | ||
| 1868 | { | 1867 | { |
| 1869 | int i, sh_order_index, file_offset; | 1868 | int i, sh_order_index, file_offset; |
| 1870 | Section *s; | 1869 | Section *s; |
| @@ -1912,9 +1911,6 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, · 41 unmodified lines | |||
| 1912 | if (interp) | 1911 | if (interp) |
| 1913 | ph += 2; | 1912 | ph += 2; |
| 1914 | 1913 | ||
| 1915 | /* dynamic relocation table information, for .dynamic section */ | ||
| 1916 | dyninf->rel_addr = dyninf->rel_size = 0; | ||
| 1917 | |||
| 1918 | /* read only segment mapping for GNU_RELRO */ | 1914 | /* read only segment mapping for GNU_RELRO */ |
| 1919 | roinf->sh_offset = roinf->sh_addr = roinf->sh_size = 0; | 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 | ph->p_vaddr = addr; | 1997 | ph->p_vaddr = addr; |
| 2002 | ph->p_paddr = ph->p_vaddr; | 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 | if (s == data_ro_section || | 2000 | if (s == data_ro_section || |
| 2011 | #ifdef CONFIG_TCC_BCHECK | 2001 | #ifdef CONFIG_TCC_BCHECK |
| 2012 | s == bounds_section || | 2002 | s == bounds_section || |
| @@ -2248,6 +2238,32 @@ static int final_sections_reloc(TCCState *s1) · 235 unmodified lines | |||
| 2248 | } | 2238 | } |
| 2249 | return 0; | 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 | #endif | 2267 | #endif |
| 2252 | 2268 | ||
| 2253 | /* Create an ELF file on disk. | 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 | /* compute section to program header mapping */ | 2688 | /* compute section to program header mapping */ |
| 2673 | file_offset = layout_sections(s1, phdr, phnum, phfill, interp, strsec, | 2689 | file_offset = layout_sections(s1, phdr, phnum, phfill, interp, strsec, |
| 2674 | &dyninf, &roinf, sec_order); | 2690 | &roinf, sec_order); |
| 2675 | 2691 | ||
| 2676 | #ifndef ELF_OBJ_ONLY | 2692 | #ifndef ELF_OBJ_ONLY |
| 2677 | /* Fill remaining program header and finalize relocation related to dynamic | 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 | fill_unloadable_phdr(phdr, phnum, interp, dynamic, note, roinf_use); | 2696 | fill_unloadable_phdr(phdr, phnum, interp, dynamic, note, roinf_use); |
| 2681 | if (dynamic) { | 2697 | if (dynamic) { |
| 2682 | ElfW(Sym) *sym; | 2698 | ElfW(Sym) *sym; |
| 2683 | dynamic->data_offset = dyninf.data_offset; | ||
| 2684 | fill_dynamic(s1, &dyninf); | ||
| 2685 | 2699 | ||
| 2686 | /* put in GOT the dynamic section address and relocate PLT */ | 2700 | /* put in GOT the dynamic section address and relocate PLT */ |
| 2687 | write32le(s1->got->data, dynamic->sh_addr); | 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 | ret = final_sections_reloc(s1); | 2717 | ret = final_sections_reloc(s1); |
| 2704 | if (ret) | 2718 | if (ret) |
| 2705 | goto the_end; | 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 | tidy_section_headers(s1, sec_order); | 2725 | tidy_section_headers(s1, sec_order); |
| 2707 | 2726 | ||
| 2708 | /* Perform relocation to GOT or PLT entries */ | 2727 | /* Perform relocation to GOT or PLT entries */ |