History

Revert "Split elf_output_file in smaller functions"

This reverts commit b5b82df3e388e2565ee424994e3d5041fbf91161.

Thomas Preud'homme committed 12 years ago

Commit e5a706a1 parent f62e97e1 file · +551 −659Browse files

Unified · Split

tccelf.c+551−659
@@ -20,7 +20,6 @@ · 19 unmodified lines
2020
2121 #include "tcc.h"
2222
23−/* XXX: avoid static variable */
2423 static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */
2524
2625 ST_FUNC int put_elf_str(Section *s, const char *sym)
@@ -430,7 +429,6 @@ ST_FUNC void relocate_syms(TCCState *s1, int do_resolve) · 403 unmodified lines
430429 sh_num = sym->st_shndx;
431430 if (sh_num == SHN_UNDEF) {
432431 name = strtab_section->data + sym->st_name;
433− /* Use ld.so to resolve symbol for us (for tcc -run) */
434432 if (do_resolve) {
435433 #if defined TCC_IS_NATIVE && !defined _WIN32
436434 void *addr;
@@ -506,8 +504,7 @@ static addr_t add_jmp_table(TCCState *s1, int val) · 69 unmodified lines
506504 #endif
507505 #endif /* def TCC_HAS_RUNTIME_PLTGOT */
508506
509−/* relocate a given section (CPU dependent) by applying the relocations
510− in the associated relocation section */
507+/* relocate a given section (CPU dependent) */
511508 ST_FUNC void relocate_section(TCCState *s1, Section *s)
512509 {
513510 Section *sr;
@@ -1425,14 +1422,14 @@ ST_FUNC void tcc_add_linker_symbols(TCCState *s1) · 911 unmodified lines
14251422 }
14261423
14271424 static void tcc_output_binary(TCCState *s1, FILE *f,
1428− const int *sec_order)
1425+ const int *section_order)
14291426 {
14301427 Section *s;
14311428 int i, offset, size;
14321429
14331430 offset = 0;
14341431 for(i=1;i<s1->nb_sections;i++) {
1435− s = s1->sections[sec_order[i]];
1432+ s = s1->sections[section_order[i]];
14361433 if (s->sh_type != SHT_NOBITS &&
14371434 (s->sh_flags & SHF_ALLOC)) {
14381435 while (offset < s->sh_offset) {
@@ -1497,7 +1494,6 @@ ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel) · 58 unmodified lines
14971494 put32(s1->got->data + offset, sym->st_value & 0xffffffff);
14981495 }
14991496
1500−/* Perform relocation to GOT or PLT entries */
15011497 ST_FUNC void fill_got(TCCState *s1)
15021498 {
15031499 Section *s;
@@ -1513,213 +1509,301 @@ ST_FUNC void fill_got(TCCState *s1) · 9 unmodified lines
15131509 continue;
15141510 for_each_elem(s, 0, rel, ElfW_Rel) {
15151511 switch (ELFW(R_TYPE) (rel->r_info)) {
1516−#ifdef TCC_TARGET_X86_64
15171512 case R_X86_64_GOT32:
15181513 case R_X86_64_GOTPCREL:
15191514 case R_X86_64_PLT32:
15201515 fill_got_entry(s1, rel);
15211516 break;
1522−#endif
15231517 }
15241518 }
15251519 }
15261520 }
15271521
1528−/* Bind symbols of executable: resolve undefined symbols from exported symbols
1529− in shared libraries and export non local defined symbols to shared libraries
1530− if -rdynamic switch was given on command line */
1531−static void bind_exe_dynsyms(TCCState *s1)
1522+
1523+/* output an ELF file */
1524+/* XXX: suppress unneeded sections */
1525+static int elf_output_file(TCCState *s1, const char *filename)
15321526 {
1533− const char *name;
1534− int sym_index, index;
1535− ElfW(Sym) *sym, *esym;
1536− int type;
1527+ ElfW(Ehdr) ehdr;
1528+ FILE *f;
1529+ int fd, mode, ret;
1530+ int *section_order;
1531+ int shnum, i, phnum, file_offset, offset, size, j, sh_order_index, k;
1532+ long long tmp;
1533+ addr_t addr;
1534+ Section *strsec, *s;
1535+ ElfW(Shdr) shdr, *sh;
1536+ ElfW(Phdr) *phdr, *ph;
1537+ Section *interp, *dynamic, *dynstr;
1538+ unsigned long saved_dynamic_data_offset;
1539+ ElfW(Sym) *sym;
1540+ int type, file_type;
1541+ addr_t rel_addr, rel_size;
1542+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1543+ addr_t bss_addr, bss_size;
1544+#endif
15371545
1538− /* Resolve undefined symbols from dynamic symbols. When there is a match:
1539− - if STT_FUNC or STT_GNU_IFUNC symbol -> add it in PLT
1540− - if STT_OBJECT symbol -> add it in .bss section with suitable reloc */
1541− for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
1542− if (sym->st_shndx == SHN_UNDEF) {
1543− name = symtab_section->link->data + sym->st_name;
1544− sym_index = find_elf_sym(s1->dynsymtab_section, name);
1545− if (sym_index) {
1546− esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1547− type = ELFW(ST_TYPE)(esym->st_info);
1548− if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1549− /* Indirect functions shall have STT_FUNC type in executable
1550− * dynsym section. Indeed, a dlsym call following a lazy
1551− * resolution would pick the symbol value from the
1552− * executable dynsym entry which would contain the address
1553− * of the function wanted by the caller of dlsym instead of
1554− * the address of the function that would return that
1555− * address */
1556− put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1557− ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC),
1558− sym - (ElfW(Sym) *)symtab_section->data);
1559− } else if (type == STT_OBJECT) {
1560− unsigned long offset;
1561− ElfW(Sym) *dynsym;
1562− offset = bss_section->data_offset;
1563− /* XXX: which alignment ? */
1564− offset = (offset + 16 - 1) & -16;
1565− index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1566− esym->st_info, 0, bss_section->sh_num,
1567− name);
1568− /* Ensure R_COPY works for weak symbol aliases */
1569− if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1570− for_each_elem(s1->dynsymtab_section, 1, dynsym, ElfW(Sym)) {
1571− if ((dynsym->st_value == esym->st_value)
1572− && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
1573− char *dynname = s1->dynsymtab_section->link->data
1574− + dynsym->st_name;
1575− put_elf_sym(s1->dynsym, offset, dynsym->st_size,
1576− dynsym->st_info, 0,
1577− bss_section->sh_num, dynname);
1578− break;
1546+ file_type = s1->output_type;
1547+ s1->nb_errors = 0;
1548+
1549+ if (file_type != TCC_OUTPUT_OBJ) {
1550+ tcc_add_runtime(s1);
1551+ }
1552+
1553+ phdr = NULL;
1554+ section_order = NULL;
1555+ interp = NULL;
1556+ dynamic = NULL;
1557+ dynstr = NULL; /* avoid warning */
1558+ saved_dynamic_data_offset = 0; /* avoid warning */
1559+
1560+ if (file_type != TCC_OUTPUT_OBJ) {
1561+ relocate_common_syms();
1562+
1563+ tcc_add_linker_symbols(s1);
1564+
1565+ if (!s1->static_link) {
1566+ const char *name;
1567+ int sym_index, index;
1568+ ElfW(Sym) *esym;
1569+
1570+ if (file_type == TCC_OUTPUT_EXE) {
1571+ char *ptr;
1572+ /* allow override the dynamic loader */
1573+ const char *elfint = getenv("LD_SO");
1574+ if (elfint == NULL)
1575+ elfint = DEFAULT_ELFINTERP(s1);
1576+ /* add interpreter section only if executable */
1577+ interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1578+ interp->sh_addralign = 1;
1579+ ptr = section_ptr_add(interp, 1+strlen(elfint));
1580+ strcpy(ptr, elfint);
1581+ }
1582+
1583+ /* add dynamic symbol table */
1584+ s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1585+ ".dynstr",
1586+ ".hash", SHF_ALLOC);
1587+ dynstr = s1->dynsym->link;
1588+
1589+ /* add dynamic section */
1590+ dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1591+ SHF_ALLOC | SHF_WRITE);
1592+ dynamic->link = dynstr;
1593+ dynamic->sh_entsize = sizeof(ElfW(Dyn));
1594+
1595+ /* add PLT */
1596+ s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1597+ SHF_ALLOC | SHF_EXECINSTR);
1598+ s1->plt->sh_entsize = 4;
1599+
1600+ build_got(s1);
1601+
1602+ /* scan for undefined symbols and see if they are in the
1603+ dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1604+ is found, then we add it in the PLT. If a symbol
1605+ STT_OBJECT is found, we add it in the .bss section with
1606+ a suitable relocation */
1607+ if (file_type == TCC_OUTPUT_EXE) {
1608+ for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
1609+ if (sym->st_shndx == SHN_UNDEF) {
1610+ name = symtab_section->link->data + sym->st_name;
1611+ sym_index = find_elf_sym(s1->dynsymtab_section, name);
1612+ if (sym_index) {
1613+ esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1614+ type = ELFW(ST_TYPE)(esym->st_info);
1615+ if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1616+ /* Indirect functions shall have STT_FUNC type
1617+ * in executable dynsym section. Indeed, a dlsym
1618+ * call following a lazy resolution would pick
1619+ * the symbol value from the executable dynsym
1620+ * entry which would contain the address of the
1621+ * function wanted by the caller of dlsym
1622+ * instead of the address of the function that
1623+ * would return that address */
1624+ put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1625+ ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC),
1626+ sym - (ElfW(Sym) *)symtab_section->data);
1627+ } else if (type == STT_OBJECT) {
1628+ unsigned long offset;
1629+ ElfW(Sym) *dynsym;
1630+ offset = bss_section->data_offset;
1631+ /* XXX: which alignment ? */
1632+ offset = (offset + 16 - 1) & -16;
1633+ index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1634+ esym->st_info, 0,
1635+ bss_section->sh_num, name);
1636+ /* Ensure R_COPY works for weak symbol aliases */
1637+ if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1638+ for_each_elem(s1->dynsymtab_section, 1, dynsym, ElfW(Sym)) {
1639+ if ((dynsym->st_value == esym->st_value)
1640+ && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
1641+ char *dynname;
1642+ dynname = s1->dynsymtab_section->link->data
1643+ + dynsym->st_name;
1644+ put_elf_sym(s1->dynsym, offset,
1645+ dynsym->st_size,
1646+ dynsym->st_info, 0,
1647+ bss_section->sh_num,
1648+ dynname);
1649+ break;
1650+ }
1651+ }
1652+ }
1653+ put_elf_reloc(s1->dynsym, bss_section,
1654+ offset, R_COPY, index);
1655+ offset += esym->st_size;
1656+ bss_section->data_offset = offset;
1657+ }
1658+ } else {
1659+ /* STB_WEAK undefined symbols are accepted */
1660+ /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1661+ it */
1662+ if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1663+ !strcmp(name, "_fp_hw")) {
1664+ } else {
1665+ tcc_error_noabort("undefined symbol '%s'", name);
1666+ }
1667+ }
1668+ } else if (s1->rdynamic &&
1669+ ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1670+ /* if -rdynamic option, then export all non
1671+ local symbols */
1672+ name = symtab_section->link->data + sym->st_name;
1673+ put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1674+ sym->st_info, 0,
1675+ sym->st_shndx, name);
1676+ }
1677+ }
1678+
1679+ if (s1->nb_errors)
1680+ goto fail;
1681+
1682+ /* now look at unresolved dynamic symbols and export
1683+ corresponding symbol */
1684+ for_each_elem(s1->dynsymtab_section, 1, esym, ElfW(Sym)) {
1685+ if (esym->st_shndx == SHN_UNDEF) {
1686+ name = s1->dynsymtab_section->link->data + esym->st_name;
1687+ sym_index = find_elf_sym(symtab_section, name);
1688+ if (sym_index) {
1689+ /* XXX: avoid adding a symbol if already
1690+ present because of -rdynamic ? */
1691+ sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1692+ put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1693+ sym->st_info, 0,
1694+ sym->st_shndx, name);
1695+ } else {
1696+ if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1697+ /* weak symbols can stay undefined */
1698+ } else {
1699+ tcc_warning("undefined dynamic symbol '%s'", name);
15791700 }
15801701 }
15811702 }
1582− put_elf_reloc(s1->dynsym, bss_section,
1583− offset, R_COPY, index);
1584− offset += esym->st_size;
1585− bss_section->data_offset = offset;
15861703 }
15871704 } else {
1588− /* STB_WEAK undefined symbols are accepted */
1589− /* XXX: _fp_hw seems to be part of the ABI, so we ignore it */
1590− if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1591− !strcmp(name, "_fp_hw")) {
1592− } else {
1593− tcc_error_noabort("undefined symbol '%s'", name);
1705+ int nb_syms;
1706+ /* shared library case : we simply export all the global symbols */
1707+ nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1708+ s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1709+ for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
1710+ if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1711+#if defined(TCC_OUTPUT_DLL_WITH_PLT)
1712+ if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
1713+ ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC)
1714+ && sym->st_shndx == SHN_UNDEF) {
1715+ int visibility = ELFW(ST_BIND)(sym->st_info);
1716+ put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1717+ ELFW(ST_INFO)(visibility,STT_FUNC),
1718+ sym - (ElfW(Sym) *)symtab_section->data);
1719+ }
1720+ else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1721+ put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1722+ sym->st_info,
1723+ sym - (ElfW(Sym) *)symtab_section->data);
1724+ }
1725+ else
1726+#endif
1727+ {
1728+ name = symtab_section->link->data + sym->st_name;
1729+ index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1730+ sym->st_info, 0,
1731+ sym->st_shndx, name);
1732+ s1->symtab_to_dynsym[sym -
1733+ (ElfW(Sym) *)symtab_section->data] =
1734+ index;
1735+ }
1736+ }
15941737 }
15951738 }
1596− } else if (s1->rdynamic && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1597− /* if -rdynamic option, then export all non local symbols */
1598− name = symtab_section->link->data + sym->st_name;
1599− put_elf_sym(s1->dynsym, sym->st_value, sym->st_size, sym->st_info,
1600− 0, sym->st_shndx, name);
1601− }
1602− }
1603−}
16041739
1605−/* Bind symbols of libraries: export non local symbols of executable that
1606− resolve undefined symbols of shared libraries */
1607−static void bind_libs_dynsyms(TCCState *s1)
1608−{
1609− const char *name;
1610− int sym_index;
1611− ElfW(Sym) *sym, *esym;
1740+ build_got_entries(s1);
16121741
1613− /* now look at unresolved dynamic symbols and export
1614− corresponding symbol */
1615− for_each_elem(s1->dynsymtab_section, 1, esym, ElfW(Sym)) {
1616− if (esym->st_shndx == SHN_UNDEF) {
1617− name = s1->dynsymtab_section->link->data + esym->st_name;
1618− sym_index = find_elf_sym(symtab_section, name);
1619− if (sym_index) {
1620− /* XXX: avoid adding a symbol if already present because of
1621− -rdynamic ? */
1622− sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1623− put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1624− sym->st_info, 0, sym->st_shndx, name);
1625− } else {
1626− /* weak symbols can stay undefined */
1627− if (ELFW(ST_BIND)(esym->st_info) != STB_WEAK)
1628− tcc_warning("undefined dynamic symbol '%s'", name);
1742+ /* add a list of needed dlls */
1743+ for(i = 0; i < s1->nb_loaded_dlls; i++) {
1744+ DLLReference *dllref = s1->loaded_dlls[i];
1745+ if (dllref->level == 0)
1746+ put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
16291747 }
1630− }
1631− }
1632−}
16331748
1634−/* Export all non local symbols (for shared libraries) */
1635−static void export_global_syms(TCCState *s1)
1636−{
1637− int nb_syms, dynindex, index;
1638− const char *name;
1639− ElfW(Sym) *sym;
1749+ if (s1->rpath)
1750+ put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
16401751
1641− nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1642− s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1643− for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
1644− if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1645−#if defined(TCC_OUTPUT_DLL_WITH_PLT)
1646− int type = ELFW(ST_TYPE)(sym->st_info);
1647− if ((type == STT_FUNC || type == STT_GNU_IFUNC)
1648− && sym->st_shndx == SHN_UNDEF) {
1649− int visibility = ELFW(ST_BIND)(sym->st_info);
1650− put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1651− ELFW(ST_INFO)(visibility, STT_FUNC),
1652− sym - (ElfW(Sym) *) symtab_section->data);
1653− } else if (type == STT_OBJECT) {
1654− put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size, sym->st_info,
1655− sym - (ElfW(Sym) *) symtab_section->data);
1656− } else
1657−#endif
1658− {
1659− name = symtab_section->link->data + sym->st_name;
1660− dynindex = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1661− sym->st_info, 0, sym->st_shndx, name);
1662− index = sym - (ElfW(Sym) *) symtab_section->data;
1663− s1->symtab_to_dynsym[index] = dynindex;
1752+ /* XXX: currently, since we do not handle PIC code, we
1753+ must relocate the readonly segments */
1754+ if (file_type == TCC_OUTPUT_DLL) {
1755+ if (s1->soname)
1756+ put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1757+ put_dt(dynamic, DT_TEXTREL, 0);
16641758 }
1665− }
1666− }
1667−}
16681759
1669−/* relocate the PLT: compute addresses and offsets in the PLT now that final
1670− address for PLT and GOT are known (see fill_program_header) */
1671−static void relocate_plt(TCCState *s1)
1672−{
1673− uint8_t *p, *p_end;
1760+ if (s1->symbolic)
1761+ put_dt(dynamic, DT_SYMBOLIC, 0);
16741762
1675− p = s1->plt->data;
1676− p_end = p + s1->plt->data_offset;
1677− if (p < p_end) {
1678−#if defined(TCC_TARGET_I386)
1679− put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1680− put32(p + 8, get32(p + 8) + s1->got->sh_addr);
1681− p += 16;
1682− while (p < p_end) {
1683− put32(p + 2, get32(p + 2) + s1->got->sh_addr);
1684− p += 16;
1685− }
1686−#elif defined(TCC_TARGET_X86_64)
1687− int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
1688− put32(p + 2, get32(p + 2) + x);
1689− put32(p + 8, get32(p + 8) + x - 6);
1690− p += 16;
1691− while (p < p_end) {
1692− put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
1693− p += 16;
1694− }
1695−#elif defined(TCC_TARGET_ARM)
1696− int x;
1697− x=s1->got->sh_addr - s1->plt->sh_addr - 12;
1698− p += 16;
1699− while (p < p_end) {
1700− if (get32(p) == 0x46c04778) /* PLT Thumb stub present */
1701− p += 4;
1702− put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
1703− p += 16;
1763+ /* add necessary space for other entries */
1764+ saved_dynamic_data_offset = dynamic->data_offset;
1765+ dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1766+ } else {
1767+ /* still need to build got entries in case of static link */
1768+ build_got_entries(s1);
17041769 }
1705−#elif defined(TCC_TARGET_C67)
1706− /* XXX: TODO */
1707−#else
1708−#error unsupported CPU
1709−#endif
17101770 }
1711−}
17121771
1713−/* Allocate strings for section names and decide if an unallocated section
1714− should be output.
1772+ memset(&ehdr, 0, sizeof(ehdr));
17151773
1716− NOTE: the strsec section comes last, so its size is also correct ! */
1717−static void alloc_sec_names(TCCState *s1, int file_type, Section *strsec)
1718−{
1719− int i;
1720− Section *s;
1774+ /* we add a section for symbols */
1775+ strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1776+ put_elf_str(strsec, "");
1777+
1778+ /* compute number of sections */
1779+ shnum = s1->nb_sections;
17211780
1722− /* Allocate strings for section names */
1781+ /* this array is used to reorder sections in the output file */
1782+ section_order = tcc_malloc(sizeof(int) * shnum);
1783+ section_order[0] = 0;
1784+ sh_order_index = 1;
1785+
1786+ /* compute number of program headers */
1787+ switch(file_type) {
1788+ default:
1789+ case TCC_OUTPUT_OBJ:
1790+ phnum = 0;
1791+ break;
1792+ case TCC_OUTPUT_EXE:
1793+ if (!s1->static_link)
1794+ phnum = 4 + HAVE_PHDR;
1795+ else
1796+ phnum = 2;
1797+ break;
1798+ case TCC_OUTPUT_DLL:
1799+ phnum = 3;
1800+ break;
1801+ }
1802+
1803+ /* allocate strings for section names and decide if an unallocated
1804+ section should be output */
1805+ /* NOTE: the strsec section comes last, so its size is also
1806+ correct ! */
17231807 for(i = 1; i < s1->nb_sections; i++) {
17241808 s = s1->sections[i];
17251809 s->sh_name = put_elf_str(strsec, s->name);
@@ -1741,41 +1825,17 @@ static void alloc_sec_names(TCCState *s1, int file_type, Section *strsec) · 15 unmodified lines
17411825 s->sh_size = s->data_offset;
17421826 }
17431827 }
1744−}
1745−
1746−/* Info to be copied in dynamic section */
1747−struct dyn_inf {
1748− Section *dynamic;
1749− Section *dynstr;
1750− unsigned long dyn_rel_off;
1751− addr_t rel_addr;
1752− addr_t rel_size;
1753−#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1754− addr_t bss_addr;
1755− addr_t bss_size;
1756−#endif
1757−};
17581828
1759−/* Assign sections to segments and decide how are sections laid out when loaded
1760− in memory. This function also fills corresponding program headers. */
1761−static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,
1762− Section *interp, struct dyn_inf *dyninf,
1763− int *sec_order)
1764−{
1765− int i, j, k, file_type, sh_order_index, file_offset;
1766− long long tmp;
1767− addr_t addr;
1768− ElfW(Phdr) *ph;
1769− Section *s;
1829+ /* allocate program segment headers */
1830+ phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
17701831
1771− file_type = s1->output_type;
1772− sh_order_index = 1;
1773− if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
1832+ if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
17741833 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1775− else
1834+ } else {
17761835 file_offset = 0;
1777−
1836+ }
17781837 if (phnum > 0) {
1838+ /* compute section to program header mapping */
17791839 if (s1->has_text_addr) {
17801840 int a_offset, p_offset;
17811841 addr = s1->text_addr;
@@ -1795,18 +1855,17 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, · 13 unmodified lines
17951855 addr += (file_offset & (s1->section_align - 1));
17961856 }
17971857
1798− ph = &phdr[0];
1799− /* Leave one program headers for the program interpreter and one for
1800− the program header table itself if needed. These are done later as
1801− they require section layout to be done first. */
1802− if (interp)
1803− ph += 1 + HAVE_PHDR;
1804−
18051858 /* dynamic relocation table information, for .dynamic section */
1806− dyninf->rel_addr = dyninf->rel_size = 0;
1859+ rel_size = 0;
1860+ rel_addr = 0;
1861+
18071862 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1808− dyninf->bss_addr = dyninf->bss_size = 0;
1863+ bss_addr = bss_size = 0;
18091864 #endif
1865+ /* leave one program header for the program interpreter */
1866+ ph = &phdr[0];
1867+ if (interp)
1868+ ph += 1 + HAVE_PHDR;
18101869
18111870 for(j = 0; j < 2; j++) {
18121871 ph->p_type = PT_LOAD;
@@ -1816,10 +1875,8 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, · 3 unmodified lines
18161875 ph->p_flags = PF_R | PF_W;
18171876 ph->p_align = s1->section_align;
18181877
1819− /* Decide the layout of sections loaded in memory. This must
1820− be done before program headers are filled since they contain
1821− info about the layout. We do the following ordering: interp,
1822− symbol tables, relocations, progbits, nobits */
1878+ /* we do the following ordering: interp, symbol tables,
1879+ relocations, progbits, nobits */
18231880 /* XXX: do faster and simpler sorting */
18241881 for(k = 0; k < 5; k++) {
18251882 for(i = 1; i < s1->nb_sections; i++) {
@@ -1852,7 +1909,7 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, · 26 unmodified lines
18521909 if (k != 3)
18531910 continue;
18541911 }
1855− sec_order[sh_order_index++] = i;
1912+ section_order[sh_order_index++] = i;
18561913
18571914 /* section matches: we align it and add its size */
18581915 tmp = addr;
@@ -1872,17 +1929,17 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, · 13 unmodified lines
18721929 if (s->sh_type == SHT_RELX) {
18731930 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
18741931 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) {
1875− dyninf->rel_addr = addr;
1876− dyninf->rel_size += s->sh_size; /* XXX only first rel. */
1932+ rel_addr = addr;
1933+ rel_size += s->sh_size; /* XXX only first rel. */
18771934 }
18781935 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) {
1879− dyninf->bss_addr = addr;
1880− dyninf->bss_size = s->sh_size; /* XXX only first rel. */
1936+ bss_addr = addr;
1937+ bss_size = s->sh_size; /* XXX only first rel. */
18811938 }
18821939 #else
1883− if (dyninf->rel_size == 0)
1884− dyninf->rel_addr = addr;
1885− dyninf->rel_size += s->sh_size;
1940+ if (rel_size == 0)
1941+ rel_addr = addr;
1942+ rel_size += s->sh_size;
18861943 #endif
18871944 }
18881945 addr += s->sh_size;
@@ -1906,269 +1963,199 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, · 17 unmodified lines
19061963 }
19071964 }
19081965 }
1909− }
19101966
1911− /* all other sections come after */
1912− for(i = 1; i < s1->nb_sections; i++) {
1913− s = s1->sections[i];
1914− if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
1915− continue;
1916− sec_order[sh_order_index++] = i;
1967+ /* if interpreter, then add corresponing program header */
1968+ if (interp) {
1969+ ph = &phdr[0];
19171970
1918− file_offset = (file_offset + s->sh_addralign - 1) &
1919− ~(s->sh_addralign - 1);
1920− s->sh_offset = file_offset;
1921− if (s->sh_type != SHT_NOBITS)
1922− file_offset += s->sh_size;
1923− }
1924−
1925− return file_offset;
1926−}
1927−
1928−static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp,
1929− Section *dynamic)
1930−{
1931− ElfW(Phdr) *ph;
1971+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1972+ {
1973+ int len = phnum * sizeof(ElfW(Phdr));
1974+
1975+ ph->p_type = PT_PHDR;
1976+ ph->p_offset = sizeof(ElfW(Ehdr));
1977+ ph->p_vaddr = interp->sh_addr - len;
1978+ ph->p_paddr = ph->p_vaddr;
1979+ ph->p_filesz = ph->p_memsz = len;
1980+ ph->p_flags = PF_R | PF_X;
1981+ ph->p_align = 4; /* interp->sh_addralign; */
1982+ ph++;
1983+ }
1984+#endif
19321985
1933− /* if interpreter, then add corresponding program header */
1934− if (interp) {
1935− ph = &phdr[0];
1986+ ph->p_type = PT_INTERP;
1987+ ph->p_offset = interp->sh_offset;
1988+ ph->p_vaddr = interp->sh_addr;
1989+ ph->p_paddr = ph->p_vaddr;
1990+ ph->p_filesz = interp->sh_size;
1991+ ph->p_memsz = interp->sh_size;
1992+ ph->p_flags = PF_R;
1993+ ph->p_align = interp->sh_addralign;
1994+ }
19361995
1937− if (HAVE_PHDR)
1938− {
1939− int len = phnum * sizeof(ElfW(Phdr));
1996+ /* if dynamic section, then add corresponing program header */
1997+ if (dynamic) {
1998+ ph = &phdr[phnum - 1];
19401999
1941− ph->p_type = PT_PHDR;
1942− ph->p_offset = sizeof(ElfW(Ehdr));
1943− ph->p_vaddr = interp->sh_addr - len;
2000+ ph->p_type = PT_DYNAMIC;
2001+ ph->p_offset = dynamic->sh_offset;
2002+ ph->p_vaddr = dynamic->sh_addr;
19442003 ph->p_paddr = ph->p_vaddr;
1945− ph->p_filesz = ph->p_memsz = len;
1946− ph->p_flags = PF_R | PF_X;
1947− ph->p_align = 4; /* interp->sh_addralign; */
1948− ph++;
1949− }
2004+ ph->p_filesz = dynamic->sh_size;
2005+ ph->p_memsz = dynamic->sh_size;
2006+ ph->p_flags = PF_R | PF_W;
2007+ ph->p_align = dynamic->sh_addralign;
19502008
1951− ph->p_type = PT_INTERP;
1952− ph->p_offset = interp->sh_offset;
1953− ph->p_vaddr = interp->sh_addr;
1954− ph->p_paddr = ph->p_vaddr;
1955− ph->p_filesz = interp->sh_size;
1956− ph->p_memsz = interp->sh_size;
1957− ph->p_flags = PF_R;
1958− ph->p_align = interp->sh_addralign;
1959− }
2009+ /* put GOT dynamic section address */
2010+ put32(s1->got->data, dynamic->sh_addr);
19602011
1961− /* if dynamic section, then add corresponding program header */
1962− if (dynamic) {
1963− ph = &phdr[phnum - 1];
1964−
1965− ph->p_type = PT_DYNAMIC;
1966− ph->p_offset = dynamic->sh_offset;
1967− ph->p_vaddr = dynamic->sh_addr;
1968− ph->p_paddr = ph->p_vaddr;
1969− ph->p_filesz = dynamic->sh_size;
1970− ph->p_memsz = dynamic->sh_size;
1971− ph->p_flags = PF_R | PF_W;
1972− ph->p_align = dynamic->sh_addralign;
1973− }
1974−}
2012+ /* relocate the PLT */
2013+ if (file_type == TCC_OUTPUT_EXE
2014+#if defined(TCC_OUTPUT_DLL_WITH_PLT)
2015+ || file_type == TCC_OUTPUT_DLL
2016+#endif
2017+ ) {
2018+ uint8_t *p, *p_end;
19752019
1976−/* Fill the dynamic section with tags describing the address and size of
1977− sections */
1978−static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
1979−{
1980− Section *dynamic;
2020+ p = s1->plt->data;
2021+ p_end = p + s1->plt->data_offset;
2022+ if (p < p_end) {
2023+#if defined(TCC_TARGET_I386)
2024+ put32(p + 2, get32(p + 2) + s1->got->sh_addr);
2025+ put32(p + 8, get32(p + 8) + s1->got->sh_addr);
2026+ p += 16;
2027+ while (p < p_end) {
2028+ put32(p + 2, get32(p + 2) + s1->got->sh_addr);
2029+ p += 16;
2030+ }
2031+#elif defined(TCC_TARGET_X86_64)
2032+ int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
2033+ put32(p + 2, get32(p + 2) + x);
2034+ put32(p + 8, get32(p + 8) + x - 6);
2035+ p += 16;
2036+ while (p < p_end) {
2037+ put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
2038+ p += 16;
2039+ }
2040+#elif defined(TCC_TARGET_ARM)
2041+ int x;
2042+ x=s1->got->sh_addr - s1->plt->sh_addr - 12;
2043+ p += 16;
2044+ while (p < p_end) {
2045+ if (get32(p) == 0x46c04778) /* PLT Thumb stub present */
2046+ p += 4;
2047+ put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
2048+ p += 16;
2049+ }
2050+#elif defined(TCC_TARGET_C67)
2051+ /* XXX: TODO */
2052+#else
2053+#error unsupported CPU
2054+#endif
2055+ }
2056+ }
19812057
1982− dynamic = dyninf->dynamic;
2058+ /* relocate symbols in .dynsym */
2059+ for_each_elem(s1->dynsym, 1, sym, ElfW(Sym)) {
2060+ if (sym->st_shndx == SHN_UNDEF) {
2061+ /* relocate to the PLT if the symbol corresponds
2062+ to a PLT entry */
2063+ if (sym->st_value)
2064+ sym->st_value += s1->plt->sh_addr;
2065+ } else if (sym->st_shndx < SHN_LORESERVE) {
2066+ /* do symbol relocation */
2067+ sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
2068+ }
2069+ }
19832070
1984− /* put dynamic section entries */
1985− dynamic->data_offset = dyninf->dyn_rel_off;
1986− put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
1987− put_dt(dynamic, DT_STRTAB, dyninf->dynstr->sh_addr);
1988− put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
1989− put_dt(dynamic, DT_STRSZ, dyninf->dynstr->data_offset);
1990− put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
2071+ /* put dynamic section entries */
2072+ dynamic->data_offset = saved_dynamic_data_offset;
2073+ put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
2074+ put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
2075+ put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
2076+ put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
2077+ put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
19912078 #ifdef TCC_TARGET_X86_64
1992− put_dt(dynamic, DT_RELA, dyninf->rel_addr);
1993− put_dt(dynamic, DT_RELASZ, dyninf->rel_size);
1994− put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2079+ put_dt(dynamic, DT_RELA, rel_addr);
2080+ put_dt(dynamic, DT_RELASZ, rel_size);
2081+ put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
19952082 #else
19962083 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1997− put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
1998− put_dt(dynamic, DT_PLTRELSZ, dyninf->rel_size);
1999− put_dt(dynamic, DT_JMPREL, dyninf->rel_addr);
2000− put_dt(dynamic, DT_PLTREL, DT_REL);
2001− put_dt(dynamic, DT_REL, dyninf->bss_addr);
2002− put_dt(dynamic, DT_RELSZ, dyninf->bss_size);
2084+ put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2085+ put_dt(dynamic, DT_PLTRELSZ, rel_size);
2086+ put_dt(dynamic, DT_JMPREL, rel_addr);
2087+ put_dt(dynamic, DT_PLTREL, DT_REL);
2088+ put_dt(dynamic, DT_REL, bss_addr);
2089+ put_dt(dynamic, DT_RELSZ, bss_size);
20032090 #else
2004− put_dt(dynamic, DT_REL, dyninf->rel_addr);
2005− put_dt(dynamic, DT_RELSZ, dyninf->rel_size);
2006− put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2091+ put_dt(dynamic, DT_REL, rel_addr);
2092+ put_dt(dynamic, DT_RELSZ, rel_size);
2093+ put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
20072094 #endif
20082095 #endif
2009− if (s1->do_debug)
2010− put_dt(dynamic, DT_DEBUG, 0);
2011− put_dt(dynamic, DT_NULL, 0);
2012−}
2013−
2014−/* Relocate remaining sections and symbols (that is those not related to
2015− dynamic linking) */
2016−static int final_sections_reloc(TCCState *s1)
2017−{
2018− int i;
2019− Section *s;
2020−
2021− relocate_syms(s1, 0);
2022−
2023− if (s1->nb_errors != 0)
2024− return -1;
2096+ if (s1->do_debug)
2097+ put_dt(dynamic, DT_DEBUG, 0);
2098+ put_dt(dynamic, DT_NULL, 0);
2099+ }
20252100
2026− /* relocate sections */
2027− /* XXX: ignore sections with allocated relocations ? */
2028− for(i = 1; i < s1->nb_sections; i++) {
2029− s = s1->sections[i];
2030− if (s->reloc && s != s1->got)
2031− relocate_section(s1, s);
2101+ ehdr.e_phentsize = sizeof(ElfW(Phdr));
2102+ ehdr.e_phnum = phnum;
2103+ ehdr.e_phoff = sizeof(ElfW(Ehdr));
20322104 }
20332105
2034− /* relocate relocation entries if the relocation tables are
2035− allocated in the executable */
2106+ /* all other sections come after */
20362107 for(i = 1; i < s1->nb_sections; i++) {
20372108 s = s1->sections[i];
2038− if ((s->sh_flags & SHF_ALLOC) &&
2039− s->sh_type == SHT_RELX) {
2040− relocate_rel(s1, s);
2041− }
2042− }
2043− return 0;
2044−}
2109+ if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2110+ continue;
2111+ section_order[sh_order_index++] = i;
20452112
2046−/* Create an ELF file on disk.
2047− This function handle ELF specific layout requirements */
2048−static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
2049− int file_offset, int *sec_order)
2050−{
2051− int i, shnum, offset, size, file_type;
2052− Section *s;
2053− ElfW(Ehdr) ehdr;
2054− ElfW(Shdr) shdr, *sh;
2113+ file_offset = (file_offset + s->sh_addralign - 1) &
2114+ ~(s->sh_addralign - 1);
2115+ s->sh_offset = file_offset;
2116+ if (s->sh_type != SHT_NOBITS)
2117+ file_offset += s->sh_size;
2118+ }
20552119
2056− file_type = s1->output_type;
2057− shnum = s1->nb_sections;
2120+ /* if building executable or DLL, then relocate each section
2121+ except the GOT which is already relocated */
2122+ if (file_type != TCC_OUTPUT_OBJ) {
2123+ relocate_syms(s1, 0);
20582124
2059− memset(&ehdr, 0, sizeof(ehdr));
2125+ if (s1->nb_errors != 0) {
2126+ fail:
2127+ ret = -1;
2128+ goto the_end;
2129+ }
20602130
2061− if (phnum > 0) {
2062− ehdr.e_phentsize = sizeof(ElfW(Phdr));
2063− ehdr.e_phnum = phnum;
2064− ehdr.e_phoff = sizeof(ElfW(Ehdr));
2065− }
2131+ /* relocate sections */
2132+ /* XXX: ignore sections with allocated relocations ? */
2133+ for(i = 1; i < s1->nb_sections; i++) {
2134+ s = s1->sections[i];
2135+ if (s->reloc && s != s1->got)
2136+ relocate_section(s1, s);
2137+ }
20662138
2067− /* align to 4 */
2068− file_offset = (file_offset + 3) & -4;
2069−
2070− /* fill header */
2071− ehdr.e_ident[0] = ELFMAG0;
2072− ehdr.e_ident[1] = ELFMAG1;
2073− ehdr.e_ident[2] = ELFMAG2;
2074− ehdr.e_ident[3] = ELFMAG3;
2075− ehdr.e_ident[4] = ELFCLASSW;
2076− ehdr.e_ident[5] = ELFDATA2LSB;
2077− ehdr.e_ident[6] = EV_CURRENT;
2078−#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2079− ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2080−#endif
2081−#ifdef TCC_TARGET_ARM
2082−#ifdef TCC_ARM_EABI
2083− ehdr.e_ident[EI_OSABI] = 0;
2084− ehdr.e_flags = EF_ARM_EABI_VER4;
2085− if (file_type == TCC_OUTPUT_EXE || file_type == TCC_OUTPUT_DLL)
2086− ehdr.e_flags |= EF_ARM_HASENTRY;
2087− if (s1->float_abi == ARM_HARD_FLOAT)
2088− ehdr.e_flags |= EF_ARM_VFP_FLOAT;
2089− else
2090− ehdr.e_flags |= EF_ARM_SOFT_FLOAT;
2091−#else
2092− ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2093−#endif
2094−#endif
2095− switch(file_type) {
2096− default:
2097− case TCC_OUTPUT_EXE:
2098− ehdr.e_type = ET_EXEC;
2099− ehdr.e_entry = get_elf_sym_addr(s1, "_start", 1);
2100− break;
2101− case TCC_OUTPUT_DLL:
2102− ehdr.e_type = ET_DYN;
2103− ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2104− break;
2105− case TCC_OUTPUT_OBJ:
2106− ehdr.e_type = ET_REL;
2107− break;
2108− }
2109− ehdr.e_machine = EM_TCC_TARGET;
2110− ehdr.e_version = EV_CURRENT;
2111− ehdr.e_shoff = file_offset;
2112− ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2113− ehdr.e_shentsize = sizeof(ElfW(Shdr));
2114− ehdr.e_shnum = shnum;
2115− ehdr.e_shstrndx = shnum - 1;
2116−
2117− fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2118− fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2119− offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2120−
2121− sort_syms(s1, symtab_section);
2122− for(i = 1; i < s1->nb_sections; i++) {
2123− s = s1->sections[sec_order[i]];
2124− if (s->sh_type != SHT_NOBITS) {
2125− if (s->sh_type == SHT_DYNSYM)
2126− patch_dynsym_undef(s1, s);
2127− while (offset < s->sh_offset) {
2128− fputc(0, f);
2129− offset++;
2139+ /* relocate relocation entries if the relocation tables are
2140+ allocated in the executable */
2141+ for(i = 1; i < s1->nb_sections; i++) {
2142+ s = s1->sections[i];
2143+ if ((s->sh_flags & SHF_ALLOC) &&
2144+ s->sh_type == SHT_RELX) {
2145+ relocate_rel(s1, s);
21302146 }
2131− size = s->sh_size;
2132− fwrite(s->data, 1, size, f);
2133− offset += size;
21342147 }
2135− }
2136−
2137− /* output section headers */
2138− while (offset < ehdr.e_shoff) {
2139− fputc(0, f);
2140− offset++;
2141− }
21422148
2143− for(i = 0; i < s1->nb_sections; i++) {
2144− sh = &shdr;
2145− memset(sh, 0, sizeof(ElfW(Shdr)));
2146− s = s1->sections[i];
2147− if (s) {
2148− sh->sh_name = s->sh_name;
2149− sh->sh_type = s->sh_type;
2150− sh->sh_flags = s->sh_flags;
2151− sh->sh_entsize = s->sh_entsize;
2152− sh->sh_info = s->sh_info;
2153− if (s->link)
2154− sh->sh_link = s->link->sh_num;
2155− sh->sh_addralign = s->sh_addralign;
2156− sh->sh_addr = s->sh_addr;
2157− sh->sh_offset = s->sh_offset;
2158− sh->sh_size = s->sh_size;
2159− }
2160− fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2149+ /* get entry point address */
2150+ if (file_type == TCC_OUTPUT_EXE)
2151+ ehdr.e_entry = get_elf_sym_addr(s1, "_start", 1);
2152+ else
2153+ ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
21612154 }
2162−}
2163−
2164−/* Write an elf, coff or "binary" file */
2165−static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum,
2166− ElfW(Phdr) *phdr, int file_offset, int *sec_order)
2167−{
2168− int fd, mode, file_type;
2169− FILE *f;
2155+ if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2156+ fill_got(s1);
21702157
2171− file_type = s1->output_type;
2158+ /* write elf file */
21722159 if (file_type == TCC_OUTPUT_OBJ)
21732160 mode = 0666;
21742161 else
@@ -2177,218 +2164,121 @@ static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum, · 2 unmodified lines
21772164 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
21782165 if (fd < 0) {
21792166 tcc_error_noabort("could not write '%s'", filename);
2180− return -1;
2167+ goto fail;
21812168 }
21822169 f = fdopen(fd, "wb");
21832170 if (s1->verbose)
21842171 printf("<- %s\n", filename);
21852172
21862173 #ifdef TCC_TARGET_COFF
2187− if (s1->output_format == TCC_OUTPUT_FORMAT_COFF)
2174+ if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
21882175 tcc_output_coff(s1, f);
2189− else
2176+ } else
21902177 #endif
2191− if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
2192− tcc_output_elf(s1, f, phnum, phdr, file_offset, sec_order);
2193− else
2194− tcc_output_binary(s1, f, sec_order);
2195− fclose(f);
2196−
2197− return 0;
2198−}
2199−
2200−/* Output an elf, coff or binary file */
2201−/* XXX: suppress unneeded sections */
2202−static int elf_output_file(TCCState *s1, const char *filename)
2203−{
2204− int i, ret, phnum, shnum, file_type, file_offset, *sec_order;
2205− struct dyn_inf dyninf;
2206− ElfW(Phdr) *phdr;
2207− ElfW(Sym) *sym;
2208− Section *strsec, *interp, *dynamic, *dynstr;
2209−
2210− file_type = s1->output_type;
2211− s1->nb_errors = 0;
2212−
2213− /* if linking, also link in runtime libraries (libc, libgcc, etc.) */
2214− if (file_type != TCC_OUTPUT_OBJ) {
2215− tcc_add_runtime(s1);
2216− }
2217−
2218− phdr = NULL;
2219− sec_order = NULL;
2220− interp = dynamic = dynstr = NULL; /* avoid warning */
2221− dyninf.dyn_rel_off = 0; /* avoid warning */
2222−
2223− if (file_type != TCC_OUTPUT_OBJ) {
2224− relocate_common_syms();
2225−
2226− tcc_add_linker_symbols(s1);
2227−
2228− if (!s1->static_link) {
2229− if (file_type == TCC_OUTPUT_EXE) {
2230− char *ptr;
2231− /* allow override the dynamic loader */
2232− const char *elfint = getenv("LD_SO");
2233− if (elfint == NULL)
2234− elfint = DEFAULT_ELFINTERP(s1);
2235− /* add interpreter section only if executable */
2236− interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
2237− interp->sh_addralign = 1;
2238− ptr = section_ptr_add(interp, 1 + strlen(elfint));
2239− strcpy(ptr, elfint);
2240− }
2241−
2242− /* add dynamic symbol table */
2243− s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
2244− ".dynstr",
2245− ".hash", SHF_ALLOC);
2246− dynstr = s1->dynsym->link;
2247−
2248− /* add dynamic section */
2249− dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
2250− SHF_ALLOC | SHF_WRITE);
2251− dynamic->link = dynstr;
2252− dynamic->sh_entsize = sizeof(ElfW(Dyn));
2253−
2254− /* add PLT */
2255− s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
2256− SHF_ALLOC | SHF_EXECINSTR);
2257− s1->plt->sh_entsize = 4;
2258−
2259− build_got(s1);
2260−
2261− if (file_type == TCC_OUTPUT_EXE) {
2262− bind_exe_dynsyms(s1);
2263−
2264− if (s1->nb_errors) {
2265− ret = -1;
2266− goto the_end;
2178+ if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2179+ sort_syms(s1, symtab_section);
2180+
2181+ /* align to 4 */
2182+ file_offset = (file_offset + 3) & -4;
2183+
2184+ /* fill header */
2185+ ehdr.e_ident[0] = ELFMAG0;
2186+ ehdr.e_ident[1] = ELFMAG1;
2187+ ehdr.e_ident[2] = ELFMAG2;
2188+ ehdr.e_ident[3] = ELFMAG3;
2189+ ehdr.e_ident[4] = ELFCLASSW;
2190+ ehdr.e_ident[5] = ELFDATA2LSB;
2191+ ehdr.e_ident[6] = EV_CURRENT;
2192+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2193+ ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2194+#endif
2195+#ifdef TCC_TARGET_ARM
2196+#ifdef TCC_ARM_EABI
2197+ ehdr.e_ident[EI_OSABI] = 0;
2198+ ehdr.e_flags = EF_ARM_EABI_VER4;
2199+ if (file_type == TCC_OUTPUT_EXE || file_type == TCC_OUTPUT_DLL)
2200+ ehdr.e_flags |= EF_ARM_HASENTRY;
2201+ if (s1->float_abi == ARM_HARD_FLOAT)
2202+ ehdr.e_flags |= EF_ARM_VFP_FLOAT;
2203+ else
2204+ ehdr.e_flags |= EF_ARM_SOFT_FLOAT;
2205+#else
2206+ ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2207+#endif
2208+#endif
2209+ switch(file_type) {
2210+ default:
2211+ case TCC_OUTPUT_EXE:
2212+ ehdr.e_type = ET_EXEC;
2213+ break;
2214+ case TCC_OUTPUT_DLL:
2215+ ehdr.e_type = ET_DYN;
2216+ break;
2217+ case TCC_OUTPUT_OBJ:
2218+ ehdr.e_type = ET_REL;
2219+ break;
2220+ }
2221+ ehdr.e_machine = EM_TCC_TARGET;
2222+ ehdr.e_version = EV_CURRENT;
2223+ ehdr.e_shoff = file_offset;
2224+ ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2225+ ehdr.e_shentsize = sizeof(ElfW(Shdr));
2226+ ehdr.e_shnum = shnum;
2227+ ehdr.e_shstrndx = shnum - 1;
2228+
2229+ fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2230+ fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2231+ offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2232+
2233+ for(i=1;i<s1->nb_sections;i++) {
2234+ s = s1->sections[section_order[i]];
2235+ if (s->sh_type != SHT_NOBITS) {
2236+ if (s->sh_type == SHT_DYNSYM)
2237+ patch_dynsym_undef(s1, s);
2238+ while (offset < s->sh_offset) {
2239+ fputc(0, f);
2240+ offset++;
22672241 }
2268−
2269− bind_libs_dynsyms(s1);
2270− } else /* shared library case: simply export all global symbols */
2271− export_global_syms(s1);
2272−
2273− build_got_entries(s1);
2274−
2275− /* add a list of needed dlls */
2276− for(i = 0; i < s1->nb_loaded_dlls; i++) {
2277− DLLReference *dllref = s1->loaded_dlls[i];
2278− if (dllref->level == 0)
2279− put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
2242+ size = s->sh_size;
2243+ fwrite(s->data, 1, size, f);
2244+ offset += size;
22802245 }
2281−
2282− if (s1->rpath)
2283− put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
2284−
2285− /* XXX: currently, since we do not handle PIC code, we
2286− must relocate the readonly segments */
2287− if (file_type == TCC_OUTPUT_DLL) {
2288− if (s1->soname)
2289− put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
2290− put_dt(dynamic, DT_TEXTREL, 0);
2291− }
2292−
2293− if (s1->symbolic)
2294− put_dt(dynamic, DT_SYMBOLIC, 0);
2295−
2296− /* add necessary space for other entries */
2297− dyninf.dyn_rel_off = dynamic->data_offset;
2298− dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
2299− } else {
2300− /* still need to build got entries in case of static link */
2301− build_got_entries(s1);
23022246 }
2303− }
23042247
2305− /* we add a section for symbols */
2306− strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
2307− put_elf_str(strsec, "");
2308−
2309− /* compute number of sections */
2310− shnum = s1->nb_sections;
2311−
2312− /* this array is used to reorder sections in the output file */
2313− sec_order = tcc_malloc(sizeof(int) * shnum);
2314− sec_order[0] = 0;
2315−
2316− /* compute number of program headers */
2317− switch(file_type) {
2318− default:
2319− case TCC_OUTPUT_OBJ:
2320− phnum = 0;
2321− break;
2322− case TCC_OUTPUT_EXE:
2323− if (!s1->static_link)
2324− phnum = 4 + HAVE_PHDR;
2325− else
2326− phnum = 2;
2327− break;
2328− case TCC_OUTPUT_DLL:
2329− phnum = 3;
2330− break;
2331− }
2332−
2333− /* Allocate strings for section names */
2334− alloc_sec_names(s1, file_type, strsec);
2335−
2336− /* allocate program segment headers */
2337− phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
2338−
2339− /* compute section to program header mapping */
2340− file_offset = layout_sections(s1, phdr, phnum, interp, &dyninf, sec_order);
2341−
2342− /* Fill remaining program header and finalize relocation related to dynamic
2343− linking. */
2344− if (phnum > 0) {
2345− fill_unloadable_phdr(phdr, phnum, interp, dynamic);
2346− if (dynamic) {
2347− dyninf.dynamic = dynamic;
2348− dyninf.dynstr = dynstr;
2349−
2350− fill_dynamic(s1, &dyninf);
2351−
2352− /* put in GOT the dynamic section address and relocate PLT */
2353− put32(s1->got->data, dynamic->sh_addr);
2354− if (file_type == TCC_OUTPUT_EXE
2355−#if defined(TCC_OUTPUT_DLL_WITH_PLT)
2356− || file_type == TCC_OUTPUT_DLL
2357−#endif
2358− )
2359− relocate_plt(s1);
2248+ /* output section headers */
2249+ while (offset < ehdr.e_shoff) {
2250+ fputc(0, f);
2251+ offset++;
2252+ }
23602253
2361− /* relocate symbols in .dynsym now that final addresses are known */
2362− for_each_elem(s1->dynsym, 1, sym, ElfW(Sym)) {
2363− /* relocate to PLT if symbol corresponds to a PLT entry */
2364− if (sym->st_shndx == SHN_UNDEF) {
2365− if (sym->st_value)
2366− sym->st_value += s1->plt->sh_addr;
2367− } else if (sym->st_shndx < SHN_LORESERVE) {
2368− /* do symbol relocation */
2369− sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
2370− }
2254+ for(i=0;i<s1->nb_sections;i++) {
2255+ sh = &shdr;
2256+ memset(sh, 0, sizeof(ElfW(Shdr)));
2257+ s = s1->sections[i];
2258+ if (s) {
2259+ sh->sh_name = s->sh_name;
2260+ sh->sh_type = s->sh_type;
2261+ sh->sh_flags = s->sh_flags;
2262+ sh->sh_entsize = s->sh_entsize;
2263+ sh->sh_info = s->sh_info;
2264+ if (s->link)
2265+ sh->sh_link = s->link->sh_num;
2266+ sh->sh_addralign = s->sh_addralign;
2267+ sh->sh_addr = s->sh_addr;
2268+ sh->sh_offset = s->sh_offset;
2269+ sh->sh_size = s->sh_size;
23712270 }
2271+ fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
23722272 }
2273+ } else {
2274+ tcc_output_binary(s1, f, section_order);
23732275 }
2276+ fclose(f);
23742277
2375− /* if building executable or DLL, then relocate each section
2376− except the GOT which is already relocated */
2377− if (file_type != TCC_OUTPUT_OBJ) {
2378− ret = final_sections_reloc(s1);
2379− if (ret)
2380− goto the_end;
2381− }
2382−
2383− /* Perform relocation to GOT or PLT entries */
2384− if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2385− fill_got(s1);
2386−
2387− /* Create the ELF file with name 'filename' */
2388− ret = tcc_write_elf_file(s1, filename, phnum, phdr, file_offset, sec_order);
2278+ ret = 0;
23892279 the_end:
23902280 tcc_free(s1->symtab_to_dynsym);
2391− tcc_free(sec_order);
2281+ tcc_free(section_order);
23922282 tcc_free(phdr);
23932283 tcc_free(s1->sym_attrs);
23942284 return ret;
@@ -2402,7 +2292,9 @@ LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename) · 7 unmodified lines
24022292 ret = pe_output_file(s, filename);
24032293 } else
24042294 #endif
2295+ {
24052296 ret = elf_output_file(s, filename);
2297+ }
24062298 return ret;
24072299 }
24082300
@@ -2687,8 +2579,8 @@ ST_FUNC int tcc_load_object_file(TCCState *s1, · 278 unmodified lines
26872579 handled by converting these instructions into blx
26882580 instructions. Other case of instructions referencing a PLT
26892581 entry require to add a Thumb stub before the PLT entry to
2690− switch to ARM mode. We set bit plt_thumb_stub of the
2691− attribute of a symbol to indicate such a case. */
2582+ switch to ARM mode. We set bit 0 of the got offset of a
2583+ symbol to indicate such a case. */
26922584 if (type == R_ARM_THM_JUMP24)
26932585 alloc_sym_attr(s1, sym_index)->plt_thumb_stub = 1;
26942586 #endif

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