Unified · Split
| @@ -955,8 +955,6 @@ static void add_init_array_defines(TCCState *s1, const char *section_name) · 954 unmodified lines | ||
| 955 | 955 | static void tcc_add_runtime(TCCState *s1) |
| 956 | 956 | { |
| 957 | 957 | char buf[1024]; |
| 958 | − int i; | |
| 959 | − Section *s; | |
| 960 | 958 | |
| 961 | 959 | if (!s1->nostdlib) { |
| 962 | 960 | snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "libtcc1.a"); |
| @@ -1000,7 +998,17 @@ static void tcc_add_runtime(TCCState *s1) · 37 unmodified lines | ||
| 1000 | 998 | if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) { |
| 1001 | 999 | tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o"); |
| 1002 | 1000 | } |
| 1003 | − /* add various standard linker symbols */ | |
| 1001 | +} | |
| 1002 | + | |
| 1003 | +/* add various standard linker symbols (must be done after the | |
| 1004 | + sections are filled (for example after allocating common | |
| 1005 | + symbols)) */ | |
| 1006 | +static void tcc_add_linker_symbols(TCCState *s1) | |
| 1007 | +{ | |
| 1008 | + char buf[1024]; | |
| 1009 | + int i; | |
| 1010 | + Section *s; | |
| 1011 | + | |
| 1004 | 1012 | add_elf_sym(symtab_section, |
| 1005 | 1013 | text_section->data_offset, 0, |
| 1006 | 1014 | ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), |
| @@ -1059,6 +1067,28 @@ static char elf_interp[] = "/usr/libexec/ld-elf.so.1"; · 52 unmodified lines | ||
| 1059 | 1067 | static char elf_interp[] = "/lib/ld-linux.so.2"; |
| 1060 | 1068 | #endif |
| 1061 | 1069 | |
| 1070 | +static void tcc_output_binary(TCCState *s1, FILE *f, | |
| 1071 | + const int *section_order) | |
| 1072 | +{ | |
| 1073 | + Section *s; | |
| 1074 | + int i, offset, size; | |
| 1075 | + | |
| 1076 | + offset = 0; | |
| 1077 | + for(i=1;i<s1->nb_sections;i++) { | |
| 1078 | + s = s1->sections[section_order[i]]; | |
| 1079 | + if (s->sh_type != SHT_NOBITS && | |
| 1080 | + (s->sh_flags & SHF_ALLOC)) { | |
| 1081 | + while (offset < s->sh_offset) { | |
| 1082 | + fputc(0, f); | |
| 1083 | + offset++; | |
| 1084 | + } | |
| 1085 | + size = s->sh_size; | |
| 1086 | + fwrite(s->data, 1, size, f); | |
| 1087 | + offset += size; | |
| 1088 | + } | |
| 1089 | + } | |
| 1090 | +} | |
| 1091 | + | |
| 1062 | 1092 | /* output an ELF file */ |
| 1063 | 1093 | /* XXX: suppress unneeded sections */ |
| 1064 | 1094 | int tcc_output_file(TCCState *s1, const char *filename) |
| @@ -1082,8 +1112,6 @@ int tcc_output_file(TCCState *s1, const char *filename) · 17 unmodified lines | ||
| 1082 | 1112 | s1->nb_errors = 0; |
| 1083 | 1113 | |
| 1084 | 1114 | if (file_type != TCC_OUTPUT_OBJ) { |
| 1085 | − relocate_common_syms(); | |
| 1086 | − | |
| 1087 | 1115 | tcc_add_runtime(s1); |
| 1088 | 1116 | } |
| 1089 | 1117 | |
| @@ -1095,6 +1123,9 @@ int tcc_output_file(TCCState *s1, const char *filename) · 5 unmodified lines | ||
| 1095 | 1123 | saved_dynamic_data_offset = 0; /* avoid warning */ |
| 1096 | 1124 | |
| 1097 | 1125 | if (file_type != TCC_OUTPUT_OBJ) { |
| 1126 | + relocate_common_syms(); | |
| 1127 | + | |
| 1128 | + tcc_add_linker_symbols(s1); | |
| 1098 | 1129 | |
| 1099 | 1130 | if (!s1->static_link) { |
| 1100 | 1131 | const char *name; |
| @@ -1310,7 +1341,11 @@ int tcc_output_file(TCCState *s1, const char *filename) · 209 unmodified lines | ||
| 1310 | 1341 | /* allocate program segment headers */ |
| 1311 | 1342 | phdr = tcc_mallocz(phnum * sizeof(Elf32_Phdr)); |
| 1312 | 1343 | |
| 1313 | − file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr); | |
| 1344 | + if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) { | |
| 1345 | + file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr); | |
| 1346 | + } else { | |
| 1347 | + file_offset = 0; | |
| 1348 | + } | |
| 1314 | 1349 | if (phnum > 0) { |
| 1315 | 1350 | /* compute section to program header mapping */ |
| 1316 | 1351 | if (s1->has_text_addr) { |
| @@ -1413,10 +1448,18 @@ int tcc_output_file(TCCState *s1, const char *filename) · 96 unmodified lines | ||
| 1413 | 1448 | ph->p_filesz = file_offset - ph->p_offset; |
| 1414 | 1449 | ph->p_memsz = addr - ph->p_vaddr; |
| 1415 | 1450 | ph++; |
| 1416 | − /* if in the middle of a page, we duplicate the page in | |
| 1417 | − memory so that one copy is RX and the other is RW */ | |
| 1418 | − if ((addr & (ELF_PAGE_SIZE - 1)) != 0) | |
| 1419 | − addr += ELF_PAGE_SIZE; | |
| 1451 | + if (j == 0) { | |
| 1452 | + if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) { | |
| 1453 | + /* if in the middle of a page, we duplicate the page in | |
| 1454 | + memory so that one copy is RX and the other is RW */ | |
| 1455 | + if ((addr & (ELF_PAGE_SIZE - 1)) != 0) | |
| 1456 | + addr += ELF_PAGE_SIZE; | |
| 1457 | + } else { | |
| 1458 | + addr = (addr + ELF_PAGE_SIZE - 1) & ~(ELF_PAGE_SIZE - 1); | |
| 1459 | + file_offset = (file_offset + ELF_PAGE_SIZE - 1) & | |
| 1460 | + ~(ELF_PAGE_SIZE - 1); | |
| 1461 | + } | |
| 1462 | + } | |
| 1420 | 1463 | } |
| 1421 | 1464 | |
| 1422 | 1465 | /* if interpreter, then add corresponing program header */ |
| @@ -1566,103 +1609,111 @@ int tcc_output_file(TCCState *s1, const char *filename) · 143 unmodified lines | ||
| 1566 | 1609 | ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */ |
| 1567 | 1610 | } |
| 1568 | 1611 | |
| 1569 | −#ifdef TCC_TARGET_COFF | |
| 1570 | − ret = tcc_output_coff(s1, filename); | |
| 1571 | −#else | |
| 1572 | − sort_syms(s1, symtab_section); | |
| 1573 | − | |
| 1574 | − /* align to 4 */ | |
| 1575 | − file_offset = (file_offset + 3) & -4; | |
| 1576 | − | |
| 1577 | − /* fill header */ | |
| 1578 | − ehdr.e_ident[0] = ELFMAG0; | |
| 1579 | − ehdr.e_ident[1] = ELFMAG1; | |
| 1580 | − ehdr.e_ident[2] = ELFMAG2; | |
| 1581 | − ehdr.e_ident[3] = ELFMAG3; | |
| 1582 | − ehdr.e_ident[4] = ELFCLASS32; | |
| 1583 | − ehdr.e_ident[5] = ELFDATA2LSB; | |
| 1584 | − ehdr.e_ident[6] = EV_CURRENT; | |
| 1585 | −#ifdef __FreeBSD__ | |
| 1586 | − ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD; | |
| 1587 | −#endif | |
| 1588 | −#ifdef TCC_TARGET_ARM | |
| 1589 | − ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM; | |
| 1590 | −#endif | |
| 1591 | − switch(file_type) { | |
| 1592 | − default: | |
| 1593 | − case TCC_OUTPUT_EXE: | |
| 1594 | − ehdr.e_type = ET_EXEC; | |
| 1595 | − break; | |
| 1596 | − case TCC_OUTPUT_DLL: | |
| 1597 | − ehdr.e_type = ET_DYN; | |
| 1598 | − break; | |
| 1599 | − case TCC_OUTPUT_OBJ: | |
| 1600 | − ehdr.e_type = ET_REL; | |
| 1601 | − break; | |
| 1602 | − } | |
| 1603 | − ehdr.e_machine = EM_TCC_TARGET; | |
| 1604 | − ehdr.e_version = EV_CURRENT; | |
| 1605 | − ehdr.e_shoff = file_offset; | |
| 1606 | − ehdr.e_ehsize = sizeof(Elf32_Ehdr); | |
| 1607 | − ehdr.e_shentsize = sizeof(Elf32_Shdr); | |
| 1608 | − ehdr.e_shnum = shnum; | |
| 1609 | − ehdr.e_shstrndx = shnum - 1; | |
| 1610 | − | |
| 1611 | 1612 | /* write elf file */ |
| 1612 | 1613 | if (file_type == TCC_OUTPUT_OBJ) |
| 1613 | 1614 | mode = 0666; |
| 1614 | 1615 | else |
| 1615 | 1616 | mode = 0777; |
| 1616 | − fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, mode); | |
| 1617 | + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode); | |
| 1617 | 1618 | if (fd < 0) { |
| 1618 | 1619 | error_noabort("could not write '%s'", filename); |
| 1619 | 1620 | goto fail; |
| 1620 | 1621 | } |
| 1621 | − f = fdopen(fd, "w"); | |
| 1622 | − fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f); | |
| 1623 | − fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f); | |
| 1624 | − offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr); | |
| 1625 | − for(i=1;i<s1->nb_sections;i++) { | |
| 1626 | − s = s1->sections[section_order[i]]; | |
| 1627 | − if (s->sh_type != SHT_NOBITS) { | |
| 1628 | − while (offset < s->sh_offset) { | |
| 1629 | − fputc(0, f); | |
| 1630 | − offset++; | |
| 1622 | + f = fdopen(fd, "wb"); | |
| 1623 | + | |
| 1624 | +#ifdef TCC_TARGET_COFF | |
| 1625 | + if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) { | |
| 1626 | + tcc_output_coff(s1, f); | |
| 1627 | + } else | |
| 1628 | +#endif | |
| 1629 | + if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) { | |
| 1630 | + sort_syms(s1, symtab_section); | |
| 1631 | + | |
| 1632 | + /* align to 4 */ | |
| 1633 | + file_offset = (file_offset + 3) & -4; | |
| 1634 | + | |
| 1635 | + /* fill header */ | |
| 1636 | + ehdr.e_ident[0] = ELFMAG0; | |
| 1637 | + ehdr.e_ident[1] = ELFMAG1; | |
| 1638 | + ehdr.e_ident[2] = ELFMAG2; | |
| 1639 | + ehdr.e_ident[3] = ELFMAG3; | |
| 1640 | + ehdr.e_ident[4] = ELFCLASS32; | |
| 1641 | + ehdr.e_ident[5] = ELFDATA2LSB; | |
| 1642 | + ehdr.e_ident[6] = EV_CURRENT; | |
| 1643 | +#ifdef __FreeBSD__ | |
| 1644 | + ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD; | |
| 1645 | +#endif | |
| 1646 | +#ifdef TCC_TARGET_ARM | |
| 1647 | + ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM; | |
| 1648 | +#endif | |
| 1649 | + switch(file_type) { | |
| 1650 | + default: | |
| 1651 | + case TCC_OUTPUT_EXE: | |
| 1652 | + ehdr.e_type = ET_EXEC; | |
| 1653 | + break; | |
| 1654 | + case TCC_OUTPUT_DLL: | |
| 1655 | + ehdr.e_type = ET_DYN; | |
| 1656 | + break; | |
| 1657 | + case TCC_OUTPUT_OBJ: | |
| 1658 | + ehdr.e_type = ET_REL; | |
| 1659 | + break; | |
| 1660 | + } | |
| 1661 | + ehdr.e_machine = EM_TCC_TARGET; | |
| 1662 | + ehdr.e_version = EV_CURRENT; | |
| 1663 | + ehdr.e_shoff = file_offset; | |
| 1664 | + ehdr.e_ehsize = sizeof(Elf32_Ehdr); | |
| 1665 | + ehdr.e_shentsize = sizeof(Elf32_Shdr); | |
| 1666 | + ehdr.e_shnum = shnum; | |
| 1667 | + ehdr.e_shstrndx = shnum - 1; | |
| 1668 | + | |
| 1669 | + fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f); | |
| 1670 | + fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f); | |
| 1671 | + offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr); | |
| 1672 | + | |
| 1673 | + for(i=1;i<s1->nb_sections;i++) { | |
| 1674 | + s = s1->sections[section_order[i]]; | |
| 1675 | + if (s->sh_type != SHT_NOBITS) { | |
| 1676 | + while (offset < s->sh_offset) { | |
| 1677 | + fputc(0, f); | |
| 1678 | + offset++; | |
| 1679 | + } | |
| 1680 | + size = s->sh_size; | |
| 1681 | + fwrite(s->data, 1, size, f); | |
| 1682 | + offset += size; | |
| 1631 | 1683 | } |
| 1632 | − size = s->sh_size; | |
| 1633 | − fwrite(s->data, 1, size, f); | |
| 1634 | − offset += size; | |
| 1635 | 1684 | } |
| 1636 | − } | |
| 1637 | − while (offset < ehdr.e_shoff) { | |
| 1638 | − fputc(0, f); | |
| 1639 | − offset++; | |
| 1640 | − } | |
| 1685 | + | |
| 1686 | + /* output section headers */ | |
| 1687 | + while (offset < ehdr.e_shoff) { | |
| 1688 | + fputc(0, f); | |
| 1689 | + offset++; | |
| 1690 | + } | |
| 1641 | 1691 | |
| 1642 | − /* output section headers */ | |
| 1643 | − for(i=0;i<s1->nb_sections;i++) { | |
| 1644 | − sh = &shdr; | |
| 1645 | − memset(sh, 0, sizeof(Elf32_Shdr)); | |
| 1646 | − s = s1->sections[i]; | |
| 1647 | − if (s) { | |
| 1648 | − sh->sh_name = s->sh_name; | |
| 1649 | − sh->sh_type = s->sh_type; | |
| 1650 | − sh->sh_flags = s->sh_flags; | |
| 1651 | − sh->sh_entsize = s->sh_entsize; | |
| 1652 | − sh->sh_info = s->sh_info; | |
| 1653 | − if (s->link) | |
| 1654 | − sh->sh_link = s->link->sh_num; | |
| 1655 | − sh->sh_addralign = s->sh_addralign; | |
| 1656 | − sh->sh_addr = s->sh_addr; | |
| 1657 | − sh->sh_offset = s->sh_offset; | |
| 1658 | − sh->sh_size = s->sh_size; | |
| 1692 | + for(i=0;i<s1->nb_sections;i++) { | |
| 1693 | + sh = &shdr; | |
| 1694 | + memset(sh, 0, sizeof(Elf32_Shdr)); | |
| 1695 | + s = s1->sections[i]; | |
| 1696 | + if (s) { | |
| 1697 | + sh->sh_name = s->sh_name; | |
| 1698 | + sh->sh_type = s->sh_type; | |
| 1699 | + sh->sh_flags = s->sh_flags; | |
| 1700 | + sh->sh_entsize = s->sh_entsize; | |
| 1701 | + sh->sh_info = s->sh_info; | |
| 1702 | + if (s->link) | |
| 1703 | + sh->sh_link = s->link->sh_num; | |
| 1704 | + sh->sh_addralign = s->sh_addralign; | |
| 1705 | + sh->sh_addr = s->sh_addr; | |
| 1706 | + sh->sh_offset = s->sh_offset; | |
| 1707 | + sh->sh_size = s->sh_size; | |
| 1708 | + } | |
| 1709 | + fwrite(sh, 1, sizeof(Elf32_Shdr), f); | |
| 1659 | 1710 | } |
| 1660 | − fwrite(sh, 1, sizeof(Elf32_Shdr), f); | |
| 1711 | + } else { | |
| 1712 | + tcc_output_binary(s1, f, section_order); | |
| 1661 | 1713 | } |
| 1662 | 1714 | fclose(f); |
| 1663 | 1715 | |
| 1664 | 1716 | ret = 0; |
| 1665 | −#endif | |
| 1666 | 1717 | the_end: |
| 1667 | 1718 | tcc_free(s1->symtab_to_dynsym); |
| 1668 | 1719 | tcc_free(section_order); |