| @@ -1682,6 +1682,55 @@ typedef struct ArchiveHeader { · 1681 unmodified lines |
| 1682 | char ar_fmag[2]; /* should contain ARFMAG */ | 1682 | char ar_fmag[2]; /* should contain ARFMAG */ |
| 1683 | } ArchiveHeader; | 1683 | } ArchiveHeader; |
| 1684 | | 1684 | |
| | 1685 | static int get_be32(const uint8_t *b) |
| | 1686 | { |
| | 1687 | return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24); |
| | 1688 | } |
| | 1689 | |
| | 1690 | /* load only the objects which resolve undefined symbols */ |
| | 1691 | static int tcc_load_alacarte(TCCState *s1, int fd, int size) |
| | 1692 | { |
| | 1693 | int i, bound, nsyms, sym_index, off, ret; |
| | 1694 | uint8_t *data; |
| | 1695 | const char *ar_names, *p; |
| | 1696 | const uint8_t *ar_index; |
| | 1697 | Elf32_Sym *sym; |
| | 1698 | |
| | 1699 | data = tcc_malloc(size); |
| | 1700 | if (read(fd, data, size) != size) |
| | 1701 | goto fail; |
| | 1702 | nsyms = get_be32(data); |
| | 1703 | ar_index = data + 4; |
| | 1704 | ar_names = ar_index + nsyms * 4; |
| | 1705 | |
| | 1706 | do { |
| | 1707 | bound = 0; |
| | 1708 | for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) { |
| | 1709 | sym_index = find_elf_sym(symtab_section, p); |
| | 1710 | if(sym_index) { |
| | 1711 | sym = &((Elf32_Sym *)symtab_section->data)[sym_index]; |
| | 1712 | if(sym->st_shndx == SHN_UNDEF) { |
| | 1713 | off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader); |
| | 1714 | #if 0 |
| | 1715 | printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx); |
| | 1716 | #endif |
| | 1717 | ++bound; |
| | 1718 | lseek(fd, off, SEEK_SET); |
| | 1719 | if(tcc_load_object_file(s1, fd, off) < 0) { |
| | 1720 | fail: |
| | 1721 | ret = -1; |
| | 1722 | goto the_end; |
| | 1723 | } |
| | 1724 | } |
| | 1725 | } |
| | 1726 | } |
| | 1727 | } while(bound); |
| | 1728 | ret = 0; |
| | 1729 | the_end: |
| | 1730 | tcc_free(data); |
| | 1731 | return ret; |
| | 1732 | } |
| | 1733 | |
| 1685 | /* load a '.a' file */ | 1734 | /* load a '.a' file */ |
| 1686 | static int tcc_load_archive(TCCState *s1, int fd) | 1735 | static int tcc_load_archive(TCCState *s1, int fd) |
| 1687 | { | 1736 | { |
| @@ -1714,18 +1763,21 @@ static int tcc_load_archive(TCCState *s1, int fd) · 26 unmodified lines |
| 1714 | ar_name[i + 1] = '\0'; | 1763 | ar_name[i + 1] = '\0'; |
| 1715 | // printf("name='%s' size=%d %s\n", ar_name, size, ar_size); | 1764 | // printf("name='%s' size=%d %s\n", ar_name, size, ar_size); |
| 1716 | file_offset = lseek(fd, 0, SEEK_CUR); | 1765 | file_offset = lseek(fd, 0, SEEK_CUR); |
| 1717 | if (!strcmp(ar_name, "/") || | 1766 | /* align to even */ |
| 1718 | !strcmp(ar_name, "//") || | 1767 | size = (size + 1) & ~1; |
| 1719 | !strcmp(ar_name, "__.SYMDEF") || | 1768 | if (!strcmp(ar_name, "/")) { |
| 1720 | !strcmp(ar_name, "__.SYMDEF/") || | 1769 | /* coff symbol table : we handle it */ |
| 1721 | !strcmp(ar_name, "ARFILENAMES/")) { | 1770 | if(s1->alacarte_link) |
| | 1771 | return tcc_load_alacarte(s1, fd, size); |
| | 1772 | } else if (!strcmp(ar_name, "//") || |
| | 1773 | !strcmp(ar_name, "__.SYMDEF") || |
| | 1774 | !strcmp(ar_name, "__.SYMDEF/") || |
| | 1775 | !strcmp(ar_name, "ARFILENAMES/")) { |
| 1722 | /* skip symbol table or archive names */ | 1776 | /* skip symbol table or archive names */ |
| 1723 | } else { | 1777 | } else { |
| 1724 | if (tcc_load_object_file(s1, fd, file_offset) < 0) | 1778 | if (tcc_load_object_file(s1, fd, file_offset) < 0) |
| 1725 | return -1; | 1779 | return -1; |
| 1726 | } | 1780 | } |
| 1727 | /* align to even */ | | |
| 1728 | size = (size + 1) & ~1; | | |
| 1729 | lseek(fd, file_offset + size, SEEK_SET); | 1781 | lseek(fd, file_offset + size, SEEK_SET); |
| 1730 | } | 1782 | } |
| 1731 | return 0; | 1783 | return 0; |