History

tccelf.c: factor out elf_output_obj()

The small common parts within elf_output_file() aren't worth the many #ifdefs. Also, set section sizes and allocate section names in 2 separate functions.

grischka committed 5 years ago

Commit 62c0c4c1 parent c74c6ed4 files · +152 −141Browse files

Unified · Split

4 files
  1. Makefile +0 −4
  2. libtcc.c +4 −7
  3. tccelf.c +147 −129
  4. tests/Makefile +1 −1
Makefile+0−4
@@ -62,10 +62,6 @@ else · 61 unmodified lines
6262 endif
6363 export MACOSX_DEPLOYMENT_TARGET := 10.6
6464 endif
65− # Unclear why the following ifdef was defined. Build fails on all *BSD
66− # ifdef CONFIG_BSD
67− # NATIVE_TARGET = $(ARCH)-$(TARGETOS)
68− # endif
6965 endif
7066
7167 # run local version of tcc with local libraries and includes
libtcc.c+4−7
@@ -1105,7 +1105,7 @@ ST_FUNC int tcc_add_crt(TCCState *s1, const char *filename) · 1104 unmodified lines
11051105
11061106 /* OpenBSD only has suffixed .so files; e.g., libc.so.96.0 */
11071107 /* So we must process that */
1108−#if defined TARGETOS_OpenBSD
1108+#if defined TARGETOS_OpenBSD && !defined _WIN32/* no dirent */
11091109 #include <dirent.h>
11101110 ST_FUNC char *tcc_openbsd_library_soversion(TCCState *s, const char *libraryname)
11111111 {
@@ -1185,7 +1185,7 @@ LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname) · 73 unmodified lines
11851185 #elif defined TCC_TARGET_MACHO
11861186 const char *libs[] = { "%s/lib%s.dylib", "%s/lib%s.a", NULL };
11871187 const char **pp = s->static_link ? libs + 1 : libs;
1188−#elif defined TARGETOS_OpenBSD
1188+#elif defined TARGETOS_OpenBSD && !defined _WIN32
11891189 const char *libs[] = { s->static_link
11901190 ? NULL
11911191 /* find exact versionned .so.x.y name as no
@@ -1479,11 +1479,8 @@ static int tcc_set_linker(TCCState *s, const char *option) · 287 unmodified lines
14791479 s->filetype |= AFF_WHOLE_ARCHIVE;
14801480 else
14811481 s->filetype &= ~AFF_WHOLE_ARCHIVE;
1482− } else if (ret = link_option(option, "z=", &p), ret) {
1483− if (!strcmp(p, "notext"))
1484− ; /* ignore */
1485− else
1486− goto err;
1482+ } else if (link_option(option, "z=", &p)) {
1483+ ignoring = 1;
14871484 } else if (p) {
14881485 return 0;
14891486 } else {
tccelf.c+147−129
@@ -1071,11 +1071,6 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr) · 1070 unmodified lines
10711071 break;
10721072 }
10731073 }
1074− if (count) {
1075− /* allocate the section */
1076− sr->sh_flags |= SHF_ALLOC;
1077− sr->sh_size = count * sizeof(ElfW_Rel);
1078− }
10791074 #endif
10801075 return count;
10811076 }
@@ -1566,29 +1561,8 @@ ST_FUNC void resolve_common_syms(TCCState *s1) · 484 unmodified lines
15661561 tcc_add_linker_symbols(s1);
15671562 }
15681563
1569−static void tcc_output_binary(TCCState *s1, FILE *f,
1570− const int *sec_order)
1571−{
1572− Section *s;
1573− int i, offset, size;
1574−
1575− offset = 0;
1576− for(i=1;i<s1->nb_sections;i++) {
1577− s = s1->sections[sec_order[i]];
1578− if (s->sh_type != SHT_NOBITS &&
1579− (s->sh_flags & SHF_ALLOC)) {
1580− while (offset < s->sh_offset) {
1581− fputc(0, f);
1582− offset++;
1583− }
1584− size = s->sh_size;
1585− fwrite(s->data, 1, size, f);
1586− offset += size;
1587− }
1588− }
1589−}
1590−
15911564 #ifndef ELF_OBJ_ONLY
1565+
15921566 ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
15931567 {
15941568 int sym_index = ELFW(R_SYM) (rel->r_info);
@@ -1791,43 +1765,40 @@ static void export_global_syms(TCCState *s1) · 196 unmodified lines
17911765 }
17921766 }
17931767 }
1794−#endif
17951768
1796−/* Allocate strings for section names and decide if an unallocated section
1797− should be output.
1798− NOTE: the strsec section comes last, so its size is also correct ! */
1799−static int alloc_sec_names(TCCState *s1, int file_type, Section *strsec)
1769+/* decide if an unallocated section should be output. */
1770+static int set_sec_sizes(TCCState *s1)
18001771 {
18011772 int i;
18021773 Section *s;
18031774 int textrel = 0;
1775+ int file_type = s1->output_type;
18041776
18051777 /* Allocate strings for section names */
18061778 for(i = 1; i < s1->nb_sections; i++) {
18071779 s = s1->sections[i];
1808− /* when generating a DLL, we include relocations but we may
1809− patch them */
1810−#ifndef ELF_OBJ_ONLY
1811− if (file_type == TCC_OUTPUT_DLL &&
1812− s->sh_type == SHT_RELX &&
1813− !(s->sh_flags & SHF_ALLOC) &&
1814− (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC) &&
1815− prepare_dynamic_rel(s1, s)) {
1816− if (!(s1->sections[s->sh_info]->sh_flags & SHF_WRITE))
1817− textrel = 1;
1818− } else
1819−#endif
1820− if ((s1->do_debug && s->sh_type != SHT_RELX) ||
1821− file_type == TCC_OUTPUT_OBJ ||
1822− (s->sh_flags & SHF_ALLOC) ||
1823− i == (s1->nb_sections - 1)
1780+ if (s->sh_type == SHT_RELX && !(s->sh_flags & SHF_ALLOC)) {
1781+ /* when generating a DLL, we include relocations but
1782+ we may patch them */
1783+ if (file_type == TCC_OUTPUT_DLL
1784+ && (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)) {
1785+ int count = prepare_dynamic_rel(s1, s);
1786+ if (count) {
1787+ /* allocate the section */
1788+ s->sh_flags |= SHF_ALLOC;
1789+ s->sh_size = count * sizeof(ElfW_Rel);
1790+ if (!(s1->sections[s->sh_info]->sh_flags & SHF_WRITE))
1791+ textrel = 1;
1792+ }
1793+ }
1794+ } else if ((s->sh_flags & SHF_ALLOC)
18241795 #ifdef TCC_TARGET_ARM
1825− || s->sh_type == SHT_ARM_ATTRIBUTES
1796+ || s->sh_type == SHT_ARM_ATTRIBUTES
18261797 #endif
1827− ) {
1828− /* we output all sections if debug or object file */
1798+ || s1->do_debug) {
18291799 s->sh_size = s->data_offset;
18301800 }
1801+
18311802 #ifdef TCC_TARGET_ARM
18321803 /* XXX: Suppress stack unwinding section. */
18331804 if (s->sh_type == SHT_ARM_EXIDX) {
@@ -1835,13 +1806,12 @@ static int alloc_sec_names(TCCState *s1, int file_type, Section *strsec) · 1 unmodified line
18351806 s->sh_size = 0;
18361807 }
18371808 #endif
1838− if (s->sh_size || (s->sh_flags & SHF_ALLOC))
1839− s->sh_name = put_elf_str(strsec, s->name);
1809+
18401810 }
1841− strsec->sh_size = strsec->data_offset;
18421811 return textrel;
18431812 }
18441813
1814+
18451815 /* Info to be copied in dynamic section */
18461816 struct dyn_inf {
18471817 Section *dynamic;
@@ -1858,23 +1828,29 @@ struct ro_inf { · 10 unmodified lines
18581828 addr_t sh_size;
18591829 };
18601830
1831+static void alloc_sec_names(
1832+ TCCState *s1, int is_obj
1833+ );
1834+
1835+static int layout_any_sections(
1836+ TCCState *s1, int file_offset, int *sec_order, int is_obj
1837+ );
1838+
18611839 /* Assign sections to segments and decide how are sections laid out when loaded
18621840 in memory. This function also fills corresponding program headers. */
18631841 static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr,
18641842 int phnum, int phfill,
1865− Section *interp, Section* strsec,
1843+ Section *interp,
18661844 struct ro_inf *roinf, int *sec_order)
18671845 {
1868− int i, sh_order_index, file_offset;
1846+ int i, file_offset;
18691847 Section *s;
18701848
1871− sh_order_index = 1;
18721849 file_offset = 0;
18731850 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
18741851 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
18751852
1876−#ifndef ELF_OBJ_ONLY
1877− if (phnum > 0) { /* phnum is 0 for TCC_OUTPUT_OBJ */
1853+ {
18781854 unsigned long s_align;
18791855 long long tmp;
18801856 addr_t addr;
@@ -1979,7 +1955,7 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, · 98 unmodified lines
19791955 if (k != 5)
19801956 continue;
19811957 }
1982− sec_order[sh_order_index++] = i;
1958+ *sec_order++ = i;
19831959
19841960 /* section matches: we align it and add its size */
19851961 tmp = addr;
@@ -2039,26 +2015,11 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, · 53 unmodified lines
20392015 }
20402016 }
20412017 }
2042−#endif /* ELF_OBJ_ONLY */
20432018
20442019 /* all other sections come after */
2045− for(i = 1; i < s1->nb_sections; i++) {
2046− s = s1->sections[i];
2047− if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2048− continue;
2049− sec_order[sh_order_index++] = i;
2050−
2051− file_offset = (file_offset + s->sh_addralign - 1) &
2052− ~(s->sh_addralign - 1);
2053− s->sh_offset = file_offset;
2054− if (s->sh_type != SHT_NOBITS)
2055− file_offset += s->sh_size;
2056− }
2057−
2058− return file_offset;
2020+ return layout_any_sections(s1, file_offset, sec_order, 0);
20592021 }
20602022
2061−#ifndef ELF_OBJ_ONLY
20622023 /* put dynamic tag */
20632024 static void put_dt(Section *dynamic, int dt, addr_t val)
20642025 {
@@ -2269,7 +2230,8 @@ static void update_reloc_sections(TCCState *s1, struct dyn_inf *dyninf) · 204 unmodified lines
22692230 }
22702231 }
22712232 }
2272−#endif
2233+
2234+#endif /* ndef ELF_OBJ_ONLY */
22732235
22742236 /* Create an ELF file on disk.
22752237 This function handle ELF specific layout requirements */
@@ -2390,6 +2352,28 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr, · 114 unmodified lines
23902352 }
23912353 }
23922354
2355+static void tcc_output_binary(TCCState *s1, FILE *f,
2356+ const int *sec_order)
2357+{
2358+ Section *s;
2359+ int i, offset, size;
2360+
2361+ offset = 0;
2362+ for(i=1;i<s1->nb_sections;i++) {
2363+ s = s1->sections[sec_order[i]];
2364+ if (s->sh_type != SHT_NOBITS &&
2365+ (s->sh_flags & SHF_ALLOC)) {
2366+ while (offset < s->sh_offset) {
2367+ fputc(0, f);
2368+ offset++;
2369+ }
2370+ size = s->sh_size;
2371+ fwrite(s->data, 1, size, f);
2372+ offset += size;
2373+ }
2374+ }
2375+}
2376+
23932377 /* Write an elf, coff or "binary" file */
23942378 static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum,
23952379 ElfW(Phdr) *phdr, int file_offset, int *sec_order)
@@ -2472,7 +2456,6 @@ static void tidy_section_headers(TCCState *s1, int *sec_order) · 76 unmodified lines
24722456 s1->nb_sections = nnew;
24732457 tcc_free(backmap);
24742458 }
2475−#endif
24762459
24772460 #ifdef TCC_TARGET_ARM
24782461 static void create_arm_attribute_section(TCCState *s1)
@@ -2539,33 +2522,30 @@ static int elf_output_file(TCCState *s1, const char *filename) · 60 unmodified lines
25392522 struct dyn_inf dyninf = {0};
25402523 struct ro_inf roinf;
25412524 ElfW(Phdr) *phdr;
2542− Section *strsec, *interp, *dynamic, *dynstr, *note = NULL;
2543−//#ifndef ELF_OBJ_ONLY
2525+ Section *interp, *dynamic, *dynstr, *note;
25442526 struct ro_inf *roinf_use = NULL;
2545−//#endif
2527+ int textrel;
25462528
25472529 file_type = s1->output_type;
2530+ s1->nb_errors = 0;
2531+ ret = -1;
2532+ phdr = NULL;
2533+ sec_order = NULL;
2534+ interp = dynamic = dynstr = note = NULL;
25482535
25492536 #ifdef TCC_TARGET_ARM
25502537 create_arm_attribute_section (s1);
25512538 #endif
2539+
25522540 #if TARGETOS_OpenBSD
2553− if (file_type != TCC_OUTPUT_OBJ)
2554− note = create_bsd_note_section (s1, ".note.openbsd.ident", "OpenBSD");
2541+ note = create_bsd_note_section (s1, ".note.openbsd.ident", "OpenBSD");
25552542 #endif
2543+
25562544 #if TARGETOS_NetBSD
2557− if (file_type != TCC_OUTPUT_OBJ)
2558− note = create_bsd_note_section (s1, ".note.netbsd.ident", "NetBSD");
2545+ note = create_bsd_note_section (s1, ".note.netbsd.ident", "NetBSD");
25592546 #endif
25602547
2561− s1->nb_errors = 0;
2562− ret = -1;
2563− phdr = NULL;
2564− sec_order = NULL;
2565− interp = dynamic = dynstr = NULL; /* avoid warning */
2566−
2567−#ifndef ELF_OBJ_ONLY
2568− if (file_type != TCC_OUTPUT_OBJ) {
2548+ {
25692549 /* if linking, also link in runtime libraries (libc, libgcc, etc.) */
25702550 tcc_add_runtime(s1);
25712551 resolve_common_syms(s1);
@@ -2612,17 +2592,11 @@ static int elf_output_file(TCCState *s1, const char *filename) · 40 unmodified lines
26122592 build_got_entries(s1);
26132593 version_add (s1);
26142594 }
2615−#endif
26162595
2617− /* we add a section for symbols */
2618− strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
2619− put_elf_str(strsec, "");
2620−
2621− /* Allocate strings for section names */
2622− ret = alloc_sec_names(s1, file_type, strsec);
2596+ textrel = set_sec_sizes(s1);
2597+ alloc_sec_names(s1, 0);
26232598
2624−#ifndef ELF_OBJ_ONLY
2625− if (dynamic) {
2599+ if (!s1->static_link) {
26262600 int i;
26272601 /* add a list of needed dlls */
26282602 for(i = 0; i < s1->nb_loaded_dlls; i++) {
@@ -2640,7 +2614,7 @@ static int elf_output_file(TCCState *s1, const char *filename) · 11 unmodified lines
26402614 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
26412615 /* XXX: currently, since we do not handle PIC code, we
26422616 must relocate the readonly segments */
2643− if (ret)
2617+ if (textrel)
26442618 put_dt(dynamic, DT_TEXTREL, 0);
26452619 }
26462620
@@ -2655,16 +2629,13 @@ static int elf_output_file(TCCState *s1, const char *filename) · 8 unmodified lines
26552629 dynamic->sh_size = dynamic->data_offset;
26562630 dynstr->sh_size = dynstr->data_offset;
26572631 }
2658−#endif
26592632
26602633 for (i = 1; i < s1->nb_sections &&
26612634 !(s1->sections[i]->sh_flags & SHF_TLS); i++);
26622635 phfill = 2 + (i < s1->nb_sections);
26632636
26642637 /* compute number of program headers */
2665− if (file_type == TCC_OUTPUT_OBJ)
2666− phnum = phfill = 0;
2667− else if (file_type == TCC_OUTPUT_DLL)
2638+ if (file_type == TCC_OUTPUT_DLL)
26682639 phnum = 3;
26692640 else if (s1->static_link)
26702641 phnum = 3;
@@ -2673,31 +2644,25 @@ static int elf_output_file(TCCState *s1, const char *filename) · 2 unmodified lines
26732644 }
26742645
26752646 phnum += note != NULL;
2676−
2677−#if !TARGETOS_FreeBSD && !TARGETOS_NetBSD && !defined(__APPLE__) && !defined(_WIN32)
2647+#if !TARGETOS_FreeBSD && !TARGETOS_NetBSD
26782648 /* GNU_RELRO */
2679− if (file_type != TCC_OUTPUT_OBJ)
2680− phnum++, roinf_use = &roinf;
2649+ phnum++, roinf_use = &roinf;
26812650 #endif
26822651
26832652 /* allocate program segment headers */
26842653 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
2685−
26862654 /* compute number of sections */
26872655 shnum = s1->nb_sections;
2688−
26892656 /* this array is used to reorder sections in the output file */
26902657 sec_order = tcc_malloc(sizeof(int) * shnum);
26912658 sec_order[0] = 0;
26922659
26932660 /* compute section to program header mapping */
2694− file_offset = layout_sections(s1, phdr, phnum, phfill, interp, strsec,
2695− &roinf, sec_order);
2661+ file_offset = layout_sections(s1, phdr, phnum, phfill, interp, &roinf, sec_order + 1);
26962662
2697−#ifndef ELF_OBJ_ONLY
26982663 /* Fill remaining program header and finalize relocation related to dynamic
26992664 linking. */
2700− if (file_type != TCC_OUTPUT_OBJ) {
2665+ {
27012666 fill_unloadable_phdr(phdr, phnum, interp, dynamic, note, roinf_use);
27022667 if (dynamic) {
27032668 ElfW(Sym) *sym;
@@ -2735,32 +2700,85 @@ static int elf_output_file(TCCState *s1, const char *filename) · 31 unmodified lines
27352700 else if (s1->got)
27362701 fill_local_got_entries(s1);
27372702 }
2738−#endif
2739−
27402703 /* Create the ELF file with name 'filename' */
27412704 ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order);
27422705 s1->nb_sections = shnum;
2743− goto the_end;
2706+
27442707 the_end:
27452708 tcc_free(sec_order);
27462709 tcc_free(phdr);
27472710 return ret;
27482711 }
2712+#endif /* ndef ELF_OBJ_ONLY */
2713+
2714+/* Allocate strings for section names */
2715+static void alloc_sec_names(TCCState *s1, int is_obj)
2716+{
2717+ int i;
2718+ Section *s, *strsec;
2719+
2720+ strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
2721+ put_elf_str(strsec, "");
2722+ for(i = 1; i < s1->nb_sections; i++) {
2723+ s = s1->sections[i];
2724+ if (is_obj)
2725+ s->sh_size = s->data_offset;
2726+ if (s->sh_size || (s->sh_flags & SHF_ALLOC))
2727+ s->sh_name = put_elf_str(strsec, s->name);
2728+ }
2729+ strsec->sh_size = strsec->data_offset;
2730+}
2731+
2732+static int layout_any_sections(TCCState *s1, int file_offset, int *sec_order, int is_obj)
2733+{
2734+ int i;
2735+ Section *s;
2736+ for(i = 1; i < s1->nb_sections; i++) {
2737+ s = s1->sections[i];
2738+ if (!is_obj && (s->sh_flags & SHF_ALLOC))
2739+ continue;
2740+ *sec_order++ = i;
2741+ file_offset = (file_offset + s->sh_addralign - 1) &
2742+ ~(s->sh_addralign - 1);
2743+ s->sh_offset = file_offset;
2744+ if (s->sh_type != SHT_NOBITS)
2745+ file_offset += s->sh_size;
2746+ }
2747+ return file_offset;
2748+}
2749+
2750+/* Output an elf .o file */
2751+static int elf_output_obj(TCCState *s1, const char *filename)
2752+{
2753+ int ret, file_offset;
2754+ int *sec_order;
2755+ s1->nb_errors = 0;
2756+
2757+ /* Allocate strings for section names */
2758+ alloc_sec_names(s1, 1);
2759+
2760+ /* this array is used to reorder sections in the output file */
2761+ sec_order = tcc_malloc(sizeof(int) * s1->nb_sections);
2762+ sec_order[0] = 0;
2763+ file_offset = layout_any_sections(s1, sizeof (ElfW(Ehdr)), sec_order + 1, 1);
2764+
2765+ /* Create the ELF file with name 'filename' */
2766+ ret = tcc_write_elf_file(s1, filename, 0, NULL, file_offset, sec_order);
2767+ tcc_free(sec_order);
2768+ return ret;
2769+}
27492770
27502771 LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
27512772 {
2752− int ret;
2773+ if (s->output_type == TCC_OUTPUT_OBJ)
2774+ return elf_output_obj(s, filename);
27532775 #ifdef TCC_TARGET_PE
2754− if (s->output_type != TCC_OUTPUT_OBJ) {
2755− ret = pe_output_file(s, filename);
2756− } else
2776+ return pe_output_file(s, filename);
27572777 #elif TCC_TARGET_MACHO
2758− if (s->output_type != TCC_OUTPUT_OBJ) {
2759− ret = macho_output_file(s, filename);
2760− } else
2778+ return macho_output_file(s, filename);
2779+#else
2780+ return elf_output_file(s, filename);
27612781 #endif
2762− ret = elf_output_file(s, filename);
2763− return ret;
27642782 }
27652783
27662784 ST_FUNC ssize_t full_read(int fd, void *buf, size_t count) {
tests/Makefile+1−1
@@ -53,7 +53,7 @@ ifeq ($(ARCH),arm) · 52 unmodified lines
5353 # of functions via bit masking comes out as 1. Just disable thumb.
5454 test.ref: CFLAGS+=-marm
5555 endif
56−ifeq ($(ARCH),i386)
56+ifeq ($(ARCH)$(CONFIG_WIN32),i386)
5757 # tcctest.c:get_asm_string uses a construct that is checked too strictly
5858 # by GCC in 32bit mode when PIC is enabled.
5959 test.ref: CFLAGS+=-fno-PIC -fno-PIE -Wl,-z,notext

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