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

📄 tccelf.c

📁 小而快的c编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
    Section *s;    long end_offset;    char sym_start[1024];    char sym_end[1024];        snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);    snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);    s = find_section(s1, section_name);    if (!s) {        end_offset = 0;        s = data_section;    } else {        end_offset = s->data_offset;    }    add_elf_sym(symtab_section,                 0, 0,                ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),                s->sh_num, sym_start);    add_elf_sym(symtab_section,                 end_offset, 0,                ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),                s->sh_num, sym_end);}/* add tcc runtime libraries */static void tcc_add_runtime(TCCState *s1){    char buf[1024];    int i;    Section *s;    if (!s1->nostdlib) {        snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "libtcc1.a");        tcc_add_file(s1, buf);    }#ifdef CONFIG_TCC_BCHECK    if (do_bounds_check) {        unsigned long *ptr;        Section *init_section;        unsigned char *pinit;        int sym_index;        /* XXX: add an object file to do that */        ptr = section_ptr_add(bounds_section, sizeof(unsigned long));        *ptr = 0;        add_elf_sym(symtab_section, 0, 0,                     ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),                    bounds_section->sh_num, "__bounds_start");        /* add bound check code */        snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "bcheck.o");        tcc_add_file(s1, buf);#ifdef TCC_TARGET_I386        if (s1->output_type != TCC_OUTPUT_MEMORY) {            /* add 'call __bound_init()' in .init section */            init_section = find_section(s1, ".init");            pinit = section_ptr_add(init_section, 5);            pinit[0] = 0xe8;            put32(pinit + 1, -4);            sym_index = find_elf_sym(symtab_section, "__bound_init");            put_elf_reloc(symtab_section, init_section,                           init_section->data_offset - 4, R_386_PC32, sym_index);        }#endif    }#endif    /* add libc */    if (!s1->nostdlib) {        tcc_add_library(s1, "c");    }    /* add crt end if not memory output */    if (s1->output_type != TCC_OUTPUT_MEMORY && !s1->nostdlib) {        tcc_add_file(s1, CONFIG_TCC_CRT_PREFIX "/crtn.o");    }    /* add various standard linker symbols */    add_elf_sym(symtab_section,                 text_section->data_offset, 0,                ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),                text_section->sh_num, "_etext");    add_elf_sym(symtab_section,                 data_section->data_offset, 0,                ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),                data_section->sh_num, "_edata");    add_elf_sym(symtab_section,                 bss_section->data_offset, 0,                ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),                bss_section->sh_num, "_end");    /* horrible new standard ldscript defines */    add_init_array_defines(s1, ".preinit_array");    add_init_array_defines(s1, ".init_array");    add_init_array_defines(s1, ".fini_array");        /* add start and stop symbols for sections whose name can be       expressed in C */    for(i = 1; i < s1->nb_sections; i++) {        s = s1->sections[i];        if (s->sh_type == SHT_PROGBITS &&            (s->sh_flags & SHF_ALLOC)) {            const char *p;            int ch;            /* check if section name can be expressed in C */            p = s->name;            for(;;) {                ch = *p;                if (!ch)                    break;                if (!isid(ch) && !isnum(ch))                    goto next_sec;                p++;            }            snprintf(buf, sizeof(buf), "__start_%s", s->name);            add_elf_sym(symtab_section,                         0, 0,                        ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),                        s->sh_num, buf);            snprintf(buf, sizeof(buf), "__stop_%s", s->name);            add_elf_sym(symtab_section,                        s->data_offset, 0,                        ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE),                        s->sh_num, buf);        }    next_sec: ;    }}/* name of ELF interpreter */#ifdef __FreeBSD__static char elf_interp[] = "/usr/libexec/ld-elf.so.1";#elsestatic char elf_interp[] = "/lib/ld-linux.so.2";#endif#define ELF_START_ADDR 0x08048000#define ELF_PAGE_SIZE  0x1000/* output an ELF file *//* XXX: suppress unneeded sections */int tcc_output_file(TCCState *s1, const char *filename){    Elf32_Ehdr ehdr;    FILE *f;    int fd, mode, ret;    int *section_order;    int shnum, i, phnum, file_offset, offset, size, j, tmp, sh_order_index, k;    unsigned long addr;    Section *strsec, *s;    Elf32_Shdr shdr, *sh;    Elf32_Phdr *phdr, *ph;    Section *interp, *dynamic, *dynstr;    unsigned long saved_dynamic_data_offset;    Elf32_Sym *sym;    int type, file_type;    unsigned long rel_addr, rel_size;        file_type = s1->output_type;    s1->nb_errors = 0;    if (file_type != TCC_OUTPUT_OBJ)        tcc_add_runtime(s1);    phdr = NULL;    section_order = NULL;    interp = NULL;    dynamic = NULL;    dynstr = NULL; /* avoid warning */    saved_dynamic_data_offset = 0; /* avoid warning */        if (file_type != TCC_OUTPUT_OBJ) {        relocate_common_syms();        if (!s1->static_link) {            const char *name;            int sym_index, index;            Elf32_Sym *esym, *sym_end;                        if (file_type == TCC_OUTPUT_EXE) {                char *ptr;                /* add interpreter section only if executable */                interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);                interp->sh_addralign = 1;                ptr = section_ptr_add(interp, sizeof(elf_interp));                strcpy(ptr, elf_interp);            }                    /* add dynamic symbol table */            s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,                                    ".dynstr",                                     ".hash", SHF_ALLOC);            dynstr = s1->dynsym->link;                        /* add dynamic section */            dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,                                   SHF_ALLOC | SHF_WRITE);            dynamic->link = dynstr;            dynamic->sh_entsize = sizeof(Elf32_Dyn);                    /* add PLT */            s1->plt = new_section(s1, ".plt", SHT_PROGBITS,                                   SHF_ALLOC | SHF_EXECINSTR);            s1->plt->sh_entsize = 4;            build_got(s1);            /* scan for undefined symbols and see if they are in the               dynamic symbols. If a symbol STT_FUNC is found, then we               add it in the PLT. If a symbol STT_OBJECT is found, we               add it in the .bss section with a suitable relocation */            sym_end = (Elf32_Sym *)(symtab_section->data +                                     symtab_section->data_offset);            if (file_type == TCC_OUTPUT_EXE) {                for(sym = (Elf32_Sym *)symtab_section->data + 1;                     sym < sym_end;                    sym++) {                    if (sym->st_shndx == SHN_UNDEF) {                        name = symtab_section->link->data + sym->st_name;                        sym_index = find_elf_sym(s1->dynsymtab_section, name);                        if (sym_index) {                            esym = &((Elf32_Sym *)s1->dynsymtab_section->data)[sym_index];                            type = ELF32_ST_TYPE(esym->st_info);                            if (type == STT_FUNC) {                                put_got_entry(s1, R_386_JMP_SLOT, esym->st_size,                                               esym->st_info,                                               sym - (Elf32_Sym *)symtab_section->data);                            } else if (type == STT_OBJECT) {                                unsigned long offset;                                offset = bss_section->data_offset;                                /* XXX: which alignment ? */                                offset = (offset + 16 - 1) & -16;                                index = put_elf_sym(s1->dynsym, offset, esym->st_size,                                                     esym->st_info, 0,                                                     bss_section->sh_num, name);                                put_elf_reloc(s1->dynsym, bss_section,                                               offset, R_386_COPY, index);                                offset += esym->st_size;                                bss_section->data_offset = offset;                            }                        } else {                                /* STB_WEAK undefined symbols are accepted */                                /* XXX: _fp_hw seems to be part of the ABI, so we ignore                                   it */                            if (ELF32_ST_BIND(sym->st_info) == STB_WEAK ||                                !strcmp(name, "_fp_hw")) {                            } else {                                error_noabort("undefined symbol '%s'", name);                            }                        }                    } else if (s1->rdynamic &&                                ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {                        /* if -rdynamic option, then export all non                           local symbols */                        name = symtab_section->link->data + sym->st_name;                        put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,                                     sym->st_info, 0,                                     sym->st_shndx, name);                    }                }                            if (s1->nb_errors)                    goto fail;                /* now look at unresolved dynamic symbols and export                   corresponding symbol */                sym_end = (Elf32_Sym *)(s1->dynsymtab_section->data +                                         s1->dynsymtab_section->data_offset);                for(esym = (Elf32_Sym *)s1->dynsymtab_section->data + 1;                     esym < sym_end;                    esym++) {                    if (esym->st_shndx == SHN_UNDEF) {                        name = s1->dynsymtab_section->link->data + esym->st_name;                        sym_index = find_elf_sym(symtab_section, name);                        if (sym_index) {                            /* XXX: avoid adding a symbol if already                               present because of -rdynamic ? */                            sym = &((Elf32_Sym *)symtab_section->data)[sym_index];                            put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,                                         sym->st_info, 0,                                         sym->st_shndx, name);                        } else {                            if (ELF32_ST_BIND(esym->st_info) == STB_WEAK) {                                /* weak symbols can stay undefined */                            } else {                                warning("undefined dynamic symbol '%s'", name);                            }                        }                    }                }            } else {                int nb_syms;                /* shared library case : we simply export all the global symbols */                nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym);                s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);                for(sym = (Elf32_Sym *)symtab_section->data + 1;                     sym < sym_end;                    sym++) {                    if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) {                        name = symtab_section->link->data + sym->st_name;                        index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,                                             sym->st_info, 0,                                             sym->st_shndx, name);                        s1->symtab_to_dynsym[sym -                                             (Elf32_Sym *)symtab_section->data] =                             index;                    }                }            }            build_got_entries(s1);                    /* add a list of needed dlls */            for(i = 0; i < s1->nb_loaded_dlls; i++) {                DLLReference *dllref = s1->loaded_dlls[i];                if (dllref->level == 0)                    put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));            }            /* XXX: currently, since we do not handle PIC code, we               must relocate the readonly segments */            if (file_type == TCC_OUTPUT_DLL)                put_dt(dynamic, DT_TEXTREL, 0);            /* add necessary space for other entries */            saved_dynamic_data_offset = dynamic->data_offset;            dynamic->data_offset += 8 * 9;        } else {            /* still need to build got entries in case of static link */            build_got_entries(s1);        }    }    memset(&ehdr, 0, sizeof(ehdr));    /* we add a section for symbols */    strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);    put_elf_str(strsec, "");        /* compute number of sections */    shnum = s1->nb_sections;    /* this array is used to reorder sections in the output file */    section_order = tcc_malloc(sizeof(int) * shnum);    section_order[0] = 0;    sh_order_index = 1;        /* compute number of program headers */    switch(file_type) {    default:    case TCC_OUTPUT_OBJ:        phnum = 0;        break;    case TCC_OUTPUT_EXE:        if (!s1->static_link)            phnum = 4;        else            phnum = 2;        break;    case TCC_OUTPUT_DLL:        phnum = 3;        break;    }    /* allocate strings for section names and decide if an unallocated       section should be output */    /* NOTE: the strsec section comes last, so its size is also       correct ! */    for(i = 1; i < s1->nb_sections; i++) {        s = s1->sections[i];        s->sh_name = put_elf_str(strsec, s->name);        /* when generating a DLL, we include relocations but we may           patch them */        if (file_type == TCC_OUTPUT_DLL &&             s->sh_type == SHT_REL &&             !(s->sh_flags & SHF_ALLOC)) {            prepare_dynamic_rel(s1, s);        } else if (do_debug ||             file_type == TCC_OUTPUT_OBJ ||             (s->sh_flags & SHF_ALLOC) ||            i == (s1->nb_sections - 1)) {            /* we output all sections if debug or object file */            s->sh_size = s->data_offset;        }    }    /* allocate program segment headers */    phdr = tcc_mallocz(phnum * sizeof(Elf32_Phdr));            file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);    if (phnum > 0) {        /* compute section to program header mapping */        if (file_type == TCC_OUTPUT_DLL)            addr = 0;

⌨️ 快捷键说明

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