Currently tcc does not use lazy binding. It puts all relocations in the RELX section and solve them all at startup. This was not working on bsd. tcc.h: - New RELPLT_SECTION_FMT for plt relocations - New entry relocplt in struct Section tccelf.c: - put_elf_reloca: put R_JMP_SLOT in relocplt section - build_got_entries*: Use two passes because R_JMP_SLOT and R_GLOB_DAT can not be intermixed on some targets (arm, arm64) - layout_sections: Calculate correct size relocplt section for DT_ values. Make sure relocplt is last - fill_dynamic: Add DT_ values when got is filled move DT_VERSYM because dynamic linker cannot handle it standone - Add note section for NetBSD arm-link.c/arm64-link.c/i386-link.c/riscv64-link.c/x86_64-link.c: - fill got table with pointer to plt section or symbol value in case of TCC_OUTPUT_MEMORY arm-link.c/arm64-link.c: - fix offset first plt entry i386-link.c/x86_64-link.c: - use correct reloc entry - use relofs - sizeof (ElfW_Rel) because the reloc is already done lib/bcheck.c: - no __libc_freeres on FreeBSD and NetBSD tests/Makefile: - Add -fno-stack-protector for OpenBSD tests/tests2/Makefile: - disable 106_pthread/114_bound_signal
Unified · Split
| @@ -145,7 +145,7 @@ ST_FUNC void relocate_plt(TCCState *s1) · 144 unmodified lines | ||
| 145 | 145 | |
| 146 | 146 | if (p < p_end) { |
| 147 | 147 | int x = s1->got->sh_addr - s1->plt->sh_addr - 12; |
| 148 | − write32le(s1->plt->data + 16, x - 16); | |
| 148 | + write32le(s1->plt->data + 16, x - 4); | |
| 149 | 149 | p += 20; |
| 150 | 150 | while (p < p_end) { |
| 151 | 151 | unsigned off = x + read32le(p + 4) + (s1->plt->data - p) + 4; |
| @@ -157,6 +157,18 @@ ST_FUNC void relocate_plt(TCCState *s1) · 5 unmodified lines | ||
| 157 | 157 | p += 12; |
| 158 | 158 | } |
| 159 | 159 | } |
| 160 | + | |
| 161 | + if (s1->got->relocplt) { | |
| 162 | + int mem = s1->output_type == TCC_OUTPUT_MEMORY; | |
| 163 | + ElfW_Rel *rel; | |
| 164 | + | |
| 165 | + p = s1->got->data; | |
| 166 | + for_each_elem(s1->got->relocplt, 0, rel, ElfW_Rel) { | |
| 167 | + int sym_index = ELFW(R_SYM)(rel->r_info); | |
| 168 | + ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; | |
| 169 | + write32le(p + rel->r_offset, mem ? sym->st_value : s1->plt->sh_addr); | |
| 170 | + } | |
| 171 | + } | |
| 160 | 172 | } |
| 161 | 173 | #endif |
| 162 | 174 | |
| @@ -113,7 +113,7 @@ ST_FUNC void relocate_plt(TCCState *s1) · 112 unmodified lines | ||
| 113 | 113 | |
| 114 | 114 | if (p < p_end) { |
| 115 | 115 | uint64_t plt = s1->plt->sh_addr; |
| 116 | − uint64_t got = s1->got->sh_addr; | |
| 116 | + uint64_t got = s1->got->sh_addr + 16; | |
| 117 | 117 | uint64_t off = (got >> 12) - (plt >> 12); |
| 118 | 118 | if ((off + ((uint32_t)1 << 20)) >> 21) |
| 119 | 119 | tcc_error("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", (long)off, (long)got, (long)plt); |
| @@ -129,6 +129,7 @@ ST_FUNC void relocate_plt(TCCState *s1) · 9 unmodified lines | ||
| 129 | 129 | write32le(p + 24, 0xd503201f); // nop |
| 130 | 130 | write32le(p + 28, 0xd503201f); // nop |
| 131 | 131 | p += 32; |
| 132 | + got = s1->got->sh_addr; | |
| 132 | 133 | while (p < p_end) { |
| 133 | 134 | uint64_t pc = plt + (p - s1->plt->data); |
| 134 | 135 | uint64_t addr = got + read64le(p); |
| @@ -145,6 +146,18 @@ ST_FUNC void relocate_plt(TCCState *s1) · 10 unmodified lines | ||
| 145 | 146 | p += 16; |
| 146 | 147 | } |
| 147 | 148 | } |
| 149 | + | |
| 150 | + if (s1->got->relocplt) { | |
| 151 | + int mem = s1->output_type == TCC_OUTPUT_MEMORY; | |
| 152 | + ElfW_Rel *rel; | |
| 153 | + | |
| 154 | + p = s1->got->data; | |
| 155 | + for_each_elem(s1->got->relocplt, 0, rel, ElfW_Rel) { | |
| 156 | + int sym_index = ELFW(R_SYM)(rel->r_info); | |
| 157 | + ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; | |
| 158 | + write64le(p + rel->r_offset, mem ? sym->st_value : s1->plt->sh_addr); | |
| 159 | + } | |
| 160 | + } | |
| 148 | 161 | } |
| 149 | 162 | |
| 150 | 163 | void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val) |
| @@ -16,7 +16,7 @@ · 15 unmodified lines | ||
| 16 | 16 | #define ELF_PAGE_SIZE 0x1000 |
| 17 | 17 | |
| 18 | 18 | #define PCRELATIVE_DLLPLT 0 |
| 19 | −#define RELOCATE_DLLPLT 0 | |
| 19 | +#define RELOCATE_DLLPLT 1 | |
| 20 | 20 | |
| 21 | 21 | #else /* !TARGET_DEFS_ONLY */ |
| 22 | 22 | |
| @@ -121,7 +121,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_ · 98 unmodified lines | ||
| 121 | 121 | /* The PLT slot refers to the relocation entry it needs via offset. |
| 122 | 122 | The reloc entry is created below, so its offset is the current |
| 123 | 123 | data_offset */ |
| 124 | − relofs = s1->got->reloc ? s1->got->reloc->data_offset : 0; | |
| 124 | + relofs = s1->got->relocplt ? s1->got->relocplt->data_offset : 0; | |
| 125 | 125 | |
| 126 | 126 | /* Jump to GOT entry where ld.so initially put the address of ip + 4 */ |
| 127 | 127 | p = section_ptr_add(plt, 16); |
| @@ -129,7 +129,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_ · 1 unmodified line | ||
| 129 | 129 | p[1] = modrm; |
| 130 | 130 | write32le(p + 2, got_offset); |
| 131 | 131 | p[6] = 0x68; /* push $xxx */ |
| 132 | − write32le(p + 7, relofs); | |
| 132 | + write32le(p + 7, relofs - sizeof (ElfW_Rel)); | |
| 133 | 133 | p[11] = 0xe9; /* jmp plt_start */ |
| 134 | 134 | write32le(p + 12, -(plt->data_offset)); |
| 135 | 135 | return plt_offset; |
| @@ -147,7 +147,7 @@ ST_FUNC void relocate_plt(TCCState *s1) · 11 unmodified lines | ||
| 147 | 147 | p = s1->plt->data; |
| 148 | 148 | p_end = p + s1->plt->data_offset; |
| 149 | 149 | |
| 150 | − if (p < p_end) { | |
| 150 | + if (s1->output_type != TCC_OUTPUT_DLL && p < p_end) { | |
| 151 | 151 | add32le(p + 2, s1->got->sh_addr); |
| 152 | 152 | add32le(p + 8, s1->got->sh_addr); |
| 153 | 153 | p += 16; |
| @@ -156,6 +156,20 @@ ST_FUNC void relocate_plt(TCCState *s1) · 2 unmodified lines | ||
| 156 | 156 | p += 16; |
| 157 | 157 | } |
| 158 | 158 | } |
| 159 | + | |
| 160 | + if (s1->got->relocplt) { | |
| 161 | + int mem = s1->output_type == TCC_OUTPUT_MEMORY; | |
| 162 | + ElfW_Rel *rel; | |
| 163 | + int x = s1->plt->sh_addr + 16 + 6; | |
| 164 | + | |
| 165 | + p = s1->got->data; | |
| 166 | + for_each_elem(s1->got->relocplt, 0, rel, ElfW_Rel) { | |
| 167 | + int sym_index = ELFW(R_SYM)(rel->r_info); | |
| 168 | + ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; | |
| 169 | + write32le(p + rel->r_offset, mem ? sym->st_value : x); | |
| 170 | + x += 16; | |
| 171 | + } | |
| 172 | + } | |
| 159 | 173 | } |
| 160 | 174 | #endif |
| 161 | 175 | |
| @@ -1153,7 +1153,8 @@ void __attribute__((destructor)) __bound_exit(void) · 1152 unmodified lines | ||
| 1153 | 1153 | dprintf(stderr, "%s, %s():\n", __FILE__, __FUNCTION__); |
| 1154 | 1154 | |
| 1155 | 1155 | if (inited) { |
| 1156 | −#if !defined(_WIN32) && !defined(__APPLE__) && !defined(__OpenBSD__) && !defined TCC_MUSL | |
| 1156 | +#if !defined(_WIN32) && !defined(__APPLE__) && !defined TCC_MUSL && \ | |
| 1157 | + !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__NetBSD__) | |
| 1157 | 1158 | if (print_heap) { |
| 1158 | 1159 | extern void __libc_freeres (void); |
| 1159 | 1160 | __libc_freeres (); |
| @@ -153,6 +153,18 @@ ST_FUNC void relocate_plt(TCCState *s1) · 152 unmodified lines | ||
| 153 | 153 | p += 16; |
| 154 | 154 | } |
| 155 | 155 | } |
| 156 | + | |
| 157 | + if (s1->got->relocplt) { | |
| 158 | + int mem = s1->output_type == TCC_OUTPUT_MEMORY; | |
| 159 | + ElfW_Rel *rel; | |
| 160 | + | |
| 161 | + p = s1->got->data; | |
| 162 | + for_each_elem(s1->got->relocplt, 0, rel, ElfW_Rel) { | |
| 163 | + int sym_index = ELFW(R_SYM)(rel->r_info); | |
| 164 | + ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; | |
| 165 | + write64le(p + rel->r_offset, mem ? sym->st_value + rel->r_addend : s1->plt->sh_addr); | |
| 166 | + } | |
| 167 | + } | |
| 156 | 168 | } |
| 157 | 169 | |
| 158 | 170 | void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, |
| @@ -397,6 +397,7 @@ extern long double strtold (const char *__nptr, char **__endptr); · 396 unmodified lines | ||
| 397 | 397 | # define ElfW_Rel ElfW(Rela) |
| 398 | 398 | # define SHT_RELX SHT_RELA |
| 399 | 399 | # define REL_SECTION_FMT ".rela%s" |
| 400 | +# define RELPLT_SECTION_FMT ".rel.plt" | |
| 400 | 401 | #else |
| 401 | 402 | # define ELFCLASSW ELFCLASS32 |
| 402 | 403 | # define ElfW(type) Elf##32##_##type |
| @@ -404,6 +405,7 @@ extern long double strtold (const char *__nptr, char **__endptr); · 1 unmodified line | ||
| 404 | 405 | # define ElfW_Rel ElfW(Rel) |
| 405 | 406 | # define SHT_RELX SHT_REL |
| 406 | 407 | # define REL_SECTION_FMT ".rel%s" |
| 408 | +# define RELPLT_SECTION_FMT ".rel.plt" | |
| 407 | 409 | #endif |
| 408 | 410 | /* target address type */ |
| 409 | 411 | #define addr_t ElfW(Addr) |
| @@ -565,6 +567,7 @@ typedef struct Section { · 155 unmodified lines | ||
| 565 | 567 | struct Section *reloc; /* corresponding section for relocation, if any */ |
| 566 | 568 | struct Section *hash; /* hash table for symbols */ |
| 567 | 569 | struct Section *prev; /* previous section on section stack */ |
| 570 | + struct Section *relocplt;/* reloc with JMP_SLOTs */ | |
| 568 | 571 | char name[1]; /* section name */ |
| 569 | 572 | } Section; |
| 570 | 573 | |
| @@ -735,18 +735,25 @@ ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset, · 734 unmodified lines | ||
| 735 | 735 | char buf[256]; |
| 736 | 736 | Section *sr; |
| 737 | 737 | ElfW_Rel *rel; |
| 738 | + int jmp_slot = type == R_JMP_SLOT; | |
| 738 | 739 | |
| 739 | − sr = s->reloc; | |
| 740 | + sr = jmp_slot ? s->relocplt : s->reloc; | |
| 740 | 741 | if (!sr) { |
| 741 | 742 | /* if no relocation section, create it */ |
| 742 | − snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name); | |
| 743 | + if (jmp_slot) | |
| 744 | + snprintf(buf, sizeof(buf), RELPLT_SECTION_FMT); | |
| 745 | + else | |
| 746 | + snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name); | |
| 743 | 747 | /* if the symtab is allocated, then we consider the relocation |
| 744 | 748 | are also */ |
| 745 | 749 | sr = new_section(s->s1, buf, SHT_RELX, symtab->sh_flags); |
| 746 | 750 | sr->sh_entsize = sizeof(ElfW_Rel); |
| 747 | 751 | sr->link = symtab; |
| 748 | 752 | sr->sh_info = s->sh_num; |
| 749 | − s->reloc = sr; | |
| 753 | + if (jmp_slot) | |
| 754 | + s->relocplt = sr; | |
| 755 | + else | |
| 756 | + s->reloc = sr; | |
| 750 | 757 | } |
| 751 | 758 | rel = section_ptr_add(sr, sizeof(ElfW_Rel)); |
| 752 | 759 | rel->r_offset = offset; |
| @@ -1164,7 +1171,7 @@ static struct sym_attr * put_got_entry(TCCState *s1, int dyn_reloc_type, · 411 unmodified lines | ||
| 1164 | 1171 | } |
| 1165 | 1172 | |
| 1166 | 1173 | /* build GOT and PLT entries */ |
| 1167 | −ST_FUNC void build_got_entries(TCCState *s1) | |
| 1174 | +static void build_got_entries_pass(TCCState *s1, int pass) | |
| 1168 | 1175 | { |
| 1169 | 1176 | Section *s; |
| 1170 | 1177 | ElfW_Rel *rel; |
| @@ -1235,6 +1242,8 @@ ST_FUNC void build_got_entries(TCCState *s1) · 64 unmodified lines | ||
| 1235 | 1242 | (ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT || |
| 1236 | 1243 | ELFW(ST_BIND)(sym->st_info) == STB_LOCAL || |
| 1237 | 1244 | s1->output_type == TCC_OUTPUT_EXE)) { |
| 1245 | + if (pass == 0) | |
| 1246 | + continue; | |
| 1238 | 1247 | rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32); |
| 1239 | 1248 | continue; |
| 1240 | 1249 | } |
| @@ -1248,6 +1257,11 @@ ST_FUNC void build_got_entries(TCCState *s1) · 7 unmodified lines | ||
| 1248 | 1257 | } else |
| 1249 | 1258 | reloc_type = R_GLOB_DAT; |
| 1250 | 1259 | |
| 1260 | + | |
| 1261 | + if ((pass == 0 && reloc_type == R_GLOB_DAT) || | |
| 1262 | + (pass == 1 && reloc_type == R_JMP_SLOT)) | |
| 1263 | + continue; | |
| 1264 | + | |
| 1251 | 1265 | if (!s1->got) |
| 1252 | 1266 | build_got(s1); |
| 1253 | 1267 | |
| @@ -1261,6 +1275,16 @@ ST_FUNC void build_got_entries(TCCState *s1) · 7 unmodified lines | ||
| 1261 | 1275 | } |
| 1262 | 1276 | } |
| 1263 | 1277 | } |
| 1278 | + | |
| 1279 | +ST_FUNC void build_got_entries(TCCState *s1) | |
| 1280 | +{ | |
| 1281 | + int i; | |
| 1282 | + | |
| 1283 | + /* Two passes because R_JMP_SLOT should become first. | |
| 1284 | + Some targets (arm, arm64) do not allow mixing R_JMP_SLOT and R_GLOB_DAT. */ | |
| 1285 | + for (i = 0; i < 2; i++) | |
| 1286 | + build_got_entries_pass(s1, i); | |
| 1287 | +} | |
| 1264 | 1288 | #endif |
| 1265 | 1289 | |
| 1266 | 1290 | ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t offs) |
| @@ -1801,7 +1825,7 @@ struct dyn_inf { · 534 unmodified lines | ||
| 1801 | 1825 | unsigned long data_offset; |
| 1802 | 1826 | addr_t rel_addr; |
| 1803 | 1827 | addr_t rel_size; |
| 1804 | −#if TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel | |
| 1828 | +#if PTR_SIZE == 4 && (TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel) | |
| 1805 | 1829 | addr_t bss_addr; |
| 1806 | 1830 | addr_t bss_size; |
| 1807 | 1831 | #endif |
| @@ -1861,11 +1885,13 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, · 53 unmodified lines | ||
| 1861 | 1885 | |
| 1862 | 1886 | /* dynamic relocation table information, for .dynamic section */ |
| 1863 | 1887 | dyninf->rel_addr = dyninf->rel_size = 0; |
| 1864 | −#if TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel | |
| 1888 | +#if PTR_SIZE == 4 && (TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel) | |
| 1865 | 1889 | dyninf->bss_addr = dyninf->bss_size = 0; |
| 1866 | 1890 | #endif |
| 1867 | 1891 | |
| 1868 | 1892 | for(j = 0; j < (phnum == 6 ? 3 : 2); j++) { |
| 1893 | + Section *relocplt = s1->got ? s1->got->relocplt : NULL; | |
| 1894 | + | |
| 1869 | 1895 | ph->p_type = j == 2 ? PT_TLS : PT_LOAD; |
| 1870 | 1896 | if (j == 0) |
| 1871 | 1897 | ph->p_flags = PF_R | PF_X; |
| @@ -1878,7 +1904,7 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, · 6 unmodified lines | ||
| 1878 | 1904 | info about the layout. We do the following ordering: interp, |
| 1879 | 1905 | symbol tables, relocations, progbits, nobits */ |
| 1880 | 1906 | /* XXX: do faster and simpler sorting */ |
| 1881 | − for(k = 0; k < 5; k++) { | |
| 1907 | + for(k = 0; k < 6; k++) { | |
| 1882 | 1908 | for(i = 1; i < s1->nb_sections; i++) { |
| 1883 | 1909 | s = s1->sections[i]; |
| 1884 | 1910 | /* compute if section should be included */ |
| @@ -1905,13 +1931,15 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, · 20 unmodified lines | ||
| 1905 | 1931 | if (k != 1) |
| 1906 | 1932 | continue; |
| 1907 | 1933 | } else if (s->sh_type == SHT_RELX) { |
| 1908 | − if (k != 2) | |
| 1934 | + if (k != 2 && s != relocplt) | |
| 1935 | + continue; | |
| 1936 | + else if (k != 3 && s == relocplt) | |
| 1909 | 1937 | continue; |
| 1910 | 1938 | } else if (s->sh_type == SHT_NOBITS) { |
| 1911 | − if (k != 4) | |
| 1939 | + if (k != 5) | |
| 1912 | 1940 | continue; |
| 1913 | 1941 | } else { |
| 1914 | − if (k != 3) | |
| 1942 | + if (k != 4) | |
| 1915 | 1943 | continue; |
| 1916 | 1944 | } |
| 1917 | 1945 | sec_order[sh_order_index++] = i; |
| @@ -1931,8 +1959,8 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, · 13 unmodified lines | ||
| 1931 | 1959 | ph->p_paddr = ph->p_vaddr; |
| 1932 | 1960 | } |
| 1933 | 1961 | /* update dynamic relocation infos */ |
| 1934 | − if (s->sh_type == SHT_RELX) { | |
| 1935 | −#if TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel | |
| 1962 | + if (s->sh_type == SHT_RELX && s != relocplt) { | |
| 1963 | +#if PTR_SIZE == 4 && (TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel) | |
| 1936 | 1964 | if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { |
| 1937 | 1965 | dyninf->rel_addr = addr; |
| 1938 | 1966 | dyninf->rel_size += s->sh_size; /* XXX only first rel. */ |
| @@ -2079,16 +2107,17 @@ static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf) · 140 unmodified lines | ||
| 2079 | 2107 | put_dt(dynamic, DT_RELA, dyninf->rel_addr); |
| 2080 | 2108 | put_dt(dynamic, DT_RELASZ, dyninf->rel_size); |
| 2081 | 2109 | put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel)); |
| 2082 | −#if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD | |
| 2083 | − put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr); | |
| 2084 | − put_dt(dynamic, DT_PLTRELSZ, dyninf->rel_size); | |
| 2085 | − put_dt(dynamic, DT_JMPREL, dyninf->rel_addr); | |
| 2086 | − put_dt(dynamic, DT_PLTREL, DT_RELA); | |
| 2087 | − put_dt(dynamic, DT_BIND_NOW, 1); /* Dirty hack */ | |
| 2088 | −#endif | |
| 2110 | + if (s1->got && s1->got->relocplt) { | |
| 2111 | + put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr); | |
| 2112 | + put_dt(dynamic, DT_PLTRELSZ, s1->got->relocplt->data_offset); | |
| 2113 | + put_dt(dynamic, DT_JMPREL, s1->got->relocplt->sh_addr); | |
| 2114 | + put_dt(dynamic, DT_PLTREL, DT_RELA); | |
| 2115 | + } | |
| 2116 | + put_dt(dynamic, DT_RELACOUNT, 0); | |
| 2089 | 2117 | #else |
| 2090 | −#if TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel | |
| 2091 | − put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr); | |
| 2118 | +#if PTR_SIZE == 4 && (TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel) | |
| 2119 | + if (s1->got) | |
| 2120 | + put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr); | |
| 2092 | 2121 | put_dt(dynamic, DT_PLTRELSZ, dyninf->rel_size); |
| 2093 | 2122 | put_dt(dynamic, DT_JMPREL, dyninf->rel_addr); |
| 2094 | 2123 | put_dt(dynamic, DT_PLTREL, DT_REL); |
| @@ -2098,11 +2127,18 @@ static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf) · 3 unmodified lines | ||
| 2098 | 2127 | put_dt(dynamic, DT_REL, dyninf->rel_addr); |
| 2099 | 2128 | put_dt(dynamic, DT_RELSZ, dyninf->rel_size); |
| 2100 | 2129 | put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel)); |
| 2130 | + if (s1->got && s1->got->relocplt) { | |
| 2131 | + put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr); | |
| 2132 | + put_dt(dynamic, DT_PLTRELSZ, s1->got->relocplt->data_offset); | |
| 2133 | + put_dt(dynamic, DT_JMPREL, s1->got->relocplt->sh_addr); | |
| 2134 | + put_dt(dynamic, DT_PLTREL, DT_REL); | |
| 2135 | + } | |
| 2136 | + put_dt(dynamic, DT_RELCOUNT, 0); | |
| 2101 | 2137 | #endif |
| 2102 | 2138 | #endif |
| 2103 | − if (versym_section) | |
| 2139 | + if (versym_section && verneed_section) { | |
| 2140 | + /* The dynamic linker can not handle VERSYM without VERNEED */ | |
| 2104 | 2141 | put_dt(dynamic, DT_VERSYM, versym_section->sh_addr); |
| 2105 | − if (verneed_section) { | |
| 2106 | 2142 | put_dt(dynamic, DT_VERNEED, verneed_section->sh_addr); |
| 2107 | 2143 | put_dt(dynamic, DT_VERNEEDNUM, dt_verneednum); |
| 2108 | 2144 | } |
| @@ -2406,10 +2442,12 @@ static void create_arm_attribute_section(TCCState *s1) · 297 unmodified lines | ||
| 2406 | 2442 | } |
| 2407 | 2443 | #endif |
| 2408 | 2444 | |
| 2409 | −#if TARGETOS_OpenBSD | |
| 2410 | −static Section *create_openbsd_note_section(TCCState *s1) | |
| 2445 | +#if TARGETOS_OpenBSD || TARGETOS_NetBSD | |
| 2446 | +static Section *create_bsd_note_section(TCCState *s1, | |
| 2447 | + const char *name, | |
| 2448 | + const char *value) | |
| 2411 | 2449 | { |
| 2412 | − Section *s = find_section (s1, ".note.openbsd.ident"); | |
| 2450 | + Section *s = find_section (s1, name); | |
| 2413 | 2451 | |
| 2414 | 2452 | if (s->data_offset == 0) { |
| 2415 | 2453 | unsigned char *ptr = section_ptr_add(s, sizeof(ElfW(Nhdr)) + 8 + 4); |
| @@ -2419,7 +2457,7 @@ static Section *create_openbsd_note_section(TCCState *s1) · 3 unmodified lines | ||
| 2419 | 2457 | note->n_namesz = 8; |
| 2420 | 2458 | note->n_descsz = 4; |
| 2421 | 2459 | note->n_type = ELF_NOTE_OS_GNU; |
| 2422 | − strcpy (ptr + sizeof(ElfW(Nhdr)), "OpenBSD"); | |
| 2460 | + strcpy (ptr + sizeof(ElfW(Nhdr)), value); | |
| 2423 | 2461 | } |
| 2424 | 2462 | return s; |
| 2425 | 2463 | } |
| @@ -2441,7 +2479,11 @@ static int elf_output_file(TCCState *s1, const char *filename) · 15 unmodified lines | ||
| 2441 | 2479 | #endif |
| 2442 | 2480 | #if TARGETOS_OpenBSD |
| 2443 | 2481 | if (file_type != TCC_OUTPUT_OBJ) |
| 2444 | − note = create_openbsd_note_section (s1); | |
| 2482 | + note = create_bsd_note_section (s1, ".note.openbsd.ident", "OpenBSD"); | |
| 2483 | +#endif | |
| 2484 | +#if TARGETOS_NetBSD | |
| 2485 | + if (file_type != TCC_OUTPUT_OBJ) | |
| 2486 | + note = create_bsd_note_section (s1, ".note.netbsd.ident", "NetBSD"); | |
| 2445 | 2487 | #endif |
| 2446 | 2488 | |
| 2447 | 2489 | s1->nb_errors = 0; |
| @@ -2814,8 +2856,13 @@ ST_FUNC int tcc_load_object_file(TCCState *s1, · 366 unmodified lines | ||
| 2814 | 2856 | sm_table[i].new_section = 1; |
| 2815 | 2857 | found: |
| 2816 | 2858 | if (sh->sh_type != s->sh_type) { |
| 2817 | − tcc_error_noabort("invalid section type"); | |
| 2818 | − goto fail; | |
| 2859 | +#if TARGETOS_OpenBSD | |
| 2860 | + if (strcmp (s->name, ".eh_frame") || sh->sh_type != SHT_PROGBITS) | |
| 2861 | +#endif | |
| 2862 | + { | |
| 2863 | + tcc_error_noabort("invalid section type"); | |
| 2864 | + goto fail; | |
| 2865 | + } | |
| 2819 | 2866 | } |
| 2820 | 2867 | /* align start of section */ |
| 2821 | 2868 | s->data_offset += -s->data_offset & (sh->sh_addralign - 1); |
| @@ -61,6 +61,9 @@ endif · 60 unmodified lines | ||
| 61 | 61 | ifeq ($(CC_NAME),msvc) |
| 62 | 62 | test.ref abitest : CC = gcc |
| 63 | 63 | endif |
| 64 | +ifeq ($(TARGETOS),OpenBSD) | |
| 65 | +dlltest: CFLAGS+=-fno-stack-protector | |
| 66 | +endif | |
| 64 | 67 | |
| 65 | 68 | RUN_TCC = $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS) |
| 66 | 69 | DISAS = objdump -d |
| @@ -48,6 +48,10 @@ ifeq (-$(CONFIG_WIN32)-,-yes-) · 47 unmodified lines | ||
| 48 | 48 | SKIP += 106_pthread.test # No pthread support |
| 49 | 49 | SKIP += 114_bound_signal.test # No pthread support |
| 50 | 50 | endif |
| 51 | +ifneq (,$(filter OpenBSD FreeBSD NetBSD,$(TARGETOS))) | |
| 52 | + SKIP += 106_pthread.test # no pthread_condattr_setpshared | |
| 53 | + SKIP += 114_bound_signal.test # libc problem signal/fork | |
| 54 | +endif | |
| 51 | 55 | |
| 52 | 56 | # Some tests might need arguments |
| 53 | 57 | ARGS = |
| @@ -131,7 +131,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_ · 130 unmodified lines | ||
| 131 | 131 | /* The PLT slot refers to the relocation entry it needs via offset. |
| 132 | 132 | The reloc entry is created below, so its offset is the current |
| 133 | 133 | data_offset */ |
| 134 | − relofs = s1->got->reloc ? s1->got->reloc->data_offset : 0; | |
| 134 | + relofs = s1->got->relocplt ? s1->got->relocplt->data_offset : 0; | |
| 135 | 135 | |
| 136 | 136 | /* Jump to GOT entry where ld.so initially put the address of ip + 4 */ |
| 137 | 137 | p = section_ptr_add(plt, 16); |
| @@ -140,7 +140,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_ · 2 unmodified lines | ||
| 140 | 140 | write32le(p + 2, got_offset); |
| 141 | 141 | p[6] = 0x68; /* push $xxx */ |
| 142 | 142 | /* On x86-64, the relocation is referred to by _index_ */ |
| 143 | − write32le(p + 7, relofs / sizeof (ElfW_Rel)); | |
| 143 | + write32le(p + 7, relofs / sizeof (ElfW_Rel) - 1); | |
| 144 | 144 | p[11] = 0xe9; /* jmp plt_start */ |
| 145 | 145 | write32le(p + 12, -(plt->data_offset)); |
| 146 | 146 | return plt_offset; |
| @@ -168,6 +168,20 @@ ST_FUNC void relocate_plt(TCCState *s1) · 21 unmodified lines | ||
| 168 | 168 | p += 16; |
| 169 | 169 | } |
| 170 | 170 | } |
| 171 | + | |
| 172 | + if (s1->got->relocplt) { | |
| 173 | + int mem = s1->output_type == TCC_OUTPUT_MEMORY; | |
| 174 | + ElfW_Rel *rel; | |
| 175 | + int x = s1->plt->sh_addr + 16 + 6; | |
| 176 | + | |
| 177 | + p = s1->got->data; | |
| 178 | + for_each_elem(s1->got->relocplt, 0, rel, ElfW_Rel) { | |
| 179 | + int sym_index = ELFW(R_SYM)(rel->r_info); | |
| 180 | + ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; | |
| 181 | + write64le(p + rel->r_offset, mem ? sym->st_value : x); | |
| 182 | + x += 16; | |
| 183 | + } | |
| 184 | + } | |
| 171 | 185 | } |
| 172 | 186 | #endif |
| 173 | 187 | #endif |