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

📄 tccelf.c

📁 Tiny C&C++,看看吧,也许用的着
💻 C
📖 第 1 页 / 共 5 页
字号:
            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_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_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));            if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {        file_offset = sizeof(Elf32_Ehdr) + phnum * sizeof(Elf32_Phdr);    } else {        file_offset = 0;    }    if (phnum > 0) {        /* compute section to program header mapping */        if (s1->has_text_addr) {             int a_offset, p_offset;            addr = s1->text_addr;            /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %               ELF_PAGE_SIZE */            a_offset = addr & (ELF_PAGE_SIZE - 1);            p_offset = file_offset & (ELF_PAGE_SIZE - 1);            if (a_offset < p_offset)                 a_offset += ELF_PAGE_SIZE;            file_offset += (a_offset - p_offset);        } else {            if (file_type == TCC_OUTPUT_DLL)                addr = 0;            else                addr = ELF_START_ADDR;            /* compute address after headers */            addr += (file_offset & (ELF_PAGE_SIZE - 1));        }                /* dynamic relocation table information, for .dynamic section */        rel_size = 0;        rel_addr = 0;        /* 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 = addr;                    addr = (addr + s->sh_addralign - 1) &                         ~(s->sh_addralign - 1);                    file_offset += addr - tmp;                    s->sh_offset = file_offset;                    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 (j == 0) {                if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {                    /* 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;                } else {                    addr = (addr + ELF_PAGE_SIZE - 1) & ~(ELF_PAGE_SIZE - 1);                    file_offset = (file_offset + ELF_PAGE_SIZE - 1) &                         ~(ELF_PAGE_SIZE - 1);                }            }        }        /* 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) {#if defined(TCC_TARGET_I386)                    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;                    }#elif defined(TCC_TARGET_ARM)		    int x;		    x=s1->got->sh_addr - s1->plt->sh_addr - 12;		    p +=16;		    while (p < p_end) {		        put32(p + 12, x + get32(p + 12) + s1->plt->data - p);			p += 16;		    }#elif defined(TCC_TARGET_C67)                    /* XXX: TODO */#else#error unsupported CPU#endif                }            }            /* 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);

⌨️ 快捷键说明

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