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