Unified · Split
| @@ -955,8 +955,6 @@ static void add_init_array_defines(TCCState *s1, const char *section_name) · 954 unmodified lines | |||
| 955 | static void tcc_add_runtime(TCCState *s1) | 955 | static void tcc_add_runtime(TCCState *s1) |
| 956 | { | 956 | { |
| 957 | char buf[1024]; | 957 | char buf[1024]; |
| 958 | int i; | ||
| 959 | Section *s; | ||
| 960 | 958 | ||
| 961 | if (!s1->nostdlib) { | 959 | if (!s1->nostdlib) { |
| 962 | snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "libtcc1.a"); | 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 | if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) { | 998 | if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) { |
| 1001 | tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o"); | 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 | add_elf_sym(symtab_section, | 1012 | add_elf_sym(symtab_section, |
| 1005 | text_section->data_offset, 0, | 1013 | text_section->data_offset, 0, |
| 1006 | ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), | 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 | static char elf_interp[] = "/lib/ld-linux.so.2"; | 1067 | static char elf_interp[] = "/lib/ld-linux.so.2"; |
| 1060 | #endif | 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 | /* output an ELF file */ | 1092 | /* output an ELF file */ |
| 1063 | /* XXX: suppress unneeded sections */ | 1093 | /* XXX: suppress unneeded sections */ |
| 1064 | int tcc_output_file(TCCState *s1, const char *filename) | 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 | s1->nb_errors = 0; | 1112 | s1->nb_errors = 0; |
| 1083 | 1113 | ||
| 1084 | if (file_type != TCC_OUTPUT_OBJ) { | 1114 | if (file_type != TCC_OUTPUT_OBJ) { |
| 1085 | relocate_common_syms(); | ||
| 1086 | |||
| 1087 | tcc_add_runtime(s1); | 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 | saved_dynamic_data_offset = 0; /* avoid warning */ | 1123 | saved_dynamic_data_offset = 0; /* avoid warning */ |
| 1096 | 1124 | ||
| 1097 | if (file_type != TCC_OUTPUT_OBJ) { | 1125 | if (file_type != TCC_OUTPUT_OBJ) { |
| 1126 | relocate_common_syms(); | ||
| 1127 | |||
| 1128 | tcc_add_linker_symbols(s1); | ||
| 1098 | 1129 | ||
| 1099 | if (!s1->static_link) { | 1130 | if (!s1->static_link) { |
| 1100 | const char *name; | 1131 | const char *name; |
| @@ -1310,7 +1341,11 @@ int tcc_output_file(TCCState *s1, const char *filename) · 209 unmodified lines | |||
| 1310 | /* allocate program segment headers */ | 1341 | /* allocate program segment headers */ |
| 1311 | phdr = tcc_mallocz(phnum * sizeof(Elf32_Phdr)); | 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 | if (phnum > 0) { | 1349 | if (phnum > 0) { |
| 1315 | /* compute section to program header mapping */ | 1350 | /* compute section to program header mapping */ |
| 1316 | if (s1->has_text_addr) { | 1351 | if (s1->has_text_addr) { |
| @@ -1413,10 +1448,18 @@ int tcc_output_file(TCCState *s1, const char *filename) · 96 unmodified lines | |||
| 1413 | ph->p_filesz = file_offset - ph->p_offset; | 1448 | ph->p_filesz = file_offset - ph->p_offset; |
| 1414 | ph->p_memsz = addr - ph->p_vaddr; | 1449 | ph->p_memsz = addr - ph->p_vaddr; |
| 1415 | ph++; | 1450 | ph++; |
| 1416 | /* if in the middle of a page, we duplicate the page in | 1451 | if (j == 0) { |
| 1417 | memory so that one copy is RX and the other is RW */ | 1452 | if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) { |
| 1418 | if ((addr & (ELF_PAGE_SIZE - 1)) != 0) | 1453 | /* if in the middle of a page, we duplicate the page in |
| 1419 | addr += ELF_PAGE_SIZE; | 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 | /* if interpreter, then add corresponing program header */ | 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 | ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */ | 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 | /* write elf file */ | 1612 | /* write elf file */ |
| 1612 | if (file_type == TCC_OUTPUT_OBJ) | 1613 | if (file_type == TCC_OUTPUT_OBJ) |
| 1613 | mode = 0666; | 1614 | mode = 0666; |
| 1614 | else | 1615 | else |
| 1615 | mode = 0777; | 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 | if (fd < 0) { | 1618 | if (fd < 0) { |
| 1618 | error_noabort("could not write '%s'", filename); | 1619 | error_noabort("could not write '%s'", filename); |
| 1619 | goto fail; | 1620 | goto fail; |
| 1620 | } | 1621 | } |
| 1621 | f = fdopen(fd, "w"); | 1622 | f = fdopen(fd, "wb"); |
| 1622 | fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f); | 1623 | |
| 1623 | fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f); | 1624 | #ifdef TCC_TARGET_COFF |
| 1624 | offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr); | 1625 | if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) { |
| 1625 | for(i=1;i<s1->nb_sections;i++) { | 1626 | tcc_output_coff(s1, f); |
| 1626 | s = s1->sections[section_order[i]]; | 1627 | } else |
| 1627 | if (s->sh_type != SHT_NOBITS) { | 1628 | #endif |
| 1628 | while (offset < s->sh_offset) { | 1629 | if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) { |
| 1629 | fputc(0, f); | 1630 | sort_syms(s1, symtab_section); |
| 1630 | offset++; | 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 | } | 1685 | |
| 1637 | while (offset < ehdr.e_shoff) { | 1686 | /* output section headers */ |
| 1638 | fputc(0, f); | 1687 | while (offset < ehdr.e_shoff) { |
| 1639 | offset++; | 1688 | fputc(0, f); |
| 1640 | } | 1689 | offset++; |
| 1690 | } | ||
| 1641 | 1691 | ||
| 1642 | /* output section headers */ | 1692 | for(i=0;i<s1->nb_sections;i++) { |
| 1643 | for(i=0;i<s1->nb_sections;i++) { | 1693 | sh = &shdr; |
| 1644 | sh = &shdr; | 1694 | memset(sh, 0, sizeof(Elf32_Shdr)); |
| 1645 | memset(sh, 0, sizeof(Elf32_Shdr)); | 1695 | s = s1->sections[i]; |
| 1646 | s = s1->sections[i]; | 1696 | if (s) { |
| 1647 | if (s) { | 1697 | sh->sh_name = s->sh_name; |
| 1648 | sh->sh_name = s->sh_name; | 1698 | sh->sh_type = s->sh_type; |
| 1649 | sh->sh_type = s->sh_type; | 1699 | sh->sh_flags = s->sh_flags; |
| 1650 | sh->sh_flags = s->sh_flags; | 1700 | sh->sh_entsize = s->sh_entsize; |
| 1651 | sh->sh_entsize = s->sh_entsize; | 1701 | sh->sh_info = s->sh_info; |
| 1652 | sh->sh_info = s->sh_info; | 1702 | if (s->link) |
| 1653 | if (s->link) | 1703 | sh->sh_link = s->link->sh_num; |
| 1654 | sh->sh_link = s->link->sh_num; | 1704 | sh->sh_addralign = s->sh_addralign; |
| 1655 | sh->sh_addralign = s->sh_addralign; | 1705 | sh->sh_addr = s->sh_addr; |
| 1656 | sh->sh_addr = s->sh_addr; | 1706 | sh->sh_offset = s->sh_offset; |
| 1657 | sh->sh_offset = s->sh_offset; | 1707 | sh->sh_size = s->sh_size; |
| 1658 | 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 | fclose(f); | 1714 | fclose(f); |
| 1663 | 1715 | ||
| 1664 | ret = 0; | 1716 | ret = 0; |
| 1665 | #endif | ||
| 1666 | the_end: | 1717 | the_end: |
| 1667 | tcc_free(s1->symtab_to_dynsym); | 1718 | tcc_free(s1->symtab_to_dynsym); |
| 1668 | tcc_free(section_order); | 1719 | tcc_free(section_order); |