Alien-TinyCCx
view release on metacpan or search on metacpan
src/tccelf.c view on Meta::CPAN
/* take relocation offset information */
offseti = sm_table[sh->sh_info].offset;
for_each_elem(s, (offset / sizeof(*rel)), rel, ElfW_Rel) {
int type;
unsigned sym_index;
/* convert symbol index */
type = ELFW(R_TYPE)(rel->r_info);
sym_index = ELFW(R_SYM)(rel->r_info);
/* NOTE: only one symtab assumed */
if (sym_index >= nb_syms)
goto invalid_reloc;
sym_index = old_to_new_syms[sym_index];
/* ignore link_once in rel section. */
if (!sym_index && !sm->link_once
#ifdef TCC_TARGET_ARM
&& type != R_ARM_V4BX
#endif
) {
invalid_reloc:
tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
i, strsec + sh->sh_name, rel->r_offset);
goto fail;
}
rel->r_info = ELFW(R_INFO)(sym_index, type);
/* offset the relocation offset */
rel->r_offset += offseti;
#ifdef TCC_TARGET_ARM
/* Jumps and branches from a Thumb code to a PLT entry need
special handling since PLT entries are ARM code.
Unconditional bl instructions referencing PLT entries are
handled by converting these instructions into blx
instructions. Other case of instructions referencing a PLT
entry require to add a Thumb stub before the PLT entry to
switch to ARM mode. We set bit plt_thumb_stub of the
attribute of a symbol to indicate such a case. */
if (type == R_ARM_THM_JUMP24)
alloc_sym_attr(s1, sym_index)->plt_thumb_stub = 1;
#endif
}
break;
default:
break;
}
}
ret = 0;
the_end:
tcc_free(symtab);
tcc_free(strtab);
tcc_free(old_to_new_syms);
tcc_free(sm_table);
tcc_free(strsec);
tcc_free(shdr);
return ret;
}
typedef struct ArchiveHeader {
char ar_name[16]; /* name of this member */
char ar_date[12]; /* file mtime */
char ar_uid[6]; /* owner uid; printed as decimal */
char ar_gid[6]; /* owner gid; printed as decimal */
char ar_mode[8]; /* file mode, printed as octal */
char ar_size[10]; /* file size, printed as decimal */
char ar_fmag[2]; /* should contain ARFMAG */
} ArchiveHeader;
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, int entrysize)
{
long i, bound, nsyms, sym_index, off, ret;
uint8_t *data;
const char *ar_names, *p;
const uint8_t *ar_index;
ElfW(Sym) *sym;
data = tcc_malloc(size);
if (read(fd, data, size) != size)
goto fail;
nsyms = entrysize == 4 ? get_be32(data) : get_be64(data);
ar_index = data + entrysize;
ar_names = (char *) ar_index + nsyms * entrysize;
do {
bound = 0;
for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
sym_index = find_elf_sym(symtab_section, p);
if(sym_index) {
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
if(sym->st_shndx == SHN_UNDEF) {
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:
ret = -1;
goto the_end;
}
}
}
}
} while(bound);
ret = 0;
the_end:
tcc_free(data);
return ret;
}
( run in 0.717 second using v1.01-cache-2.11-cpan-5735350b133 )