Alien-TinyCCx

 view release on metacpan or  search on metacpan

src/tccpe.c  view on Meta::CPAN

    return 0;
}

/* ------------------------------------------------------------- */
static void pe_relocate_rva (struct pe_info *pe, Section *s)
{
    Section *sr = s->reloc;
    ElfW_Rel *rel, *rel_end;
    rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
    for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
        if (ELFW(R_TYPE)(rel->r_info) == R_XXX_RELATIVE) {
            int sym_index = ELFW(R_SYM)(rel->r_info);
            DWORD addr = s->sh_addr;
            if (sym_index) {
                ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + sym_index;
                addr = sym->st_value;
            }
            // printf("reloc rva %08x %08x %s\n", (DWORD)rel->r_offset, addr, s->name);
            *(DWORD*)(s->data + rel->r_offset) += addr - pe->imagebase;
        }
    }
}

/*----------------------------------------------------------------------------*/

static int pe_isafunc(int sym_index)
{
    Section *sr = text_section->reloc;
    ElfW_Rel *rel, *rel_end;
    Elf32_Word info = ELF32_R_INFO(sym_index, R_386_PC32);
    if (!sr)
        return 0;
    rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
    for (rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++)
        if (rel->r_info == info)
            return 1;
    return 0;
}

/*----------------------------------------------------------------------------*/
static int pe_check_symbols(struct pe_info *pe)
{
    ElfW(Sym) *sym;
    int sym_index, sym_end;
    int ret = 0;

    pe_align_section(text_section, 8);

    sym_end = symtab_section->data_offset / sizeof(ElfW(Sym));
    for (sym_index = 1; sym_index < sym_end; ++sym_index) {

        sym = (ElfW(Sym) *)symtab_section->data + sym_index;
        if (sym->st_shndx == SHN_UNDEF) {

            const char *name = symtab_section->link->data + sym->st_name;
            unsigned type = ELFW(ST_TYPE)(sym->st_info);
            int imp_sym = pe_find_import(pe->s1, sym);
            struct import_symbol *is;

            if (0 == imp_sym)
                goto not_found;

            if (type == STT_NOTYPE) {
                /* symbols from assembler have no type, find out which */
                if (pe_isafunc(sym_index))
                    type = STT_FUNC;
                else
                    type = STT_OBJECT;
            }

            is = pe_add_import(pe, imp_sym);

            if (type == STT_FUNC) {
                unsigned long offset = is->thk_offset;
                if (offset) {
                    /* got aliased symbol, like stricmp and _stricmp */

                } else {
                    char buffer[100];
                    WORD *p;

                    offset = text_section->data_offset;
                    /* add the 'jmp IAT[x]' instruction */
#ifdef TCC_TARGET_ARM
                    p = section_ptr_add(text_section, 8+4); // room for code and address
                    (*(DWORD*)(p)) = 0xE59FC000; // arm code ldr ip, [pc] ; PC+8+0 = 0001xxxx
                    (*(DWORD*)(p+2)) = 0xE59CF000; // arm code ldr pc, [ip]
#else
                    p = section_ptr_add(text_section, 8);
                    *p = 0x25FF;
#ifdef TCC_TARGET_X86_64
                    *(DWORD*)(p+1) = (DWORD)-4;
#endif
#endif
                    /* add a helper symbol, will be patched later in
                       pe_build_imports */
                    sprintf(buffer, "IAT.%s", name);
                    is->iat_index = put_elf_sym(
                        symtab_section, 0, sizeof(DWORD),
                        ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
                        0, SHN_UNDEF, buffer);
#ifdef TCC_TARGET_ARM
                    put_elf_reloc(symtab_section, text_section,
                        offset + 8, R_XXX_THUNKFIX, is->iat_index); // offset to IAT position
#else
                    put_elf_reloc(symtab_section, text_section, 
                        offset + 2, R_XXX_THUNKFIX, is->iat_index);
#endif
                    is->thk_offset = offset;
                }

                /* tcc_realloc might have altered sym's address */
                sym = (ElfW(Sym) *)symtab_section->data + sym_index;

                /* patch the original symbol */
                sym->st_value = offset;
                sym->st_shndx = text_section->sh_num;
                sym->st_other &= ~ST_PE_EXPORT; /* do not export */
                continue;
            }

            if (type == STT_OBJECT) { /* data, ptr to that should be */
                if (0 == is->iat_index) {
                    /* original symbol will be patched later in pe_build_imports */
                    is->iat_index = sym_index;
                    continue;
                }
            }

        not_found:
            tcc_error_noabort("undefined symbol '%s'", name);
            ret = -1;

        } else if (pe->s1->rdynamic
                   && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
            /* if -rdynamic option, then export all non local symbols */
            sym->st_other |= ST_PE_EXPORT;
        }
    }
    return ret;
}

/*----------------------------------------------------------------------------*/
#ifdef PE_PRINT_SECTIONS
static void pe_print_section(FILE * f, Section * s)
{
    /* just if you'r curious */
    BYTE *p, *e, b;
    int i, n, l, m;
    p = s->data;
    e = s->data + s->data_offset;
    l = e - p;

    fprintf(f, "section  \"%s\"", s->name);
    if (s->link)
        fprintf(f, "\nlink     \"%s\"", s->link->name);
    if (s->reloc)
        fprintf(f, "\nreloc    \"%s\"", s->reloc->name);
    fprintf(f, "\nv_addr   %08X", (unsigned)s->sh_addr);
    fprintf(f, "\ncontents %08X", (unsigned)l);
    fprintf(f, "\n\n");

    if (s->sh_type == SHT_NOBITS)
        return;

    if (0 == l)
        return;

    if (s->sh_type == SHT_SYMTAB)
        m = sizeof(ElfW(Sym));
    else if (s->sh_type == SHT_RELX)
        m = sizeof(ElfW_Rel);
    else
        m = 16;

    fprintf(f, "%-8s", "offset");
    for (i = 0; i < m; ++i)
        fprintf(f, " %02x", i);
    n = 56;

    if (s->sh_type == SHT_SYMTAB || s->sh_type == SHT_RELX) {
        const char *fields1[] = {
            "name",
            "value",
            "size",
            "bind",
            "type",
            "other",
            "shndx",
            NULL



( run in 0.647 second using v1.01-cache-2.11-cpan-e1769b4cff6 )