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

📄 tccelf.c

📁 一个GNU的C语言编译器源代码,源代码过万行.
💻 C
📖 第 1 页 / 共 5 页
字号:
                error_noabort("object must contain only one symtab");            fail:                ret = -1;                goto the_end;            }            nb_syms = sh->sh_size / sizeof(Elf32_Sym);            symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);            sm_table[i].s = symtab_section;            /* now load strtab */            sh = &shdr[sh->sh_link];            strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);        }    }            /* now examine each section and try to merge its content with the       ones in memory */    for(i = 1; i < ehdr.e_shnum; i++) {        /* no need to examine section name strtab */        if (i == ehdr.e_shstrndx)            continue;        sh = &shdr[i];        sh_name = strsec + sh->sh_name;        /* ignore sections types we do not handle */        if (sh->sh_type != SHT_PROGBITS &&            sh->sh_type != SHT_REL &&             sh->sh_type != SHT_NOBITS)            continue;        if (sh->sh_addralign < 1)            sh->sh_addralign = 1;        /* find corresponding section, if any */        for(j = 1; j < s1->nb_sections;j++) {            s = s1->sections[j];            if (!strcmp(s->name, sh_name)) {                if (!strncmp(sh_name, ".gnu.linkonce",                              sizeof(".gnu.linkonce") - 1)) {                    /* if a 'linkonce' section is already present, we                       do not add it again. It is a little tricky as                       symbols can still be defined in                       it. */                    sm_table[i].link_once = 1;                    goto next;                } else {                    goto found;                }            }        }        /* not found: create new section */        s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);        /* take as much info as possible from the section. sh_link and           sh_info will be updated later */        s->sh_addralign = sh->sh_addralign;        s->sh_entsize = sh->sh_entsize;        sm_table[i].new_section = 1;    found:        if (sh->sh_type != s->sh_type) {            error_noabort("invalid section type");            goto fail;        }        /* align start of section */        offset = s->data_offset;        size = sh->sh_addralign - 1;        offset = (offset + size) & ~size;        if (sh->sh_addralign > s->sh_addralign)            s->sh_addralign = sh->sh_addralign;        s->data_offset = offset;        sm_table[i].offset = offset;        sm_table[i].s = s;        /* concatenate sections */        size = sh->sh_size;        if (sh->sh_type != SHT_NOBITS) {            unsigned char *ptr;            lseek(fd, file_offset + sh->sh_offset, SEEK_SET);            ptr = section_ptr_add(s, size);            read(fd, ptr, size);        } else {            s->data_offset += size;        }    next: ;    }    /* second short pass to update sh_link and sh_info fields of new       sections */    sm = sm_table;    for(i = 1; i < ehdr.e_shnum; i++) {        s = sm_table[i].s;        if (!s || !sm_table[i].new_section)            continue;        sh = &shdr[i];        if (sh->sh_link > 0)            s->link = sm_table[sh->sh_link].s;        if (sh->sh_type == SHT_REL) {            s->sh_info = sm_table[sh->sh_info].s->sh_num;            /* update backward link */            s1->sections[s->sh_info]->reloc = s;        }    }    /* resolve symbols */    old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));    sym = symtab + 1;    for(i = 1; i < nb_syms; i++, sym++) {        if (sym->st_shndx != SHN_UNDEF &&            sym->st_shndx < SHN_LORESERVE) {            sm = &sm_table[sym->st_shndx];            if (sm->link_once) {                /* if a symbol is in a link once section, we use the                   already defined symbol. It is very important to get                   correct relocations */                if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {                    name = strtab + sym->st_name;                    sym_index = find_elf_sym(symtab_section, name);                    if (sym_index)                        old_to_new_syms[i] = sym_index;                }                continue;            }            /* if no corresponding section added, no need to add symbol */            if (!sm->s)                continue;            /* convert section number */            sym->st_shndx = sm->s->sh_num;            /* offset value */            sym->st_value += sm->offset;        }        /* add symbol */        name = strtab + sym->st_name;        sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,                                 sym->st_info, sym->st_shndx, name);        old_to_new_syms[i] = sym_index;    }    /* third pass to patch relocation entries */    for(i = 1; i < ehdr.e_shnum; i++) {        s = sm_table[i].s;        if (!s)            continue;        sh = &shdr[i];        offset = sm_table[i].offset;        switch(s->sh_type) {        case SHT_REL:            /* take relocation offset information */            offseti = sm_table[sh->sh_info].offset;            rel_end = (Elf32_Rel *)(s->data + s->data_offset);            for(rel = (Elf32_Rel *)(s->data + offset);                rel < rel_end;                rel++) {                int type;                unsigned sym_index;                /* convert symbol index */                type = ELF32_R_TYPE(rel->r_info);                sym_index = ELF32_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];                if (!sym_index) {                invalid_reloc:                    error_noabort("Invalid relocation entry");                    goto fail;                }                rel->r_info = ELF32_R_INFO(sym_index, type);                /* offset the relocation offset */                rel->r_offset += offseti;            }            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;}#define ARMAG  "!<arch>\012"	/* For COFF and a.out archives */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);}/* load only the objects which resolve undefined symbols */static int tcc_load_alacarte(TCCState *s1, int fd, int size){    int i, bound, nsyms, sym_index, off, ret;    uint8_t *data;    const char *ar_names, *p;    const uint8_t *ar_index;    Elf32_Sym *sym;    data = tcc_malloc(size);    if (read(fd, data, size) != size)        goto fail;    nsyms = get_be32(data);    ar_index = data + 4;    ar_names = ar_index + nsyms * 4;    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 = &((Elf32_Sym *)symtab_section->data)[sym_index];		if(sym->st_shndx == SHN_UNDEF) {		    off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);#if 0		    printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);#endif		    ++bound;		    lseek(fd, off, SEEK_SET);		    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;}/* load a '.a' file */static int tcc_load_archive(TCCState *s1, int fd){    ArchiveHeader hdr;    char ar_size[11];    char ar_name[17];    char magic[8];    int size, len, i;    unsigned long file_offset;    /* skip magic which was already checked */    read(fd, magic, sizeof(magic));        for(;;) {        len = read(fd, &hdr, sizeof(hdr));        if (len == 0)            break;        if (len != sizeof(hdr)) {            error_noabort("invalid archive");            return -1;        }        memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));        ar_size[sizeof(hdr.ar_size)] = '\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';        //        printf("name='%s' size=%d %s\n", ar_name, size, ar_size);        file_offset = lseek(fd, 0, SEEK_CUR);        /* align to even */        size = (size + 1) & ~1;        if (!strcmp(ar_name, "/")) {            /* coff symbol table : we handle it */	    if(s1->alacarte_link)		return tcc_load_alacarte(s1, fd, size);        } else if (!strcmp(ar_name, "//") ||                   !strcmp(ar_name, "__.SYMDEF") ||                   !strcmp(ar_name, "__.SYMDEF/") ||                   !strcmp(ar_name, "ARFILENAMES/")) {            /* skip symbol table or archive names */        } else {            if (tcc_load_object_file(s1, fd, file_offset) < 0)                return -1;        }        lseek(fd, file_offset + size, SEEK_SET);    }    return 0;}/* load a DLL and all referenced DLLs. 'level = 0' means that the DLL   is referenced by the user (so it should be added as DT_NEEDED in   the generated ELF file) */static int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level){     Elf32_Ehdr ehdr;    Elf32_Shdr *shdr, *sh, *sh1;    int i, nb_syms, nb_dts, sym_bind, ret;    Elf32_Sym *sym, *dynsym;    Elf32_Dyn *dt, *dynamic;    unsigned char *dynstr;    const char *name, *soname, *p;    DLLReference *dllref;        read(fd, &ehdr, sizeof(ehdr));    /* test CPU specific stuff */    if (ehdr.e_ident[5] != ELFDATA2LSB ||        ehdr.e_machine != EM_386) {        error_noabort("bad architecture");        return -1;    }    /* read sections */    shdr = load_data(fd, ehdr.e_shoff, sizeof(Elf32_Shdr) * ehdr.e_shnum);    /* load dynamic section and dynamic symbols */    nb_syms = 0;    nb_dts = 0;    dynamic = NULL;    dynsym = NULL; /* avoid warning */    dynstr = NULL; /* avoid warning */    for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {        switch(sh->sh_type) {        case SHT_DYNAMIC:            nb_dts = sh->sh_size / sizeof(Elf32_Dyn);            dynamic = load_data(fd, sh->sh_offset, sh->sh_size);            break;        case SHT_DYNSYM:            nb_syms = sh->sh_size / sizeof(Elf32_Sym);            dynsym = load_data(fd, sh->sh_offset, sh->sh_size);            sh1 = &shdr[sh->sh_link];            dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);            break;        default:            break;        }    }        /* compute the real library name */    soname = filename;    p = strrchr(soname, '/');    if (p)        soname = p + 1;            for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {        if (dt->d_tag == DT_SONAME) {            soname = dynstr + dt->d_un.d_val;        }    }    /* if the dll is already loaded, do not load it */    for(i = 0; i < s1->nb_loaded_dlls; i++) {        dllref = s1->loaded_dlls[i];        if (!strcmp(soname, dllref->name)) {            /* but update level if needed */            if (level < dllref->level)                dllref->level = level;            ret = 0;            goto the_end;        }    }        //    printf("loading dll '%s'\n", soname);    /* add the dll and its level */    dllref = tcc_malloc(sizeof(DLLReference) + strlen(soname));    dllref->level = level;    strcpy(dllref->name, soname);    dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);    /* add dynamic symbols in dynsym_section */    for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {        sym_bind = ELF32_ST_BIND(sym->st_info);        if (sym_bind == STB_LOCAL)            continue;        name = dynstr + sym->st_name;        add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,                    sym->st_info, sym->st_shndx, name);    }  

⌨️ 快捷键说明

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