| @@ -1071,11 +1071,6 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr) · 1070 unmodified lines |
| 1071 | break; | 1071 | break; |
| 1072 | } | 1072 | } |
| 1073 | } | 1073 | } |
| 1074 | if (count) { | | |
| 1075 | /* allocate the section */ | | |
| 1076 | sr->sh_flags |= SHF_ALLOC; | | |
| 1077 | sr->sh_size = count * sizeof(ElfW_Rel); | | |
| 1078 | } | | |
| 1079 | #endif | 1074 | #endif |
| 1080 | return count; | 1075 | return count; |
| 1081 | } | 1076 | } |
| @@ -1566,29 +1561,8 @@ ST_FUNC void resolve_common_syms(TCCState *s1) · 484 unmodified lines |
| 1566 | tcc_add_linker_symbols(s1); | 1561 | tcc_add_linker_symbols(s1); |
| 1567 | } | 1562 | } |
| 1568 | | 1563 | |
| 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 | | | |
| 1591 | #ifndef ELF_OBJ_ONLY | 1564 | #ifndef ELF_OBJ_ONLY |
| | 1565 | |
| 1592 | ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel) | 1566 | ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel) |
| 1593 | { | 1567 | { |
| 1594 | int sym_index = ELFW(R_SYM) (rel->r_info); | 1568 | int sym_index = ELFW(R_SYM) (rel->r_info); |
| @@ -1791,43 +1765,40 @@ static void export_global_syms(TCCState *s1) · 196 unmodified lines |
| 1791 | } | 1765 | } |
| 1792 | } | 1766 | } |
| 1793 | } | 1767 | } |
| 1794 | #endif | | |
| 1795 | | 1768 | |
| 1796 | /* Allocate strings for section names and decide if an unallocated section | 1769 | /* decide if an unallocated section should be output. */ |
| 1797 | should be output. | 1770 | static int set_sec_sizes(TCCState *s1) |
| 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) | | |
| 1800 | { | 1771 | { |
| 1801 | int i; | 1772 | int i; |
| 1802 | Section *s; | 1773 | Section *s; |
| 1803 | int textrel = 0; | 1774 | int textrel = 0; |
| | 1775 | int file_type = s1->output_type; |
| 1804 | | 1776 | |
| 1805 | /* Allocate strings for section names */ | 1777 | /* Allocate strings for section names */ |
| 1806 | for(i = 1; i < s1->nb_sections; i++) { | 1778 | for(i = 1; i < s1->nb_sections; i++) { |
| 1807 | s = s1->sections[i]; | 1779 | s = s1->sections[i]; |
| 1808 | /* when generating a DLL, we include relocations but we may | 1780 | if (s->sh_type == SHT_RELX && !(s->sh_flags & SHF_ALLOC)) { |
| 1809 | patch them */ | 1781 | /* when generating a DLL, we include relocations but |
| 1810 | #ifndef ELF_OBJ_ONLY | 1782 | we may patch them */ |
| 1811 | if (file_type == TCC_OUTPUT_DLL && | 1783 | if (file_type == TCC_OUTPUT_DLL |
| 1812 | s->sh_type == SHT_RELX && | 1784 | && (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)) { |
| 1813 | !(s->sh_flags & SHF_ALLOC) && | 1785 | int count = prepare_dynamic_rel(s1, s); |
| 1814 | (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC) && | 1786 | if (count) { |
| 1815 | prepare_dynamic_rel(s1, s)) { | 1787 | /* allocate the section */ |
| 1816 | if (!(s1->sections[s->sh_info]->sh_flags & SHF_WRITE)) | 1788 | s->sh_flags |= SHF_ALLOC; |
| 1817 | textrel = 1; | 1789 | s->sh_size = count * sizeof(ElfW_Rel); |
| 1818 | } else | 1790 | if (!(s1->sections[s->sh_info]->sh_flags & SHF_WRITE)) |
| 1819 | #endif | 1791 | textrel = 1; |
| 1820 | if ((s1->do_debug && s->sh_type != SHT_RELX) || | 1792 | } |
| 1821 | file_type == TCC_OUTPUT_OBJ || | 1793 | } |
| 1822 | (s->sh_flags & SHF_ALLOC) || | 1794 | } else if ((s->sh_flags & SHF_ALLOC) |
| 1823 | i == (s1->nb_sections - 1) | | |
| 1824 | #ifdef TCC_TARGET_ARM | 1795 | #ifdef TCC_TARGET_ARM |
| 1825 | || s->sh_type == SHT_ARM_ATTRIBUTES | 1796 | || s->sh_type == SHT_ARM_ATTRIBUTES |
| 1826 | #endif | 1797 | #endif |
| 1827 | ) { | 1798 | || s1->do_debug) { |
| 1828 | /* we output all sections if debug or object file */ | | |
| 1829 | s->sh_size = s->data_offset; | 1799 | s->sh_size = s->data_offset; |
| 1830 | } | 1800 | } |
| | 1801 | |
| 1831 | #ifdef TCC_TARGET_ARM | 1802 | #ifdef TCC_TARGET_ARM |
| 1832 | /* XXX: Suppress stack unwinding section. */ | 1803 | /* XXX: Suppress stack unwinding section. */ |
| 1833 | if (s->sh_type == SHT_ARM_EXIDX) { | 1804 | 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 |
| 1835 | s->sh_size = 0; | 1806 | s->sh_size = 0; |
| 1836 | } | 1807 | } |
| 1837 | #endif | 1808 | #endif |
| 1838 | if (s->sh_size || (s->sh_flags & SHF_ALLOC)) | 1809 | |
| 1839 | s->sh_name = put_elf_str(strsec, s->name); | | |
| 1840 | } | 1810 | } |
| 1841 | strsec->sh_size = strsec->data_offset; | | |
| 1842 | return textrel; | 1811 | return textrel; |
| 1843 | } | 1812 | } |
| 1844 | | 1813 | |
| | 1814 | |
| 1845 | /* Info to be copied in dynamic section */ | 1815 | /* Info to be copied in dynamic section */ |
| 1846 | struct dyn_inf { | 1816 | struct dyn_inf { |
| 1847 | Section *dynamic; | 1817 | Section *dynamic; |
| @@ -1858,23 +1828,29 @@ struct ro_inf { · 10 unmodified lines |
| 1858 | addr_t sh_size; | 1828 | addr_t sh_size; |
| 1859 | }; | 1829 | }; |
| 1860 | | 1830 | |
| | 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 | |
| 1861 | /* Assign sections to segments and decide how are sections laid out when loaded | 1839 | /* Assign sections to segments and decide how are sections laid out when loaded |
| 1862 | in memory. This function also fills corresponding program headers. */ | 1840 | in memory. This function also fills corresponding program headers. */ |
| 1863 | static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, | 1841 | static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, |
| 1864 | int phnum, int phfill, | 1842 | int phnum, int phfill, |
| 1865 | Section *interp, Section* strsec, | 1843 | Section *interp, |
| 1866 | struct ro_inf *roinf, int *sec_order) | 1844 | struct ro_inf *roinf, int *sec_order) |
| 1867 | { | 1845 | { |
| 1868 | int i, sh_order_index, file_offset; | 1846 | int i, file_offset; |
| 1869 | Section *s; | 1847 | Section *s; |
| 1870 | | 1848 | |
| 1871 | sh_order_index = 1; | | |
| 1872 | file_offset = 0; | 1849 | file_offset = 0; |
| 1873 | if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) | 1850 | if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) |
| 1874 | file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr)); | 1851 | file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr)); |
| 1875 | | 1852 | |
| 1876 | #ifndef ELF_OBJ_ONLY | 1853 | { |
| 1877 | if (phnum > 0) { /* phnum is 0 for TCC_OUTPUT_OBJ */ | | |
| 1878 | unsigned long s_align; | 1854 | unsigned long s_align; |
| 1879 | long long tmp; | 1855 | long long tmp; |
| 1880 | addr_t addr; | 1856 | addr_t addr; |
| @@ -1979,7 +1955,7 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, · 98 unmodified lines |
| 1979 | if (k != 5) | 1955 | if (k != 5) |
| 1980 | continue; | 1956 | continue; |
| 1981 | } | 1957 | } |
| 1982 | sec_order[sh_order_index++] = i; | 1958 | *sec_order++ = i; |
| 1983 | | 1959 | |
| 1984 | /* section matches: we align it and add its size */ | 1960 | /* section matches: we align it and add its size */ |
| 1985 | tmp = addr; | 1961 | tmp = addr; |
| @@ -2039,26 +2015,11 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, · 53 unmodified lines |
| 2039 | } | 2015 | } |
| 2040 | } | 2016 | } |
| 2041 | } | 2017 | } |
| 2042 | #endif /* ELF_OBJ_ONLY */ | | |
| 2043 | | 2018 | |
| 2044 | /* all other sections come after */ | 2019 | /* all other sections come after */ |
| 2045 | for(i = 1; i < s1->nb_sections; i++) { | 2020 | return layout_any_sections(s1, file_offset, sec_order, 0); |
| 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; | | |
| 2059 | } | 2021 | } |
| 2060 | | 2022 | |
| 2061 | #ifndef ELF_OBJ_ONLY | | |
| 2062 | /* put dynamic tag */ | 2023 | /* put dynamic tag */ |
| 2063 | static void put_dt(Section *dynamic, int dt, addr_t val) | 2024 | static void put_dt(Section *dynamic, int dt, addr_t val) |
| 2064 | { | 2025 | { |
| @@ -2269,7 +2230,8 @@ static void update_reloc_sections(TCCState *s1, struct dyn_inf *dyninf) · 204 unmodified lines |
| 2269 | } | 2230 | } |
| 2270 | } | 2231 | } |
| 2271 | } | 2232 | } |
| 2272 | #endif | 2233 | |
| | 2234 | #endif /* ndef ELF_OBJ_ONLY */ |
| 2273 | | 2235 | |
| 2274 | /* Create an ELF file on disk. | 2236 | /* Create an ELF file on disk. |
| 2275 | This function handle ELF specific layout requirements */ | 2237 | 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 |
| 2390 | } | 2352 | } |
| 2391 | } | 2353 | } |
| 2392 | | 2354 | |
| | 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 | |
| 2393 | /* Write an elf, coff or "binary" file */ | 2377 | /* Write an elf, coff or "binary" file */ |
| 2394 | static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum, | 2378 | static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum, |
| 2395 | ElfW(Phdr) *phdr, int file_offset, int *sec_order) | 2379 | 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 |
| 2472 | s1->nb_sections = nnew; | 2456 | s1->nb_sections = nnew; |
| 2473 | tcc_free(backmap); | 2457 | tcc_free(backmap); |
| 2474 | } | 2458 | } |
| 2475 | #endif | | |
| 2476 | | 2459 | |
| 2477 | #ifdef TCC_TARGET_ARM | 2460 | #ifdef TCC_TARGET_ARM |
| 2478 | static void create_arm_attribute_section(TCCState *s1) | 2461 | 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 |
| 2539 | struct dyn_inf dyninf = {0}; | 2522 | struct dyn_inf dyninf = {0}; |
| 2540 | struct ro_inf roinf; | 2523 | struct ro_inf roinf; |
| 2541 | ElfW(Phdr) *phdr; | 2524 | ElfW(Phdr) *phdr; |
| 2542 | Section *strsec, *interp, *dynamic, *dynstr, *note = NULL; | 2525 | Section *interp, *dynamic, *dynstr, *note; |
| 2543 | //#ifndef ELF_OBJ_ONLY | | |
| 2544 | struct ro_inf *roinf_use = NULL; | 2526 | struct ro_inf *roinf_use = NULL; |
| 2545 | //#endif | 2527 | int textrel; |
| 2546 | | 2528 | |
| 2547 | file_type = s1->output_type; | 2529 | 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; |
| 2548 | | 2535 | |
| 2549 | #ifdef TCC_TARGET_ARM | 2536 | #ifdef TCC_TARGET_ARM |
| 2550 | create_arm_attribute_section (s1); | 2537 | create_arm_attribute_section (s1); |
| 2551 | #endif | 2538 | #endif |
| | 2539 | |
| 2552 | #if TARGETOS_OpenBSD | 2540 | #if TARGETOS_OpenBSD |
| 2553 | if (file_type != TCC_OUTPUT_OBJ) | 2541 | note = create_bsd_note_section (s1, ".note.openbsd.ident", "OpenBSD"); |
| 2554 | note = create_bsd_note_section (s1, ".note.openbsd.ident", "OpenBSD"); | | |
| 2555 | #endif | 2542 | #endif |
| | 2543 | |
| 2556 | #if TARGETOS_NetBSD | 2544 | #if TARGETOS_NetBSD |
| 2557 | if (file_type != TCC_OUTPUT_OBJ) | 2545 | note = create_bsd_note_section (s1, ".note.netbsd.ident", "NetBSD"); |
| 2558 | note = create_bsd_note_section (s1, ".note.netbsd.ident", "NetBSD"); | | |
| 2559 | #endif | 2546 | #endif |
| 2560 | | 2547 | |
| 2561 | s1->nb_errors = 0; | 2548 | { |
| 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) { | | |
| 2569 | /* if linking, also link in runtime libraries (libc, libgcc, etc.) */ | 2549 | /* if linking, also link in runtime libraries (libc, libgcc, etc.) */ |
| 2570 | tcc_add_runtime(s1); | 2550 | tcc_add_runtime(s1); |
| 2571 | resolve_common_syms(s1); | 2551 | resolve_common_syms(s1); |
| @@ -2612,17 +2592,11 @@ static int elf_output_file(TCCState *s1, const char *filename) · 40 unmodified lines |
| 2612 | build_got_entries(s1); | 2592 | build_got_entries(s1); |
| 2613 | version_add (s1); | 2593 | version_add (s1); |
| 2614 | } | 2594 | } |
| 2615 | #endif | | |
| 2616 | | 2595 | |
| 2617 | /* we add a section for symbols */ | 2596 | textrel = set_sec_sizes(s1); |
| 2618 | strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0); | 2597 | alloc_sec_names(s1, 0); |
| 2619 | put_elf_str(strsec, ""); | | |
| 2620 | | | |
| 2621 | /* Allocate strings for section names */ | | |
| 2622 | ret = alloc_sec_names(s1, file_type, strsec); | | |
| 2623 | | 2598 | |
| 2624 | #ifndef ELF_OBJ_ONLY | 2599 | if (!s1->static_link) { |
| 2625 | if (dynamic) { | | |
| 2626 | int i; | 2600 | int i; |
| 2627 | /* add a list of needed dlls */ | 2601 | /* add a list of needed dlls */ |
| 2628 | for(i = 0; i < s1->nb_loaded_dlls; i++) { | 2602 | 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 |
| 2640 | put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname)); | 2614 | put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname)); |
| 2641 | /* XXX: currently, since we do not handle PIC code, we | 2615 | /* XXX: currently, since we do not handle PIC code, we |
| 2642 | must relocate the readonly segments */ | 2616 | must relocate the readonly segments */ |
| 2643 | if (ret) | 2617 | if (textrel) |
| 2644 | put_dt(dynamic, DT_TEXTREL, 0); | 2618 | put_dt(dynamic, DT_TEXTREL, 0); |
| 2645 | } | 2619 | } |
| 2646 | | 2620 | |
| @@ -2655,16 +2629,13 @@ static int elf_output_file(TCCState *s1, const char *filename) · 8 unmodified lines |
| 2655 | dynamic->sh_size = dynamic->data_offset; | 2629 | dynamic->sh_size = dynamic->data_offset; |
| 2656 | dynstr->sh_size = dynstr->data_offset; | 2630 | dynstr->sh_size = dynstr->data_offset; |
| 2657 | } | 2631 | } |
| 2658 | #endif | | |
| 2659 | | 2632 | |
| 2660 | for (i = 1; i < s1->nb_sections && | 2633 | for (i = 1; i < s1->nb_sections && |
| 2661 | !(s1->sections[i]->sh_flags & SHF_TLS); i++); | 2634 | !(s1->sections[i]->sh_flags & SHF_TLS); i++); |
| 2662 | phfill = 2 + (i < s1->nb_sections); | 2635 | phfill = 2 + (i < s1->nb_sections); |
| 2663 | | 2636 | |
| 2664 | /* compute number of program headers */ | 2637 | /* compute number of program headers */ |
| 2665 | if (file_type == TCC_OUTPUT_OBJ) | 2638 | if (file_type == TCC_OUTPUT_DLL) |
| 2666 | phnum = phfill = 0; | | |
| 2667 | else if (file_type == TCC_OUTPUT_DLL) | | |
| 2668 | phnum = 3; | 2639 | phnum = 3; |
| 2669 | else if (s1->static_link) | 2640 | else if (s1->static_link) |
| 2670 | phnum = 3; | 2641 | phnum = 3; |
| @@ -2673,31 +2644,25 @@ static int elf_output_file(TCCState *s1, const char *filename) · 2 unmodified lines |
| 2673 | } | 2644 | } |
| 2674 | | 2645 | |
| 2675 | phnum += note != NULL; | 2646 | phnum += note != NULL; |
| 2676 | | 2647 | #if !TARGETOS_FreeBSD && !TARGETOS_NetBSD |
| 2677 | #if !TARGETOS_FreeBSD && !TARGETOS_NetBSD && !defined(__APPLE__) && !defined(_WIN32) | | |
| 2678 | /* GNU_RELRO */ | 2648 | /* GNU_RELRO */ |
| 2679 | if (file_type != TCC_OUTPUT_OBJ) | 2649 | phnum++, roinf_use = &roinf; |
| 2680 | phnum++, roinf_use = &roinf; | | |
| 2681 | #endif | 2650 | #endif |
| 2682 | | 2651 | |
| 2683 | /* allocate program segment headers */ | 2652 | /* allocate program segment headers */ |
| 2684 | phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr))); | 2653 | phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr))); |
| 2685 | | | |
| 2686 | /* compute number of sections */ | 2654 | /* compute number of sections */ |
| 2687 | shnum = s1->nb_sections; | 2655 | shnum = s1->nb_sections; |
| 2688 | | | |
| 2689 | /* this array is used to reorder sections in the output file */ | 2656 | /* this array is used to reorder sections in the output file */ |
| 2690 | sec_order = tcc_malloc(sizeof(int) * shnum); | 2657 | sec_order = tcc_malloc(sizeof(int) * shnum); |
| 2691 | sec_order[0] = 0; | 2658 | sec_order[0] = 0; |
| 2692 | | 2659 | |
| 2693 | /* compute section to program header mapping */ | 2660 | /* compute section to program header mapping */ |
| 2694 | file_offset = layout_sections(s1, phdr, phnum, phfill, interp, strsec, | 2661 | file_offset = layout_sections(s1, phdr, phnum, phfill, interp, &roinf, sec_order + 1); |
| 2695 | &roinf, sec_order); | | |
| 2696 | | 2662 | |
| 2697 | #ifndef ELF_OBJ_ONLY | | |
| 2698 | /* Fill remaining program header and finalize relocation related to dynamic | 2663 | /* Fill remaining program header and finalize relocation related to dynamic |
| 2699 | linking. */ | 2664 | linking. */ |
| 2700 | if (file_type != TCC_OUTPUT_OBJ) { | 2665 | { |
| 2701 | fill_unloadable_phdr(phdr, phnum, interp, dynamic, note, roinf_use); | 2666 | fill_unloadable_phdr(phdr, phnum, interp, dynamic, note, roinf_use); |
| 2702 | if (dynamic) { | 2667 | if (dynamic) { |
| 2703 | ElfW(Sym) *sym; | 2668 | ElfW(Sym) *sym; |
| @@ -2735,32 +2700,85 @@ static int elf_output_file(TCCState *s1, const char *filename) · 31 unmodified lines |
| 2735 | else if (s1->got) | 2700 | else if (s1->got) |
| 2736 | fill_local_got_entries(s1); | 2701 | fill_local_got_entries(s1); |
| 2737 | } | 2702 | } |
| 2738 | #endif | | |
| 2739 | | | |
| 2740 | /* Create the ELF file with name 'filename' */ | 2703 | /* Create the ELF file with name 'filename' */ |
| 2741 | ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order); | 2704 | ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order); |
| 2742 | s1->nb_sections = shnum; | 2705 | s1->nb_sections = shnum; |
| 2743 | goto the_end; | 2706 | |
| 2744 | the_end: | 2707 | the_end: |
| 2745 | tcc_free(sec_order); | 2708 | tcc_free(sec_order); |
| 2746 | tcc_free(phdr); | 2709 | tcc_free(phdr); |
| 2747 | return ret; | 2710 | return ret; |
| 2748 | } | 2711 | } |
| | 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 | } |
| 2749 | | 2770 | |
| 2750 | LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename) | 2771 | LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename) |
| 2751 | { | 2772 | { |
| 2752 | int ret; | 2773 | if (s->output_type == TCC_OUTPUT_OBJ) |
| | 2774 | return elf_output_obj(s, filename); |
| 2753 | #ifdef TCC_TARGET_PE | 2775 | #ifdef TCC_TARGET_PE |
| 2754 | if (s->output_type != TCC_OUTPUT_OBJ) { | 2776 | return pe_output_file(s, filename); |
| 2755 | ret = pe_output_file(s, filename); | | |
| 2756 | } else | | |
| 2757 | #elif TCC_TARGET_MACHO | 2777 | #elif TCC_TARGET_MACHO |
| 2758 | if (s->output_type != TCC_OUTPUT_OBJ) { | 2778 | return macho_output_file(s, filename); |
| 2759 | ret = macho_output_file(s, filename); | 2779 | #else |
| 2760 | } else | 2780 | return elf_output_file(s, filename); |
| 2761 | #endif | 2781 | #endif |
| 2762 | ret = elf_output_file(s, filename); | | |
| 2763 | return ret; | | |
| 2764 | } | 2782 | } |
| 2765 | | 2783 | |
| 2766 | ST_FUNC ssize_t full_read(int fd, void *buf, size_t count) { | 2784 | ST_FUNC ssize_t full_read(int fd, void *buf, size_t count) { |