Allows to create dynamic executables, using the code path for TCC_OUTPUT_DLL but add an .interp header (plus a FLAGS_1 entry in the dynamic section to make 'readelf' say "PIE") Introduces TCC_OUTPUT_DYN as alias for TCC_OUTPUT_DLL. There is no runtime option, only one to configure: ./configure --config-pie 100 insertions(+), 76 deletions(-)
Unified · Split
| @@ -91,6 +91,7 @@ NATIVE_DEFINES_$(CONFIG_arm64) += -DTCC_TARGET_ARM64 · 90 unmodified lines | ||
| 91 | 91 | NATIVE_DEFINES_$(CONFIG_riscv64) += -DTCC_TARGET_RISCV64 |
| 92 | 92 | NATIVE_DEFINES_$(CONFIG_BSD) += -DTARGETOS_$(TARGETOS) |
| 93 | 93 | NATIVE_DEFINES_$(CONFIG_pie) += -DCONFIG_TCC_PIE |
| 94 | +NATIVE_DEFINES_$(CONFIG_pic) += -DCONFIG_TCC_PIC | |
| 94 | 95 | NATIVE_DEFINES_no_$(CONFIG_bcheck) += -DCONFIG_TCC_BCHECK=0 |
| 95 | 96 | NATIVE_DEFINES_no_$(CONFIG_backtrace) += -DCONFIG_TCC_BACKTRACE=0 |
| 96 | 97 | NATIVE_DEFINES += $(NATIVE_DEFINES_yes) $(NATIVE_DEFINES_no_no) |
| @@ -275,7 +276,7 @@ libtcc.a: $(LIBTCC_OBJ) · 178 unmodified lines | ||
| 275 | 276 | |
| 276 | 277 | # dynamic libtcc library |
| 277 | 278 | libtcc.so: $(LIBTCC_OBJ) |
| 278 | − $S$(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LDFLAGS) | |
| 279 | + $S$(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LIBS) $(LDFLAGS) | |
| 279 | 280 | |
| 280 | 281 | libtcc.so: CFLAGS+=-fPIC |
| 281 | 282 | libtcc.so: LDFLAGS+=-fPIC |
| @@ -543,7 +543,7 @@ static void load_value(SValue *sv, int r) · 542 unmodified lines | ||
| 543 | 543 | { |
| 544 | 544 | o(0xE59F0000|(intr(r)<<12)); /* ldr r, [pc] */ |
| 545 | 545 | o(0xEA000000); /* b $+4 */ |
| 546 | −#ifndef CONFIG_TCC_PIE | |
| 546 | +#ifndef CONFIG_TCC_PIC | |
| 547 | 547 | if(sv->r & VT_SYM) |
| 548 | 548 | greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32); |
| 549 | 549 | o(sv->c.i); |
| @@ -380,7 +380,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t · 379 unmodified lines | ||
| 380 | 380 | return; |
| 381 | 381 | case R_ARM_ABS32: |
| 382 | 382 | case R_ARM_TARGET1: |
| 383 | − if (s1->output_type == TCC_OUTPUT_DLL) { | |
| 383 | + if (s1->output_type & TCC_OUTPUT_DYN) { | |
| 384 | 384 | esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index; |
| 385 | 385 | qrel->r_offset = rel->r_offset; |
| 386 | 386 | if (esym_index) { |
| @@ -177,7 +177,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t · 176 unmodified lines | ||
| 177 | 177 | |
| 178 | 178 | switch(type) { |
| 179 | 179 | case R_AARCH64_ABS64: |
| 180 | − if (s1->output_type == TCC_OUTPUT_DLL) { | |
| 180 | + if ((s1->output_type & TCC_OUTPUT_DYN)) { | |
| 181 | 181 | esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index; |
| 182 | 182 | qrel->r_offset = rel->r_offset; |
| 183 | 183 | if (esym_index) { |
| @@ -194,7 +194,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t · 10 unmodified lines | ||
| 194 | 194 | add64le(ptr, val); |
| 195 | 195 | return; |
| 196 | 196 | case R_AARCH64_ABS32: |
| 197 | − if (s1->output_type == TCC_OUTPUT_DLL) { | |
| 197 | + if (s1->output_type & TCC_OUTPUT_DYN) { | |
| 198 | 198 | /* XXX: this logic may depend on TCC's codegen |
| 199 | 199 | now TCC uses R_AARCH64_RELATIVE even for a 64bit pointer */ |
| 200 | 200 | qrel->r_offset = rel->r_offset; |
| @@ -825,6 +825,7 @@ typedef struct · 824 unmodified lines | ||
| 825 | 825 | #define DF_1_SYMINTPOSE 0x00800000 /* Object has individual interposers. */ |
| 826 | 826 | #define DF_1_GLOBAUDIT 0x01000000 /* Global auditing required. */ |
| 827 | 827 | #define DF_1_SINGLETON 0x02000000 /* Singleton symbols are used. */ |
| 828 | +#define DF_1_PIE 0x08000000 | |
| 828 | 829 | |
| 829 | 830 | /* Flags for the feature selection in DT_FEATURE_1. */ |
| 830 | 831 | #define DTF_1_PARINIT 0x00000001 |
| @@ -100,7 +100,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_ · 99 unmodified lines | ||
| 100 | 100 | unsigned plt_offset, relofs; |
| 101 | 101 | |
| 102 | 102 | /* on i386 if we build a DLL, we add a %ebx offset */ |
| 103 | − if (s1->output_type == TCC_OUTPUT_DLL) | |
| 103 | + if (s1->output_type & TCC_OUTPUT_DYN) | |
| 104 | 104 | modrm = 0xa3; |
| 105 | 105 | else |
| 106 | 106 | modrm = 0x25; |
| @@ -148,7 +148,7 @@ ST_FUNC void relocate_plt(TCCState *s1) · 41 unmodified lines | ||
| 148 | 148 | p = s1->plt->data; |
| 149 | 149 | p_end = p + s1->plt->data_offset; |
| 150 | 150 | |
| 151 | − if (s1->output_type != TCC_OUTPUT_DLL && p < p_end) { | |
| 151 | + if (!(s1->output_type & TCC_OUTPUT_DYN) && p < p_end) { | |
| 152 | 152 | add32le(p + 2, s1->got->sh_addr); |
| 153 | 153 | add32le(p + 8, s1->got->sh_addr); |
| 154 | 154 | p += 16; |
| @@ -179,7 +179,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t · 24 unmodified lines | ||
| 179 | 179 | |
| 180 | 180 | switch (type) { |
| 181 | 181 | case R_386_32: |
| 182 | − if (s1->output_type == TCC_OUTPUT_DLL) { | |
| 182 | + if (s1->output_type & TCC_OUTPUT_DYN) { | |
| 183 | 183 | esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index; |
| 184 | 184 | qrel->r_offset = rel->r_offset; |
| 185 | 185 | if (esym_index) { |
| @@ -862,6 +862,10 @@ LIBTCCAPI void tcc_delete(TCCState *s1) · 861 unmodified lines | ||
| 862 | 862 | |
| 863 | 863 | LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) |
| 864 | 864 | { |
| 865 | +#ifdef CONFIG_TCC_PIE | |
| 866 | + if (output_type == TCC_OUTPUT_EXE) | |
| 867 | + output_type |= TCC_OUTPUT_DYN; | |
| 868 | +#endif | |
| 865 | 869 | s->output_type = output_type; |
| 866 | 870 | |
| 867 | 871 | if (!s->nostdinc) { |
| @@ -869,6 +873,10 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) · 1 unmodified line | ||
| 869 | 873 | /* -isystem paths have already been handled */ |
| 870 | 874 | tcc_add_sysinclude_path(s, CONFIG_TCC_SYSINCLUDEPATHS); |
| 871 | 875 | } |
| 876 | + | |
| 877 | + if (output_type == TCC_OUTPUT_PREPROCESS) | |
| 878 | + return 0; | |
| 879 | + | |
| 872 | 880 | #ifdef CONFIG_TCC_BCHECK |
| 873 | 881 | if (s->do_bounds_check) { |
| 874 | 882 | /* if bound checking, then add corresponding sections */ |
| @@ -905,13 +913,13 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) · 30 unmodified lines | ||
| 905 | 913 | #else |
| 906 | 914 | /* paths for crt objects */ |
| 907 | 915 | tcc_split_path(s, &s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX); |
| 916 | + | |
| 908 | 917 | /* add libc crt1/crti objects */ |
| 909 | − if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) && | |
| 910 | − !s->nostdlib) { | |
| 918 | + if (output_type != TCC_OUTPUT_MEMORY && !s->nostdlib) { | |
| 911 | 919 | #if TARGETOS_OpenBSD |
| 912 | 920 | if (output_type != TCC_OUTPUT_DLL) |
| 913 | 921 | tcc_add_crt(s, "crt0.o"); |
| 914 | − if (output_type == TCC_OUTPUT_DLL) | |
| 922 | + if (output_type & TCC_OUTPUT_DYN) | |
| 915 | 923 | tcc_add_crt(s, "crtbeginS.o"); |
| 916 | 924 | else |
| 917 | 925 | tcc_add_crt(s, "crtbegin.o"); |
| @@ -921,7 +929,7 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) · 3 unmodified lines | ||
| 921 | 929 | tcc_add_crt(s, "crti.o"); |
| 922 | 930 | if (s->static_link) |
| 923 | 931 | tcc_add_crt(s, "crtbeginT.o"); |
| 924 | − else if (output_type == TCC_OUTPUT_DLL) | |
| 932 | + else if (output_type & TCC_OUTPUT_DYN) | |
| 925 | 933 | tcc_add_crt(s, "crtbeginS.o"); |
| 926 | 934 | else |
| 927 | 935 | tcc_add_crt(s, "crtbegin.o"); |
| @@ -931,7 +939,7 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) · 3 unmodified lines | ||
| 931 | 939 | tcc_add_crt(s, "crti.o"); |
| 932 | 940 | if (s->static_link) |
| 933 | 941 | tcc_add_crt(s, "crtbeginT.o"); |
| 934 | − else if (output_type == TCC_OUTPUT_DLL) | |
| 942 | + else if (output_type & TCC_OUTPUT_DYN) | |
| 935 | 943 | tcc_add_crt(s, "crtbeginS.o"); |
| 936 | 944 | else |
| 937 | 945 | tcc_add_crt(s, "crtbegin.o"); |
| @@ -65,11 +65,11 @@ LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf); · 64 unmodified lines | ||
| 65 | 65 | |
| 66 | 66 | /* set output type. MUST BE CALLED before any compilation */ |
| 67 | 67 | LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type); |
| 68 | −#define TCC_OUTPUT_MEMORY 1 /* output will be run in memory (default) */ | |
| 68 | +#define TCC_OUTPUT_MEMORY 1 /* output will be run in memory */ | |
| 69 | 69 | #define TCC_OUTPUT_EXE 2 /* executable file */ |
| 70 | −#define TCC_OUTPUT_DLL 3 /* dynamic library */ | |
| 71 | −#define TCC_OUTPUT_OBJ 4 /* object file */ | |
| 72 | −#define TCC_OUTPUT_PREPROCESS 5 /* only preprocess (used internally) */ | |
| 70 | +#define TCC_OUTPUT_DLL 4 /* dynamic library */ | |
| 71 | +#define TCC_OUTPUT_OBJ 3 /* object file */ | |
| 72 | +#define TCC_OUTPUT_PREPROCESS 5 /* only preprocess */ | |
| 73 | 73 | |
| 74 | 74 | /* equivalent to -Lpath option */ |
| 75 | 75 | LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname); |
| @@ -284,7 +284,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, · 283 unmodified lines | ||
| 284 | 284 | return; |
| 285 | 285 | |
| 286 | 286 | case R_RISCV_32: |
| 287 | − if (s1->output_type == TCC_OUTPUT_DLL) { | |
| 287 | + if (s1->output_type & TCC_OUTPUT_DYN) { | |
| 288 | 288 | /* XXX: this logic may depend on TCC's codegen |
| 289 | 289 | now TCC uses R_RISCV_RELATIVE even for a 64bit pointer */ |
| 290 | 290 | qrel->r_offset = rel->r_offset; |
| @@ -296,7 +296,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, · 5 unmodified lines | ||
| 296 | 296 | add32le(ptr, val); |
| 297 | 297 | return; |
| 298 | 298 | case R_RISCV_64: |
| 299 | − if (s1->output_type == TCC_OUTPUT_DLL) { | |
| 299 | + if (s1->output_type & TCC_OUTPUT_DYN) { | |
| 300 | 300 | esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index; |
| 301 | 301 | qrel->r_offset = rel->r_offset; |
| 302 | 302 | if (esym_index) { |
| @@ -236,6 +236,10 @@ extern long double strtold (const char *__nptr, char **__endptr); · 235 unmodified lines | ||
| 236 | 236 | # define TCC_USING_DOUBLE_FOR_LDOUBLE 1 |
| 237 | 237 | #endif |
| 238 | 238 | |
| 239 | +#ifdef CONFIG_TCC_PIE | |
| 240 | +# define CONFIG_TCC_PIC 1 | |
| 241 | +#endif | |
| 242 | + | |
| 239 | 243 | /* ------------ path configuration ------------ */ |
| 240 | 244 | |
| 241 | 245 | #ifndef CONFIG_SYSROOT |
| @@ -1485,6 +1489,7 @@ ST_DATA int func_bound_add_epilog; · 1243 unmodified lines | ||
| 1485 | 1489 | #define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */ |
| 1486 | 1490 | #define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */ |
| 1487 | 1491 | #define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */ |
| 1492 | +#define TCC_OUTPUT_DYN TCC_OUTPUT_DLL | |
| 1488 | 1493 | |
| 1489 | 1494 | #define ARMAG "!<arch>\012" /* For COFF and a.out archives */ |
| 1490 | 1495 | |
| @@ -392,9 +392,7 @@ ST_FUNC void tcc_debug_new(TCCState *s1) · 391 unmodified lines | ||
| 392 | 392 | #ifdef CONFIG_TCC_BACKTRACE |
| 393 | 393 | /* include stab info with standalone backtrace support */ |
| 394 | 394 | if (s1->do_backtrace |
| 395 | − && (s1->output_type == TCC_OUTPUT_EXE | |
| 396 | − || s1->output_type == TCC_OUTPUT_DLL) | |
| 397 | − ) | |
| 395 | + && (s1->output_type & (TCC_OUTPUT_EXE | TCC_OUTPUT_DLL))) | |
| 398 | 396 | shf = SHF_ALLOC | SHF_WRITE; // SHF_WRITE needed for musl/SELINUX |
| 399 | 397 | #endif |
| 400 | 398 | if (s1->dwarf) { |
| @@ -928,12 +928,16 @@ static void relocate_section(TCCState *s1, Section *s, Section *sr) · 927 unmodified lines | ||
| 928 | 928 | /* if the relocation is allocated, we change its symbol table */ |
| 929 | 929 | if (sr->sh_flags & SHF_ALLOC) { |
| 930 | 930 | sr->link = s1->dynsym; |
| 931 | − if (s1->output_type == TCC_OUTPUT_DLL) { | |
| 931 | + if (s1->output_type & TCC_OUTPUT_DYN) { | |
| 932 | 932 | size_t r = (uint8_t*)qrel - sr->data; |
| 933 | 933 | if (sizeof ((Stab_Sym*)0)->n_value < PTR_SIZE |
| 934 | 934 | && 0 == strcmp(s->name, ".stab")) |
| 935 | 935 | r = 0; /* cannot apply 64bit relocation to 32bit value */ |
| 936 | 936 | sr->data_offset = sr->sh_size = r; |
| 937 | +#ifdef CONFIG_TCC_PIE | |
| 938 | + if (r && 0 == (s->sh_flags & SHF_WRITE)) | |
| 939 | + tcc_warning("%d relocations to ro-section %s", (unsigned)(r / sizeof *qrel), s->name); | |
| 940 | +#endif | |
| 937 | 941 | } |
| 938 | 942 | } |
| 939 | 943 | #endif |
| @@ -1013,7 +1017,6 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr) · 73 unmodified lines | ||
| 1013 | 1017 | case R_X86_64_PC32: |
| 1014 | 1018 | { |
| 1015 | 1019 | ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; |
| 1016 | − | |
| 1017 | 1020 | /* Hidden defined symbols can and must be resolved locally. |
| 1018 | 1021 | We're misusing a PLT32 reloc for this, as that's always |
| 1019 | 1022 | resolved to its address even in shared libs. */ |
| @@ -1026,6 +1029,8 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr) · 6 unmodified lines | ||
| 1026 | 1029 | #elif defined(TCC_TARGET_ARM64) |
| 1027 | 1030 | case R_AARCH64_PREL32: |
| 1028 | 1031 | #endif |
| 1032 | + if (s1->output_type != TCC_OUTPUT_DLL) | |
| 1033 | + break; | |
| 1029 | 1034 | if (get_sym_attr(s1, sym_index, 0)->dyn_index) |
| 1030 | 1035 | count++; |
| 1031 | 1036 | break; |
| @@ -1188,7 +1193,8 @@ redo: · 156 unmodified lines | ||
| 1188 | 1193 | if (sym->st_shndx == SHN_UNDEF) { |
| 1189 | 1194 | ElfW(Sym) *esym; |
| 1190 | 1195 | int dynindex; |
| 1191 | − if (s1->output_type == TCC_OUTPUT_DLL && ! PCRELATIVE_DLLPLT) | |
| 1196 | + if (!PCRELATIVE_DLLPLT | |
| 1197 | + && (s1->output_type & TCC_OUTPUT_DYN)) | |
| 1192 | 1198 | continue; |
| 1193 | 1199 | /* Relocations for UNDEF symbols would normally need |
| 1194 | 1200 | to be transferred into the executable or shared object. |
| @@ -1228,7 +1234,7 @@ redo: · 33 unmodified lines | ||
| 1228 | 1234 | sym->st_shndx != SHN_UNDEF && |
| 1229 | 1235 | (ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT || |
| 1230 | 1236 | ELFW(ST_BIND)(sym->st_info) == STB_LOCAL || |
| 1231 | − s1->output_type == TCC_OUTPUT_EXE)) { | |
| 1237 | + s1->output_type & TCC_OUTPUT_EXE)) { | |
| 1232 | 1238 | if (pass != 0) |
| 1233 | 1239 | continue; |
| 1234 | 1240 | rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32); |
| @@ -1483,7 +1489,7 @@ ST_FUNC void tcc_add_runtime(TCCState *s1) · 248 unmodified lines | ||
| 1483 | 1489 | #endif |
| 1484 | 1490 | #ifdef CONFIG_TCC_BACKTRACE |
| 1485 | 1491 | if (s1->do_backtrace) { |
| 1486 | − if (s1->output_type == TCC_OUTPUT_EXE) | |
| 1492 | + if (s1->output_type & TCC_OUTPUT_EXE) | |
| 1487 | 1493 | tcc_add_support(s1, "bt-exe.o"); |
| 1488 | 1494 | if (s1->output_type != TCC_OUTPUT_DLL) |
| 1489 | 1495 | tcc_add_support(s1, "bt-log.o"); |
| @@ -1513,7 +1519,7 @@ ST_FUNC void tcc_add_runtime(TCCState *s1) · 23 unmodified lines | ||
| 1513 | 1519 | #if defined TCC_TARGET_MACHO |
| 1514 | 1520 | /* nothing to do */ |
| 1515 | 1521 | #elif TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD |
| 1516 | − if (s1->output_type == TCC_OUTPUT_DLL) | |
| 1522 | + if (s1->output_type & TCC_OUTPUT_DYN) | |
| 1517 | 1523 | tcc_add_crt(s1, "crtendS.o"); |
| 1518 | 1524 | else |
| 1519 | 1525 | tcc_add_crt(s1, "crtend.o"); |
| @@ -1812,7 +1818,7 @@ static int set_sec_sizes(TCCState *s1) · 292 unmodified lines | ||
| 1812 | 1818 | if (s->sh_type == SHT_RELX && !(s->sh_flags & SHF_ALLOC)) { |
| 1813 | 1819 | /* when generating a DLL, we include relocations but |
| 1814 | 1820 | we may patch them */ |
| 1815 | − if (file_type == TCC_OUTPUT_DLL | |
| 1821 | + if ((file_type & TCC_OUTPUT_DYN) | |
| 1816 | 1822 | && (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)) { |
| 1817 | 1823 | int count = prepare_dynamic_rel(s1, s); |
| 1818 | 1824 | if (count) { |
| @@ -1820,7 +1826,7 @@ static int set_sec_sizes(TCCState *s1) · 1 unmodified line | ||
| 1820 | 1826 | s->sh_flags |= SHF_ALLOC; |
| 1821 | 1827 | s->sh_size = count * sizeof(ElfW_Rel); |
| 1822 | 1828 | if (!(s1->sections[s->sh_info]->sh_flags & SHF_WRITE)) |
| 1823 | − textrel = 1; | |
| 1829 | + textrel += count; | |
| 1824 | 1830 | } |
| 1825 | 1831 | } |
| 1826 | 1832 | } else if ((s->sh_flags & SHF_ALLOC) |
| @@ -1904,7 +1910,7 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, · 77 unmodified lines | ||
| 1904 | 1910 | a_offset += s_align; |
| 1905 | 1911 | file_offset += (a_offset - p_offset); |
| 1906 | 1912 | } else { |
| 1907 | − if (file_type == TCC_OUTPUT_DLL) | |
| 1913 | + if (file_type & TCC_OUTPUT_DYN) | |
| 1908 | 1914 | addr = 0; |
| 1909 | 1915 | else |
| 1910 | 1916 | addr = ELF_START_ADDR; |
| @@ -1936,7 +1942,7 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, · 25 unmodified lines | ||
| 1936 | 1942 | symbol tables, relocations, progbits, nobits */ |
| 1937 | 1943 | /* XXX: do faster and simpler sorting */ |
| 1938 | 1944 | f = -1; |
| 1939 | − for(k = 0; k < 7; k++) { | |
| 1945 | + for(k = 0; k < 10; k++) { | |
| 1940 | 1946 | for(i = 1; i < s1->nb_sections; i++) { |
| 1941 | 1947 | s = s1->sections[i]; |
| 1942 | 1948 | /* compute if section should be included */ |
| @@ -1970,9 +1976,6 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, · 27 unmodified lines | ||
| 1970 | 1976 | if (k != 2) |
| 1971 | 1977 | continue; |
| 1972 | 1978 | } |
| 1973 | − } else if (s->sh_type == SHT_NOBITS) { | |
| 1974 | − if (k != 6) | |
| 1975 | − continue; | |
| 1976 | 1979 | } else if ((s == rodata_section |
| 1977 | 1980 | #ifdef CONFIG_TCC_BCHECK |
| 1978 | 1981 | || s == bounds_section |
| @@ -1984,6 +1987,19 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, · 5 unmodified lines | ||
| 1984 | 1987 | /* Align next section on page size. |
| 1985 | 1988 | This is needed to remap roinf section ro. */ |
| 1986 | 1989 | f = 1; |
| 1990 | + | |
| 1991 | + } else if (s->sh_type == SHT_PREINIT_ARRAY) { | |
| 1992 | + if (k != 6) | |
| 1993 | + continue; | |
| 1994 | + } else if (s->sh_type == SHT_INIT_ARRAY) { | |
| 1995 | + if (k != 7) | |
| 1996 | + continue; | |
| 1997 | + } else if (s->sh_type == SHT_FINI_ARRAY) { | |
| 1998 | + if (k != 8) | |
| 1999 | + continue; | |
| 2000 | + } else if (s->sh_type == SHT_NOBITS) { | |
| 2001 | + if (k != 9) | |
| 2002 | + continue; | |
| 1987 | 2003 | } else { |
| 1988 | 2004 | if (k != 5) |
| 1989 | 2005 | continue; |
| @@ -2270,7 +2286,7 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr, · 280 unmodified lines | ||
| 2270 | 2286 | #ifdef TCC_ARM_EABI |
| 2271 | 2287 | ehdr.e_ident[EI_OSABI] = 0; |
| 2272 | 2288 | ehdr.e_flags = EF_ARM_EABI_VER4; |
| 2273 | − if (file_type == TCC_OUTPUT_EXE || file_type == TCC_OUTPUT_DLL) | |
| 2289 | + if (file_type & (TCC_OUTPUT_EXE | TCC_OUTPUT_DLL)) | |
| 2274 | 2290 | ehdr.e_flags |= EF_ARM_HASENTRY; |
| 2275 | 2291 | if (s1->float_abi == ARM_HARD_FLOAT) |
| 2276 | 2292 | ehdr.e_flags |= EF_ARM_VFP_FLOAT; |
| @@ -2282,26 +2298,22 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr, · 5 unmodified lines | ||
| 2282 | 2298 | #elif defined TCC_TARGET_RISCV64 |
| 2283 | 2299 | ehdr.e_flags = EF_RISCV_FLOAT_ABI_DOUBLE; |
| 2284 | 2300 | #endif |
| 2285 | − switch(file_type) { | |
| 2286 | − default: | |
| 2287 | − case TCC_OUTPUT_EXE: | |
| 2288 | − ehdr.e_type = ET_EXEC; | |
| 2289 | − ehdr.e_entry = get_sym_addr(s1, | |
| 2290 | − s1->elf_entryname ? | |
| 2291 | − s1->elf_entryname : "_start", | |
| 2292 | − 1, 0); | |
| 2293 | − break; | |
| 2294 | − case TCC_OUTPUT_DLL: | |
| 2295 | − ehdr.e_type = ET_DYN; | |
| 2296 | − ehdr.e_entry = s1->elf_entryname ? | |
| 2297 | − get_sym_addr(s1,s1->elf_entryname,1,0) : | |
| 2298 | − text_section->sh_addr; | |
| 2299 | − /* XXX: is it correct ? */ | |
| 2300 | − break; | |
| 2301 | − case TCC_OUTPUT_OBJ: | |
| 2301 | + | |
| 2302 | + if (file_type == TCC_OUTPUT_OBJ) { | |
| 2302 | 2303 | ehdr.e_type = ET_REL; |
| 2303 | − break; | |
| 2304 | + } else { | |
| 2305 | + if (file_type & TCC_OUTPUT_DYN) | |
| 2306 | + ehdr.e_type = ET_DYN; | |
| 2307 | + else | |
| 2308 | + ehdr.e_type = ET_EXEC; | |
| 2309 | + if (s1->elf_entryname) | |
| 2310 | + ehdr.e_entry = get_sym_addr(s1, s1->elf_entryname, 1, 0); | |
| 2311 | + else | |
| 2312 | + ehdr.e_entry = get_sym_addr(s1, "_start", !!(file_type & TCC_OUTPUT_EXE), 0); | |
| 2313 | + if (ehdr.e_entry == (addr_t)-1) | |
| 2314 | + ehdr.e_entry = text_section->sh_addr; | |
| 2304 | 2315 | } |
| 2316 | + | |
| 2305 | 2317 | ehdr.e_machine = EM_TCC_TARGET; |
| 2306 | 2318 | ehdr.e_version = EV_CURRENT; |
| 2307 | 2319 | ehdr.e_shoff = file_offset; |
| @@ -2530,7 +2542,7 @@ static int elf_output_file(TCCState *s1, const char *filename) · 222 unmodified lines | ||
| 2530 | 2542 | ElfW(Phdr) *phdr; |
| 2531 | 2543 | Section *interp, *dynamic, *dynstr, *note; |
| 2532 | 2544 | struct ro_inf *roinf_use = NULL; |
| 2533 | − int textrel, got_sym; | |
| 2545 | + int textrel, got_sym, dt_flags_1; | |
| 2534 | 2546 | |
| 2535 | 2547 | file_type = s1->output_type; |
| 2536 | 2548 | s1->nb_errors = 0; |
| @@ -2557,7 +2569,7 @@ static int elf_output_file(TCCState *s1, const char *filename) · 20 unmodified lines | ||
| 2557 | 2569 | resolve_common_syms(s1); |
| 2558 | 2570 | |
| 2559 | 2571 | if (!s1->static_link) { |
| 2560 | − if (file_type == TCC_OUTPUT_EXE) { | |
| 2572 | + if (file_type & TCC_OUTPUT_EXE) { | |
| 2561 | 2573 | char *ptr; |
| 2562 | 2574 | /* allow override the dynamic loader */ |
| 2563 | 2575 | const char *elfint = getenv("LD_SO"); |
| @@ -2590,7 +2602,7 @@ static int elf_output_file(TCCState *s1, const char *filename) · 26 unmodified lines | ||
| 2590 | 2602 | goto the_end; |
| 2591 | 2603 | } |
| 2592 | 2604 | build_got_entries(s1, got_sym); |
| 2593 | − if (file_type == TCC_OUTPUT_EXE) { | |
| 2605 | + if (file_type & TCC_OUTPUT_EXE) { | |
| 2594 | 2606 | bind_libs_dynsyms(s1); |
| 2595 | 2607 | } else { |
| 2596 | 2608 | /* shared library case: simply export all global symbols */ |
| @@ -2606,7 +2618,6 @@ static int elf_output_file(TCCState *s1, const char *filename) · 9 unmodified lines | ||
| 2606 | 2618 | alloc_sec_names(s1, 0); |
| 2607 | 2619 | |
| 2608 | 2620 | if (!s1->static_link) { |
| 2609 | − int i; | |
| 2610 | 2621 | /* add a list of needed dlls */ |
| 2611 | 2622 | for(i = 0; i < s1->nb_loaded_dlls; i++) { |
| 2612 | 2623 | DLLReference *dllref = s1->loaded_dlls[i]; |
| @@ -2618,15 +2629,19 @@ static int elf_output_file(TCCState *s1, const char *filename) · 5 unmodified lines | ||
| 2618 | 2629 | put_dt(dynamic, s1->enable_new_dtags ? DT_RUNPATH : DT_RPATH, |
| 2619 | 2630 | put_elf_str(dynstr, s1->rpath)); |
| 2620 | 2631 | |
| 2621 | − if (file_type == TCC_OUTPUT_DLL) { | |
| 2632 | + dt_flags_1 = DF_1_NOW; | |
| 2633 | + if (file_type & TCC_OUTPUT_DYN) { | |
| 2622 | 2634 | if (s1->soname) |
| 2623 | 2635 | put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname)); |
| 2624 | 2636 | /* XXX: currently, since we do not handle PIC code, we |
| 2625 | 2637 | must relocate the readonly segments */ |
| 2626 | 2638 | if (textrel) |
| 2627 | 2639 | put_dt(dynamic, DT_TEXTREL, 0); |
| 2640 | + if (file_type & TCC_OUTPUT_EXE) | |
| 2641 | + dt_flags_1 = DF_1_NOW | DF_1_PIE; | |
| 2628 | 2642 | } |
| 2629 | − | |
| 2643 | + put_dt(dynamic, DT_FLAGS, DF_BIND_NOW); | |
| 2644 | + put_dt(dynamic, DT_FLAGS_1, dt_flags_1); | |
| 2630 | 2645 | if (s1->symbolic) |
| 2631 | 2646 | put_dt(dynamic, DT_SYMBOLIC, 0); |
| 2632 | 2647 | |
| @@ -2639,20 +2654,16 @@ static int elf_output_file(TCCState *s1, const char *filename) · 6 unmodified lines | ||
| 2639 | 2654 | dynstr->sh_size = dynstr->data_offset; |
| 2640 | 2655 | } |
| 2641 | 2656 | |
| 2642 | − for (i = 1; i < s1->nb_sections && | |
| 2643 | − !(s1->sections[i]->sh_flags & SHF_TLS); i++); | |
| 2644 | − phfill = 2 + (i < s1->nb_sections); | |
| 2645 | − | |
| 2646 | 2657 | /* compute number of program headers */ |
| 2647 | − if (file_type == TCC_OUTPUT_DLL) | |
| 2648 | − phnum = 3; | |
| 2649 | − else if (s1->static_link) | |
| 2650 | − phnum = 3; | |
| 2651 | − else { | |
| 2652 | − phnum = 5 + (i < s1->nb_sections); | |
| 2653 | − } | |
| 2654 | − | |
| 2655 | − phnum += note != NULL; | |
| 2658 | + phfill = 2; | |
| 2659 | + for (i = 1; i < s1->nb_sections; i++) | |
| 2660 | + if (s1->sections[i]->sh_flags & SHF_TLS) | |
| 2661 | + phfill = 3; | |
| 2662 | + phnum = 3; | |
| 2663 | + if (interp) | |
| 2664 | + phnum += phfill; | |
| 2665 | + if (note) | |
| 2666 | + phnum++; | |
| 2656 | 2667 | #if !TARGETOS_FreeBSD && !TARGETOS_NetBSD |
| 2657 | 2668 | /* GNU_RELRO */ |
| 2658 | 2669 | phnum++, roinf_use = &roinf; |
| @@ -2679,7 +2690,7 @@ static int elf_output_file(TCCState *s1, const char *filename) · 20 unmodified lines | ||
| 2679 | 2690 | /* put in GOT the dynamic section address and relocate PLT */ |
| 2680 | 2691 | write32le(s1->got->data, dynamic->sh_addr); |
| 2681 | 2692 | if (file_type == TCC_OUTPUT_EXE |
| 2682 | − || (RELOCATE_DLLPLT && file_type == TCC_OUTPUT_DLL)) | |
| 2693 | + || (RELOCATE_DLLPLT && (file_type & TCC_OUTPUT_DYN))) | |
| 2683 | 2694 | relocate_plt(s1); |
| 2684 | 2695 | |
| 2685 | 2696 | /* relocate symbols in .dynsym now that final addresses are known */ |
| @@ -194,7 +194,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t · 193 unmodified lines | ||
| 194 | 194 | |
| 195 | 195 | switch (type) { |
| 196 | 196 | case R_X86_64_64: |
| 197 | − if (s1->output_type == TCC_OUTPUT_DLL) { | |
| 197 | + if (s1->output_type & TCC_OUTPUT_DYN) { | |
| 198 | 198 | esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index; |
| 199 | 199 | qrel->r_offset = rel->r_offset; |
| 200 | 200 | if (esym_index) { |
| @@ -212,7 +212,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t · 11 unmodified lines | ||
| 212 | 212 | break; |
| 213 | 213 | case R_X86_64_32: |
| 214 | 214 | case R_X86_64_32S: |
| 215 | − if (s1->output_type == TCC_OUTPUT_DLL) { | |
| 215 | + if (s1->output_type & TCC_OUTPUT_DYN) { | |
| 216 | 216 | /* XXX: this logic may depend on TCC's codegen |
| 217 | 217 | now TCC uses R_X86_64_32 even for a 64bit pointer */ |
| 218 | 218 | qrel->r_offset = rel->r_offset; |