⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tccelf.c

📁 Tiny C&C++,看看吧,也许用的着
💻 C
📖 第 1 页 / 共 5 页
字号:
{    return dlsym(RTLD_DEFAULT, sym);}/* relocate symbol table, resolve undefined symbols if do_resolve is   true and output error if undefined symbol. */static void relocate_syms(TCCState *s1, int do_resolve){    Elf32_Sym *sym, *esym, *sym_end;    int sym_bind, sh_num, sym_index;    const char *name;    unsigned long addr;    sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);    for(sym = (Elf32_Sym *)symtab_section->data + 1;         sym < sym_end;        sym++) {        sh_num = sym->st_shndx;        if (sh_num == SHN_UNDEF) {            name = strtab_section->data + sym->st_name;            if (do_resolve) {                name = symtab_section->link->data + sym->st_name;                addr = (unsigned long)resolve_sym(name);                if (addr) {                    sym->st_value = addr;                    goto found;                }            } else if (s1->dynsym) {                /* if dynamic symbol exist, then use it */                sym_index = find_elf_sym(s1->dynsym, name);                if (sym_index) {                    esym = &((Elf32_Sym *)s1->dynsym->data)[sym_index];                    sym->st_value = esym->st_value;                    goto found;                }            }            /* XXX: _fp_hw seems to be part of the ABI, so we ignore               it */            if (!strcmp(name, "_fp_hw"))                goto found;            /* only weak symbols are accepted to be undefined. Their               value is zero */            sym_bind = ELF32_ST_BIND(sym->st_info);            if (sym_bind == STB_WEAK) {                sym->st_value = 0;            } else {                error_noabort("undefined symbol '%s'", name);            }        } else if (sh_num < SHN_LORESERVE) {            /* add section base */            sym->st_value += s1->sections[sym->st_shndx]->sh_addr;        }    found: ;    }}/* relocate a given section (CPU dependent) */static void relocate_section(TCCState *s1, Section *s){    Section *sr;    Elf32_Rel *rel, *rel_end, *qrel;    Elf32_Sym *sym;    int type, sym_index;    unsigned char *ptr;    unsigned long val, addr;#if defined(TCC_TARGET_I386)    int esym_index;#endif    sr = s->reloc;    rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);    qrel = (Elf32_Rel *)sr->data;    for(rel = qrel;        rel < rel_end;        rel++) {        ptr = s->data + rel->r_offset;        sym_index = ELF32_R_SYM(rel->r_info);        sym = &((Elf32_Sym *)symtab_section->data)[sym_index];        val = sym->st_value;        type = ELF32_R_TYPE(rel->r_info);        addr = s->sh_addr + rel->r_offset;        /* CPU specific */        switch(type) {#if defined(TCC_TARGET_I386)        case R_386_32:            if (s1->output_type == TCC_OUTPUT_DLL) {                esym_index = s1->symtab_to_dynsym[sym_index];                qrel->r_offset = rel->r_offset;                if (esym_index) {                    qrel->r_info = ELF32_R_INFO(esym_index, R_386_32);                    qrel++;                    break;                } else {                    qrel->r_info = ELF32_R_INFO(0, R_386_RELATIVE);                    qrel++;                }            }            *(int *)ptr += val;            break;        case R_386_PC32:            if (s1->output_type == TCC_OUTPUT_DLL) {                /* DLL relocation */                esym_index = s1->symtab_to_dynsym[sym_index];                if (esym_index) {                    qrel->r_offset = rel->r_offset;                    qrel->r_info = ELF32_R_INFO(esym_index, R_386_PC32);                    qrel++;                    break;                }            }            *(int *)ptr += val - addr;            break;        case R_386_PLT32:            *(int *)ptr += val - addr;            break;        case R_386_GLOB_DAT:        case R_386_JMP_SLOT:            *(int *)ptr = val;            break;        case R_386_GOTPC:            *(int *)ptr += s1->got->sh_addr - addr;            break;        case R_386_GOTOFF:            *(int *)ptr += val - s1->got->sh_addr;            break;        case R_386_GOT32:            /* we load the got offset */            *(int *)ptr += s1->got_offsets[sym_index];            break;#elif defined(TCC_TARGET_ARM)	case R_ARM_PC24:	case R_ARM_PLT32:	    {                int x;                x = (*(int *)ptr)&0xffffff;                (*(int *)ptr) &= 0xff000000;                if (x & 0x800000)                    x -= 0x1000000;                x *= 4;                x += val - addr;                if((x & 3) != 0 || x >= 0x4000000 || x < -0x4000000)                    error("can't relocate value at %x",addr);                x >>= 2;                x &= 0xffffff;                (*(int *)ptr) |= x;	    }	    break;	case R_ARM_ABS32:	    *(int *)ptr += val;	    break;	case R_ARM_GOTPC:	    *(int *)ptr += s1->got->sh_addr - addr;	    break;        case R_ARM_GOT32:            /* we load the got offset */            *(int *)ptr += s1->got_offsets[sym_index];            break;	case R_ARM_COPY:            break;	default:	    fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",                    type,addr,(unsigned int )ptr,val);            break;#elif defined(TCC_TARGET_C67)	case R_C60_32:	    *(int *)ptr += val;	    break;        case R_C60LO16:            {                uint32_t orig;                                /* put the low 16 bits of the absolute address */                // add to what is already there                                orig  =   ((*(int *)(ptr  )) >> 7) & 0xffff;                orig |=  (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;                                //patch both at once - assumes always in pairs Low - High                                *(int *) ptr    = (*(int *) ptr    & (~(0xffff << 7)) ) |  (((val+orig)      & 0xffff) << 7);                *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);            }            break;        case R_C60HI16:            break;        default:	    fprintf(stderr,"FIXME: handle reloc type %x at %lx [%.8x] to %lx\n",                    type,addr,(unsigned int )ptr,val);            break;#else#error unsupported processor#endif        }    }    /* if the relocation is allocated, we change its symbol table */    if (sr->sh_flags & SHF_ALLOC)        sr->link = s1->dynsym;}/* relocate relocation table in 'sr' */static void relocate_rel(TCCState *s1, Section *sr){    Section *s;    Elf32_Rel *rel, *rel_end;        s = s1->sections[sr->sh_info];    rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);    for(rel = (Elf32_Rel *)sr->data;        rel < rel_end;        rel++) {        rel->r_offset += s->sh_addr;    }}/* count the number of dynamic relocations so that we can reserve   their space */static int prepare_dynamic_rel(TCCState *s1, Section *sr){    Elf32_Rel *rel, *rel_end;    int sym_index, esym_index, type, count;    count = 0;    rel_end = (Elf32_Rel *)(sr->data + sr->data_offset);    for(rel = (Elf32_Rel *)sr->data; rel < rel_end; rel++) {        sym_index = ELF32_R_SYM(rel->r_info);        type = ELF32_R_TYPE(rel->r_info);        switch(type) {        case R_386_32:            count++;            break;        case R_386_PC32:            esym_index = s1->symtab_to_dynsym[sym_index];            if (esym_index)                count++;            break;        default:            break;        }    }    if (count) {        /* allocate the section */        sr->sh_flags |= SHF_ALLOC;        sr->sh_size = count * sizeof(Elf32_Rel);    }    return count;}static void put_got_offset(TCCState *s1, int index, unsigned long val){    int n;    unsigned long *tab;    if (index >= s1->nb_got_offsets) {        /* find immediately bigger power of 2 and reallocate array */        n = 1;        while (index >= n)            n *= 2;        tab = tcc_realloc(s1->got_offsets, n * sizeof(unsigned long));        if (!tab)            error("memory full");        s1->got_offsets = tab;        memset(s1->got_offsets + s1->nb_got_offsets, 0,               (n - s1->nb_got_offsets) * sizeof(unsigned long));        s1->nb_got_offsets = n;    }    s1->got_offsets[index] = val;}/* XXX: suppress that */static void put32(unsigned char *p, uint32_t val){    p[0] = val;    p[1] = val >> 8;    p[2] = val >> 16;    p[3] = val >> 24;}#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM)static uint32_t get32(unsigned char *p){    return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);}#endifstatic void build_got(TCCState *s1){    unsigned char *ptr;    /* if no got, then create it */    s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);    s1->got->sh_entsize = 4;    add_elf_sym(symtab_section, 0, 4, ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT),                 s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");    ptr = section_ptr_add(s1->got, 3 * sizeof(int));    /* keep space for _DYNAMIC pointer, if present */    put32(ptr, 0);    /* two dummy got entries */    put32(ptr + 4, 0);    put32(ptr + 8, 0);}/* put a got entry corresponding to a symbol in symtab_section. 'size'   and 'info' can be modifed if more precise info comes from the DLL */static void put_got_entry(TCCState *s1,                          int reloc_type, unsigned long size, int info,                           int sym_index){    int index;    const char *name;    Elf32_Sym *sym;    unsigned long offset;    int *ptr;    if (!s1->got)        build_got(s1);    /* if a got entry already exists for that symbol, no need to add one */    if (sym_index < s1->nb_got_offsets &&        s1->got_offsets[sym_index] != 0)        return;        put_got_offset(s1, sym_index, s1->got->data_offset);    if (s1->dynsym) {        sym = &((Elf32_Sym *)symtab_section->data)[sym_index];        name = symtab_section->link->data + sym->st_name;        offset = sym->st_value;#ifdef TCC_TARGET_I386        if (reloc_type == R_386_JMP_SLOT) {            Section *plt;            uint8_t *p;            int modrm;            /* if we build a DLL, we add a %ebx offset */            if (s1->output_type == TCC_OUTPUT_DLL)                modrm = 0xa3;            else                modrm = 0x25;            /* add a PLT entry */            plt = s1->plt;            if (plt->data_offset == 0) {                /* first plt entry */                p = section_ptr_add(plt, 16);                p[0] = 0xff; /* pushl got + 4 */                p[1] = modrm + 0x10;                put32(p + 2, 4);                p[6] = 0xff; /* jmp *(got + 8) */                p[7] = modrm;                put32(p + 8, 8);            }            p = section_ptr_add(plt, 16);            p[0] = 0xff; /* jmp *(got + x) */            p[1] = modrm;            put32(p + 2, s1->got->data_offset);            p[6] = 0x68; /* push $xxx */            put32(p + 7, (plt->data_offset - 32) >> 1);            p[11] = 0xe9; /* jmp plt_start */            put32(p + 12, -(plt->data_offset));            /* the symbol is modified so that it will be relocated to               the PLT */            if (s1->output_type == TCC_OUTPUT_EXE)                offset = plt->data_offset - 16;        }#elif defined(TCC_TARGET_ARM)	if (reloc_type == R_ARM_JUMP_SLOT) {            Section *plt;            uint8_t *p;                        /* if we build a DLL, we add a %ebx offset */            if (s1->output_type == TCC_OUTPUT_DLL)                error("DLLs unimplemented!");            /* add a PLT entry */            plt = s1->plt;            if (plt->data_offset == 0) {                /* first plt entry */                p = section_ptr_add(plt, 16);		put32(p     , 0xe52de004);		put32(p +  4, 0xe59fe010);		put32(p +  8, 0xe08fe00e);		put32(p + 12, 0xe5bef008);            }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -