mirror of
git://repo.or.cz/tinycc.git
synced 2026-07-04 18:38:41 +08:00
tcc -vv ... : show objects loaded from archives
This commit is contained in:
parent
df349ddc43
commit
6082dd62bb
122
tccelf.c
122
tccelf.c
@ -2795,59 +2795,78 @@ typedef struct ArchiveHeader {
|
|||||||
char ar_fmag[2]; /* should contain ARFMAG */
|
char ar_fmag[2]; /* should contain ARFMAG */
|
||||||
} ArchiveHeader;
|
} ArchiveHeader;
|
||||||
|
|
||||||
static int get_be32(const uint8_t *b)
|
#define ARFMAG "`\n"
|
||||||
|
|
||||||
|
static unsigned long long get_be(const uint8_t *b, int n)
|
||||||
{
|
{
|
||||||
return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
|
unsigned long long ret = 0;
|
||||||
|
while (n)
|
||||||
|
ret = (ret << 8) | *b++, --n;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long get_be64(const uint8_t *b)
|
static int read_ar_header(int fd, int offset, ArchiveHeader *hdr)
|
||||||
{
|
{
|
||||||
long long ret = get_be32(b);
|
char *p, *e;
|
||||||
ret = (ret << 32) | (unsigned)get_be32(b+4);
|
int len;
|
||||||
return (long)ret;
|
lseek(fd, offset, SEEK_SET);
|
||||||
|
len = full_read(fd, hdr, sizeof(ArchiveHeader));
|
||||||
|
if (len != sizeof(ArchiveHeader))
|
||||||
|
return len ? -1 : 0;
|
||||||
|
p = hdr->ar_name;
|
||||||
|
for (e = p + sizeof hdr->ar_name; e > p && e[-1] == ' ';)
|
||||||
|
--e;
|
||||||
|
*e = '\0';
|
||||||
|
hdr->ar_size[sizeof hdr->ar_size-1] = 0;
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* load only the objects which resolve undefined symbols */
|
/* load only the objects which resolve undefined symbols */
|
||||||
static int tcc_load_alacarte(TCCState *s1, int fd, int size, int entrysize)
|
static int tcc_load_alacarte(TCCState *s1, int fd, int size, int entrysize)
|
||||||
{
|
{
|
||||||
long i, bound, nsyms, sym_index, off, ret;
|
int i, bound, nsyms, sym_index, len, ret = -1;
|
||||||
|
unsigned long long off;
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
const char *ar_names, *p;
|
const char *ar_names, *p;
|
||||||
const uint8_t *ar_index;
|
const uint8_t *ar_index;
|
||||||
ElfW(Sym) *sym;
|
ElfW(Sym) *sym;
|
||||||
Section *s;
|
ArchiveHeader hdr;
|
||||||
|
|
||||||
data = tcc_malloc(size);
|
data = tcc_malloc(size);
|
||||||
if (full_read(fd, data, size) != size)
|
if (full_read(fd, data, size) != size)
|
||||||
goto fail;
|
goto the_end;
|
||||||
nsyms = entrysize == 4 ? get_be32(data) : get_be64(data);
|
nsyms = get_be(data, entrysize);
|
||||||
ar_index = data + entrysize;
|
ar_index = data + entrysize;
|
||||||
ar_names = (char *) ar_index + nsyms * entrysize;
|
ar_names = (char *) ar_index + nsyms * entrysize;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
bound = 0;
|
bound = 0;
|
||||||
for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
|
for (p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
|
||||||
s = symtab_section;
|
Section *s = symtab_section;
|
||||||
sym_index = find_elf_sym(s, p);
|
sym_index = find_elf_sym(s, p);
|
||||||
if(sym_index == 0) {
|
#ifdef TCC_TARGET_PE /* windows DLL's don't have UNDEF syms */
|
||||||
|
if (sym_index == 0) {
|
||||||
s = s1->dynsymtab_section;
|
s = s1->dynsymtab_section;
|
||||||
sym_index = find_elf_sym(s, p);
|
sym_index = find_elf_sym(s, p);
|
||||||
}
|
}
|
||||||
if(sym_index) {
|
#endif
|
||||||
sym = &((ElfW(Sym) *)s->data)[sym_index];
|
if (!sym_index)
|
||||||
if(sym->st_shndx == SHN_UNDEF) {
|
continue;
|
||||||
off = (entrysize == 4
|
sym = &((ElfW(Sym) *)s->data)[sym_index];
|
||||||
? get_be32(ar_index + i * 4)
|
if(sym->st_shndx != SHN_UNDEF)
|
||||||
: get_be64(ar_index + i * 8))
|
continue;
|
||||||
+ sizeof(ArchiveHeader);
|
off = get_be(ar_index + i * entrysize, entrysize);
|
||||||
++bound;
|
len = read_ar_header(fd, off, &hdr);
|
||||||
if(tcc_load_object_file(s1, fd, off) < 0) {
|
if (len <= 0 || memcmp(hdr.ar_fmag, ARFMAG, 2)) {
|
||||||
fail:
|
tcc_error_noabort("invalid archive");
|
||||||
ret = -1;
|
goto the_end;
|
||||||
goto the_end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
off += len;
|
||||||
|
if (s1->verbose == 2)
|
||||||
|
printf(" -> %s\n", hdr.ar_name);
|
||||||
|
if (tcc_load_object_file(s1, fd, off) < 0)
|
||||||
|
goto the_end;
|
||||||
|
++bound;
|
||||||
}
|
}
|
||||||
} while(bound);
|
} while(bound);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@ -2860,52 +2879,41 @@ static int tcc_load_alacarte(TCCState *s1, int fd, int size, int entrysize)
|
|||||||
ST_FUNC int tcc_load_archive(TCCState *s1, int fd, int alacarte)
|
ST_FUNC int tcc_load_archive(TCCState *s1, int fd, int alacarte)
|
||||||
{
|
{
|
||||||
ArchiveHeader hdr;
|
ArchiveHeader hdr;
|
||||||
char ar_size[11];
|
/* char magic[8]; */
|
||||||
char ar_name[17];
|
int size, len;
|
||||||
char magic[8];
|
|
||||||
int size, len, i;
|
|
||||||
unsigned long file_offset;
|
unsigned long file_offset;
|
||||||
|
ElfW(Ehdr) ehdr;
|
||||||
|
|
||||||
/* skip magic which was already checked */
|
/* skip magic which was already checked */
|
||||||
full_read(fd, magic, sizeof(magic));
|
/* full_read(fd, magic, sizeof(magic)); */
|
||||||
|
file_offset = sizeof ARMAG - 1;
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
len = full_read(fd, &hdr, sizeof(hdr));
|
len = read_ar_header(fd, file_offset, &hdr);
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
break;
|
return 0;
|
||||||
if (len != sizeof(hdr)) {
|
if (len < 0) {
|
||||||
tcc_error_noabort("invalid archive");
|
tcc_error_noabort("invalid archive");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
|
file_offset += len;
|
||||||
ar_size[sizeof(hdr.ar_size)] = '\0';
|
size = strtol(hdr.ar_size, NULL, 0);
|
||||||
size = strtol(ar_size, NULL, 0);
|
|
||||||
memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
|
|
||||||
for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
|
|
||||||
if (ar_name[i] != ' ')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ar_name[i + 1] = '\0';
|
|
||||||
file_offset = lseek(fd, 0, SEEK_CUR);
|
|
||||||
/* align to even */
|
/* align to even */
|
||||||
size = (size + 1) & ~1;
|
size = (size + 1) & ~1;
|
||||||
if (!strcmp(ar_name, "/")) {
|
if (alacarte) {
|
||||||
/* coff symbol table : we handle it */
|
/* coff symbol table : we handle it */
|
||||||
if (alacarte)
|
if (!strcmp(hdr.ar_name, "/"))
|
||||||
return tcc_load_alacarte(s1, fd, size, 4);
|
return tcc_load_alacarte(s1, fd, size, 4);
|
||||||
} else if (!strcmp(ar_name, "/SYM64/")) {
|
if (!strcmp(hdr.ar_name, "/SYM64/"))
|
||||||
if (alacarte)
|
|
||||||
return tcc_load_alacarte(s1, fd, size, 8);
|
return tcc_load_alacarte(s1, fd, size, 8);
|
||||||
} else {
|
} else if (tcc_object_type(fd, &ehdr) == AFF_BINTYPE_REL) {
|
||||||
ElfW(Ehdr) ehdr;
|
if (s1->verbose == 2)
|
||||||
if (tcc_object_type(fd, &ehdr) == AFF_BINTYPE_REL) {
|
printf(" -> %s\n", hdr.ar_name);
|
||||||
if (tcc_load_object_file(s1, fd, file_offset) < 0)
|
if (tcc_load_object_file(s1, fd, file_offset) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
lseek(fd, file_offset + size, SEEK_SET);
|
file_offset += size;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ELF_OBJ_ONLY
|
#ifndef ELF_OBJ_ONLY
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user