📄 tccelf.c
字号:
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 + -