aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2016-10-14 16:44:41 +0200
committerMichael Matz <matz@suse.de>2016-10-14 16:47:43 +0200
commitc232af7ddbbf55055e0a47d9f0ca43dc6dd3d9de (patch)
tree0b6b507486f3431760f97ac69a4310668641c130
parented15cddacd145c74e4600af50f6616ba59ca0d8d (diff)
downloadtinycc-c232af7ddbbf55055e0a47d9f0ca43dc6dd3d9de.tar.gz
tinycc-c232af7ddbbf55055e0a47d9f0ca43dc6dd3d9de.tar.bz2
Support archives with 64 bit indices
Some systems started using SYM64 .a libraries, so start supporting them.
-rw-r--r--tccelf.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/tccelf.c b/tccelf.c
index e6468b2..6c54036 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -3037,10 +3037,17 @@ static int get_be32(const uint8_t *b)
return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
}
+static long get_be64(const uint8_t *b)
+{
+ long long ret = get_be32(b);
+ ret = (ret << 32) | (unsigned)get_be32(b+4);
+ return (long)ret;
+}
+
/* load only the objects which resolve undefined symbols */
-static int tcc_load_alacarte(TCCState *s1, int fd, int size)
+static int tcc_load_alacarte(TCCState *s1, int fd, int size, int entrysize)
{
- int i, bound, nsyms, sym_index, off, ret;
+ long i, bound, nsyms, sym_index, off, ret;
uint8_t *data;
const char *ar_names, *p;
const uint8_t *ar_index;
@@ -3049,9 +3056,9 @@ static int tcc_load_alacarte(TCCState *s1, int fd, int size)
data = tcc_malloc(size);
if (read(fd, data, size) != size)
goto fail;
- nsyms = get_be32(data);
- ar_index = data + 4;
- ar_names = (char *) ar_index + nsyms * 4;
+ nsyms = entrysize == 4 ? get_be32(data) : get_be64(data);
+ ar_index = data + entrysize;
+ ar_names = (char *) ar_index + nsyms * entrysize;
do {
bound = 0;
@@ -3060,7 +3067,10 @@ static int tcc_load_alacarte(TCCState *s1, int fd, int size)
if(sym_index) {
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
if(sym->st_shndx == SHN_UNDEF) {
- off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
+ off = (entrysize == 4
+ ? get_be32(ar_index + i * 4)
+ : get_be64(ar_index + i * 8))
+ + sizeof(ArchiveHeader);
++bound;
if(tcc_load_object_file(s1, fd, off) < 0) {
fail:
@@ -3113,7 +3123,10 @@ ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
if (!strcmp(ar_name, "/")) {
/* coff symbol table : we handle it */
if(s1->alacarte_link)
- return tcc_load_alacarte(s1, fd, size);
+ return tcc_load_alacarte(s1, fd, size, 4);
+ } else if (!strcmp(ar_name, "/SYM64/")) {
+ if(s1->alacarte_link)
+ return tcc_load_alacarte(s1, fd, size, 8);
} else {
ElfW(Ehdr) ehdr;
if (tcc_object_type(fd, &ehdr) == AFF_BINTYPE_REL) {