History

Split elf_output_file in smaller functions

Thomas Preud'homme committed 12 years ago

Commit b5b82df1 parent 3cbc7a21 file · +659 −551Browse files

Unified · Split

tccelf.c+659−551
@@ -20,6 +20,7 @@ · 19 unmodified lines
2020
2121 #include "tcc.h"
2222
23+/* XXX: avoid static variable */
2324 static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */
2425
2526 ST_FUNC int put_elf_str(Section *s, const char *sym)
@@ -429,6 +430,7 @@ ST_FUNC void relocate_syms(TCCState *s1, int do_resolve) · 403 unmodified lines
429430 sh_num = sym->st_shndx;
430431 if (sh_num == SHN_UNDEF) {
431432 name = strtab_section->data + sym->st_name;
433+ /* Use ld.so to resolve symbol for us (for tcc -run) */
432434 if (do_resolve) {
433435 #if defined TCC_IS_NATIVE && !defined _WIN32
434436 void *addr;
@@ -504,7 +506,8 @@ static addr_t add_jmp_table(TCCState *s1, int val) · 69 unmodified lines
504506 #endif
505507 #endif /* def TCC_HAS_RUNTIME_PLTGOT */
506508
507−/* relocate a given section (CPU dependent) */
509+/* relocate a given section (CPU dependent) by applying the relocations
510+ in the associated relocation section */
508511 ST_FUNC void relocate_section(TCCState *s1, Section *s)
509512 {
510513 Section *sr;
@@ -1422,14 +1425,14 @@ ST_FUNC void tcc_add_linker_symbols(TCCState *s1) · 911 unmodified lines
14221425 }
14231426
14241427 static void tcc_output_binary(TCCState *s1, FILE *f,
1425− const int *section_order)
1428+ const int *sec_order)
14261429 {
14271430 Section *s;
14281431 int i, offset, size;
14291432
14301433 offset = 0;
14311434 for(i=1;i<s1->nb_sections;i++) {
1432− s = s1->sections[section_order[i]];
1435+ s = s1->sections[sec_order[i]];
14331436 if (s->sh_type != SHT_NOBITS &&
14341437 (s->sh_flags & SHF_ALLOC)) {
14351438 while (offset < s->sh_offset) {
@@ -1494,6 +1497,7 @@ ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel) · 58 unmodified lines
14941497 put32(s1->got->data + offset, sym->st_value & 0xffffffff);
14951498 }
14961499
1500+/* Perform relocation to GOT or PLT entries */
14971501 ST_FUNC void fill_got(TCCState *s1)
14981502 {
14991503 Section *s;
@@ -1509,301 +1513,213 @@ ST_FUNC void fill_got(TCCState *s1) · 9 unmodified lines
15091513 continue;
15101514 for_each_elem(s, 0, rel, ElfW_Rel) {
15111515 switch (ELFW(R_TYPE) (rel->r_info)) {
1516+#ifdef TCC_TARGET_X86_64
15121517 case R_X86_64_GOT32:
15131518 case R_X86_64_GOTPCREL:
15141519 case R_X86_64_PLT32:
15151520 fill_got_entry(s1, rel);
15161521 break;
1522+#endif
15171523 }
15181524 }
15191525 }
15201526 }
15211527
1522−
1523−/* output an ELF file */
1524−/* XXX: suppress unneeded sections */
1525−static int elf_output_file(TCCState *s1, const char *filename)
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)
15261532 {
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
1545−
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;
1533+ const char *name;
1534+ int sym_index, index;
1535+ ElfW(Sym) *sym, *esym;
1536+ int type;
16811537
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);
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;
17001579 }
17011580 }
17021581 }
1582+ put_elf_reloc(s1->dynsym, bss_section,
1583+ offset, R_COPY, index);
1584+ offset += esym->st_size;
1585+ bss_section->data_offset = offset;
17031586 }
17041587 } else {
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− }
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);
17371594 }
17381595 }
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+}
17391604
1740− build_got_entries(s1);
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;
17411612
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));
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);
17471629 }
1630+ }
1631+ }
1632+}
17481633
1749− if (s1->rpath)
1750− put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
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;
17511640
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);
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;
17581664 }
1759−
1760− if (s1->symbolic)
1761− put_dt(dynamic, DT_SYMBOLIC, 0);
1762−
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);
17691665 }
17701666 }
1667+}
17711668
1772− memset(&ehdr, 0, sizeof(ehdr));
1773−
1774− /* we add a section for symbols */
1775− strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1776− put_elf_str(strsec, "");
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;
17771674
1778− /* compute number of sections */
1779− shnum = s1->nb_sections;
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;
1704+ }
1705+#elif defined(TCC_TARGET_C67)
1706+ /* XXX: TODO */
1707+#else
1708+#error unsupported CPU
1709+#endif
1710+ }
1711+}
17801712
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;
1713+/* Allocate strings for section names and decide if an unallocated section
1714+ should be output.
17851715
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− }
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;
18021721
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 ! */
1722+ /* Allocate strings for section names */
18071723 for(i = 1; i < s1->nb_sections; i++) {
18081724 s = s1->sections[i];
18091725 s->sh_name = put_elf_str(strsec, s->name);
@@ -1825,17 +1741,41 @@ static int elf_output_file(TCCState *s1, const char *filename) · 15 unmodified lines
18251741 s->sh_size = s->data_offset;
18261742 }
18271743 }
1744+}
18281745
1829− /* allocate program segment headers */
1830− phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
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+};
1758+
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;
18311770
1832− if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1771+ file_type = s1->output_type;
1772+ sh_order_index = 1;
1773+ if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
18331774 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1834− } else {
1775+ else
18351776 file_offset = 0;
1836− }
1777+
18371778 if (phnum > 0) {
1838− /* compute section to program header mapping */
18391779 if (s1->has_text_addr) {
18401780 int a_offset, p_offset;
18411781 addr = s1->text_addr;
@@ -1855,18 +1795,19 @@ static int elf_output_file(TCCState *s1, const char *filename) · 13 unmodified lines
18551795 addr += (file_offset & (s1->section_align - 1));
18561796 }
18571797
1858− /* dynamic relocation table information, for .dynamic section */
1859− rel_size = 0;
1860− rel_addr = 0;
1861−
1862−#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1863− bss_addr = bss_size = 0;
1864−#endif
1865− /* leave one program header for the program interpreter */
18661798 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. */
18671802 if (interp)
18681803 ph += 1 + HAVE_PHDR;
18691804
1805+ /* dynamic relocation table information, for .dynamic section */
1806+ dyninf->rel_addr = dyninf->rel_size = 0;
1807+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1808+ dyninf->bss_addr = dyninf->bss_size = 0;
1809+#endif
1810+
18701811 for(j = 0; j < 2; j++) {
18711812 ph->p_type = PT_LOAD;
18721813 if (j == 0)
@@ -1875,8 +1816,10 @@ static int elf_output_file(TCCState *s1, const char *filename) · 2 unmodified lines
18751816 ph->p_flags = PF_R | PF_W;
18761817 ph->p_align = s1->section_align;
18771818
1878− /* we do the following ordering: interp, symbol tables,
1879− relocations, progbits, nobits */
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 */
18801823 /* XXX: do faster and simpler sorting */
18811824 for(k = 0; k < 5; k++) {
18821825 for(i = 1; i < s1->nb_sections; i++) {
@@ -1909,7 +1852,7 @@ static int elf_output_file(TCCState *s1, const char *filename) · 26 unmodified lines
19091852 if (k != 3)
19101853 continue;
19111854 }
1912− section_order[sh_order_index++] = i;
1855+ sec_order[sh_order_index++] = i;
19131856
19141857 /* section matches: we align it and add its size */
19151858 tmp = addr;
@@ -1929,17 +1872,17 @@ static int elf_output_file(TCCState *s1, const char *filename) · 13 unmodified lines
19291872 if (s->sh_type == SHT_RELX) {
19301873 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
19311874 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) {
1932− rel_addr = addr;
1933− rel_size += s->sh_size; /* XXX only first rel. */
1875+ dyninf->rel_addr = addr;
1876+ dyninf->rel_size += s->sh_size; /* XXX only first rel. */
19341877 }
19351878 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) {
1936− bss_addr = addr;
1937− bss_size = s->sh_size; /* XXX only first rel. */
1879+ dyninf->bss_addr = addr;
1880+ dyninf->bss_size = s->sh_size; /* XXX only first rel. */
19381881 }
19391882 #else
1940− if (rel_size == 0)
1941− rel_addr = addr;
1942− rel_size += s->sh_size;
1883+ if (dyninf->rel_size == 0)
1884+ dyninf->rel_addr = addr;
1885+ dyninf->rel_size += s->sh_size;
19431886 #endif
19441887 }
19451888 addr += s->sh_size;
@@ -1963,199 +1906,269 @@ static int elf_output_file(TCCState *s1, const char *filename) · 17 unmodified lines
19631906 }
19641907 }
19651908 }
1909+ }
19661910
1967− /* if interpreter, then add corresponing program header */
1968− if (interp) {
1969− ph = &phdr[0];
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;
19701917
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
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+ }
19851924
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− }
1925+ return file_offset;
1926+}
19951927
1996− /* if dynamic section, then add corresponing program header */
1997− if (dynamic) {
1998− ph = &phdr[phnum - 1];
1928+static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp,
1929+ Section *dynamic)
1930+{
1931+ ElfW(Phdr) *ph;
1932+
1933+ /* if interpreter, then add corresponding program header */
1934+ if (interp) {
1935+ ph = &phdr[0];
19991936
2000− ph->p_type = PT_DYNAMIC;
2001− ph->p_offset = dynamic->sh_offset;
2002− ph->p_vaddr = dynamic->sh_addr;
1937+ if (HAVE_PHDR)
1938+ {
1939+ int len = phnum * sizeof(ElfW(Phdr));
1940+
1941+ ph->p_type = PT_PHDR;
1942+ ph->p_offset = sizeof(ElfW(Ehdr));
1943+ ph->p_vaddr = interp->sh_addr - len;
20031944 ph->p_paddr = ph->p_vaddr;
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;
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+ }
20081950
2009− /* put GOT dynamic section address */
2010− put32(s1->got->data, dynamic->sh_addr);
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+ }
20111960
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;
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+}
20191975
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− }
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;
20571981
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− }
1982+ dynamic = dyninf->dynamic;
20701983
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)));
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)));
20781991 #ifdef TCC_TARGET_X86_64
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));
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));
20821995 #else
20831996 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
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);
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);
20902003 #else
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));
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));
20942007 #endif
20952008 #endif
2096− if (s1->do_debug)
2097− put_dt(dynamic, DT_DEBUG, 0);
2098− put_dt(dynamic, DT_NULL, 0);
2099− }
2009+ if (s1->do_debug)
2010+ put_dt(dynamic, DT_DEBUG, 0);
2011+ put_dt(dynamic, DT_NULL, 0);
2012+}
21002013
2101− ehdr.e_phentsize = sizeof(ElfW(Phdr));
2102− ehdr.e_phnum = phnum;
2103− ehdr.e_phoff = sizeof(ElfW(Ehdr));
2104− }
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;
21052020
2106− /* all other sections come after */
2021+ relocate_syms(s1, 0);
2022+
2023+ if (s1->nb_errors != 0)
2024+ return -1;
2025+
2026+ /* relocate sections */
2027+ /* XXX: ignore sections with allocated relocations ? */
21072028 for(i = 1; i < s1->nb_sections; i++) {
21082029 s = s1->sections[i];
2109− if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2110− continue;
2111− section_order[sh_order_index++] = i;
2030+ if (s->reloc && s != s1->got)
2031+ relocate_section(s1, s);
2032+ }
21122033
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;
2034+ /* relocate relocation entries if the relocation tables are
2035+ allocated in the executable */
2036+ for(i = 1; i < s1->nb_sections; i++) {
2037+ s = s1->sections[i];
2038+ if ((s->sh_flags & SHF_ALLOC) &&
2039+ s->sh_type == SHT_RELX) {
2040+ relocate_rel(s1, s);
2041+ }
21182042 }
2043+ return 0;
2044+}
21192045
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);
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;
21242055
2125− if (s1->nb_errors != 0) {
2126− fail:
2127− ret = -1;
2128− goto the_end;
2129− }
2056+ file_type = s1->output_type;
2057+ shnum = s1->nb_sections;
21302058
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− }
2059+ memset(&ehdr, 0, sizeof(ehdr));
2060+
2061+ if (phnum > 0) {
2062+ ehdr.e_phentsize = sizeof(ElfW(Phdr));
2063+ ehdr.e_phnum = phnum;
2064+ ehdr.e_phoff = sizeof(ElfW(Ehdr));
2065+ }
21382066
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);
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++;
21462130 }
2131+ size = s->sh_size;
2132+ fwrite(s->data, 1, size, f);
2133+ offset += size;
21472134 }
2135+ }
21482136
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 ? */
2137+ /* output section headers */
2138+ while (offset < ehdr.e_shoff) {
2139+ fputc(0, f);
2140+ offset++;
21542141 }
2155− if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2156− fill_got(s1);
21572142
2158− /* write elf file */
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);
2161+ }
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;
2170+
2171+ file_type = s1->output_type;
21592172 if (file_type == TCC_OUTPUT_OBJ)
21602173 mode = 0666;
21612174 else
@@ -2164,121 +2177,218 @@ static int elf_output_file(TCCState *s1, const char *filename) · 2 unmodified lines
21642177 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
21652178 if (fd < 0) {
21662179 tcc_error_noabort("could not write '%s'", filename);
2167− goto fail;
2180+ return -1;
21682181 }
21692182 f = fdopen(fd, "wb");
21702183 if (s1->verbose)
21712184 printf("<- %s\n", filename);
21722185
21732186 #ifdef TCC_TARGET_COFF
2174− if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2187+ if (s1->output_format == TCC_OUTPUT_FORMAT_COFF)
21752188 tcc_output_coff(s1, f);
2176− } else
2177−#endif
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
2189+ else
22082190 #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++;
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;
22412267 }
2242− size = s->sh_size;
2243− fwrite(s->data, 1, size, f);
2244− offset += size;
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));
22452280 }
2246− }
22472281
2248− /* output section headers */
2249− while (offset < ehdr.e_shoff) {
2250− fputc(0, f);
2251− offset++;
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);
22522302 }
2303+ }
22532304
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;
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);
2360+
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+ }
22702371 }
2271− fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
22722372 }
2273− } else {
2274− tcc_output_binary(s1, f, section_order);
22752373 }
2276− fclose(f);
22772374
2278− ret = 0;
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);
22792389 the_end:
22802390 tcc_free(s1->symtab_to_dynsym);
2281− tcc_free(section_order);
2391+ tcc_free(sec_order);
22822392 tcc_free(phdr);
22832393 tcc_free(s1->sym_attrs);
22842394 return ret;
@@ -2292,9 +2402,7 @@ LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename) · 7 unmodified lines
22922402 ret = pe_output_file(s, filename);
22932403 } else
22942404 #endif
2295− {
22962405 ret = elf_output_file(s, filename);
2297− }
22982406 return ret;
22992407 }
23002408
@@ -2579,8 +2687,8 @@ ST_FUNC int tcc_load_object_file(TCCState *s1, · 278 unmodified lines
25792687 handled by converting these instructions into blx
25802688 instructions. Other case of instructions referencing a PLT
25812689 entry require to add a Thumb stub before the PLT entry to
2582− switch to ARM mode. We set bit 0 of the got offset of a
2583− symbol to indicate such a case. */
2690+ switch to ARM mode. We set bit plt_thumb_stub of the
2691+ attribute of a symbol to indicate such a case. */
25842692 if (type == R_ARM_THM_JUMP24)
25852693 alloc_sym_attr(s1, sym_index)->plt_thumb_stub = 1;
25862694 #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