mirror of
https://github.com/mirror/tinycc.git
synced 2024-12-24 03:40:09 +08:00
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(-)
This commit is contained in:
parent
e460f7dbb2
commit
ebaa5c81f4
3
Makefile
3
Makefile
@ -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)
|
||||
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
@ -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;
|
||||
|
1
elf.h
1
elf.h
@ -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
|
||||
|
@ -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;
|
||||
@ -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;
|
||||
@ -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) {
|
||||
|
18
libtcc.c
18
libtcc.c
@ -862,6 +862,10 @@ 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) {
|
||||
@ -869,6 +873,10 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
|
||||
/* -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 */
|
||||
@ -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");
|
||||
@ -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");
|
||||
@ -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");
|
||||
|
8
libtcc.h
8
libtcc.h
@ -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);
|
||||
|
@ -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;
|
||||
@ -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) {
|
||||
|
5
tcc.h
5
tcc.h
@ -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
|
||||
@ -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 */
|
||||
|
||||
|
4
tccdbg.c
4
tccdbg.c
@ -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) {
|
||||
|
115
tccelf.c
115
tccelf.c
@ -928,12 +928,16 @@ static void relocate_section(TCCState *s1, Section *s, Section *sr)
|
||||
/* if the relocation is allocated, we change its symbol table */
|
||||
if (sr->sh_flags & SHF_ALLOC) {
|
||||
sr->link = s1->dynsym;
|
||||
if (s1->output_type == TCC_OUTPUT_DLL) {
|
||||
if (s1->output_type & TCC_OUTPUT_DYN) {
|
||||
size_t r = (uint8_t*)qrel - sr->data;
|
||||
if (sizeof ((Stab_Sym*)0)->n_value < PTR_SIZE
|
||||
&& 0 == strcmp(s->name, ".stab"))
|
||||
r = 0; /* cannot apply 64bit relocation to 32bit value */
|
||||
sr->data_offset = sr->sh_size = r;
|
||||
#ifdef CONFIG_TCC_PIE
|
||||
if (r && 0 == (s->sh_flags & SHF_WRITE))
|
||||
tcc_warning("%d relocations to ro-section %s", (unsigned)(r / sizeof *qrel), s->name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -1013,7 +1017,6 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr)
|
||||
case R_X86_64_PC32:
|
||||
{
|
||||
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||
|
||||
/* Hidden defined symbols can and must be resolved locally.
|
||||
We're misusing a PLT32 reloc for this, as that's always
|
||||
resolved to its address even in shared libs. */
|
||||
@ -1026,6 +1029,8 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr)
|
||||
#elif defined(TCC_TARGET_ARM64)
|
||||
case R_AARCH64_PREL32:
|
||||
#endif
|
||||
if (s1->output_type != TCC_OUTPUT_DLL)
|
||||
break;
|
||||
if (get_sym_attr(s1, sym_index, 0)->dyn_index)
|
||||
count++;
|
||||
break;
|
||||
@ -1188,7 +1193,8 @@ redo:
|
||||
if (sym->st_shndx == SHN_UNDEF) {
|
||||
ElfW(Sym) *esym;
|
||||
int dynindex;
|
||||
if (s1->output_type == TCC_OUTPUT_DLL && ! PCRELATIVE_DLLPLT)
|
||||
if (!PCRELATIVE_DLLPLT
|
||||
&& (s1->output_type & TCC_OUTPUT_DYN))
|
||||
continue;
|
||||
/* Relocations for UNDEF symbols would normally need
|
||||
to be transferred into the executable or shared object.
|
||||
@ -1228,7 +1234,7 @@ redo:
|
||||
sym->st_shndx != SHN_UNDEF &&
|
||||
(ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT ||
|
||||
ELFW(ST_BIND)(sym->st_info) == STB_LOCAL ||
|
||||
s1->output_type == TCC_OUTPUT_EXE)) {
|
||||
s1->output_type & TCC_OUTPUT_EXE)) {
|
||||
if (pass != 0)
|
||||
continue;
|
||||
rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32);
|
||||
@ -1483,7 +1489,7 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
|
||||
#endif
|
||||
#ifdef CONFIG_TCC_BACKTRACE
|
||||
if (s1->do_backtrace) {
|
||||
if (s1->output_type == TCC_OUTPUT_EXE)
|
||||
if (s1->output_type & TCC_OUTPUT_EXE)
|
||||
tcc_add_support(s1, "bt-exe.o");
|
||||
if (s1->output_type != TCC_OUTPUT_DLL)
|
||||
tcc_add_support(s1, "bt-log.o");
|
||||
@ -1513,7 +1519,7 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
|
||||
#if defined TCC_TARGET_MACHO
|
||||
/* nothing to do */
|
||||
#elif TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD
|
||||
if (s1->output_type == TCC_OUTPUT_DLL)
|
||||
if (s1->output_type & TCC_OUTPUT_DYN)
|
||||
tcc_add_crt(s1, "crtendS.o");
|
||||
else
|
||||
tcc_add_crt(s1, "crtend.o");
|
||||
@ -1812,7 +1818,7 @@ static int set_sec_sizes(TCCState *s1)
|
||||
if (s->sh_type == SHT_RELX && !(s->sh_flags & SHF_ALLOC)) {
|
||||
/* when generating a DLL, we include relocations but
|
||||
we may patch them */
|
||||
if (file_type == TCC_OUTPUT_DLL
|
||||
if ((file_type & TCC_OUTPUT_DYN)
|
||||
&& (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)) {
|
||||
int count = prepare_dynamic_rel(s1, s);
|
||||
if (count) {
|
||||
@ -1820,7 +1826,7 @@ static int set_sec_sizes(TCCState *s1)
|
||||
s->sh_flags |= SHF_ALLOC;
|
||||
s->sh_size = count * sizeof(ElfW_Rel);
|
||||
if (!(s1->sections[s->sh_info]->sh_flags & SHF_WRITE))
|
||||
textrel = 1;
|
||||
textrel += count;
|
||||
}
|
||||
}
|
||||
} else if ((s->sh_flags & SHF_ALLOC)
|
||||
@ -1904,7 +1910,7 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr,
|
||||
a_offset += s_align;
|
||||
file_offset += (a_offset - p_offset);
|
||||
} else {
|
||||
if (file_type == TCC_OUTPUT_DLL)
|
||||
if (file_type & TCC_OUTPUT_DYN)
|
||||
addr = 0;
|
||||
else
|
||||
addr = ELF_START_ADDR;
|
||||
@ -1936,7 +1942,7 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr,
|
||||
symbol tables, relocations, progbits, nobits */
|
||||
/* XXX: do faster and simpler sorting */
|
||||
f = -1;
|
||||
for(k = 0; k < 7; k++) {
|
||||
for(k = 0; k < 10; k++) {
|
||||
for(i = 1; i < s1->nb_sections; i++) {
|
||||
s = s1->sections[i];
|
||||
/* compute if section should be included */
|
||||
@ -1970,9 +1976,6 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr,
|
||||
if (k != 2)
|
||||
continue;
|
||||
}
|
||||
} else if (s->sh_type == SHT_NOBITS) {
|
||||
if (k != 6)
|
||||
continue;
|
||||
} else if ((s == rodata_section
|
||||
#ifdef CONFIG_TCC_BCHECK
|
||||
|| s == bounds_section
|
||||
@ -1984,6 +1987,19 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr,
|
||||
/* Align next section on page size.
|
||||
This is needed to remap roinf section ro. */
|
||||
f = 1;
|
||||
|
||||
} else if (s->sh_type == SHT_PREINIT_ARRAY) {
|
||||
if (k != 6)
|
||||
continue;
|
||||
} else if (s->sh_type == SHT_INIT_ARRAY) {
|
||||
if (k != 7)
|
||||
continue;
|
||||
} else if (s->sh_type == SHT_FINI_ARRAY) {
|
||||
if (k != 8)
|
||||
continue;
|
||||
} else if (s->sh_type == SHT_NOBITS) {
|
||||
if (k != 9)
|
||||
continue;
|
||||
} else {
|
||||
if (k != 5)
|
||||
continue;
|
||||
@ -2270,7 +2286,7 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
|
||||
#ifdef TCC_ARM_EABI
|
||||
ehdr.e_ident[EI_OSABI] = 0;
|
||||
ehdr.e_flags = EF_ARM_EABI_VER4;
|
||||
if (file_type == TCC_OUTPUT_EXE || file_type == TCC_OUTPUT_DLL)
|
||||
if (file_type & (TCC_OUTPUT_EXE | TCC_OUTPUT_DLL))
|
||||
ehdr.e_flags |= EF_ARM_HASENTRY;
|
||||
if (s1->float_abi == ARM_HARD_FLOAT)
|
||||
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,
|
||||
#elif defined TCC_TARGET_RISCV64
|
||||
ehdr.e_flags = EF_RISCV_FLOAT_ABI_DOUBLE;
|
||||
#endif
|
||||
switch(file_type) {
|
||||
default:
|
||||
case TCC_OUTPUT_EXE:
|
||||
ehdr.e_type = ET_EXEC;
|
||||
ehdr.e_entry = get_sym_addr(s1,
|
||||
s1->elf_entryname ?
|
||||
s1->elf_entryname : "_start",
|
||||
1, 0);
|
||||
break;
|
||||
case TCC_OUTPUT_DLL:
|
||||
ehdr.e_type = ET_DYN;
|
||||
ehdr.e_entry = s1->elf_entryname ?
|
||||
get_sym_addr(s1,s1->elf_entryname,1,0) :
|
||||
text_section->sh_addr;
|
||||
/* XXX: is it correct ? */
|
||||
break;
|
||||
case TCC_OUTPUT_OBJ:
|
||||
|
||||
if (file_type == TCC_OUTPUT_OBJ) {
|
||||
ehdr.e_type = ET_REL;
|
||||
break;
|
||||
} else {
|
||||
if (file_type & TCC_OUTPUT_DYN)
|
||||
ehdr.e_type = ET_DYN;
|
||||
else
|
||||
ehdr.e_type = ET_EXEC;
|
||||
if (s1->elf_entryname)
|
||||
ehdr.e_entry = get_sym_addr(s1, s1->elf_entryname, 1, 0);
|
||||
else
|
||||
ehdr.e_entry = get_sym_addr(s1, "_start", !!(file_type & TCC_OUTPUT_EXE), 0);
|
||||
if (ehdr.e_entry == (addr_t)-1)
|
||||
ehdr.e_entry = text_section->sh_addr;
|
||||
}
|
||||
|
||||
ehdr.e_machine = EM_TCC_TARGET;
|
||||
ehdr.e_version = EV_CURRENT;
|
||||
ehdr.e_shoff = file_offset;
|
||||
@ -2530,7 +2542,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||
ElfW(Phdr) *phdr;
|
||||
Section *interp, *dynamic, *dynstr, *note;
|
||||
struct ro_inf *roinf_use = NULL;
|
||||
int textrel, got_sym;
|
||||
int textrel, got_sym, dt_flags_1;
|
||||
|
||||
file_type = s1->output_type;
|
||||
s1->nb_errors = 0;
|
||||
@ -2557,7 +2569,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||
resolve_common_syms(s1);
|
||||
|
||||
if (!s1->static_link) {
|
||||
if (file_type == TCC_OUTPUT_EXE) {
|
||||
if (file_type & TCC_OUTPUT_EXE) {
|
||||
char *ptr;
|
||||
/* allow override the dynamic loader */
|
||||
const char *elfint = getenv("LD_SO");
|
||||
@ -2590,7 +2602,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||
goto the_end;
|
||||
}
|
||||
build_got_entries(s1, got_sym);
|
||||
if (file_type == TCC_OUTPUT_EXE) {
|
||||
if (file_type & TCC_OUTPUT_EXE) {
|
||||
bind_libs_dynsyms(s1);
|
||||
} else {
|
||||
/* shared library case: simply export all global symbols */
|
||||
@ -2606,7 +2618,6 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||
alloc_sec_names(s1, 0);
|
||||
|
||||
if (!s1->static_link) {
|
||||
int i;
|
||||
/* add a list of needed dlls */
|
||||
for(i = 0; i < s1->nb_loaded_dlls; i++) {
|
||||
DLLReference *dllref = s1->loaded_dlls[i];
|
||||
@ -2618,15 +2629,19 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||
put_dt(dynamic, s1->enable_new_dtags ? DT_RUNPATH : DT_RPATH,
|
||||
put_elf_str(dynstr, s1->rpath));
|
||||
|
||||
if (file_type == TCC_OUTPUT_DLL) {
|
||||
dt_flags_1 = DF_1_NOW;
|
||||
if (file_type & TCC_OUTPUT_DYN) {
|
||||
if (s1->soname)
|
||||
put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
|
||||
/* XXX: currently, since we do not handle PIC code, we
|
||||
must relocate the readonly segments */
|
||||
if (textrel)
|
||||
put_dt(dynamic, DT_TEXTREL, 0);
|
||||
if (file_type & TCC_OUTPUT_EXE)
|
||||
dt_flags_1 = DF_1_NOW | DF_1_PIE;
|
||||
}
|
||||
|
||||
put_dt(dynamic, DT_FLAGS, DF_BIND_NOW);
|
||||
put_dt(dynamic, DT_FLAGS_1, dt_flags_1);
|
||||
if (s1->symbolic)
|
||||
put_dt(dynamic, DT_SYMBOLIC, 0);
|
||||
|
||||
@ -2639,20 +2654,16 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||
dynstr->sh_size = dynstr->data_offset;
|
||||
}
|
||||
|
||||
for (i = 1; i < s1->nb_sections &&
|
||||
!(s1->sections[i]->sh_flags & SHF_TLS); i++);
|
||||
phfill = 2 + (i < s1->nb_sections);
|
||||
|
||||
/* compute number of program headers */
|
||||
if (file_type == TCC_OUTPUT_DLL)
|
||||
phnum = 3;
|
||||
else if (s1->static_link)
|
||||
phnum = 3;
|
||||
else {
|
||||
phnum = 5 + (i < s1->nb_sections);
|
||||
}
|
||||
|
||||
phnum += note != NULL;
|
||||
phfill = 2;
|
||||
for (i = 1; i < s1->nb_sections; i++)
|
||||
if (s1->sections[i]->sh_flags & SHF_TLS)
|
||||
phfill = 3;
|
||||
phnum = 3;
|
||||
if (interp)
|
||||
phnum += phfill;
|
||||
if (note)
|
||||
phnum++;
|
||||
#if !TARGETOS_FreeBSD && !TARGETOS_NetBSD
|
||||
/* GNU_RELRO */
|
||||
phnum++, roinf_use = &roinf;
|
||||
@ -2679,7 +2690,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
|
||||
/* put in GOT the dynamic section address and relocate PLT */
|
||||
write32le(s1->got->data, dynamic->sh_addr);
|
||||
if (file_type == TCC_OUTPUT_EXE
|
||||
|| (RELOCATE_DLLPLT && file_type == TCC_OUTPUT_DLL))
|
||||
|| (RELOCATE_DLLPLT && (file_type & TCC_OUTPUT_DYN)))
|
||||
relocate_plt(s1);
|
||||
|
||||
/* 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
|
||||
|
||||
switch (type) {
|
||||
case R_X86_64_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) {
|
||||
@ -212,7 +212,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
||||
break;
|
||||
case R_X86_64_32:
|
||||
case R_X86_64_32S:
|
||||
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_X86_64_32 even for a 64bit pointer */
|
||||
qrel->r_offset = rel->r_offset;
|
||||
|
Loading…
Reference in New Issue
Block a user