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

📄 tccelf.c

📁 Tiny C&C++,看看吧,也许用的着
💻 C
📖 第 1 页 / 共 5 页
字号:
            put_dt(dynamic, DT_STRSZ, dynstr->data_offset);            put_dt(dynamic, DT_SYMENT, sizeof(Elf32_Sym));            put_dt(dynamic, DT_REL, rel_addr);            put_dt(dynamic, DT_RELSZ, rel_size);            put_dt(dynamic, DT_RELENT, sizeof(Elf32_Rel));            put_dt(dynamic, DT_NULL, 0);        }        ehdr.e_phentsize = sizeof(Elf32_Phdr);        ehdr.e_phnum = phnum;        ehdr.e_phoff = sizeof(Elf32_Ehdr);    }    /* all other sections come after */    for(i = 1; i < s1->nb_sections; i++) {        s = s1->sections[i];        if (phnum > 0 && (s->sh_flags & SHF_ALLOC))            continue;        section_order[sh_order_index++] = i;                file_offset = (file_offset + s->sh_addralign - 1) &             ~(s->sh_addralign - 1);        s->sh_offset = file_offset;        if (s->sh_type != SHT_NOBITS)            file_offset += s->sh_size;    }        /* if building executable or DLL, then relocate each section       except the GOT which is already relocated */    if (file_type != TCC_OUTPUT_OBJ) {        relocate_syms(s1, 0);        if (s1->nb_errors != 0) {        fail:            ret = -1;            goto the_end;        }        /* relocate sections */        /* XXX: ignore sections with allocated relocations ? */        for(i = 1; i < s1->nb_sections; i++) {            s = s1->sections[i];            if (s->reloc && s != s1->got)                relocate_section(s1, s);        }        /* relocate relocation entries if the relocation tables are           allocated in the executable */        for(i = 1; i < s1->nb_sections; i++) {            s = s1->sections[i];            if ((s->sh_flags & SHF_ALLOC) &&                s->sh_type == SHT_REL) {                relocate_rel(s1, s);            }        }        /* get entry point address */        if (file_type == TCC_OUTPUT_EXE)            ehdr.e_entry = (unsigned long)tcc_get_symbol_err(s1, "_start");        else            ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */    }    /* write elf file */    if (file_type == TCC_OUTPUT_OBJ)        mode = 0666;    else        mode = 0777;    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);     if (fd < 0) {        error_noabort("could not write '%s'", filename);        goto fail;    }    f = fdopen(fd, "wb");#ifdef TCC_TARGET_COFF    if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {        tcc_output_coff(s1, f);    } else#endif    if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {        sort_syms(s1, symtab_section);                /* align to 4 */        file_offset = (file_offset + 3) & -4;            /* fill header */        ehdr.e_ident[0] = ELFMAG0;        ehdr.e_ident[1] = ELFMAG1;        ehdr.e_ident[2] = ELFMAG2;        ehdr.e_ident[3] = ELFMAG3;        ehdr.e_ident[4] = ELFCLASS32;        ehdr.e_ident[5] = ELFDATA2LSB;        ehdr.e_ident[6] = EV_CURRENT;#ifdef __FreeBSD__        ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;#endif#ifdef TCC_TARGET_ARM        ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;#endif        switch(file_type) {        default:        case TCC_OUTPUT_EXE:            ehdr.e_type = ET_EXEC;            break;        case TCC_OUTPUT_DLL:            ehdr.e_type = ET_DYN;            break;        case TCC_OUTPUT_OBJ:            ehdr.e_type = ET_REL;            break;        }        ehdr.e_machine = EM_TCC_TARGET;        ehdr.e_version = EV_CURRENT;        ehdr.e_shoff = file_offset;        ehdr.e_ehsize = sizeof(Elf32_Ehdr);        ehdr.e_shentsize = sizeof(Elf32_Shdr);        ehdr.e_shnum = shnum;        ehdr.e_shstrndx = shnum - 1;                fwrite(&ehdr, 1, sizeof(Elf32_Ehdr), f);        fwrite(phdr, 1, phnum * sizeof(Elf32_Phdr), f);        offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);        for(i=1;i<s1->nb_sections;i++) {            s = s1->sections[section_order[i]];            if (s->sh_type != SHT_NOBITS) {                while (offset < s->sh_offset) {                    fputc(0, f);                    offset++;                }                size = s->sh_size;                fwrite(s->data, 1, size, f);                offset += size;            }        }        /* output section headers */        while (offset < ehdr.e_shoff) {            fputc(0, f);            offset++;        }            for(i=0;i<s1->nb_sections;i++) {            sh = &shdr;            memset(sh, 0, sizeof(Elf32_Shdr));            s = s1->sections[i];            if (s) {                sh->sh_name = s->sh_name;                sh->sh_type = s->sh_type;                sh->sh_flags = s->sh_flags;                sh->sh_entsize = s->sh_entsize;                sh->sh_info = s->sh_info;                if (s->link)                    sh->sh_link = s->link->sh_num;                sh->sh_addralign = s->sh_addralign;                sh->sh_addr = s->sh_addr;                sh->sh_offset = s->sh_offset;                sh->sh_size = s->sh_size;            }            fwrite(sh, 1, sizeof(Elf32_Shdr), f);        }    } else {        tcc_output_binary(s1, f, section_order);    }    fclose(f);    ret = 0; the_end:    tcc_free(s1->symtab_to_dynsym);    tcc_free(section_order);    tcc_free(phdr);    tcc_free(s1->got_offsets);    return ret;}static void *load_data(int fd, unsigned long file_offset, unsigned long size){    void *data;    data = tcc_malloc(size);    lseek(fd, file_offset, SEEK_SET);    read(fd, data, size);    return data;}typedef struct SectionMergeInfo {    Section *s;            /* corresponding existing section */    unsigned long offset;  /* offset of the new section in the existing section */    uint8_t new_section;       /* true if section 's' was added */    uint8_t link_once;         /* true if link once section */} SectionMergeInfo;/* load an object file and merge it with current files *//* XXX: handle correctly stab (debug) info */static int tcc_load_object_file(TCCState *s1,                                 int fd, unsigned long file_offset){     Elf32_Ehdr ehdr;    Elf32_Shdr *shdr, *sh;    int size, i, j, offset, offseti, nb_syms, sym_index, ret;    unsigned char *strsec, *strtab;    int *old_to_new_syms;    char *sh_name, *name;    SectionMergeInfo *sm_table, *sm;    Elf32_Sym *sym, *symtab;    Elf32_Rel *rel, *rel_end;    Section *s;    if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))        goto fail1;    if (ehdr.e_ident[0] != ELFMAG0 ||        ehdr.e_ident[1] != ELFMAG1 ||        ehdr.e_ident[2] != ELFMAG2 ||        ehdr.e_ident[3] != ELFMAG3)        goto fail1;    /* test if object file */    if (ehdr.e_type != ET_REL)        goto fail1;    /* test CPU specific stuff */    if (ehdr.e_ident[5] != ELFDATA2LSB ||        ehdr.e_machine != EM_TCC_TARGET) {    fail1:        error_noabort("invalid object file");        return -1;    }    /* read sections */    shdr = load_data(fd, file_offset + ehdr.e_shoff,                      sizeof(Elf32_Shdr) * ehdr.e_shnum);    sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);        /* load section names */    sh = &shdr[ehdr.e_shstrndx];    strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);    /* load symtab and strtab */    old_to_new_syms = NULL;    symtab = NULL;    strtab = NULL;    nb_syms = 0;    for(i = 1; i < ehdr.e_shnum; i++) {        sh = &shdr[i];        if (sh->sh_type == SHT_SYMTAB) {            if (symtab) {                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];        off

⌨️ 快捷键说明

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