tccelf: cleanup sort_sections() & etc. fixes

with -Wl,-oformat=binary, executable code should come first.
(for linux kernel image for example)

Also:
- simplify RELRO sections: create them as readonly, but add
  SHF_WRITE flag later when needed (i.e. relocations do exist)
- tcc.h etc: exclude eh_frames on non-elf platforms
- tccelf.c:tcc_load_object_file(): don't load debug sections when
  linking without -g (special dwarf case in relocate_section()
  wont work when dwlo/hi were not initialized).
- tcc.c: avoid loop if something fails (ret < 0) without message
  (while failing without message should not happen either)
- tccelf.c:tcc_load_alacarte: give message
- tccpp.c: treat '# 123xyz' in asm file as comment
- lib/Makefile: cleanup
- libtcc.c: tcc_add_library(): fallback to try filename as is
  (also remove tcc_add_library_err())
This commit is contained in:
grischka 2024-11-17 21:39:38 +01:00
parent 3eb6352c52
commit dd2e5f8b06
9 changed files with 141 additions and 125 deletions

View file

@ -7,6 +7,8 @@ include $(TOP)/Makefile
VPATH = $(TOPSRC)/lib $(TOPSRC)/win32/lib VPATH = $(TOPSRC)/lib $(TOPSRC)/win32/lib
T = $(or $(CROSS_TARGET),$(NATIVE_TARGET),unknown) T = $(or $(CROSS_TARGET),$(NATIVE_TARGET),unknown)
X = $(if $(CROSS_TARGET),$(CROSS_TARGET)-) X = $(if $(CROSS_TARGET),$(CROSS_TARGET)-)
XCFG = $(or $(findstring -win,$T),-unx)
S = $(if $(findstring yes,$(SILENT)),@$(info * $@))
TCC = $(TOP)/$(X)tcc$(EXESUF) TCC = $(TOP)/$(X)tcc$(EXESUF)
XTCC ?= $(TOP)/$(X)tcc$(EXESUF) XTCC ?= $(TOP)/$(X)tcc$(EXESUF)
@ -16,8 +18,6 @@ XFLAGS-unx = -B$(TOPSRC)
XFLAGS-win = -B$(TOPSRC)/win32 -I$(TOPSRC)/include XFLAGS-win = -B$(TOPSRC)/win32 -I$(TOPSRC)/include
XFLAGS = $(XFLAGS$(XCFG)) -I$(TOP) XFLAGS = $(XFLAGS$(XCFG)) -I$(TOP)
BFLAGS = -bt BFLAGS = -bt
XCFG = $(or $(findstring -win,$T),-unx)
S = $(if $(findstring yes,$(SILENT)),@$(info * $@))
# in order to use gcc, type: make <target>-libtcc1-usegcc=yes # in order to use gcc, type: make <target>-libtcc1-usegcc=yes
arm-libtcc1-usegcc ?= no arm-libtcc1-usegcc ?= no
@ -29,47 +29,48 @@ arm-libtcc1-usegcc ?= no
ifeq "$($(T)-libtcc1-usegcc)" "yes" ifeq "$($(T)-libtcc1-usegcc)" "yes"
XCC = $(CC) XCC = $(CC)
XAR = $(AR) XAR = $(AR)
XFLAGS = $(CFLAGS) -fPIC -gdwarf -fno-omit-frame-pointer -Wno-unused-function -Wno-unused-variable XFLAGS = $(CFLAGS) -fPIC -fno-omit-frame-pointer -Wno-unused-function -Wno-unused-variable
BFLAGS = -g BFLAGS = $(if $(CONFIG_dwarf),-gdwarf,-gstabs)
endif endif
ifneq ($(CONFIG_backtrace),no) I386_O = libtcc1.o alloca.o alloca-bt.o $(COMMON_O)
# only for native compiler X86_64_O = libtcc1.o alloca.o alloca-bt.o $(COMMON_O)
ifneq ($(CONFIG_bcheck),no) ARM_O = libtcc1.o armeabi.o alloca.o armflush.o $(COMMON_O)
$(X)BCHECK_O = bcheck.o ARM64_O = lib-arm64.o $(COMMON_O)
endif RISCV64_O = lib-arm64.o $(COMMON_O)
$(X)BT_O = bt-exe.o bt-log.o COMMON_O = stdatomic.o atomic.o builtin.o
$(X)B_O = $(BCHECK_O) bt-exe.o bt-log.o bt-dll.o WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o
endif LIN_O = dsohandle.o
$(X)BT_O += runmain.o tcov.o OSX_O =
DSO_O = dsohandle.o # backtrace/bcheck/run only for native compiler
Nat = $(if $X,no,)
Cbt = $(Nat)$(subst yes,,$(CONFIG_backtrace))
Cbc = $(Cbt)$(subst yes,,$(CONFIG_bcheck))
$(Nat)COMMON_O += runmain.o tcov.o
$(Cbt)COMMON_O += bt-exe.o bt-log.o
$(Cbt)WIN_O += bt-dll.o
$(Cbc)COMMON_O += bcheck.o
# not in libtcc1.a # not in libtcc1.a
EXTRA_O = runmain.o bt-exe.o bt-dll.o bt-log.o bcheck.o EXTRA_O = runmain.o bt-exe.o bt-dll.o bt-log.o bcheck.o
I386_O = libtcc1.o alloca.o alloca-bt.o stdatomic.o atomic.o builtin.o $(BT_O) OBJ-i386 = $(I386_O) $(LIN_O)
X86_64_O = libtcc1.o alloca.o alloca-bt.o stdatomic.o atomic.o builtin.o $(BT_O) OBJ-x86_64 = $(X86_64_O) va_list.o $(LIN_O)
ARM_O = libtcc1.o armeabi.o alloca.o armflush.o stdatomic.o atomic.o builtin.o $(BT_O) OBJ-x86_64-osx = $(X86_64_O) va_list.o $(OSX_O)
ARM64_O = lib-arm64.o stdatomic.o atomic.o builtin.o $(BT_O) OBJ-i386-win32 = $(I386_O) chkstk.o $(WIN_O)
RISCV64_O = lib-arm64.o stdatomic.o atomic.o builtin.o $(BT_O) OBJ-x86_64-win32 = $(X86_64_O) chkstk.o $(WIN_O)
WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o OBJ-arm64 = $(ARM64_O) $(LIN_O)
OBJ-arm64-osx = $(ARM64_O) $(OSX_O)
OBJ-i386 = $(I386_O) $(BCHECK_O) $(DSO_O) OBJ-arm = $(ARM_O) $(LIN_O)
OBJ-x86_64 = $(X86_64_O) va_list.o $(BCHECK_O) $(DSO_O) OBJ-arm-fpa = $(OBJ-arm)
OBJ-x86_64-osx = $(X86_64_O) va_list.o $(BCHECK_O) OBJ-arm-fpa-ld = $(OBJ-arm)
OBJ-i386-win32 = $(I386_O) chkstk.o $(B_O) $(WIN_O) OBJ-arm-vfp = $(OBJ-arm)
OBJ-x86_64-win32 = $(X86_64_O) chkstk.o $(B_O) $(WIN_O) OBJ-arm-eabi = $(OBJ-arm)
OBJ-arm64 = $(ARM64_O) $(BCHECK_O) $(DSO_O) OBJ-arm-eabihf = $(OBJ-arm)
OBJ-arm64-osx = $(ARM64_O) $(BCHECK_O)
OBJ-arm = $(ARM_O) $(BCHECK_O) $(DSO_O)
OBJ-arm-fpa = $(ARM_O) $(DSO_O)
OBJ-arm-fpa-ld = $(ARM_O) $(DSO_O)
OBJ-arm-vfp = $(ARM_O) $(DSO_O)
OBJ-arm-eabi = $(ARM_O) $(DSO_O)
OBJ-arm-eabihf = $(ARM_O) $(DSO_O)
OBJ-arm-wince = $(ARM_O) $(WIN_O) OBJ-arm-wince = $(ARM_O) $(WIN_O)
OBJ-riscv64 = $(RISCV64_O) $(BCHECK_O) $(DSO_O) OBJ-riscv64 = $(RISCV64_O) $(LIN_O)
OBJ-extra = $(filter $(EXTRA_O),$(OBJ-$T)) OBJ-extra = $(filter $(EXTRA_O),$(OBJ-$T))
OBJ-libtcc1 = $(addprefix $(X),$(filter-out $(OBJ-extra),$(OBJ-$T))) OBJ-libtcc1 = $(addprefix $(X),$(filter-out $(OBJ-extra),$(OBJ-$T)))

View file

@ -1004,6 +1004,8 @@ static int tcc_glob_so(TCCState *s1, const char *pattern, char *buf, int size)
} }
#endif #endif
static int guess_filetype(const char *filename);
ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags) ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
{ {
int fd, ret = -1; int fd, ret = -1;
@ -1014,6 +1016,9 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
filename = buf; filename = buf;
#endif #endif
if (0 == (flags & AFF_TYPE_MASK))
flags |= guess_filetype(filename);
/* ignore binary files with -E */ /* ignore binary files with -E */
if (s1->output_type == TCC_OUTPUT_PREPROCESS if (s1->output_type == TCC_OUTPUT_PREPROCESS
&& (flags & AFF_TYPE_BIN)) && (flags & AFF_TYPE_BIN))
@ -1123,10 +1128,10 @@ check_success:
return ret; return ret;
} }
LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename) static int guess_filetype(const char *filename)
{ {
int filetype = s->filetype; int filetype = 0;
if (0 == (filetype & AFF_TYPE_MASK)) { if (1) {
/* use a file extension to detect a filetype */ /* use a file extension to detect a filetype */
const char *ext = tcc_fileextension(filename); const char *ext = tcc_fileextension(filename);
if (ext[0]) { if (ext[0]) {
@ -1145,7 +1150,12 @@ LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename)
filetype = AFF_TYPE_C; filetype = AFF_TYPE_C;
} }
} }
return tcc_add_file_internal(s, filename, filetype | AFF_PRINT_ERROR); return filetype;
}
LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename)
{
return tcc_add_file_internal(s, filename, s->filetype | AFF_PRINT_ERROR);
} }
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname) LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname)
@ -1162,12 +1172,12 @@ static int tcc_add_library_internal(TCCState *s1, const char *fmt,
for(i = 0; i < nb_paths; i++) { for(i = 0; i < nb_paths; i++) {
snprintf(buf, sizeof(buf), fmt, paths[i], filename); snprintf(buf, sizeof(buf), fmt, paths[i], filename);
ret = tcc_add_file_internal(s1, buf, (flags & ~AFF_PRINT_ERROR) | AFF_TYPE_BIN); ret = tcc_add_file_internal(s1, buf, flags & ~AFF_PRINT_ERROR);
if (ret != FILE_NOT_FOUND) if (ret != FILE_NOT_FOUND)
return ret; return ret;
} }
if (flags & AFF_PRINT_ERROR) if (flags & AFF_PRINT_ERROR)
tcc_error_noabort("file '%s' not found", filename); tcc_error_noabort("library '%s' not found", filename);
return FILE_NOT_FOUND; return FILE_NOT_FOUND;
} }
@ -1219,15 +1229,7 @@ LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname)
return ret; return ret;
++pp; ++pp;
} }
return FILE_NOT_FOUND; return tcc_add_dll(s, libraryname, AFF_PRINT_ERROR);
}
PUB_FUNC int tcc_add_library_err(TCCState *s1, const char *libname)
{
int ret = tcc_add_library(s1, libname);
if (ret == FILE_NOT_FOUND)
tcc_error_noabort("library '%s' not found", libname);
return ret;
} }
/* handle #pragma comment(lib,) */ /* handle #pragma comment(lib,) */
@ -1235,7 +1237,7 @@ ST_FUNC void tcc_add_pragma_libs(TCCState *s1)
{ {
int i; int i;
for (i = 0; i < s1->nb_pragma_libs; i++) for (i = 0; i < s1->nb_pragma_libs; i++)
tcc_add_library_err(s1, s1->pragma_libs[i]); tcc_add_library(s1, s1->pragma_libs[i]);
} }
LIBTCCAPI int tcc_add_symbol(TCCState *s1, const char *name, const void *val) LIBTCCAPI int tcc_add_symbol(TCCState *s1, const char *name, const void *val)

10
tcc.c
View file

@ -366,7 +366,7 @@ redo:
struct filespec *f = s->files[n]; struct filespec *f = s->files[n];
s->filetype = f->type; s->filetype = f->type;
if (f->type & AFF_TYPE_LIB) { if (f->type & AFF_TYPE_LIB) {
ret = tcc_add_library_err(s, f->name); ret = tcc_add_library(s, f->name);
} else { } else {
if (1 == s->verbose) if (1 == s->verbose)
printf("-> %s\n", f->name); printf("-> %s\n", f->name);
@ -392,9 +392,9 @@ redo:
} else { } else {
if (!s->outfile) if (!s->outfile)
s->outfile = default_outputfile(s, first_file); s->outfile = default_outputfile(s, first_file);
if (!s->just_deps && tcc_output_file(s, s->outfile)) if (!s->just_deps)
; ret = tcc_output_file(s, s->outfile);
else if (s->gen_deps) if (!ret && s->gen_deps)
gen_makedeps(s, s->outfile, s->deps_outfile); gen_makedeps(s, s->outfile, s->deps_outfile);
} }
} }
@ -402,7 +402,7 @@ redo:
done = 1; done = 1;
if (t) if (t)
done = 0; /* run more tests with -dt -run */ done = 0; /* run more tests with -dt -run */
else if (s->nb_errors) else if (ret)
ret = 1; ret = 1;
else if (n < s->nb_files) else if (n < s->nb_files)
done = 0; /* compile more files with -c */ done = 0; /* compile more files with -c */

13
tcc.h
View file

@ -974,8 +974,6 @@ struct TCCState {
int uw_sym; int uw_sym;
unsigned uw_offs; unsigned uw_offs;
# endif # endif
#else
unsigned shf_RELRO; /* section flags for RELRO sections */
#endif #endif
#if defined TCC_TARGET_MACHO #if defined TCC_TARGET_MACHO
@ -1874,10 +1872,6 @@ ST_FUNC int gen_makedeps(TCCState *s, const char *target, const char *filename);
/* ------------ tccdbg.c ------------ */ /* ------------ tccdbg.c ------------ */
ST_FUNC void tcc_eh_frame_start(TCCState *s1);
ST_FUNC void tcc_eh_frame_end(TCCState *s1);
ST_FUNC void tcc_eh_frame_hdr(TCCState *s1, int final);
ST_FUNC void tcc_debug_new(TCCState *s); ST_FUNC void tcc_debug_new(TCCState *s);
ST_FUNC void tcc_debug_start(TCCState *s1); ST_FUNC void tcc_debug_start(TCCState *s1);
@ -1896,6 +1890,13 @@ ST_FUNC void tcc_debug_typedef(TCCState *s1, Sym *sym);
ST_FUNC void tcc_debug_stabn(TCCState *s1, int type, int value); ST_FUNC void tcc_debug_stabn(TCCState *s1, int type, int value);
ST_FUNC void tcc_debug_fix_anon(TCCState *s1, CType *t); ST_FUNC void tcc_debug_fix_anon(TCCState *s1, CType *t);
#if !(defined ELF_OBJ_ONLY || defined TCC_TARGET_ARM || defined TARGETOS_BSD)
ST_FUNC void tcc_eh_frame_start(TCCState *s1);
ST_FUNC void tcc_eh_frame_end(TCCState *s1);
ST_FUNC void tcc_eh_frame_hdr(TCCState *s1, int final);
#define TCC_EH_FRAME 1
#endif
ST_FUNC void tcc_tcov_start(TCCState *s1); ST_FUNC void tcc_tcov_start(TCCState *s1);
ST_FUNC void tcc_tcov_end(TCCState *s1); ST_FUNC void tcc_tcov_end(TCCState *s1);
ST_FUNC void tcc_tcov_check_line(TCCState *s1, int start); ST_FUNC void tcc_tcov_check_line(TCCState *s1, int start);

View file

@ -424,7 +424,7 @@ ST_FUNC void tcc_debug_new(TCCState *s1)
if (s1->do_debug && s1->output_type == TCC_OUTPUT_MEMORY) if (s1->do_debug && s1->output_type == TCC_OUTPUT_MEMORY)
s1->do_backtrace = 1; s1->do_backtrace = 1;
if (s1->do_backtrace) if (s1->do_backtrace)
shf = SHF_ALLOC | SHF_WRITE; // SHF_WRITE needed for musl/SELINUX shf = SHF_ALLOC; /* have debug data available at runtime */
#endif #endif
if (s1->dwarf) { if (s1->dwarf) {
@ -511,7 +511,7 @@ static void put_stabn(TCCState *s1, int type, int other, int desc, int value)
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
#define dwarf_data1(s,data) \ #define dwarf_data1(s,data) \
{ unsigned char *p = section_ptr_add((s), 1); *p = (data); } (*(uint8_t*)section_ptr_add((s), 1) = (data))
#define dwarf_data2(s,data) \ #define dwarf_data2(s,data) \
write16le(section_ptr_add((s), 2), (data)) write16le(section_ptr_add((s), 2), (data))
#define dwarf_data4(s,data) \ #define dwarf_data4(s,data) \
@ -712,10 +712,9 @@ static void dwarf_sleb128_op (TCCState *s1, long long value)
} while (more); } while (more);
} }
#if TCC_EH_FRAME
ST_FUNC void tcc_eh_frame_start(TCCState *s1) ST_FUNC void tcc_eh_frame_start(TCCState *s1)
{ {
#if !(defined _WIN32 || defined __APPLE__ || defined TCC_TARGET_ARM || \
defined TARGETOS_BSD)
if (!s1->unwind_tables) if (!s1->unwind_tables)
return; return;
eh_frame_section = new_section(s1, ".eh_frame", SHT_PROGBITS, SHF_ALLOC); eh_frame_section = new_section(s1, ".eh_frame", SHT_PROGBITS, SHF_ALLOC);
@ -784,7 +783,6 @@ ST_FUNC void tcc_eh_frame_start(TCCState *s1)
dwarf_data1(eh_frame_section, DW_CFA_nop); dwarf_data1(eh_frame_section, DW_CFA_nop);
write32le(eh_frame_section->data + s1->eh_start, // length write32le(eh_frame_section->data + s1->eh_start, // length
eh_frame_section->data_offset - s1->eh_start - 4); eh_frame_section->data_offset - s1->eh_start - 4);
#endif
} }
static void tcc_debug_frame_end(TCCState *s1, int size) static void tcc_debug_frame_end(TCCState *s1, int size)
@ -1006,6 +1004,7 @@ next:
qsort(eh_frame_hdr_section->data + tab_offset, count, qsort(eh_frame_hdr_section->data + tab_offset, count,
sizeof(struct eh_search_table), sort_eh_table); sizeof(struct eh_search_table), sort_eh_table);
} }
#endif
/* start of translation unit info */ /* start of translation unit info */
ST_FUNC void tcc_debug_start(TCCState *s1) ST_FUNC void tcc_debug_start(TCCState *s1)
@ -2172,7 +2171,9 @@ ST_FUNC void tcc_debug_funcend(TCCState *s1, int size)
/* lldb does not like function end and next function start at same pc */ /* lldb does not like function end and next function start at same pc */
int min_instr_len; int min_instr_len;
#if TCC_EH_FRAME
tcc_debug_frame_end(s1, size); tcc_debug_frame_end(s1, size);
#endif
if (!s1->do_debug) if (!s1->do_debug)
return; return;
min_instr_len = dwarf_line.last_pc == ind ? 0 : DWARF_MIN_INSTR_LEN; min_instr_len = dwarf_line.last_pc == ind ? 0 : DWARF_MIN_INSTR_LEN;

View file

@ -51,7 +51,7 @@ struct sym_version {
#define shf_RELRO SHF_ALLOC #define shf_RELRO SHF_ALLOC
static const char rdata[] = ".rdata"; static const char rdata[] = ".rdata";
#else #else
#define shf_RELRO s1->shf_RELRO #define shf_RELRO SHF_ALLOC /* eventually made SHF_WRITE in sort_sections() */
static const char rdata[] = ".data.ro"; static const char rdata[] = ".data.ro";
#endif #endif
@ -61,12 +61,6 @@ ST_FUNC void tccelf_new(TCCState *s)
{ {
TCCState *s1 = s; TCCState *s1 = s;
#ifndef TCC_TARGET_PE
shf_RELRO = SHF_ALLOC;
if (s1->output_type != TCC_OUTPUT_MEMORY)
shf_RELRO |= SHF_WRITE; /* the ELF loader will set it to RO at runtime */
#endif
/* no section zero */ /* no section zero */
dynarray_add(&s->sections, &s->nb_sections, NULL); dynarray_add(&s->sections, &s->nb_sections, NULL);
@ -95,7 +89,9 @@ ST_FUNC void tccelf_new(TCCState *s)
tcc_debug_new(s); tcc_debug_new(s);
} }
#if TCC_EH_FRAME
tcc_eh_frame_start(s); tcc_eh_frame_start(s);
#endif
#ifdef CONFIG_TCC_BCHECK #ifdef CONFIG_TCC_BCHECK
if (s->do_bounds_check) { if (s->do_bounds_check) {
@ -1126,8 +1122,8 @@ static void relocate_section(TCCState *s1, Section *s, Section *sr)
r = 0; /* cannot apply 64bit relocation to 32bit value */ r = 0; /* cannot apply 64bit relocation to 32bit value */
sr->data_offset = sr->sh_size = r; sr->data_offset = sr->sh_size = r;
#ifdef CONFIG_TCC_PIE #ifdef CONFIG_TCC_PIE
if (r && 0 == (s->sh_flags & SHF_WRITE)) if (r && (s->sh_flags & SHF_EXECINSTR))
tcc_warning("%d relocations to ro-section %s", (unsigned)(r / sizeof *qrel), s->name); tcc_warning("%d relocations to %s", (unsigned)(r / sizeof *qrel), s->name);
#endif #endif
} }
} }
@ -1758,7 +1754,7 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL) { if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL) {
tcc_add_support(s1, "bcheck.o"); tcc_add_support(s1, "bcheck.o");
# if !(TARGETOS_OpenBSD || TARGETOS_NetBSD) # if !(TARGETOS_OpenBSD || TARGETOS_NetBSD)
tcc_add_library_err(s1, "dl"); tcc_add_library(s1, "dl");
# endif # endif
lpthread = 1; lpthread = 1;
} }
@ -1774,8 +1770,8 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
} }
#endif #endif
if (lpthread) if (lpthread)
tcc_add_library_err(s1, "pthread"); tcc_add_library(s1, "pthread");
tcc_add_library_err(s1, "c"); tcc_add_library(s1, "c");
#ifdef TCC_LIBGCC #ifdef TCC_LIBGCC
if (!s1->static_link) { if (!s1->static_link) {
if (TCC_LIBGCC[0] == '/') if (TCC_LIBGCC[0] == '/')
@ -1785,7 +1781,7 @@ ST_FUNC void tcc_add_runtime(TCCState *s1)
} }
#endif #endif
#if defined TCC_TARGET_ARM && TARGETOS_FreeBSD #if defined TCC_TARGET_ARM && TARGETOS_FreeBSD
tcc_add_library_err(s1, "gcc_s"); // unwind code tcc_add_library(s1, "gcc_s"); // unwind code
#endif #endif
if (TCC_LIBTCC1[0]) if (TCC_LIBTCC1[0])
tcc_add_support(s1, TCC_LIBTCC1); tcc_add_support(s1, TCC_LIBTCC1);
@ -2091,7 +2087,7 @@ static int set_sec_sizes(TCCState *s1)
/* allocate the section */ /* allocate the section */
s->sh_flags |= SHF_ALLOC; s->sh_flags |= SHF_ALLOC;
s->sh_size = count * sizeof(ElfW_Rel); s->sh_size = count * sizeof(ElfW_Rel);
if (!(s1->sections[s->sh_info]->sh_flags & SHF_WRITE)) if (s1->sections[s->sh_info]->sh_flags & SHF_EXECINSTR)
textrel += count; textrel += count;
} }
} }
@ -2161,47 +2157,58 @@ static int sort_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
} else { } else {
j = 0x700; j = 0x700;
} }
if (s1->output_format != TCC_OUTPUT_FORMAT_ELF) {
if (j >= 0x700 || 0 == strncmp(s->name, ".eh_frame", 9))
s->sh_size = 0, j = 0x900;
}
if (s->sh_type == SHT_SYMTAB || s->sh_type == SHT_DYNSYM) { if (s->sh_type == SHT_SYMTAB || s->sh_type == SHT_DYNSYM) {
k = 0x10; k = 0x10;
} else if (s->sh_type == SHT_STRTAB && strcmp(s->name, ".stabstr")) { } else if (s->sh_type == SHT_STRTAB && strcmp(s->name, ".stabstr")) {
k = 0x11; k = 0x11;
if (i == nb_sections - 1) /* ".shstrtab" assumed to remain last */ if (i == nb_sections - 1) /* ".shstrtab" assumed to stay last */
k = 0xff; k = 0xff;
} else if (s->sh_type == SHT_HASH || s->sh_type == SHT_GNU_HASH) { } else if (s->sh_type == SHT_HASH || s->sh_type == SHT_GNU_HASH) {
k = 0x12; k = 0x12;
} else if (s->sh_type == SHT_GNU_verdef
|| s->sh_type == SHT_GNU_verneed
|| s->sh_type == SHT_GNU_versym) {
k = 0x13;
} else if (s->sh_type == SHT_RELX) { } else if (s->sh_type == SHT_RELX) {
k = 0x20; k = 0x20;
if (s1->plt && s == s1->plt->reloc) if (s1->plt && s == s1->plt->reloc)
k = 0x21; k = 0x21;
} else if (s->sh_flags & SHF_EXECINSTR) {
k = 0x30;
/* RELRO sections --> */
} else if (s->sh_type == SHT_PREINIT_ARRAY) { } else if (s->sh_type == SHT_PREINIT_ARRAY) {
k = 0x41; k = 0x41;
} else if (s->sh_type == SHT_INIT_ARRAY) { } else if (s->sh_type == SHT_INIT_ARRAY) {
k = 0x42; k = 0x42;
} else if (s->sh_type == SHT_FINI_ARRAY) { } else if (s->sh_type == SHT_FINI_ARRAY) {
k = 0x43; k = 0x43;
#ifdef CONFIG_TCC_BCHECK
} else if (s == bounds_section || s == lbounds_section) {
k = 0x44;
#endif
} else if (s == rodata_section || 0 == strcmp(s->name, ".data.rel.ro")) {
k = 0x45;
} else if (s->sh_type == SHT_DYNAMIC) { } else if (s->sh_type == SHT_DYNAMIC) {
k = 0x46; k = 0x46;
} else if (s == s1->got) { } else if (s == s1->got) {
k = 0x47; /* .got as RELRO needs BIND_NOW in DT_FLAGS */ k = 0x47; /* .got as RELRO needs BIND_NOW in DT_FLAGS */
} else { } else if (s->reloc && (s->reloc->sh_flags & SHF_ALLOC) && j == 0x100) {
k = 0x50; k = 0x44;
if (s->sh_type == SHT_NOTE) /* <-- */
} else if (s->sh_type == SHT_NOTE) {
k = 0x60; k = 0x60;
if (s->sh_flags & SHF_EXECINSTR) } else if (s->sh_type == SHT_NOBITS) {
k = 0x70; k = 0x70; /* bss */
if (s->sh_type == SHT_NOBITS) } else if (s == d->interp) {
k = 0x80;
if (s == d->interp)
k = 0x00; k = 0x00;
} else {
k = 0x50; /* data */
} }
k += j; k += j;
if ((k & 0xfff0) == 0x140) {
/* make RELRO section writable */
k += 0x100, s->sh_flags |= SHF_WRITE;
}
for (n = i; n > 1 && k < (f = sec_cls[n - 1]); --n) for (n = i; n > 1 && k < (f = sec_cls[n - 1]); --n)
sec_cls[n] = f, sec_order[n] = sec_order[n - 1]; sec_cls[n] = f, sec_order[n] = sec_order[n - 1];
sec_cls[n] = k, sec_order[n] = i; sec_cls[n] = k, sec_order[n] = i;
@ -2233,7 +2240,7 @@ static int sort_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
f0 = f, ++n, f |= 1<<8; f0 = f, ++n, f |= 1<<8;
} }
sec_cls[i] = f; sec_cls[i] = f;
//printf("ph %d sec %02d : %3X %3X %8.2X %04X %s\n", (f>0) * n, i, f, k, s->sh_type, s->sh_size, s->name); //printf("ph %d sec %02d : %3X %3X %8.2X %04X %s\n", (f>0) * n, i, f, k, s->sh_type, (int)s->sh_size, s->name);
} }
return n; return n;
} }
@ -2395,12 +2402,8 @@ static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
fill_phdr(++ph, PT_NOTE, d->note); fill_phdr(++ph, PT_NOTE, d->note);
if (d->dynamic) if (d->dynamic)
fill_phdr(++ph, PT_DYNAMIC, d->dynamic)->p_flags |= PF_W; fill_phdr(++ph, PT_DYNAMIC, d->dynamic)->p_flags |= PF_W;
if (eh_frame_hdr_section) { if (eh_frame_hdr_section)
add32le(eh_frame_hdr_section->data + 4,
eh_frame_section->sh_offset -
eh_frame_hdr_section->sh_offset - 4);
fill_phdr(++ph, PT_GNU_EH_FRAME, eh_frame_hdr_section); fill_phdr(++ph, PT_GNU_EH_FRAME, eh_frame_hdr_section);
}
if (d->roinf) if (d->roinf)
fill_phdr(++ph, PT_GNU_RELRO, d->roinf)->p_flags |= PF_W; fill_phdr(++ph, PT_GNU_RELRO, d->roinf)->p_flags |= PF_W;
if (d->interp) if (d->interp)
@ -2869,10 +2872,10 @@ static int elf_output_file(TCCState *s1, const char *filename)
/* shared library case: simply export all global symbols */ /* shared library case: simply export all global symbols */
export_global_syms(s1); export_global_syms(s1);
} }
#if TCC_EH_FRAME
/* fill with initial data */ /* fill with initial data */
tcc_eh_frame_hdr(s1, 0); tcc_eh_frame_hdr(s1, 0);
#endif
dyninf.gnu_hash = create_gnu_hash(s1); dyninf.gnu_hash = create_gnu_hash(s1);
} else { } else {
build_got_entries(s1, 0); build_got_entries(s1, 0);
@ -2956,10 +2959,10 @@ static int elf_output_file(TCCState *s1, const char *filename)
update_gnu_hash(s1, dyninf.gnu_hash); update_gnu_hash(s1, dyninf.gnu_hash);
reorder_sections(s1, sec_order); reorder_sections(s1, sec_order);
#if TCC_EH_FRAME
/* fill with final data */ /* fill with final data */
tcc_eh_frame_hdr(s1, 1); tcc_eh_frame_hdr(s1, 1);
#endif
/* Create the ELF file with name 'filename' */ /* Create the ELF file with name 'filename' */
ret = tcc_write_elf_file(s1, filename, dyninf.phnum, dyninf.phdr); ret = tcc_write_elf_file(s1, filename, dyninf.phnum, dyninf.phdr);
the_end: the_end:
@ -3146,6 +3149,11 @@ invalid:
if (sh->sh_type == SHT_RELX) if (sh->sh_type == SHT_RELX)
sh = &shdr[sh->sh_info]; sh = &shdr[sh->sh_info];
/* ignore sections types we do not handle (plus relocs to those) */ /* ignore sections types we do not handle (plus relocs to those) */
if (0 == strncmp(strsec + sh->sh_name, ".debug_", 7)
|| 0 == strncmp(strsec + sh->sh_name, ".stab", 5)) {
if (!s1->do_debug || seencompressed)
continue;
} else
if (sh->sh_type != SHT_PROGBITS && if (sh->sh_type != SHT_PROGBITS &&
#ifdef TCC_ARM_EABI #ifdef TCC_ARM_EABI
sh->sh_type != SHT_ARM_EXIDX && sh->sh_type != SHT_ARM_EXIDX &&
@ -3157,12 +3165,9 @@ invalid:
sh->sh_type != SHT_NOBITS && sh->sh_type != SHT_NOBITS &&
sh->sh_type != SHT_PREINIT_ARRAY && sh->sh_type != SHT_PREINIT_ARRAY &&
sh->sh_type != SHT_INIT_ARRAY && sh->sh_type != SHT_INIT_ARRAY &&
sh->sh_type != SHT_FINI_ARRAY && sh->sh_type != SHT_FINI_ARRAY
strcmp(strsec + sh->sh_name, ".stabstr")
) )
continue; continue;
if (seencompressed && 0 == strncmp(strsec + sh->sh_name, ".debug_", 7))
continue;
sh = &shdr[i]; sh = &shdr[i];
sh_name = strsec + sh->sh_name; sh_name = strsec + sh->sh_name;
@ -3414,7 +3419,7 @@ static int tcc_load_alacarte(TCCState *s1, int fd, int size, int entrysize)
data = tcc_malloc(size); data = tcc_malloc(size);
if (full_read(fd, data, size) != size) if (full_read(fd, data, size) != size)
goto the_end; goto invalid;
nsyms = get_be(data, entrysize); nsyms = get_be(data, entrysize);
ar_index = data + entrysize; ar_index = data + entrysize;
ar_names = (char *) ar_index + nsyms * entrysize; ar_names = (char *) ar_index + nsyms * entrysize;
@ -3432,6 +3437,7 @@ static int tcc_load_alacarte(TCCState *s1, int fd, int size, int entrysize)
off = get_be(ar_index + i * entrysize, entrysize); off = get_be(ar_index + i * entrysize, entrysize);
len = read_ar_header(fd, off, &hdr); len = read_ar_header(fd, off, &hdr);
if (len <= 0 || memcmp(hdr.ar_fmag, ARFMAG, 2)) { if (len <= 0 || memcmp(hdr.ar_fmag, ARFMAG, 2)) {
invalid:
tcc_error_noabort("invalid archive"); tcc_error_noabort("invalid archive");
goto the_end; goto the_end;
} }

View file

@ -401,7 +401,9 @@ ST_FUNC int tccgen_compile(TCCState *s1)
gen_inline_functions(s1); gen_inline_functions(s1);
check_vstack(); check_vstack();
/* end of translation unit info */ /* end of translation unit info */
#if TCC_EH_FRAME
tcc_eh_frame_end(s1); tcc_eh_frame_end(s1);
#endif
tcc_debug_end(s1); tcc_debug_end(s1);
tcc_tcov_end(s1); tcc_tcov_end(s1);
return 0; return 0;

View file

@ -845,7 +845,7 @@ found_dll:
return s; return s;
} }
void pe_free_imports(struct pe_info *pe) static void pe_free_imports(struct pe_info *pe)
{ {
int i; int i;
for (i = 0; i < pe->imp_count; ++i) { for (i = 0; i < pe->imp_count; ++i) {
@ -1133,9 +1133,7 @@ static int pe_section_class(Section *s)
name = s->name; name = s->name;
if (0 == memcmp(name, ".stab", 5) || 0 == memcmp(name, ".debug_", 7)) { if (0 == memcmp(name, ".stab", 5) || 0 == memcmp(name, ".debug_", 7)) {
if (s->s1->do_debug)
return sec_debug; return sec_debug;
} else if (flags & SHF_ALLOC) { } else if (flags & SHF_ALLOC) {
if (type == SHT_PROGBITS if (type == SHT_PROGBITS
|| type == SHT_INIT_ARRAY || type == SHT_INIT_ARRAY
@ -1995,7 +1993,7 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
tcc_add_support(s1, TCC_LIBTCC1); tcc_add_support(s1, TCC_LIBTCC1);
for (pp = libs; 0 != (p = *pp); ++pp) { for (pp = libs; 0 != (p = *pp); ++pp) {
if (*p) if (*p)
tcc_add_library_err(s1, p); tcc_add_library(s1, p);
else if (PE_DLL != pe_type && PE_GUI != pe_type) else if (PE_DLL != pe_type && PE_GUI != pe_type)
break; break;
} }
@ -2068,8 +2066,8 @@ ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
#ifdef CONFIG_TCC_BCHECK #ifdef CONFIG_TCC_BCHECK
tcc_add_bcheck(s1); tcc_add_bcheck(s1);
#endif #endif
pe_add_runtime(s1, &pe);
tcc_add_pragma_libs(s1); tcc_add_pragma_libs(s1);
pe_add_runtime(s1, &pe);
resolve_common_syms(s1); resolve_common_syms(s1);
pe_set_options(s1, &pe); pe_set_options(s1, &pe);
pe_check_symbols(&pe); pe_check_symbols(&pe);

19
tccpp.c
View file

@ -1929,23 +1929,28 @@ ST_FUNC void preprocess(int is_bof)
break; break;
case TOK_LINE: case TOK_LINE:
next_nomacro(); next_nomacro();
if (tok != TOK_PPNUM) if (tok != TOK_PPNUM) {
_line_err: _line_err:
if (parse_flags & PARSE_FLAG_ASM_FILE)
goto ignore;
tcc_error("wrong #line format"); tcc_error("wrong #line format");
}
case TOK_PPNUM: case TOK_PPNUM:
parse_number(tokc.str.data); for (n = 0, q = tokc.str.data; *q; ++q) {
n = tokc.i; if (!isnum(*q))
goto _line_err;
n = n * 10 + *q - '0';
}
next_nomacro(); next_nomacro();
if (tok != TOK_LINEFEED) { if (tok != TOK_LINEFEED) {
if (tok == TOK_PPSTR && tokc.str.data[0] == '"') { if (tok == TOK_PPSTR && tokc.str.data[0] == '"') {
tokc.str.data[tokc.str.size - 2] = 0; tokc.str.data[tokc.str.size - 2] = 0;
tccpp_putfile(tokc.str.data + 1); tccpp_putfile(tokc.str.data + 1);
} else if (parse_flags & PARSE_FLAG_ASM_FILE) } else
goto ignore;
else
goto _line_err; goto _line_err;
next_nomacro(); next_nomacro();
} } else if (parse_flags & PARSE_FLAG_ASM_FILE)
goto ignore;
if (file->fd > 0) if (file->fd > 0)
total_lines += file->line_num - n; total_lines += file->line_num - n;
file->line_num = n; file->line_num = n;