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

📄 tccelf.c

📁 一个GNU的C语言编译器源代码,源代码过万行.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* 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, esym_index;    unsigned char *ptr;    unsigned long val, addr;    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) {        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;        }    }    /* 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;}static uint32_t get32(unsigned char *p){    return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);}static 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;        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;        }        index = put_elf_sym(s1->dynsym, offset,                             size, info, 0, sym->st_shndx, name);        /* put a got entry */        put_elf_reloc(s1->dynsym, s1->got,                       s1->got->data_offset,                       reloc_type, index);    }    ptr = section_ptr_add(s1->got, sizeof(int));    *ptr = 0;}/* build GOT and PLT entries */static void build_got_entries(TCCState *s1){    Section *s, *symtab;    Elf32_Rel *rel, *rel_end;    Elf32_Sym *sym;    int i, type, reloc_type, sym_index;    for(i = 1; i < s1->nb_sections; i++) {        s = s1->sections[i];        if (s->sh_type != SHT_REL)            continue;        /* no need to handle got relocations */        if (s->link != symtab_section)            continue;        symtab = s->link;        rel_end = (Elf32_Rel *)(s->data + s->data_offset);        for(rel = (Elf32_Rel *)s->data;            rel < rel_end;            rel++) {            type = ELF32_R_TYPE(rel->r_info);            switch(type) {            case R_386_GOT32:            case R_386_GOTOFF:            case R_386_GOTPC:            case R_386_PLT32:                if (!s1->got)                    build_got(s1);                if (type == R_386_GOT32 || type == R_386_PLT32) {                    sym_index = ELF32_R_SYM(rel->r_info);                    sym = &((Elf32_Sym *)symtab_section->data)[sym_index];                    /* look at the symbol got offset. If none, then add one */                    if (type == R_386_GOT32)                        reloc_type = R_386_GLOB_DAT;                    else                        reloc_type = R_386_JMP_SLOT;                    put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,                                   sym_index);                }                break;            default:                break;            }        }    }}static Section *new_symtab(TCCState *s1,                           const char *symtab_name, int sh_type, int sh_flags,                           const char *strtab_name,                            const char *hash_name, int hash_sh_flags){    Section *symtab, *strtab, *hash;    int *ptr, nb_buckets;    symtab = new_section(s1, symtab_name, sh_type, sh_flags);    symtab->sh_entsize = sizeof(Elf32_Sym);    strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);    put_elf_str(strtab, "");    symtab->link = strtab;    put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);        nb_buckets = 1;    hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);    hash->sh_entsize = sizeof(int);    symtab->hash = hash;    hash->link = symtab;    ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));    ptr[0] = nb_buckets;    ptr[1] = 1;    memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));    return symtab;}/* put dynamic tag */static void put_dt(Section *dynamic, int dt, unsigned long val){    Elf32_Dyn *dyn;    dyn = section_ptr_add(dynamic, sizeof(Elf32_Dyn));    dyn->d_tag = dt;    dyn->d_un.d_val = val;}static void add_init_array_defines(TCCState *s1, const char *section_name){

⌨️ 快捷键说明

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