History

alacarte linking (Dave Long)

bellard committed 23 years ago

Commit c4e6b2e1 parent 71f119f2 files · +63 −7Browse files

Unified · Split

2 files
  1. tcc.c +4 −0
  2. tccelf.c +59 −7
tcc.c+4−0
@@ -398,6 +398,9 @@ struct TCCState { · 397 unmodified lines
398 /* if true, static linking is performed */398 /* if true, static linking is performed */
399 int static_link;399 int static_link;
400 400
401 /* if true, only link in referenced objects from archive */
402 int alacarte_link;
403
401 /* warning switches */404 /* warning switches */
402 int warn_write_strings;405 int warn_write_strings;
403 int warn_unsupported;406 int warn_unsupported;
@@ -9207,6 +9210,7 @@ TCCState *tcc_new(void) · 8803 unmodified lines
9207 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,9210 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
9208 ".dynstrtab", 9211 ".dynstrtab",
9209 ".dynhashtab", SHF_PRIVATE);9212 ".dynhashtab", SHF_PRIVATE);
9213 s->alacarte_link = 1;
9210 return s;9214 return s;
9211}9215}
9212 9216
tccelf.c+59−7
@@ -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
1685static 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 */
1691static 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 */
1686static int tcc_load_archive(TCCState *s1, int fd)1735static 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;