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
20 20
21#include "tcc.h"21#include "tcc.h"
22 22
23/* XXX: avoid static variable */
24static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */23static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */
25 24
26ST_FUNC int put_elf_str(Section *s, const char *sym)25ST_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
430 sh_num = sym->st_shndx;429 sh_num = sym->st_shndx;
431 if (sh_num == SHN_UNDEF) {430 if (sh_num == SHN_UNDEF) {
432 name = strtab_section->data + sym->st_name;431 name = strtab_section->data + sym->st_name;
433 /* Use ld.so to resolve symbol for us (for tcc -run) */
434 if (do_resolve) {432 if (do_resolve) {
435#if defined TCC_IS_NATIVE && !defined _WIN32433#if defined TCC_IS_NATIVE && !defined _WIN32
436 void *addr;434 void *addr;
@@ -506,8 +504,7 @@ static addr_t add_jmp_table(TCCState *s1, int val) · 69 unmodified lines
506#endif504#endif
507#endif /* def TCC_HAS_RUNTIME_PLTGOT */505#endif /* def TCC_HAS_RUNTIME_PLTGOT */
508 506
509/* relocate a given section (CPU dependent) by applying the relocations507/* relocate a given section (CPU dependent) */
510 in the associated relocation section */
511ST_FUNC void relocate_section(TCCState *s1, Section *s)508ST_FUNC void relocate_section(TCCState *s1, Section *s)
512{509{
513 Section *sr;510 Section *sr;
@@ -1425,14 +1422,14 @@ ST_FUNC void tcc_add_linker_symbols(TCCState *s1) · 911 unmodified lines
1425}1422}
1426 1423
1427static void tcc_output_binary(TCCState *s1, FILE *f,1424static void tcc_output_binary(TCCState *s1, FILE *f,
1428 const int *sec_order)1425 const int *section_order)
1429{1426{
1430 Section *s;1427 Section *s;
1431 int i, offset, size;1428 int i, offset, size;
1432 1429
1433 offset = 0;1430 offset = 0;
1434 for(i=1;i<s1->nb_sections;i++) {1431 for(i=1;i<s1->nb_sections;i++) {
1435 s = s1->sections[sec_order[i]];1432 s = s1->sections[section_order[i]];
1436 if (s->sh_type != SHT_NOBITS &&1433 if (s->sh_type != SHT_NOBITS &&
1437 (s->sh_flags & SHF_ALLOC)) {1434 (s->sh_flags & SHF_ALLOC)) {
1438 while (offset < s->sh_offset) {1435 while (offset < s->sh_offset) {
@@ -1497,7 +1494,6 @@ ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel) · 58 unmodified lines
1497 put32(s1->got->data + offset, sym->st_value & 0xffffffff);1494 put32(s1->got->data + offset, sym->st_value & 0xffffffff);
1498}1495}
1499 1496
1500/* Perform relocation to GOT or PLT entries */
1501ST_FUNC void fill_got(TCCState *s1)1497ST_FUNC void fill_got(TCCState *s1)
1502{1498{
1503 Section *s;1499 Section *s;
@@ -1513,213 +1509,301 @@ ST_FUNC void fill_got(TCCState *s1) · 9 unmodified lines
1513 continue;1509 continue;
1514 for_each_elem(s, 0, rel, ElfW_Rel) {1510 for_each_elem(s, 0, rel, ElfW_Rel) {
1515 switch (ELFW(R_TYPE) (rel->r_info)) {1511 switch (ELFW(R_TYPE) (rel->r_info)) {
1516#ifdef TCC_TARGET_X86_64
1517 case R_X86_64_GOT32:1512 case R_X86_64_GOT32:
1518 case R_X86_64_GOTPCREL:1513 case R_X86_64_GOTPCREL:
1519 case R_X86_64_PLT32:1514 case R_X86_64_PLT32:
1520 fill_got_entry(s1, rel);1515 fill_got_entry(s1, rel);
1521 break;1516 break;
1522#endif
1523 }1517 }
1524 }1518 }
1525 }1519 }
1526}1520}
1527 1521
1528/* Bind symbols of executable: resolve undefined symbols from exported symbols1522
1529 in shared libraries and export non local defined symbols to shared libraries1523/* output an ELF file */
1530 if -rdynamic switch was given on command line */1524/* XXX: suppress unneeded sections */
1531static void bind_exe_dynsyms(TCCState *s1)1525static int elf_output_file(TCCState *s1, const char *filename)
1532{1526{
1533 const char *name;1527 ElfW(Ehdr) ehdr;
1534 int sym_index, index;1528 FILE *f;
1535 ElfW(Sym) *sym, *esym;1529 int fd, mode, ret;
1536 int type;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
1537 1545
1538 /* Resolve undefined symbols from dynamic symbols. When there is a match:1546 file_type = s1->output_type;
1539 - if STT_FUNC or STT_GNU_IFUNC symbol -> add it in PLT1547 s1->nb_errors = 0;
1540 - if STT_OBJECT symbol -> add it in .bss section with suitable reloc */1548
1541 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {1549 if (file_type != TCC_OUTPUT_OBJ) {
1542 if (sym->st_shndx == SHN_UNDEF) {1550 tcc_add_runtime(s1);
1543 name = symtab_section->link->data + sym->st_name;1551 }
1544 sym_index = find_elf_sym(s1->dynsymtab_section, name);1552
1545 if (sym_index) {1553 phdr = NULL;
1546 esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];1554 section_order = NULL;
1547 type = ELFW(ST_TYPE)(esym->st_info);1555 interp = NULL;
1548 if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {1556 dynamic = NULL;
1549 /* Indirect functions shall have STT_FUNC type in executable1557 dynstr = NULL; /* avoid warning */
1550 * dynsym section. Indeed, a dlsym call following a lazy1558 saved_dynamic_data_offset = 0; /* avoid warning */
1551 * resolution would pick the symbol value from the1559
1552 * executable dynsym entry which would contain the address1560 if (file_type != TCC_OUTPUT_OBJ) {
1553 * of the function wanted by the caller of dlsym instead of1561 relocate_common_syms();
1554 * the address of the function that would return that1562
1555 * address */1563 tcc_add_linker_symbols(s1);
1556 put_got_entry(s1, R_JMP_SLOT, esym->st_size,1564
1557 ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC),1565 if (!s1->static_link) {
1558 sym - (ElfW(Sym) *)symtab_section->data);1566 const char *name;
1559 } else if (type == STT_OBJECT) {1567 int sym_index, index;
1560 unsigned long offset;1568 ElfW(Sym) *esym;
1561 ElfW(Sym) *dynsym;1569
1562 offset = bss_section->data_offset;1570 if (file_type == TCC_OUTPUT_EXE) {
1563 /* XXX: which alignment ? */1571 char *ptr;
1564 offset = (offset + 16 - 1) & -16;1572 /* allow override the dynamic loader */
1565 index = put_elf_sym(s1->dynsym, offset, esym->st_size,1573 const char *elfint = getenv("LD_SO");
1566 esym->st_info, 0, bss_section->sh_num,1574 if (elfint == NULL)
1567 name);1575 elfint = DEFAULT_ELFINTERP(s1);
1568 /* Ensure R_COPY works for weak symbol aliases */1576 /* add interpreter section only if executable */
1569 if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {1577 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1570 for_each_elem(s1->dynsymtab_section, 1, dynsym, ElfW(Sym)) {1578 interp->sh_addralign = 1;
1571 if ((dynsym->st_value == esym->st_value)1579 ptr = section_ptr_add(interp, 1+strlen(elfint));
1572 && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {1580 strcpy(ptr, elfint);
1573 char *dynname = s1->dynsymtab_section->link->data1581 }
1574 + dynsym->st_name;1582
1575 put_elf_sym(s1->dynsym, offset, dynsym->st_size,1583 /* add dynamic symbol table */
1576 dynsym->st_info, 0,1584 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1577 bss_section->sh_num, dynname);1585 ".dynstr",
1578 break;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);
1579 }1700 }
1580 }1701 }
1581 }1702 }
1582 put_elf_reloc(s1->dynsym, bss_section,
1583 offset, R_COPY, index);
1584 offset += esym->st_size;
1585 bss_section->data_offset = offset;
1586 }1703 }
1587 } else {1704 } else {
1588 /* STB_WEAK undefined symbols are accepted */1705 int nb_syms;
1589 /* XXX: _fp_hw seems to be part of the ABI, so we ignore it */1706 /* shared library case : we simply export all the global symbols */
1590 if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||1707 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1591 !strcmp(name, "_fp_hw")) {1708 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1592 } else {1709 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
1593 tcc_error_noabort("undefined symbol '%s'", name);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 }
1594 }1737 }
1595 }1738 }
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}
1604 1739
1605/* Bind symbols of libraries: export non local symbols of executable that1740 build_got_entries(s1);
1606 resolve undefined symbols of shared libraries */
1607static void bind_libs_dynsyms(TCCState *s1)
1608{
1609 const char *name;
1610 int sym_index;
1611 ElfW(Sym) *sym, *esym;
1612 1741
1613 /* now look at unresolved dynamic symbols and export1742 /* add a list of needed dlls */
1614 corresponding symbol */1743 for(i = 0; i < s1->nb_loaded_dlls; i++) {
1615 for_each_elem(s1->dynsymtab_section, 1, esym, ElfW(Sym)) {1744 DLLReference *dllref = s1->loaded_dlls[i];
1616 if (esym->st_shndx == SHN_UNDEF) {1745 if (dllref->level == 0)
1617 name = s1->dynsymtab_section->link->data + esym->st_name;1746 put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->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);
1629 }1747 }
1630 }
1631 }
1632}
1633 1748
1634/* Export all non local symbols (for shared libraries) */1749 if (s1->rpath)
1635static void export_global_syms(TCCState *s1)1750 put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1636{
1637 int nb_syms, dynindex, index;
1638 const char *name;
1639 ElfW(Sym) *sym;
1640 1751
1641 nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));1752 /* XXX: currently, since we do not handle PIC code, we
1642 s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);1753 must relocate the readonly segments */
1643 for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {1754 if (file_type == TCC_OUTPUT_DLL) {
1644 if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {1755 if (s1->soname)
1645#if defined(TCC_OUTPUT_DLL_WITH_PLT)1756 put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1646 int type = ELFW(ST_TYPE)(sym->st_info);1757 put_dt(dynamic, DT_TEXTREL, 0);
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;
1664 }1758 }
1665 }
1666 }
1667}
1668 1759
1669/* relocate the PLT: compute addresses and offsets in the PLT now that final1760 if (s1->symbolic)
1670 address for PLT and GOT are known (see fill_program_header) */1761 put_dt(dynamic, DT_SYMBOLIC, 0);
1671static void relocate_plt(TCCState *s1)
1672{
1673 uint8_t *p, *p_end;
1674 1762
1675 p = s1->plt->data;1763 /* add necessary space for other entries */
1676 p_end = p + s1->plt->data_offset;1764 saved_dynamic_data_offset = dynamic->data_offset;
1677 if (p < p_end) {1765 dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1678#if defined(TCC_TARGET_I386)1766 } else {
1679 put32(p + 2, get32(p + 2) + s1->got->sh_addr);1767 /* still need to build got entries in case of static link */
1680 put32(p + 8, get32(p + 8) + s1->got->sh_addr);1768 build_got_entries(s1);
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 }1769 }
1705#elif defined(TCC_TARGET_C67)
1706 /* XXX: TODO */
1707#else
1708#error unsupported CPU
1709#endif
1710 }1770 }
1711}
1712 1771
1713/* Allocate strings for section names and decide if an unallocated section1772 memset(&ehdr, 0, sizeof(ehdr));
1714 should be output.
1715 1773
1716 NOTE: the strsec section comes last, so its size is also correct ! */1774 /* we add a section for symbols */
1717static void alloc_sec_names(TCCState *s1, int file_type, Section *strsec)1775 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1718{1776 put_elf_str(strsec, "");
1719 int i;1777
1720 Section *s;1778 /* compute number of sections */
1779 shnum = s1->nb_sections;
1721 1780
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 ! */
1723 for(i = 1; i < s1->nb_sections; i++) {1807 for(i = 1; i < s1->nb_sections; i++) {
1724 s = s1->sections[i];1808 s = s1->sections[i];
1725 s->sh_name = put_elf_str(strsec, s->name);1809 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
1741 s->sh_size = s->data_offset;1825 s->sh_size = s->data_offset;
1742 }1826 }
1743 }1827 }
1744}
1745
1746/* Info to be copied in dynamic section */
1747struct 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 1828
1759/* Assign sections to segments and decide how are sections laid out when loaded1829 /* allocate program segment headers */
1760 in memory. This function also fills corresponding program headers. */1830 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1761static 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;
1770 1831
1771 file_type = s1->output_type;1832 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1772 sh_order_index = 1;
1773 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
1774 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));1833 file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1775 else1834 } else {
1776 file_offset = 0;1835 file_offset = 0;
1777 1836 }
1778 if (phnum > 0) {1837 if (phnum > 0) {
1838 /* compute section to program header mapping */
1779 if (s1->has_text_addr) {1839 if (s1->has_text_addr) {
1780 int a_offset, p_offset;1840 int a_offset, p_offset;
1781 addr = s1->text_addr;1841 addr = s1->text_addr;
@@ -1795,18 +1855,17 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, · 13 unmodified lines
1795 addr += (file_offset & (s1->section_align - 1));1855 addr += (file_offset & (s1->section_align - 1));
1796 }1856 }
1797 1857
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
1805 /* dynamic relocation table information, for .dynamic section */1858 /* dynamic relocation table information, for .dynamic section */
1806 dyninf->rel_addr = dyninf->rel_size = 0;1859 rel_size = 0;
1860 rel_addr = 0;
1861
1807#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)1862#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1808 dyninf->bss_addr = dyninf->bss_size = 0;1863 bss_addr = bss_size = 0;
1809#endif1864#endif
1865 /* leave one program header for the program interpreter */
1866 ph = &phdr[0];
1867 if (interp)
1868 ph += 1 + HAVE_PHDR;
1810 1869
1811 for(j = 0; j < 2; j++) {1870 for(j = 0; j < 2; j++) {
1812 ph->p_type = PT_LOAD;1871 ph->p_type = PT_LOAD;
@@ -1816,10 +1875,8 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, · 3 unmodified lines
1816 ph->p_flags = PF_R | PF_W;1875 ph->p_flags = PF_R | PF_W;
1817 ph->p_align = s1->section_align;1876 ph->p_align = s1->section_align;
1818 1877
1819 /* Decide the layout of sections loaded in memory. This must1878 /* we do the following ordering: interp, symbol tables,
1820 be done before program headers are filled since they contain1879 relocations, progbits, nobits */
1821 info about the layout. We do the following ordering: interp,
1822 symbol tables, relocations, progbits, nobits */
1823 /* XXX: do faster and simpler sorting */1880 /* XXX: do faster and simpler sorting */
1824 for(k = 0; k < 5; k++) {1881 for(k = 0; k < 5; k++) {
1825 for(i = 1; i < s1->nb_sections; i++) {1882 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
1852 if (k != 3)1909 if (k != 3)
1853 continue;1910 continue;
1854 }1911 }
1855 sec_order[sh_order_index++] = i;1912 section_order[sh_order_index++] = i;
1856 1913
1857 /* section matches: we align it and add its size */1914 /* section matches: we align it and add its size */
1858 tmp = addr;1915 tmp = addr;
@@ -1872,17 +1929,17 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, · 13 unmodified lines
1872 if (s->sh_type == SHT_RELX) {1929 if (s->sh_type == SHT_RELX) {
1873#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)1930#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1874 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) {1931 if (!strcmp(strsec->data + s->sh_name, ".rel.got")) {
1875 dyninf->rel_addr = addr;1932 rel_addr = addr;
1876 dyninf->rel_size += s->sh_size; /* XXX only first rel. */1933 rel_size += s->sh_size; /* XXX only first rel. */
1877 }1934 }
1878 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) {1935 if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) {
1879 dyninf->bss_addr = addr;1936 bss_addr = addr;
1880 dyninf->bss_size = s->sh_size; /* XXX only first rel. */1937 bss_size = s->sh_size; /* XXX only first rel. */
1881 }1938 }
1882#else1939#else
1883 if (dyninf->rel_size == 0)1940 if (rel_size == 0)
1884 dyninf->rel_addr = addr;1941 rel_addr = addr;
1885 dyninf->rel_size += s->sh_size;1942 rel_size += s->sh_size;
1886#endif1943#endif
1887 }1944 }
1888 addr += s->sh_size;1945 addr += s->sh_size;
@@ -1906,269 +1963,199 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, · 17 unmodified lines
1906 }1963 }
1907 }1964 }
1908 }1965 }
1909 }
1910 1966
1911 /* all other sections come after */1967 /* if interpreter, then add corresponing program header */
1912 for(i = 1; i < s1->nb_sections; i++) {1968 if (interp) {
1913 s = s1->sections[i];1969 ph = &phdr[0];
1914 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
1915 continue;
1916 sec_order[sh_order_index++] = i;
1917 1970
1918 file_offset = (file_offset + s->sh_addralign - 1) &1971#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1919 ~(s->sh_addralign - 1);1972 {
1920 s->sh_offset = file_offset;1973 int len = phnum * sizeof(ElfW(Phdr));
1921 if (s->sh_type != SHT_NOBITS)1974
1922 file_offset += s->sh_size;1975 ph->p_type = PT_PHDR;
1923 }1976 ph->p_offset = sizeof(ElfW(Ehdr));
1924 1977 ph->p_vaddr = interp->sh_addr - len;
1925 return file_offset;1978 ph->p_paddr = ph->p_vaddr;
1926}1979 ph->p_filesz = ph->p_memsz = len;
1927 1980 ph->p_flags = PF_R | PF_X;
1928static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp,1981 ph->p_align = 4; /* interp->sh_addralign; */
1929 Section *dynamic)1982 ph++;
1930{1983 }
1931 ElfW(Phdr) *ph;1984#endif
1932 1985
1933 /* if interpreter, then add corresponding program header */1986 ph->p_type = PT_INTERP;
1934 if (interp) {1987 ph->p_offset = interp->sh_offset;
1935 ph = &phdr[0];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 }
1936 1995
1937 if (HAVE_PHDR)1996 /* if dynamic section, then add corresponing program header */
1938 {1997 if (dynamic) {
1939 int len = phnum * sizeof(ElfW(Phdr));1998 ph = &phdr[phnum - 1];
1940 1999
1941 ph->p_type = PT_PHDR;2000 ph->p_type = PT_DYNAMIC;
1942 ph->p_offset = sizeof(ElfW(Ehdr));2001 ph->p_offset = dynamic->sh_offset;
1943 ph->p_vaddr = interp->sh_addr - len;2002 ph->p_vaddr = dynamic->sh_addr;
1944 ph->p_paddr = ph->p_vaddr;2003 ph->p_paddr = ph->p_vaddr;
1945 ph->p_filesz = ph->p_memsz = len;2004 ph->p_filesz = dynamic->sh_size;
1946 ph->p_flags = PF_R | PF_X;2005 ph->p_memsz = dynamic->sh_size;
1947 ph->p_align = 4; /* interp->sh_addralign; */2006 ph->p_flags = PF_R | PF_W;
1948 ph++;2007 ph->p_align = dynamic->sh_addralign;
1949 }
1950 2008
1951 ph->p_type = PT_INTERP;2009 /* put GOT dynamic section address */
1952 ph->p_offset = interp->sh_offset;2010 put32(s1->got->data, dynamic->sh_addr);
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 }
1960 2011
1961 /* if dynamic section, then add corresponding program header */2012 /* relocate the PLT */
1962 if (dynamic) {2013 if (file_type == TCC_OUTPUT_EXE
1963 ph = &phdr[phnum - 1];2014#if defined(TCC_OUTPUT_DLL_WITH_PLT)
1964 2015 || file_type == TCC_OUTPUT_DLL
1965 ph->p_type = PT_DYNAMIC;2016#endif
1966 ph->p_offset = dynamic->sh_offset;2017 ) {
1967 ph->p_vaddr = dynamic->sh_addr;2018 uint8_t *p, *p_end;
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}
1975 2019
1976/* Fill the dynamic section with tags describing the address and size of2020 p = s1->plt->data;
1977 sections */2021 p_end = p + s1->plt->data_offset;
1978static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)2022 if (p < p_end) {
1979{2023#if defined(TCC_TARGET_I386)
1980 Section *dynamic;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 }
1981 2057
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 }
1983 2070
1984 /* put dynamic section entries */2071 /* put dynamic section entries */
1985 dynamic->data_offset = dyninf->dyn_rel_off;2072 dynamic->data_offset = saved_dynamic_data_offset;
1986 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);2073 put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
1987 put_dt(dynamic, DT_STRTAB, dyninf->dynstr->sh_addr);2074 put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
1988 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);2075 put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
1989 put_dt(dynamic, DT_STRSZ, dyninf->dynstr->data_offset);2076 put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
1990 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));2077 put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
1991#ifdef TCC_TARGET_X86_642078#ifdef TCC_TARGET_X86_64
1992 put_dt(dynamic, DT_RELA, dyninf->rel_addr);2079 put_dt(dynamic, DT_RELA, rel_addr);
1993 put_dt(dynamic, DT_RELASZ, dyninf->rel_size);2080 put_dt(dynamic, DT_RELASZ, rel_size);
1994 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));2081 put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
1995#else2082#else
1996#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)2083#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1997 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);2084 put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
1998 put_dt(dynamic, DT_PLTRELSZ, dyninf->rel_size);2085 put_dt(dynamic, DT_PLTRELSZ, rel_size);
1999 put_dt(dynamic, DT_JMPREL, dyninf->rel_addr);2086 put_dt(dynamic, DT_JMPREL, rel_addr);
2000 put_dt(dynamic, DT_PLTREL, DT_REL);2087 put_dt(dynamic, DT_PLTREL, DT_REL);
2001 put_dt(dynamic, DT_REL, dyninf->bss_addr);2088 put_dt(dynamic, DT_REL, bss_addr);
2002 put_dt(dynamic, DT_RELSZ, dyninf->bss_size);2089 put_dt(dynamic, DT_RELSZ, bss_size);
2003#else2090#else
2004 put_dt(dynamic, DT_REL, dyninf->rel_addr);2091 put_dt(dynamic, DT_REL, rel_addr);
2005 put_dt(dynamic, DT_RELSZ, dyninf->rel_size);2092 put_dt(dynamic, DT_RELSZ, rel_size);
2006 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));2093 put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2007#endif2094#endif
2008#endif2095#endif
2009 if (s1->do_debug)2096 if (s1->do_debug)
2010 put_dt(dynamic, DT_DEBUG, 0);2097 put_dt(dynamic, DT_DEBUG, 0);
2011 put_dt(dynamic, DT_NULL, 0);2098 put_dt(dynamic, DT_NULL, 0);
2012}2099 }
2013
2014/* Relocate remaining sections and symbols (that is those not related to
2015 dynamic linking) */
2016static 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;
2025 2100
2026 /* relocate sections */2101 ehdr.e_phentsize = sizeof(ElfW(Phdr));
2027 /* XXX: ignore sections with allocated relocations ? */2102 ehdr.e_phnum = phnum;
2028 for(i = 1; i < s1->nb_sections; i++) {2103 ehdr.e_phoff = sizeof(ElfW(Ehdr));
2029 s = s1->sections[i];
2030 if (s->reloc && s != s1->got)
2031 relocate_section(s1, s);
2032 }2104 }
2033 2105
2034 /* relocate relocation entries if the relocation tables are2106 /* all other sections come after */
2035 allocated in the executable */
2036 for(i = 1; i < s1->nb_sections; i++) {2107 for(i = 1; i < s1->nb_sections; i++) {
2037 s = s1->sections[i];2108 s = s1->sections[i];
2038 if ((s->sh_flags & SHF_ALLOC) &&2109 if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2039 s->sh_type == SHT_RELX) {2110 continue;
2040 relocate_rel(s1, s);2111 section_order[sh_order_index++] = i;
2041 }
2042 }
2043 return 0;
2044}
2045 2112
2046/* Create an ELF file on disk.2113 file_offset = (file_offset + s->sh_addralign - 1) &
2047 This function handle ELF specific layout requirements */2114 ~(s->sh_addralign - 1);
2048static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,2115 s->sh_offset = file_offset;
2049 int file_offset, int *sec_order)2116 if (s->sh_type != SHT_NOBITS)
2050{2117 file_offset += s->sh_size;
2051 int i, shnum, offset, size, file_type;2118 }
2052 Section *s;
2053 ElfW(Ehdr) ehdr;
2054 ElfW(Shdr) shdr, *sh;
2055 2119
2056 file_type = s1->output_type;2120 /* if building executable or DLL, then relocate each section
2057 shnum = s1->nb_sections;2121 except the GOT which is already relocated */
2122 if (file_type != TCC_OUTPUT_OBJ) {
2123 relocate_syms(s1, 0);
2058 2124
2059 memset(&ehdr, 0, sizeof(ehdr));2125 if (s1->nb_errors != 0) {
2126 fail:
2127 ret = -1;
2128 goto the_end;
2129 }
2060 2130
2061 if (phnum > 0) {2131 /* relocate sections */
2062 ehdr.e_phentsize = sizeof(ElfW(Phdr));2132 /* XXX: ignore sections with allocated relocations ? */
2063 ehdr.e_phnum = phnum;2133 for(i = 1; i < s1->nb_sections; i++) {
2064 ehdr.e_phoff = sizeof(ElfW(Ehdr));2134 s = s1->sections[i];
2065 }2135 if (s->reloc && s != s1->got)
2136 relocate_section(s1, s);
2137 }
2066 2138
2067 /* align to 4 */2139 /* relocate relocation entries if the relocation tables are
2068 file_offset = (file_offset + 3) & -4;2140 allocated in the executable */
2069 2141 for(i = 1; i < s1->nb_sections; i++) {
2070 /* fill header */2142 s = s1->sections[i];
2071 ehdr.e_ident[0] = ELFMAG0;2143 if ((s->sh_flags & SHF_ALLOC) &&
2072 ehdr.e_ident[1] = ELFMAG1;2144 s->sh_type == SHT_RELX) {
2073 ehdr.e_ident[2] = ELFMAG2;2145 relocate_rel(s1, s);
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++;
2130 }2146 }
2131 size = s->sh_size;
2132 fwrite(s->data, 1, size, f);
2133 offset += size;
2134 }2147 }
2135 }
2136
2137 /* output section headers */
2138 while (offset < ehdr.e_shoff) {
2139 fputc(0, f);
2140 offset++;
2141 }
2142 2148
2143 for(i = 0; i < s1->nb_sections; i++) {2149 /* get entry point address */
2144 sh = &shdr;2150 if (file_type == TCC_OUTPUT_EXE)
2145 memset(sh, 0, sizeof(ElfW(Shdr)));2151 ehdr.e_entry = get_elf_sym_addr(s1, "_start", 1);
2146 s = s1->sections[i];2152 else
2147 if (s) {2153 ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
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 }2154 }
2162}2155 if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2163 2156 fill_got(s1);
2164/* Write an elf, coff or "binary" file */
2165static 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 2157
2171 file_type = s1->output_type;2158 /* write elf file */
2172 if (file_type == TCC_OUTPUT_OBJ)2159 if (file_type == TCC_OUTPUT_OBJ)
2173 mode = 0666;2160 mode = 0666;
2174 else2161 else
@@ -2177,218 +2164,121 @@ static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum, · 2 unmodified lines
2177 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);2164 fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2178 if (fd < 0) {2165 if (fd < 0) {
2179 tcc_error_noabort("could not write '%s'", filename);2166 tcc_error_noabort("could not write '%s'", filename);
2180 return -1;2167 goto fail;
2181 }2168 }
2182 f = fdopen(fd, "wb");2169 f = fdopen(fd, "wb");
2183 if (s1->verbose)2170 if (s1->verbose)
2184 printf("<- %s\n", filename);2171 printf("<- %s\n", filename);
2185 2172
2186#ifdef TCC_TARGET_COFF2173#ifdef TCC_TARGET_COFF
2187 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF)2174 if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2188 tcc_output_coff(s1, f);2175 tcc_output_coff(s1, f);
2189 else2176 } else
2190#endif2177#endif
2191 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)2178 if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2192 tcc_output_elf(s1, f, phnum, phdr, file_offset, sec_order);2179 sort_syms(s1, symtab_section);
2193 else2180
2194 tcc_output_binary(s1, f, sec_order);2181 /* align to 4 */
2195 fclose(f);2182 file_offset = (file_offset + 3) & -4;
2196 2183
2197 return 0;2184 /* fill header */
2198}2185 ehdr.e_ident[0] = ELFMAG0;
2199 2186 ehdr.e_ident[1] = ELFMAG1;
2200/* Output an elf, coff or binary file */2187 ehdr.e_ident[2] = ELFMAG2;
2201/* XXX: suppress unneeded sections */2188 ehdr.e_ident[3] = ELFMAG3;
2202static int elf_output_file(TCCState *s1, const char *filename)2189 ehdr.e_ident[4] = ELFCLASSW;
2203{2190 ehdr.e_ident[5] = ELFDATA2LSB;
2204 int i, ret, phnum, shnum, file_type, file_offset, *sec_order;2191 ehdr.e_ident[6] = EV_CURRENT;
2205 struct dyn_inf dyninf;2192#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2206 ElfW(Phdr) *phdr;2193 ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2207 ElfW(Sym) *sym;2194#endif
2208 Section *strsec, *interp, *dynamic, *dynstr;2195#ifdef TCC_TARGET_ARM
2209 2196#ifdef TCC_ARM_EABI
2210 file_type = s1->output_type;2197 ehdr.e_ident[EI_OSABI] = 0;
2211 s1->nb_errors = 0;2198 ehdr.e_flags = EF_ARM_EABI_VER4;
2212 2199 if (file_type == TCC_OUTPUT_EXE || file_type == TCC_OUTPUT_DLL)
2213 /* if linking, also link in runtime libraries (libc, libgcc, etc.) */2200 ehdr.e_flags |= EF_ARM_HASENTRY;
2214 if (file_type != TCC_OUTPUT_OBJ) {2201 if (s1->float_abi == ARM_HARD_FLOAT)
2215 tcc_add_runtime(s1);2202 ehdr.e_flags |= EF_ARM_VFP_FLOAT;
2216 }2203 else
2217 2204 ehdr.e_flags |= EF_ARM_SOFT_FLOAT;
2218 phdr = NULL;2205#else
2219 sec_order = NULL;2206 ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2220 interp = dynamic = dynstr = NULL; /* avoid warning */2207#endif
2221 dyninf.dyn_rel_off = 0; /* avoid warning */2208#endif
2222 2209 switch(file_type) {
2223 if (file_type != TCC_OUTPUT_OBJ) {2210 default:
2224 relocate_common_syms();2211 case TCC_OUTPUT_EXE:
2225 2212 ehdr.e_type = ET_EXEC;
2226 tcc_add_linker_symbols(s1);2213 break;
2227 2214 case TCC_OUTPUT_DLL:
2228 if (!s1->static_link) {2215 ehdr.e_type = ET_DYN;
2229 if (file_type == TCC_OUTPUT_EXE) {2216 break;
2230 char *ptr;2217 case TCC_OUTPUT_OBJ:
2231 /* allow override the dynamic loader */2218 ehdr.e_type = ET_REL;
2232 const char *elfint = getenv("LD_SO");2219 break;
2233 if (elfint == NULL)2220 }
2234 elfint = DEFAULT_ELFINTERP(s1);2221 ehdr.e_machine = EM_TCC_TARGET;
2235 /* add interpreter section only if executable */2222 ehdr.e_version = EV_CURRENT;
2236 interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);2223 ehdr.e_shoff = file_offset;
2237 interp->sh_addralign = 1;2224 ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2238 ptr = section_ptr_add(interp, 1 + strlen(elfint));2225 ehdr.e_shentsize = sizeof(ElfW(Shdr));
2239 strcpy(ptr, elfint);2226 ehdr.e_shnum = shnum;
2240 }2227 ehdr.e_shstrndx = shnum - 1;
2241 2228
2242 /* add dynamic symbol table */2229 fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2243 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,2230 fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2244 ".dynstr",2231 offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2245 ".hash", SHF_ALLOC);2232
2246 dynstr = s1->dynsym->link;2233 for(i=1;i<s1->nb_sections;i++) {
2247 2234 s = s1->sections[section_order[i]];
2248 /* add dynamic section */2235 if (s->sh_type != SHT_NOBITS) {
2249 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,2236 if (s->sh_type == SHT_DYNSYM)
2250 SHF_ALLOC | SHF_WRITE);2237 patch_dynsym_undef(s1, s);
2251 dynamic->link = dynstr;2238 while (offset < s->sh_offset) {
2252 dynamic->sh_entsize = sizeof(ElfW(Dyn));2239 fputc(0, f);
2253 2240 offset++;
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;
2267 }2241 }
2268 2242 size = s->sh_size;
2269 bind_libs_dynsyms(s1);2243 fwrite(s->data, 1, size, f);
2270 } else /* shared library case: simply export all global symbols */2244 offset += size;
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));
2280 }2245 }
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);
2302 }2246 }
2303 }
2304 2247
2305 /* we add a section for symbols */2248 /* output section headers */
2306 strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);2249 while (offset < ehdr.e_shoff) {
2307 put_elf_str(strsec, "");2250 fputc(0, f);
2308 2251 offset++;
2309 /* compute number of sections */2252 }
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 2253
2361 /* relocate symbols in .dynsym now that final addresses are known */2254 for(i=0;i<s1->nb_sections;i++) {
2362 for_each_elem(s1->dynsym, 1, sym, ElfW(Sym)) {2255 sh = &shdr;
2363 /* relocate to PLT if symbol corresponds to a PLT entry */2256 memset(sh, 0, sizeof(ElfW(Shdr)));
2364 if (sym->st_shndx == SHN_UNDEF) {2257 s = s1->sections[i];
2365 if (sym->st_value)2258 if (s) {
2366 sym->st_value += s1->plt->sh_addr;2259 sh->sh_name = s->sh_name;
2367 } else if (sym->st_shndx < SHN_LORESERVE) {2260 sh->sh_type = s->sh_type;
2368 /* do symbol relocation */2261 sh->sh_flags = s->sh_flags;
2369 sym->st_value += s1->sections[sym->st_shndx]->sh_addr;2262 sh->sh_entsize = s->sh_entsize;
2370 }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;
2371 }2270 }
2271 fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2372 }2272 }
2273 } else {
2274 tcc_output_binary(s1, f, section_order);
2373 }2275 }
2276 fclose(f);
2374 2277
2375 /* if building executable or DLL, then relocate each section2278 ret = 0;
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);
2389 the_end:2279 the_end:
2390 tcc_free(s1->symtab_to_dynsym);2280 tcc_free(s1->symtab_to_dynsym);
2391 tcc_free(sec_order);2281 tcc_free(section_order);
2392 tcc_free(phdr);2282 tcc_free(phdr);
2393 tcc_free(s1->sym_attrs);2283 tcc_free(s1->sym_attrs);
2394 return ret;2284 return ret;
@@ -2402,7 +2292,9 @@ LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename) · 7 unmodified lines
2402 ret = pe_output_file(s, filename);2292 ret = pe_output_file(s, filename);
2403 } else2293 } else
2404#endif2294#endif
2295 {
2405 ret = elf_output_file(s, filename);2296 ret = elf_output_file(s, filename);
2297 }
2406 return ret;2298 return ret;
2407}2299}
2408 2300
@@ -2687,8 +2579,8 @@ ST_FUNC int tcc_load_object_file(TCCState *s1, · 278 unmodified lines
2687 handled by converting these instructions into blx2579 handled by converting these instructions into blx
2688 instructions. Other case of instructions referencing a PLT2580 instructions. Other case of instructions referencing a PLT
2689 entry require to add a Thumb stub before the PLT entry to2581 entry require to add a Thumb stub before the PLT entry to
2690 switch to ARM mode. We set bit plt_thumb_stub of the2582 switch to ARM mode. We set bit 0 of the got offset of a
2691 attribute of a symbol to indicate such a case. */2583 symbol to indicate such a case. */
2692 if (type == R_ARM_THM_JUMP24)2584 if (type == R_ARM_THM_JUMP24)
2693 alloc_sym_attr(s1, sym_index)->plt_thumb_stub = 1;2585 alloc_sym_attr(s1, sym_index)->plt_thumb_stub = 1;
2694#endif2586#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