History

tccelf.c: write section headers before sections

also avoid zero lenght PT_LOAD segments (which some musl loaders seem to dislike) Also: - tccasm.c: support .section with flags: .section .xyz,"wx" (fixes e4d874d88a2ef874a9c2fd7c47d3d3a35ae986e2) - tccgen,c: add __builtin_unreachable() - tccdefs.h: #define __has_attribute(x) 0 - tcc.c: tidy help for -std - tcctools.c/execvp_win32: quote strings more correctly - x86_64-gen.c:win32: set unwind begin-address to function-start - github action: add aarch64-osx (M1) & i386-win32 - configure: consider 32-bit build on MSYS64 native

grischka committed 2 years ago

Commit 45cff8f1 parent c21576f16 files · +170 −195Browse files

Unified · Split

16 files
  1. .github/workflows/build.yml +24 −6
  2. Makefile +4 −1
  3. configure +2 −1
  4. include/tccdefs.h +1 −0
  5. tcc.c +1 −2
  6. tccasm.c +12 −6
  7. tccelf.c +89 −95
  8. tccgen.c +8 −1
  9. tccpe.c +5 −4
  10. tcctok.h +1 −0
  11. tcctools.c +15 −23
  12. tests/exec_section_in_asm.c +0 −29
  13. tests/tcctest.c +1 −1
  14. tests/tests2/133_exec_section_in_c.c +0 −17
  15. tests/tests2/133_exec_section_in_c.expect +0 −1
  16. x86_64-gen.c +7 −8
.github/workflows/build.yml+24−6
@@ -10,7 +10,7 @@ jobs: · 9 unmodified lines
1010 timeout-minutes: 2
1111 steps:
1212 - uses: actions/checkout@v4
13− - name: make & test tcc
13+ - name: make & test tcc (x86_64-linux)
1414 run: ./configure && make && make test -k
1515
1616 test-x86_64-osx:
@@ -18,21 +18,36 @@ jobs: · 1 unmodified line
1818 timeout-minutes: 2
1919 steps:
2020 - uses: actions/checkout@v4
21− - name: make & test tcc
22− run: ./configure --config-codesign=no && make && make test -k
21+ - name: make & test tcc (x86_64-osx)
22+ run: ./configure && make && make test -k
23+
24+ test-aarch64-osx:
25+ runs-on: macos-14
26+ timeout-minutes: 2
27+ steps:
28+ - uses: actions/checkout@v4
29+ - name: make & test tcc (aarch64-osx)
30+ run: ./configure && make && make test -k
2331
24− test-x86_64-win32:
32+ test-x86-win32:
2533 runs-on: windows-2019
26− timeout-minutes: 4
34+ timeout-minutes: 6
2735 steps:
2836 - uses: actions/checkout@v4
29− - name: make & test tcc
37+ - name: make & test tcc (x86_64-win32)
3038 shell: cmd
3139 run: |
3240 set MSYS2_PATH_TYPE=inherit
3341 set MSYSTEM=MINGW64
3442 set CHERE_INVOKING=yes
3543 C:\msys64\usr\bin\bash -l -c "./configure && make && make test -k"
44+ - name: make & test tcc (i386-win32)
45+ shell: cmd
46+ run: |
47+ set MSYS2_PATH_TYPE=inherit
48+ set MSYSTEM=MINGW32
49+ set CHERE_INVOKING=yes
50+ C:\msys64\usr\bin\bash -l -c "./configure && make clean all && make test -k"
3651
3752 test-armv7-linux:
3853 runs-on: ubuntu-20.04
@@ -40,6 +55,7 @@ jobs: · 1 unmodified line
4055 steps:
4156 - uses: actions/checkout@v4
4257 - uses: uraimo/run-on-arch-action@v2
58+ name: make & test tcc (armv7-linux)
4359 with:
4460 arch: armv7
4561 distro: ubuntu20.04
@@ -57,6 +73,7 @@ jobs: · 11 unmodified lines
5773 steps:
5874 - uses: actions/checkout@v4
5975 - uses: uraimo/run-on-arch-action@v2
76+ name: make & test tcc (aarch64-linux)
6077 with:
6178 arch: aarch64
6279 distro: ubuntu20.04
@@ -74,6 +91,7 @@ jobs: · 11 unmodified lines
7491 steps:
7592 - uses: actions/checkout@v4
7693 - uses: uraimo/run-on-arch-action@v2
94+ name: make & test tcc (riscv64-linux)
7795 with:
7896 arch: riscv64
7997 distro: ubuntu20.04
Makefile+4−1
@@ -69,7 +69,10 @@ else · 68 unmodified lines
6969 ifdef CONFIG_OSX
7070 NATIVE_TARGET = $(ARCH)-osx
7171 ifneq ($(CC_NAME),tcc)
72− LDFLAGS += -flat_namespace -undefined warning
72+ LDFLAGS += -flat_namespace
73+ ifneq (1,$(shell expr $(GCC_MAJOR) ">=" 15))
74+ LDFLAGS += -undefined warning # depreciated in clang >= 15.0
75+ endif
7376 endif
7477 export MACOSX_DEPLOYMENT_TARGET := 10.6
7578 endif
configure+2−1
@@ -227,10 +227,12 @@ fi · 226 unmodified lines
227227
228228 # OS specific
229229 buildos=$(uname)
230+cpu_sys=$(uname -m)
230231
231232 case $buildos in
232233 Windows_NT|MINGW*|MSYS*|CYGWIN*)
233234 buildos="WIN32"
235+ test "$MSYSTEM" = "MINGW32" && cpu_sys=i386
234236 ;;
235237 Linux)
236238 if test "$(uname -o)" = "Android"; then
@@ -248,7 +250,6 @@ else · 11 unmodified lines
248250 default targetos "$buildos"
249251 fi
250252
251−cpu_sys=$(uname -m)
252253 default cpu "$cpu_sys"
253254 cpu_set="$cpu"
254255
include/tccdefs.h+1−0
@@ -152,6 +152,7 @@ · 151 unmodified lines
152152 #define __PRETTY_FUNCTION__ __FUNCTION__
153153 #define __has_builtin(x) 0
154154 #define __has_feature(x) 0
155+ #define __has_atttribute(x) 0
155156 /* C23 Keywords */
156157 #define _Nonnull
157158 #define _Nullable
tcc.c+1−2
@@ -33,8 +33,6 @@ static const char help[] = · 32 unmodified lines
3333 " -o outfile set output filename\n"
3434 " -run run compiled source\n"
3535 " -fflag set or reset (with 'no-' prefix) 'flag' (see tcc -hh)\n"
36− " -std=(c99|gnu99) Conform to the ISO 1999 C standard (default).\n"
37− " -std=(c11|gnu11) Conform to the ISO 2011 C standard.\n"
3836 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see tcc -hh)\n"
3937 " -w disable all warnings\n"
4038 " -v --version show version\n"
@@ -69,6 +67,7 @@ static const char help[] = · 28 unmodified lines
6967 " -bt[N] link with backtrace (stack dump) support [show max N callers]\n"
7068 #endif
7169 "Misc. options:\n"
70+ " -std=version define __STDC_VERSION__ according to version (c11/gnu11)\n"
7271 " -x[c|a|b|n] specify type of the next infile (C,ASM,BIN,NONE)\n"
7372 " -nostdinc do not use standard system include paths\n"
7473 " -nostdlib do not link with standard crt and libraries\n"
tccasm.c+12−6
@@ -857,6 +857,7 @@ static void asm_parse_directive(TCCState *s1, int global) · 856 unmodified lines
857857 {
858858 char sname[256];
859859 int old_nb_section = s1->nb_sections;
860+ int flags = SHF_ALLOC;
860861
861862 tok1 = tok;
862863 /* XXX: support more options */
@@ -870,10 +871,17 @@ static void asm_parse_directive(TCCState *s1, int global) · 7 unmodified lines
870871 next();
871872 }
872873 if (tok == ',') {
874+ const char *p;
873875 /* skip section options */
874876 next();
875877 if (tok != TOK_STR)
876878 expect("string constant");
879+ for (p = tokc.str.data; *p; ++p) {
880+ if (*p == 'w')
881+ flags |= SHF_WRITE;
882+ if (*p == 'x')
883+ flags |= SHF_EXECINSTR;
884+ }
877885 next();
878886 if (tok == ',') {
879887 next();
@@ -883,19 +891,17 @@ static void asm_parse_directive(TCCState *s1, int global) · 3 unmodified lines
883891 }
884892 }
885893 last_text_section = cur_text_section;
886− if (tok1 == TOK_ASMDIR_section) {
894+ if (tok1 == TOK_ASMDIR_section)
887895 use_section(s1, sname);
888− /* The section directive supports flags, but they are unsupported.
889− For now, just assume any section contains code. */
890− cur_text_section->sh_flags |= SHF_EXECINSTR;
891− }
892896 else
893897 push_section(s1, sname);
894898 /* If we just allocated a new section reset its alignment to
895899 1. new_section normally acts for GCC compatibility and
896900 sets alignment to PTR_SIZE. The assembler behaves different. */
897− if (old_nb_section != s1->nb_sections)
901+ if (old_nb_section != s1->nb_sections) {
898902 cur_text_section->sh_addralign = 1;
903+ cur_text_section->sh_flags = flags;
904+ }
899905 }
900906 break;
901907 case TOK_ASMDIR_previous:
tccelf.c+89−95
@@ -1488,7 +1488,7 @@ static void add_init_array_defines(TCCState *s1, const char *section_name) · 1487 unmodified lines
14881488 s = have_section(s1, section_name);
14891489 if (!s || !(s->sh_flags & SHF_ALLOC)) {
14901490 end_offset = 0;
1491− s = data_section;
1491+ s = text_section;
14921492 } else {
14931493 end_offset = s->data_offset;
14941494 }
@@ -1823,11 +1823,14 @@ static void tcc_add_linker_symbols(TCCState *s1) · 328 unmodified lines
18231823 for(i = 1; i < s1->nb_sections; i++) {
18241824 s = s1->sections[i];
18251825 if ((s->sh_flags & SHF_ALLOC)
1826− && (s->sh_type == SHT_PROGBITS
1826+ && (s->sh_type == SHT_PROGBITS || s->sh_type == SHT_NOBITS
18271827 || s->sh_type == SHT_STRTAB)) {
1828− const char *p;
18291828 /* check if section name can be expressed in C */
1830− p = s->name;
1829+ const char *p0, *p;
1830+ p0 = s->name;
1831+ if (*p0 == '.')
1832+ ++p0;
1833+ p = p0;
18311834 for(;;) {
18321835 int c = *p;
18331836 if (!c)
@@ -1836,9 +1839,9 @@ static void tcc_add_linker_symbols(TCCState *s1) · 2 unmodified lines
18361839 goto next_sec;
18371840 p++;
18381841 }
1839− snprintf(buf, sizeof(buf), "__start_%s", s->name);
1842+ snprintf(buf, sizeof(buf), "__start_%s", p0);
18401843 set_global_sym(s1, buf, s, 0);
1841− snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1844+ snprintf(buf, sizeof(buf), "__stop_%s", p0);
18421845 set_global_sym(s1, buf, s, -1);
18431846 }
18441847 next_sec: ;
@@ -2123,6 +2126,7 @@ struct dyn_inf { · 278 unmodified lines
21232126
21242127 ElfW(Phdr) *phdr;
21252128 int phnum;
2129+ int shnum;
21262130 Section *interp;
21272131 Section *note;
21282132 Section *gnu_hash;
@@ -2135,7 +2139,7 @@ struct dyn_inf { · 6 unmodified lines
21352139 program headers are filled since they contain info about the layout.
21362140 We do the following ordering: interp, symbol tables, relocations, progbits,
21372141 nobits */
2138−static int sort_sections(TCCState *s1, int *sec_order, Section *interp)
2142+static int sort_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
21392143 {
21402144 Section *s;
21412145 int i, j, k, f, f0, n;
@@ -2144,16 +2148,16 @@ static int sort_sections(TCCState *s1, int *sec_order, Section *interp) · 2 unmodified lines
21442148
21452149 for (i = 1; i < nb_sections; i++) {
21462150 s = s1->sections[i];
2147− if (s->sh_flags & SHF_ALLOC) {
2151+ if (0 == s->sh_name) {
2152+ j = 0x900; /* no sh_name: won't go to file */
2153+ } else if (s->sh_flags & SHF_ALLOC) {
21482154 j = 0x100;
21492155 if (s->sh_flags & SHF_WRITE)
21502156 j = 0x200;
21512157 if (s->sh_flags & SHF_TLS)
21522158 j += 0x200;
2153− } else if (s->sh_name) {
2154− j = 0x700;
21552159 } else {
2156− j = 0x900; /* no sh_name: won't go to file */
2160+ j = 0x700;
21572161 }
21582162 if (s->sh_type == SHT_SYMTAB || s->sh_type == SHT_DYNSYM) {
21592163 k = 0x10;
@@ -2191,7 +2195,7 @@ static int sort_sections(TCCState *s1, int *sec_order, Section *interp) · 31 unmodified lines
21912195 k = 0x70;
21922196 if (s->sh_type == SHT_NOBITS)
21932197 k = 0x80;
2194− if (s == interp)
2198+ if (s == d->interp)
21952199 k = 0x00;
21962200 }
21972201 k += j;
@@ -2201,6 +2205,7 @@ static int sort_sections(TCCState *s1, int *sec_order, Section *interp) · 3 unmodified lines
22012205 sec_cls[n] = k, sec_order[n] = i;
22022206 }
22032207 sec_order[0] = 0;
2208+ d->shnum = 1;
22042209
22052210 /* count PT_LOAD headers needed */
22062211 n = f0 = 0;
@@ -2208,21 +2213,25 @@ static int sort_sections(TCCState *s1, int *sec_order, Section *interp) · 1 unmodified line
22082213 s = s1->sections[sec_order[i]];
22092214 k = sec_cls[i];
22102215 f = 0;
2216+ if (k < 0x900)
2217+ ++d->shnum;
22112218 if (k < 0x700) {
22122219 f = s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR|SHF_TLS);
22132220 #if TARGETOS_NetBSD
22142221 /* NetBSD only supports 2 PT_LOAD sections.
22152222 See: https://blog.netbsd.org/tnf/entry/the_first_report_on_lld */
2216− if ((f & SHF_WRITE) == 0) f |= SHF_EXECINSTR;
2223+ if ((f & SHF_WRITE) == 0)
2224+ f |= SHF_EXECINSTR;
22172225 #else
22182226 if ((k & 0xfff0) == 0x240) /* RELRO sections */
22192227 f |= 1<<4;
22202228 #endif
2221− if (f != f0) /* start new header when flags changed or relro */
2229+ /* start new header when flags changed or relro, but avoid zero memsz */
2230+ if (f != f0 && s->sh_size)
22222231 f0 = f, ++n, f |= 1<<8;
22232232 }
22242233 sec_cls[i] = f;
2225− //printf("ph %d sec %02d : %3X %3X %8.2X %04X %s\n", !!f * n, i, f, k, s->sh_type, s->sh_size, s->name);
2234+ //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);
22262235 }
22272236 return n;
22282237 }
@@ -2253,7 +2262,7 @@ static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d) · 24 unmodified lines
22532262 int file_offset;
22542263
22552264 /* compute number of program headers */
2256− phnum = sort_sections(s1, sec_order, d->interp);
2265+ phnum = sort_sections(s1, sec_order, d);
22572266 phfill = 0; /* set to 1 to have dll's with a PT_PHDR */
22582267 if (d->interp)
22592268 phfill = 2;
@@ -2268,8 +2277,10 @@ static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d) · 8 unmodified lines
22682277 d->phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
22692278
22702279 file_offset = 0;
2271− if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
2272− file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2280+ if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2281+ file_offset = (sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr)) + 3) & -4;
2282+ file_offset += d->shnum * sizeof (ElfW(Shdr));
2283+ }
22732284
22742285 s_align = ELF_PAGE_SIZE;
22752286 if (s1->section_align)
@@ -2392,7 +2403,7 @@ static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d) · 116 unmodified lines
23922403 ph->p_align = 4;
23932404 fill_phdr(ph, PT_PHDR, NULL);
23942405 }
2395− return file_offset;
2406+ return 0;
23962407 }
23972408
23982409 /* put dynamic tag */
@@ -2505,14 +2516,11 @@ static void update_reloc_sections(TCCState *s1, struct dyn_inf *dyninf) · 106 unmodified lines
25052516 }
25062517 }
25072518 }
2508−
2509−static int tidy_section_headers(TCCState *s1, int *sec_order);
25102519 #endif /* ndef ELF_OBJ_ONLY */
25112520
25122521 /* Create an ELF file on disk.
25132522 This function handle ELF specific layout requirements */
2514−static int tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
2515− int file_offset, int *sec_order)
2523+static int tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr)
25162524 {
25172525 int i, shnum, offset, size, file_type;
25182526 Section *s;
@@ -2523,19 +2531,12 @@ static int tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr, · 4 unmodified lines
25232531 shnum = s1->nb_sections;
25242532
25252533 memset(&ehdr, 0, sizeof(ehdr));
2526−
25272534 if (phnum > 0) {
25282535 ehdr.e_phentsize = sizeof(ElfW(Phdr));
25292536 ehdr.e_phnum = phnum;
25302537 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2531−#ifndef ELF_OBJ_ONLY
2532− shnum = tidy_section_headers(s1, sec_order);
2533−#endif
25342538 }
25352539
2536− /* align to 4 */
2537− file_offset = (file_offset + 3) & -4;
2538−
25392540 /* fill header */
25402541 ehdr.e_ident[0] = ELFMAG0;
25412542 ehdr.e_ident[1] = ELFMAG1;
@@ -2577,32 +2578,15 @@ static int tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr, · 35 unmodified lines
25772578
25782579 ehdr.e_machine = EM_TCC_TARGET;
25792580 ehdr.e_version = EV_CURRENT;
2580− ehdr.e_shoff = file_offset;
2581+ ehdr.e_shoff = (sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr)) + 3) & -4;
25812582 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
25822583 ehdr.e_shentsize = sizeof(ElfW(Shdr));
25832584 ehdr.e_shnum = shnum;
25842585 ehdr.e_shstrndx = shnum - 1;
25852586
2586− fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2587+ offset = fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
25872588 if (phdr)
2588− fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2589− offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2590−
2591− sort_syms(s1, symtab_section);
2592−
2593− for(i = 1; i < shnum; i++) {
2594− s = s1->sections[sec_order ? sec_order[i] : i];
2595− if (s->sh_type != SHT_NOBITS) {
2596− while (offset < s->sh_offset) {
2597− fputc(0, f);
2598− offset++;
2599− }
2600− size = s->sh_size;
2601− if (size)
2602− fwrite(s->data, 1, size, f);
2603− offset += size;
2604− }
2605− }
2589+ offset += fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
26062590
26072591 /* output section headers */
26082592 while (offset < ehdr.e_shoff) {
@@ -2613,8 +2597,8 @@ static int tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr, · 4 unmodified lines
26132597 for(i = 0; i < shnum; i++) {
26142598 sh = &shdr;
26152599 memset(sh, 0, sizeof(ElfW(Shdr)));
2616− s = s1->sections[i];
2617− if (s) {
2600+ if (i) {
2601+ s = s1->sections[i];
26182602 sh->sh_name = s->sh_name;
26192603 sh->sh_type = s->sh_type;
26202604 sh->sh_flags = s->sh_flags;
@@ -2627,20 +2611,35 @@ static int tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr, · 6 unmodified lines
26272611 sh->sh_offset = s->sh_offset;
26282612 sh->sh_size = s->sh_size;
26292613 }
2630− fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2614+ offset += fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2615+ }
2616+
2617+ sort_syms(s1, s1->symtab);
2618+
2619+ /* output sections */
2620+ for(i = 1; i < s1->nb_sections; i++) {
2621+ s = s1->sections[i];
2622+ if (s->sh_type != SHT_NOBITS) {
2623+ while (offset < s->sh_offset) {
2624+ fputc(0, f);
2625+ offset++;
2626+ }
2627+ size = s->sh_size;
2628+ if (size)
2629+ offset += fwrite(s->data, 1, size, f);
2630+ }
26312631 }
26322632 return 0;
26332633 }
26342634
2635−static int tcc_output_binary(TCCState *s1, FILE *f,
2636− const int *sec_order)
2635+static int tcc_output_binary(TCCState *s1, FILE *f)
26372636 {
26382637 Section *s;
26392638 int i, offset, size;
26402639
26412640 offset = 0;
26422641 for(i=1;i<s1->nb_sections;i++) {
2643− s = s1->sections[sec_order[i]];
2642+ s = s1->sections[i];
26442643 if (s->sh_type != SHT_NOBITS &&
26452644 (s->sh_flags & SHF_ALLOC)) {
26462645 while (offset < s->sh_offset) {
@@ -2657,7 +2656,7 @@ static int tcc_output_binary(TCCState *s1, FILE *f, · 10 unmodified lines
26572656
26582657 /* Write an elf, coff or "binary" file */
26592658 static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum,
2660− ElfW(Phdr) *phdr, int file_offset, int *sec_order)
2659+ ElfW(Phdr) *phdr)
26612660 {
26622661 int fd, mode, file_type, ret;
26632662 FILE *f;
@@ -2679,59 +2678,50 @@ static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum, · 15 unmodified lines
26792678 else
26802679 #endif
26812680 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
2682− ret = tcc_output_elf(s1, f, phnum, phdr, file_offset, sec_order);
2681+ ret = tcc_output_elf(s1, f, phnum, phdr);
26832682 else
2684− ret = tcc_output_binary(s1, f, sec_order);
2683+ ret = tcc_output_binary(s1, f);
26852684 fclose(f);
26862685
26872686 return ret;
26882687 }
26892688
26902689 #ifndef ELF_OBJ_ONLY
2691−/* Sort section headers by assigned sh_addr, remove sections
2690+/* order sections according to sec_order, remove sections
26922691 that we aren't going to output. */
2693−static int tidy_section_headers(TCCState *s1, int *sec_order)
2692+static void reorder_sections(TCCState *s1, int *sec_order)
26942693 {
2695− int i, nnew, l, *backmap;
2694+ int i, nnew, k, *backmap;
26962695 Section **snew, *s;
26972696 ElfW(Sym) *sym;
26982697
2699− snew = tcc_malloc(s1->nb_sections * sizeof(snew[0]));
27002698 backmap = tcc_malloc(s1->nb_sections * sizeof(backmap[0]));
2701− for (i = 0, nnew = 0, l = s1->nb_sections; i < s1->nb_sections; i++) {
2702− s = s1->sections[sec_order[i]];
2699+ for (i = 0, nnew = 0, snew = NULL; i < s1->nb_sections; i++) {
2700+ k = sec_order[i];
2701+ s = s1->sections[k];
27032702 if (!i || s->sh_name) {
2704− backmap[sec_order[i]] = nnew;
2705− snew[nnew] = s;
2706− ++nnew;
2703+ backmap[k] = nnew;
2704+ dynarray_add(&snew, &nnew, s);
27072705 } else {
2708− backmap[sec_order[i]] = 0;
2709− snew[--l] = s;
2706+ backmap[k] = 0;
2707+ /* just remember to free them later */
2708+ dynarray_add(&s1->priv_sections, &s1->nb_priv_sections, s);
27102709 }
27112710 }
2712− for (i = 0; i < nnew; i++) {
2711+ for (i = 1; i < nnew; i++) {
27132712 s = snew[i];
2714− if (s) {
2715− s->sh_num = i;
2716− if (s->sh_type == SHT_RELX)
2717− s->sh_info = backmap[s->sh_info];
2718− }
2713+ s->sh_num = i;
2714+ if (s->sh_type == SHT_RELX)
2715+ s->sh_info = backmap[s->sh_info];
2716+ else if (s->sh_type == SHT_SYMTAB || s->sh_type == SHT_DYNSYM)
2717+ for_each_elem(s, 1, sym, ElfW(Sym))
2718+ if (sym->st_shndx < s1->nb_sections)
2719+ sym->st_shndx = backmap[sym->st_shndx];
27192720 }
2720−
2721− for_each_elem(symtab_section, 1, sym, ElfW(Sym))
2722− if (sym->st_shndx != SHN_UNDEF && sym->st_shndx < SHN_LORESERVE)
2723− sym->st_shndx = backmap[sym->st_shndx];
2724− if ( !s1->static_link ) {
2725− for_each_elem(s1->dynsym, 1, sym, ElfW(Sym))
2726− if (sym->st_shndx != SHN_UNDEF && sym->st_shndx < SHN_LORESERVE)
2727− sym->st_shndx = backmap[sym->st_shndx];
2728− }
2729− for (i = 0; i < s1->nb_sections; i++)
2730− sec_order[i] = i;
27312721 tcc_free(s1->sections);
27322722 s1->sections = snew;
2723+ s1->nb_sections = nnew;
27332724 tcc_free(backmap);
2734− return nnew;
27352725 }
27362726
27372727 #ifdef TCC_TARGET_ARM
@@ -2797,7 +2787,7 @@ static void alloc_sec_names(TCCState *s1, int is_obj); · 59 unmodified lines
27972787 /* XXX: suppress unneeded sections */
27982788 static int elf_output_file(TCCState *s1, const char *filename)
27992789 {
2800− int i, ret, file_type, file_offset, *sec_order;
2790+ int i, ret, file_type, *sec_order;
28012791 struct dyn_inf dyninf = {0};
28022792 Section *interp, *dynstr, *dynamic;
28032793 int textrel, got_sym, dt_flags_1;
@@ -2876,7 +2866,6 @@ static int elf_output_file(TCCState *s1, const char *filename) · 72 unmodified lines
28762866 version_add (s1);
28772867
28782868 textrel = set_sec_sizes(s1);
2879− alloc_sec_names(s1, 0);
28802869
28812870 if (!s1->static_link) {
28822871 /* add a list of needed dlls */
@@ -2915,10 +2904,12 @@ static int elf_output_file(TCCState *s1, const char *filename) · 32 unmodified lines
29152904 dynstr->sh_size = dynstr->data_offset;
29162905 }
29172906
2907+ /* create and fill .shstrtab section */
2908+ alloc_sec_names(s1, 0);
29182909 /* this array is used to reorder sections in the output file */
29192910 sec_order = tcc_malloc(sizeof(int) * 2 * s1->nb_sections);
29202911 /* compute section to program header mapping */
2921− file_offset = layout_sections(s1, sec_order, &dyninf);
2912+ layout_sections(s1, sec_order, &dyninf);
29222913
29232914 if (dynamic) {
29242915 /* put in GOT the dynamic section address and relocate PLT */
@@ -2950,8 +2941,10 @@ static int elf_output_file(TCCState *s1, const char *filename) · 25 unmodified lines
29502941 if (dyninf.gnu_hash)
29512942 update_gnu_hash(s1, dyninf.gnu_hash);
29522943
2944+ reorder_sections(s1, sec_order);
2945+
29532946 /* Create the ELF file with name 'filename' */
2954− ret = tcc_write_elf_file(s1, filename, dyninf.phnum, dyninf.phdr, file_offset, sec_order);
2947+ ret = tcc_write_elf_file(s1, filename, dyninf.phnum, dyninf.phdr);
29552948 the_end:
29562949 tcc_free(sec_order);
29572950 tcc_free(dyninf.phdr);
@@ -2971,7 +2964,7 @@ static void alloc_sec_names(TCCState *s1, int is_obj) · 13 unmodified lines
29712964 s = s1->sections[i];
29722965 if (is_obj)
29732966 s->sh_size = s->data_offset;
2974− if (s == strsec || s->sh_size || (s->sh_flags & SHF_ALLOC))
2967+ if (s->sh_size || s == strsec || (s->sh_flags & SHF_ALLOC) || is_obj)
29752968 s->sh_name = put_elf_str(strsec, s->name);
29762969 }
29772970 strsec->sh_size = strsec->data_offset;
@@ -2985,7 +2978,8 @@ static int elf_output_obj(TCCState *s1, const char *filename) · 7 unmodified lines
29852978 s1->nb_errors = 0;
29862979 /* Allocate strings for section names */
29872980 alloc_sec_names(s1, 1);
2988− file_offset = sizeof (ElfW(Ehdr));
2981+ file_offset = (sizeof (ElfW(Ehdr)) + 3) & -4;
2982+ file_offset += s1->nb_sections * sizeof(ElfW(Shdr));
29892983 for(i = 1; i < s1->nb_sections; i++) {
29902984 s = s1->sections[i];
29912985 file_offset = (file_offset + 15) & -16;
@@ -2994,7 +2988,7 @@ static int elf_output_obj(TCCState *s1, const char *filename) · 2 unmodified lines
29942988 file_offset += s->sh_size;
29952989 }
29962990 /* Create the ELF file with name 'filename' */
2997− ret = tcc_write_elf_file(s1, filename, 0, NULL, file_offset, NULL);
2991+ ret = tcc_write_elf_file(s1, filename, 0, NULL);
29982992 return ret;
29992993 }
30002994
tccgen.c+8−1
@@ -5716,6 +5716,12 @@ ST_FUNC void unary(void) · 5715 unmodified lines
57165716 vtop--;
57175717 vpushi(n);
57185718 break;
5719+ case TOK_builtin_unreachable:
5720+ parse_builtin_params(0, ""); /* just skip '()' */
5721+ type.t = VT_VOID;
5722+ vpush(&type);
5723+ CODE_OFF();
5724+ break;
57195725 case TOK_builtin_frame_address:
57205726 case TOK_builtin_return_address:
57215727 {
@@ -8306,7 +8312,6 @@ static void gen_function(Sym *sym) · 2584 unmodified lines
83068312 cur_scope = root_scope = &f;
83078313 nocode_wanted = 0;
83088314
8309− cur_text_section->sh_flags |= SHF_EXECINSTR;
83108315 ind = cur_text_section->data_offset;
83118316 if (sym->a.aligned) {
83128317 size_t newoff = section_add(cur_text_section, 0,
@@ -8602,6 +8607,8 @@ static int decl(int l) · 289 unmodified lines
86028607 cur_text_section = ad.section;
86038608 if (!cur_text_section)
86048609 cur_text_section = text_section;
8610+ else if (cur_text_section->sh_num > bss_section->sh_num)
8611+ cur_text_section->sh_flags = text_section->sh_flags;
86058612 gen_function(sym);
86068613 }
86078614 break;
tccpe.c+5−4
@@ -525,7 +525,7 @@ static int pe_put_long_secname(char *secname, const char *name) · 524 unmodified lines
525525 const char *d = dwarf_secs;
526526 do {
527527 if (0 == strcmp(d, name)) {
528− sprintf(secname, "/%d", (int)(d - dwarf_secs + 4));
528+ snprintf(secname, 8, "/%d", (int)(d - dwarf_secs + 4));
529529 return 1;
530530 }
531531 d = strchr(d, 0) + 1;
@@ -1871,10 +1871,11 @@ static unsigned pe_add_uwwind_info(TCCState *s1) · 1339 unmodified lines
18711871 0x04, // UBYTE Size of prolog
18721872 0x02, // UBYTE Count of unwind codes
18731873 0x05, // UBYTE: 4 Frame Register (rbp), UBYTE: 4 Frame Register offset (scaled)
1874− // USHORT * n Unwind codes array
1874+ // USHORT * n Unwind codes array (descending order)
18751875 // 0x0b, 0x01, 0xff, 0xff, // stack size
1876− 0x04, 0x03, // set frame ptr (mov rsp -> rbp)
1877− 0x01, 0x50 // push reg (rbp)
1876+ // UBYTE offset of end of instr in prolog + 1, UBYTE:4 operation, UBYTE:4 info
1877+ 0x04, 0x03, // 3:0 UWOP_SET_FPREG (mov rsp -> rbp)
1878+ 0x01, 0x50, // 0:5 UWOP_PUSH_NONVOL (push rbp)
18781879 };
18791880
18801881 Section *s = text_section;
tcctok.h+1−0
@@ -171,6 +171,7 @@ · 170 unmodified lines
171171 DEF(TOK_builtin_frame_address, "__builtin_frame_address")
172172 DEF(TOK_builtin_return_address, "__builtin_return_address")
173173 DEF(TOK_builtin_expect, "__builtin_expect")
174+ DEF(TOK_builtin_unreachable, "__builtin_unreachable")
174175 /*DEF(TOK_builtin_va_list, "__builtin_va_list")*/
175176 #if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64
176177 DEF(TOK_builtin_va_start, "__builtin_va_start")
tcctools.c+15−23
@@ -504,28 +504,21 @@ ST_FUNC int tcc_tool_cross(TCCState *s1, char **argv, int option) · 503 unmodified lines
504504 #ifdef _WIN32
505505 #include <process.h>
506506
507−static char *str_replace(const char *str, const char *p, const char *r)
507+/* quote quotes in string and quote string if it contains spaces */
508+static char *quote_win32(const char *s0)
508509 {
509− const char *s, *s0;
510− char *d, *d0;
511− int sl, pl, rl;
512−
513− sl = strlen(str);
514− pl = strlen(p);
515− rl = strlen(r);
516− for (d0 = NULL;; d0 = tcc_malloc(sl + 1)) {
517− for (d = d0, s = str; s0 = s, s = strstr(s, p), s; s += pl) {
518− if (d) {
519− memcpy(d, s0, sl = s - s0), d += sl;
520− memcpy(d, r, rl), d += rl;
521− } else
522− sl += rl - pl;
523− }
524− if (d) {
525− strcpy(d, s0);
526− return d0;
527− }
528− }
510+ const char *s;
511+ char *p, *q;
512+ int a = 0, b = 0, c;
513+ for (s = s0; !!(c = *s); ++s)
514+ a += c == '"', b |= c == ' ';
515+ q = p = tcc_malloc(s - s0 + a + b + b + 1);
516+ *q = '"', q += b;
517+ for (s = s0; !!(c = *s); *q++ = c, ++s)
518+ if (c == '"')
519+ *q++ = '\\';
520+ *q = '"', q += b, *q = '\0';
521+ return p;
529522 }
530523
531524 static int execvp_win32(const char *prog, char **argv)
@@ -533,8 +526,7 @@ static int execvp_win32(const char *prog, char **argv) · 1 unmodified line
533526 int ret; char **p;
534527 /* replace all " by \" */
535528 for (p = argv; *p; ++p)
536− if (strchr(*p, '"'))
537− *p = str_replace(*p, "\"", "\\\"");
529+ *p = quote_win32(*p);
538530 ret = _spawnvp(P_NOWAIT, prog, (const char *const*)argv);
539531 if (-1 == ret)
540532 return ret;
tests/exec_section_in_asm.c+0−29
@@ -1,29 +0,0 @@
1−/* This test only works on x86-64. */
2−/* Previously in TinyCC, ELF sections defined in assembly would always have the
3−execute bit not set, so you would get segmentation faults when code in these
4−sections was exectuted. This file is a minimal example of a file that will put
5−the resulting code in a non-executable section (and invoke it) prior to the fix.
6−*/
7−#include <stdio.h>
8−
9−void *memset(void *dst, int c, int len);
10−
11−__asm__ (
12−".section .text.nolibc_memset\n"
13−".weak memset\n"
14−"memset:\n"
15− "xchgl %eax, %esi\n\t"
16− "movq %rdx, %rcx\n\t"
17− "pushq %rdi\n\t"
18− "rep stosb\n\t"
19− "popq %rax\n\t"
20− "retq\n"
21−);
22−
23−int main () {
24− char buf[10];
25− memset(&buf[0], 'A', 9);
26− buf[9] = 0;
27− puts(buf);
28− return 0;
29−}
tests/tcctest.c+1−1
@@ -3989,7 +3989,7 @@ void builtin_test(void) · 3988 unmodified lines
39893989 }
39903990 }
39913991
3992−#if defined _WIN32
3992+#if defined _WIN32 || (defined __APPLE__ && GCC_MAJOR >= 15)
39933993 void weak_test(void) {}
39943994 #else
39953995 extern int __attribute__((weak)) weak_f1(void);
tests/tests2/133_exec_section_in_c.c+0−17
@@ -1,17 +0,0 @@
1−#include <stdio.h>
2−
3−/* Previously in TinyCC, ELF sections defined in attributes would always have
4−the execute bit not set, so you would get segmentation faults when code in these
5−sections was exectuted. This file is a minimal example of a file that will put
6−the resulting code in a non-executable section (and invoke it) prior to the fix.
7−*/
8−__attribute__((section(".text.wumbo")))
9−int wumbo (int arg) {
10− return arg * 2;
11−}
12−
13−int main () {
14− wumbo(2);
15− puts("hi");
16− return 0;
17−}
tests/tests2/133_exec_section_in_c.expect+0−1
@@ -1 +0,0 @@
1−hi
x86_64-gen.c+7−8
@@ -489,7 +489,7 @@ void load(int r, SValue *sv) · 488 unmodified lines
489489 }
490490 #endif
491491 } else if (is64_type(ft)) {
492− if (sv->c.i > UINT32_MAX) {
492+ if (sv->c.i >> 32) {
493493 orex(1,r,0, 0xb8 + REG_VALUE(r)); /* movabs $xx, r */
494494 gen_le64(sv->c.i);
495495 } else if (sv->c.i > 0) {
@@ -1017,7 +1017,7 @@ void gfunc_prolog(Sym *func_sym) · 521 unmodified lines
10171017 /* generate function epilog */
10181018 void gfunc_epilog(void)
10191019 {
1020− int v, saved_ind;
1020+ int v, start;
10211021
10221022 /* align local size to word & save local variables */
10231023 func_scratch = (func_scratch + 15) & -16;
@@ -1037,10 +1037,12 @@ void gfunc_epilog(void) · 13 unmodified lines
10371037 g(func_ret_sub >> 8);
10381038 }
10391039
1040− saved_ind = ind;
1041− ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
10421040 v = -loc;
1041+ start = func_sub_sp_offset - FUNC_PROLOG_SIZE;
1042+ cur_text_section->data_offset = ind;
1043+ pe_add_unwind_data(start, ind, v);
10431044
1045+ ind = start;
10441046 if (v >= 4096) {
10451047 Sym *sym = external_helper_sym(TOK___chkstk);
10461048 oad(0xb8, v); /* mov stacksize, %eax */
@@ -1052,13 +1054,10 @@ void gfunc_epilog(void) · 5 unmodified lines
10521054 o(0xec8148); /* sub rsp, stacksize */
10531055 gen_le32(v);
10541056 }
1057+ ind = cur_text_section->data_offset;
10551058
10561059 /* add the "func_scratch" area after each alloca seen */
10571060 gsym_addr(func_alloca, -func_scratch);
1058−
1059− cur_text_section->data_offset = saved_ind;
1060− pe_add_unwind_data(ind, saved_ind, v);
1061− ind = cur_text_section->data_offset;
10621061 }
10631062
10641063 #else

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t