| @@ -1682,6 +1682,55 @@ typedef struct ArchiveHeader { · 1681 unmodified lines |
| 1682 | 1682 | char ar_fmag[2]; /* should contain ARFMAG */ |
| 1683 | 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 | 1734 | /* load a '.a' file */ |
| 1686 | 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 | 1763 | ar_name[i + 1] = '\0'; |
| 1715 | 1764 | // printf("name='%s' size=%d %s\n", ar_name, size, ar_size); |
| 1716 | 1765 | file_offset = lseek(fd, 0, SEEK_CUR); |
| 1717 | | − if (!strcmp(ar_name, "/") || |
| 1718 | | − !strcmp(ar_name, "//") || |
| 1719 | | − !strcmp(ar_name, "__.SYMDEF") || |
| 1720 | | − !strcmp(ar_name, "__.SYMDEF/") || |
| 1721 | | − !strcmp(ar_name, "ARFILENAMES/")) { |
| 1766 | + /* align to even */ |
| 1767 | + size = (size + 1) & ~1; |
| 1768 | + if (!strcmp(ar_name, "/")) { |
| 1769 | + /* coff symbol table : we handle it */ |
| 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 | 1776 | /* skip symbol table or archive names */ |
| 1723 | 1777 | } else { |
| 1724 | 1778 | if (tcc_load_object_file(s1, fd, file_offset) < 0) |
| 1725 | 1779 | return -1; |
| 1726 | 1780 | } |
| 1727 | | − /* align to even */ |
| 1728 | | − size = (size + 1) & ~1; |
| 1729 | 1781 | lseek(fd, file_offset + size, SEEK_SET); |
| 1730 | 1782 | } |
| 1731 | 1783 | return 0; |