Skip to content

Commit ebaa5c8

Browse files
author
grischka
committed
dynamic executables (PIE)
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(-)
1 parent e460f7d commit ebaa5c8

13 files changed

+100
-76
lines changed

Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ NATIVE_DEFINES_$(CONFIG_arm64) += -DTCC_TARGET_ARM64
9191
NATIVE_DEFINES_$(CONFIG_riscv64) += -DTCC_TARGET_RISCV64
9292
NATIVE_DEFINES_$(CONFIG_BSD) += -DTARGETOS_$(TARGETOS)
9393
NATIVE_DEFINES_$(CONFIG_pie) += -DCONFIG_TCC_PIE
94+
NATIVE_DEFINES_$(CONFIG_pic) += -DCONFIG_TCC_PIC
9495
NATIVE_DEFINES_no_$(CONFIG_bcheck) += -DCONFIG_TCC_BCHECK=0
9596
NATIVE_DEFINES_no_$(CONFIG_backtrace) += -DCONFIG_TCC_BACKTRACE=0
9697
NATIVE_DEFINES += $(NATIVE_DEFINES_yes) $(NATIVE_DEFINES_no_no)
@@ -275,7 +276,7 @@ libtcc.a: $(LIBTCC_OBJ)
275276

276277
# dynamic libtcc library
277278
libtcc.so: $(LIBTCC_OBJ)
278-
$S$(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LDFLAGS)
279+
$S$(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LIBS) $(LDFLAGS)
279280

280281
libtcc.so: CFLAGS+=-fPIC
281282
libtcc.so: LDFLAGS+=-fPIC

arm-gen.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@ static void load_value(SValue *sv, int r)
543543
{
544544
o(0xE59F0000|(intr(r)<<12)); /* ldr r, [pc] */
545545
o(0xEA000000); /* b $+4 */
546-
#ifndef CONFIG_TCC_PIE
546+
#ifndef CONFIG_TCC_PIC
547547
if(sv->r & VT_SYM)
548548
greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32);
549549
o(sv->c.i);

arm-link.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
380380
return;
381381
case R_ARM_ABS32:
382382
case R_ARM_TARGET1:
383-
if (s1->output_type == TCC_OUTPUT_DLL) {
383+
if (s1->output_type & TCC_OUTPUT_DYN) {
384384
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
385385
qrel->r_offset = rel->r_offset;
386386
if (esym_index) {

arm64-link.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
177177

178178
switch(type) {
179179
case R_AARCH64_ABS64:
180-
if (s1->output_type == TCC_OUTPUT_DLL) {
180+
if ((s1->output_type & TCC_OUTPUT_DYN)) {
181181
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
182182
qrel->r_offset = rel->r_offset;
183183
if (esym_index) {
@@ -194,7 +194,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
194194
add64le(ptr, val);
195195
return;
196196
case R_AARCH64_ABS32:
197-
if (s1->output_type == TCC_OUTPUT_DLL) {
197+
if (s1->output_type & TCC_OUTPUT_DYN) {
198198
/* XXX: this logic may depend on TCC's codegen
199199
now TCC uses R_AARCH64_RELATIVE even for a 64bit pointer */
200200
qrel->r_offset = rel->r_offset;

elf.h

+1
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,7 @@ typedef struct
825825
#define DF_1_SYMINTPOSE 0x00800000 /* Object has individual interposers. */
826826
#define DF_1_GLOBAUDIT 0x01000000 /* Global auditing required. */
827827
#define DF_1_SINGLETON 0x02000000 /* Singleton symbols are used. */
828+
#define DF_1_PIE 0x08000000
828829

829830
/* Flags for the feature selection in DT_FEATURE_1. */
830831
#define DTF_1_PARINIT 0x00000001

i386-link.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
100100
unsigned plt_offset, relofs;
101101

102102
/* 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)
104104
modrm = 0xa3;
105105
else
106106
modrm = 0x25;
@@ -148,7 +148,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
148148
p = s1->plt->data;
149149
p_end = p + s1->plt->data_offset;
150150

151-
if (s1->output_type != TCC_OUTPUT_DLL && p < p_end) {
151+
if (!(s1->output_type & TCC_OUTPUT_DYN) && p < p_end) {
152152
add32le(p + 2, s1->got->sh_addr);
153153
add32le(p + 8, s1->got->sh_addr);
154154
p += 16;
@@ -179,7 +179,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
179179

180180
switch (type) {
181181
case R_386_32:
182-
if (s1->output_type == TCC_OUTPUT_DLL) {
182+
if (s1->output_type & TCC_OUTPUT_DYN) {
183183
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
184184
qrel->r_offset = rel->r_offset;
185185
if (esym_index) {

libtcc.c

+13-5
Original file line numberDiff line numberDiff line change
@@ -862,13 +862,21 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
862862

863863
LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
864864
{
865+
#ifdef CONFIG_TCC_PIE
866+
if (output_type == TCC_OUTPUT_EXE)
867+
output_type |= TCC_OUTPUT_DYN;
868+
#endif
865869
s->output_type = output_type;
866870

867871
if (!s->nostdinc) {
868872
/* default include paths */
869873
/* -isystem paths have already been handled */
870874
tcc_add_sysinclude_path(s, CONFIG_TCC_SYSINCLUDEPATHS);
871875
}
876+
877+
if (output_type == TCC_OUTPUT_PREPROCESS)
878+
return 0;
879+
872880
#ifdef CONFIG_TCC_BCHECK
873881
if (s->do_bounds_check) {
874882
/* if bound checking, then add corresponding sections */
@@ -905,13 +913,13 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
905913
#else
906914
/* paths for crt objects */
907915
tcc_split_path(s, &s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX);
916+
908917
/* 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) {
911919
#if TARGETOS_OpenBSD
912920
if (output_type != TCC_OUTPUT_DLL)
913921
tcc_add_crt(s, "crt0.o");
914-
if (output_type == TCC_OUTPUT_DLL)
922+
if (output_type & TCC_OUTPUT_DYN)
915923
tcc_add_crt(s, "crtbeginS.o");
916924
else
917925
tcc_add_crt(s, "crtbegin.o");
@@ -921,7 +929,7 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
921929
tcc_add_crt(s, "crti.o");
922930
if (s->static_link)
923931
tcc_add_crt(s, "crtbeginT.o");
924-
else if (output_type == TCC_OUTPUT_DLL)
932+
else if (output_type & TCC_OUTPUT_DYN)
925933
tcc_add_crt(s, "crtbeginS.o");
926934
else
927935
tcc_add_crt(s, "crtbegin.o");
@@ -931,7 +939,7 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
931939
tcc_add_crt(s, "crti.o");
932940
if (s->static_link)
933941
tcc_add_crt(s, "crtbeginT.o");
934-
else if (output_type == TCC_OUTPUT_DLL)
942+
else if (output_type & TCC_OUTPUT_DYN)
935943
tcc_add_crt(s, "crtbeginS.o");
936944
else
937945
tcc_add_crt(s, "crtbegin.o");

libtcc.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,11 @@ LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf);
6565

6666
/* set output type. MUST BE CALLED before any compilation */
6767
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 */
6969
#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 */
7373

7474
/* equivalent to -Lpath option */
7575
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname);

riscv64-link.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
284284
return;
285285

286286
case R_RISCV_32:
287-
if (s1->output_type == TCC_OUTPUT_DLL) {
287+
if (s1->output_type & TCC_OUTPUT_DYN) {
288288
/* XXX: this logic may depend on TCC's codegen
289289
now TCC uses R_RISCV_RELATIVE even for a 64bit pointer */
290290
qrel->r_offset = rel->r_offset;
@@ -296,7 +296,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
296296
add32le(ptr, val);
297297
return;
298298
case R_RISCV_64:
299-
if (s1->output_type == TCC_OUTPUT_DLL) {
299+
if (s1->output_type & TCC_OUTPUT_DYN) {
300300
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
301301
qrel->r_offset = rel->r_offset;
302302
if (esym_index) {

tcc.h

+5
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,10 @@ extern long double strtold (const char *__nptr, char **__endptr);
236236
# define TCC_USING_DOUBLE_FOR_LDOUBLE 1
237237
#endif
238238

239+
#ifdef CONFIG_TCC_PIE
240+
# define CONFIG_TCC_PIC 1
241+
#endif
242+
239243
/* ------------ path configuration ------------ */
240244

241245
#ifndef CONFIG_SYSROOT
@@ -1485,6 +1489,7 @@ ST_DATA int func_bound_add_epilog;
14851489
#define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */
14861490
#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
14871491
#define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */
1492+
#define TCC_OUTPUT_DYN TCC_OUTPUT_DLL
14881493

14891494
#define ARMAG "!<arch>\012" /* For COFF and a.out archives */
14901495

tccdbg.c

+1-3
Original file line numberDiff line numberDiff line change
@@ -392,9 +392,7 @@ ST_FUNC void tcc_debug_new(TCCState *s1)
392392
#ifdef CONFIG_TCC_BACKTRACE
393393
/* include stab info with standalone backtrace support */
394394
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)))
398396
shf = SHF_ALLOC | SHF_WRITE; // SHF_WRITE needed for musl/SELINUX
399397
#endif
400398
if (s1->dwarf) {

0 commit comments

Comments
 (0)