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

📄 tccelf.c

📁 一个GNU的C语言编译器源代码,源代码过万行.
💻 C
📖 第 1 页 / 共 5 页
字号:
        else            addr = ELF_START_ADDR;        /* dynamic relocation table information, for .dynamic section */        rel_size = 0;        rel_addr = 0;        /* compute address after headers */        addr += (file_offset & (ELF_PAGE_SIZE - 1));                /* leave one program header for the program interpreter */        ph = &phdr[0];        if (interp)            ph++;        for(j = 0; j < 2; j++) {            ph->p_type = PT_LOAD;            if (j == 0)                ph->p_flags = PF_R | PF_X;            else                ph->p_flags = PF_R | PF_W;            ph->p_align = ELF_PAGE_SIZE;                        /* we do the following ordering: interp, symbol tables,               relocations, progbits, nobits */            /* XXX: do faster and simpler sorting */            for(k = 0; k < 5; k++) {                for(i = 1; i < s1->nb_sections; i++) {                    s = s1->sections[i];                    /* compute if section should be included */                    if (j == 0) {                        if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=                             SHF_ALLOC)                            continue;                    } else {                        if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=                             (SHF_ALLOC | SHF_WRITE))                            continue;                    }                    if (s == interp) {                        if (k != 0)                            continue;                    } else if (s->sh_type == SHT_DYNSYM ||                               s->sh_type == SHT_STRTAB ||                               s->sh_type == SHT_HASH) {                        if (k != 1)                            continue;                    } else if (s->sh_type == SHT_REL) {                        if (k != 2)                            continue;                    } else if (s->sh_type == SHT_NOBITS) {                        if (k != 4)                            continue;                    } else {                        if (k != 3)                            continue;                    }                    section_order[sh_order_index++] = i;                    /* section matches: we align it and add its size */                    tmp = file_offset;                    file_offset = (file_offset + s->sh_addralign - 1) &                         ~(s->sh_addralign - 1);                    s->sh_offset = file_offset;                    addr += file_offset - tmp;                    s->sh_addr = addr;                                        /* update program header infos */                    if (ph->p_offset == 0) {                        ph->p_offset = file_offset;                        ph->p_vaddr = addr;                        ph->p_paddr = ph->p_vaddr;                    }                    /* update dynamic relocation infos */                    if (s->sh_type == SHT_REL) {                        if (rel_size == 0)                            rel_addr = addr;                        rel_size += s->sh_size;                    }                    addr += s->sh_size;                    if (s->sh_type != SHT_NOBITS)                        file_offset += s->sh_size;                }            }            ph->p_filesz = file_offset - ph->p_offset;            ph->p_memsz = addr - ph->p_vaddr;            ph++;            /* if in the middle of a page, we duplicate the page in               memory so that one copy is RX and the other is RW */            if ((addr & (ELF_PAGE_SIZE - 1)) != 0)                addr += ELF_PAGE_SIZE;        }        /* if interpreter, then add corresponing program header */        if (interp) {            ph = &phdr[0];                        ph->p_type = PT_INTERP;            ph->p_offset = interp->sh_offset;            ph->p_vaddr = interp->sh_addr;            ph->p_paddr = ph->p_vaddr;            ph->p_filesz = interp->sh_size;            ph->p_memsz = interp->sh_size;            ph->p_flags = PF_R;            ph->p_align = interp->sh_addralign;        }                /* if dynamic section, then add corresponing program header */        if (dynamic) {            Elf32_Sym *sym_end;            ph = &phdr[phnum - 1];                        ph->p_type = PT_DYNAMIC;            ph->p_offset = dynamic->sh_offset;            ph->p_vaddr = dynamic->sh_addr;            ph->p_paddr = ph->p_vaddr;            ph->p_filesz = dynamic->sh_size;            ph->p_memsz = dynamic->sh_size;            ph->p_flags = PF_R | PF_W;            ph->p_align = dynamic->sh_addralign;            /* put GOT dynamic section address */            put32(s1->got->data, dynamic->sh_addr);            /* relocate the PLT */            if (file_type == TCC_OUTPUT_EXE) {                uint8_t *p, *p_end;                p = s1->plt->data;                p_end = p + s1->plt->data_offset;                if (p < p_end) {                    put32(p + 2, get32(p + 2) + s1->got->sh_addr);                    put32(p + 8, get32(p + 8) + s1->got->sh_addr);                    p += 16;                    while (p < p_end) {                        put32(p + 2, get32(p + 2) + s1->got->sh_addr);                        p += 16;                    }                }            }            /* relocate symbols in .dynsym */            sym_end = (Elf32_Sym *)(s1->dynsym->data + s1->dynsym->data_offset);            for(sym = (Elf32_Sym *)s1->dynsym->data + 1;                 sym < sym_end;                sym++) {                if (sym->st_shndx == SHN_UNDEF) {                    /* relocate to the PLT if the symbol corresponds                       to a PLT entry */                    if (sym->st_value)                        sym->st_value += s1->plt->sh_addr;                } else if (sym->st_shndx < SHN_LORESERVE) {                    /* do symbol relocation */                    sym->st_value += s1->sections[sym->st_shndx]->sh_addr;                }            }            /* put dynamic section entries */            dynamic->data_offset = saved_dynamic_data_offset;            put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);            put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);            put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);            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 ? */    }    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    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_386;    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;        /* write elf file */    if (file_type == TCC_OUTPUT_OBJ)        mode = 0666;    else        mode = 0777;    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, mode);     if (fd < 0) {        error_noabort("could not write '%s'", filename);        goto fail;    }    f = fdopen(fd, "w");    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;        }    }    while (offset < ehdr.e_shoff) {        fputc(0, f);        offset++;    }        /* output section headers */    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);    }    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_386) {    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) {

⌨️ 快捷键说明

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