Skip to content

Commit

Permalink
dynamic executables (PIE)
Browse files Browse the repository at this point in the history
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(-)
  • Loading branch information
grischka committed Jul 24, 2022
1 parent e460f7d commit ebaa5c8
Show file tree
Hide file tree
Showing 13 changed files with 100 additions and 76 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ NATIVE_DEFINES_$(CONFIG_arm64) += -DTCC_TARGET_ARM64
NATIVE_DEFINES_$(CONFIG_riscv64) += -DTCC_TARGET_RISCV64
NATIVE_DEFINES_$(CONFIG_BSD) += -DTARGETOS_$(TARGETOS)
NATIVE_DEFINES_$(CONFIG_pie) += -DCONFIG_TCC_PIE
NATIVE_DEFINES_$(CONFIG_pic) += -DCONFIG_TCC_PIC
NATIVE_DEFINES_no_$(CONFIG_bcheck) += -DCONFIG_TCC_BCHECK=0
NATIVE_DEFINES_no_$(CONFIG_backtrace) += -DCONFIG_TCC_BACKTRACE=0
NATIVE_DEFINES += $(NATIVE_DEFINES_yes) $(NATIVE_DEFINES_no_no)
Expand Down Expand Up @@ -275,7 +276,7 @@ libtcc.a: $(LIBTCC_OBJ)

# dynamic libtcc library
libtcc.so: $(LIBTCC_OBJ)
$S$(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LDFLAGS)
$S$(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LIBS) $(LDFLAGS)

libtcc.so: CFLAGS+=-fPIC
libtcc.so: LDFLAGS+=-fPIC
Expand Down
2 changes: 1 addition & 1 deletion arm-gen.c
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ static void load_value(SValue *sv, int r)
{
o(0xE59F0000|(intr(r)<<12)); /* ldr r, [pc] */
o(0xEA000000); /* b $+4 */
#ifndef CONFIG_TCC_PIE
#ifndef CONFIG_TCC_PIC
if(sv->r & VT_SYM)
greloc(cur_text_section, sv->sym, ind, R_ARM_ABS32);
o(sv->c.i);
Expand Down
2 changes: 1 addition & 1 deletion arm-link.c
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
return;
case R_ARM_ABS32:
case R_ARM_TARGET1:
if (s1->output_type == TCC_OUTPUT_DLL) {
if (s1->output_type & TCC_OUTPUT_DYN) {
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
qrel->r_offset = rel->r_offset;
if (esym_index) {
Expand Down
4 changes: 2 additions & 2 deletions arm64-link.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t

switch(type) {
case R_AARCH64_ABS64:
if (s1->output_type == TCC_OUTPUT_DLL) {
if ((s1->output_type & TCC_OUTPUT_DYN)) {
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
qrel->r_offset = rel->r_offset;
if (esym_index) {
Expand All @@ -194,7 +194,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
add64le(ptr, val);
return;
case R_AARCH64_ABS32:
if (s1->output_type == TCC_OUTPUT_DLL) {
if (s1->output_type & TCC_OUTPUT_DYN) {
/* XXX: this logic may depend on TCC's codegen
now TCC uses R_AARCH64_RELATIVE even for a 64bit pointer */
qrel->r_offset = rel->r_offset;
Expand Down
1 change: 1 addition & 0 deletions elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,7 @@ typedef struct
#define DF_1_SYMINTPOSE 0x00800000 /* Object has individual interposers. */
#define DF_1_GLOBAUDIT 0x01000000 /* Global auditing required. */
#define DF_1_SINGLETON 0x02000000 /* Singleton symbols are used. */
#define DF_1_PIE 0x08000000

/* Flags for the feature selection in DT_FEATURE_1. */
#define DTF_1_PARINIT 0x00000001
Expand Down
6 changes: 3 additions & 3 deletions i386-link.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_
unsigned plt_offset, relofs;

/* on i386 if we build a DLL, we add a %ebx offset */
if (s1->output_type == TCC_OUTPUT_DLL)
if (s1->output_type & TCC_OUTPUT_DYN)
modrm = 0xa3;
else
modrm = 0x25;
Expand Down Expand Up @@ -148,7 +148,7 @@ ST_FUNC void relocate_plt(TCCState *s1)
p = s1->plt->data;
p_end = p + s1->plt->data_offset;

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

switch (type) {
case R_386_32:
if (s1->output_type == TCC_OUTPUT_DLL) {
if (s1->output_type & TCC_OUTPUT_DYN) {
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
qrel->r_offset = rel->r_offset;
if (esym_index) {
Expand Down
18 changes: 13 additions & 5 deletions libtcc.c
Original file line number Diff line number Diff line change
Expand Up @@ -862,13 +862,21 @@ LIBTCCAPI void tcc_delete(TCCState *s1)

LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
{
#ifdef CONFIG_TCC_PIE
if (output_type == TCC_OUTPUT_EXE)
output_type |= TCC_OUTPUT_DYN;
#endif
s->output_type = output_type;

if (!s->nostdinc) {
/* default include paths */
/* -isystem paths have already been handled */
tcc_add_sysinclude_path(s, CONFIG_TCC_SYSINCLUDEPATHS);
}

if (output_type == TCC_OUTPUT_PREPROCESS)
return 0;

#ifdef CONFIG_TCC_BCHECK
if (s->do_bounds_check) {
/* if bound checking, then add corresponding sections */
Expand Down Expand Up @@ -905,13 +913,13 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
#else
/* paths for crt objects */
tcc_split_path(s, &s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX);

/* add libc crt1/crti objects */
if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
!s->nostdlib) {
if (output_type != TCC_OUTPUT_MEMORY && !s->nostdlib) {
#if TARGETOS_OpenBSD
if (output_type != TCC_OUTPUT_DLL)
tcc_add_crt(s, "crt0.o");
if (output_type == TCC_OUTPUT_DLL)
if (output_type & TCC_OUTPUT_DYN)
tcc_add_crt(s, "crtbeginS.o");
else
tcc_add_crt(s, "crtbegin.o");
Expand All @@ -921,7 +929,7 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
tcc_add_crt(s, "crti.o");
if (s->static_link)
tcc_add_crt(s, "crtbeginT.o");
else if (output_type == TCC_OUTPUT_DLL)
else if (output_type & TCC_OUTPUT_DYN)
tcc_add_crt(s, "crtbeginS.o");
else
tcc_add_crt(s, "crtbegin.o");
Expand All @@ -931,7 +939,7 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
tcc_add_crt(s, "crti.o");
if (s->static_link)
tcc_add_crt(s, "crtbeginT.o");
else if (output_type == TCC_OUTPUT_DLL)
else if (output_type & TCC_OUTPUT_DYN)
tcc_add_crt(s, "crtbeginS.o");
else
tcc_add_crt(s, "crtbegin.o");
Expand Down
8 changes: 4 additions & 4 deletions libtcc.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf);

/* set output type. MUST BE CALLED before any compilation */
LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type);
#define TCC_OUTPUT_MEMORY 1 /* output will be run in memory (default) */
#define TCC_OUTPUT_MEMORY 1 /* output will be run in memory */
#define TCC_OUTPUT_EXE 2 /* executable file */
#define TCC_OUTPUT_DLL 3 /* dynamic library */
#define TCC_OUTPUT_OBJ 4 /* object file */
#define TCC_OUTPUT_PREPROCESS 5 /* only preprocess (used internally) */
#define TCC_OUTPUT_DLL 4 /* dynamic library */
#define TCC_OUTPUT_OBJ 3 /* object file */
#define TCC_OUTPUT_PREPROCESS 5 /* only preprocess */

/* equivalent to -Lpath option */
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname);
Expand Down
4 changes: 2 additions & 2 deletions riscv64-link.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
return;

case R_RISCV_32:
if (s1->output_type == TCC_OUTPUT_DLL) {
if (s1->output_type & TCC_OUTPUT_DYN) {
/* XXX: this logic may depend on TCC's codegen
now TCC uses R_RISCV_RELATIVE even for a 64bit pointer */
qrel->r_offset = rel->r_offset;
Expand All @@ -296,7 +296,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
add32le(ptr, val);
return;
case R_RISCV_64:
if (s1->output_type == TCC_OUTPUT_DLL) {
if (s1->output_type & TCC_OUTPUT_DYN) {
esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
qrel->r_offset = rel->r_offset;
if (esym_index) {
Expand Down
5 changes: 5 additions & 0 deletions tcc.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,10 @@ extern long double strtold (const char *__nptr, char **__endptr);
# define TCC_USING_DOUBLE_FOR_LDOUBLE 1
#endif

#ifdef CONFIG_TCC_PIE
# define CONFIG_TCC_PIC 1
#endif

/* ------------ path configuration ------------ */

#ifndef CONFIG_SYSROOT
Expand Down Expand Up @@ -1485,6 +1489,7 @@ ST_DATA int func_bound_add_epilog;
#define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */
#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
#define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */
#define TCC_OUTPUT_DYN TCC_OUTPUT_DLL

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

Expand Down
4 changes: 1 addition & 3 deletions tccdbg.c
Original file line number Diff line number Diff line change
Expand Up @@ -392,9 +392,7 @@ ST_FUNC void tcc_debug_new(TCCState *s1)
#ifdef CONFIG_TCC_BACKTRACE
/* include stab info with standalone backtrace support */
if (s1->do_backtrace
&& (s1->output_type == TCC_OUTPUT_EXE
|| s1->output_type == TCC_OUTPUT_DLL)
)
&& (s1->output_type & (TCC_OUTPUT_EXE | TCC_OUTPUT_DLL)))
shf = SHF_ALLOC | SHF_WRITE; // SHF_WRITE needed for musl/SELINUX
#endif
if (s1->dwarf) {
Expand Down
Loading

0 comments on commit ebaa5c8

Please sign in to comment.