📄 tccelf.c
字号:
p = section_ptr_add(plt, 16); put32(p , 0xe59fc004); put32(p+4, 0xe08fc00c); put32(p+8, 0xe59cf000); put32(p+12, s1->got->data_offset); /* the symbol is modified so that it will be relocated to the PLT */ if (s1->output_type == TCC_OUTPUT_EXE) offset = plt->data_offset - 16; }#elif defined(TCC_TARGET_C67) error("C67 got not implemented");#else#error unsupported CPU#endif index = put_elf_sym(s1->dynsym, offset, size, info, 0, sym->st_shndx, name); /* put a got entry */ put_elf_reloc(s1->dynsym, s1->got, s1->got->data_offset, reloc_type, index); } ptr = section_ptr_add(s1->got, sizeof(int)); *ptr = 0;}/* build GOT and PLT entries */static void build_got_entries(TCCState *s1){ Section *s, *symtab; Elf32_Rel *rel, *rel_end; Elf32_Sym *sym; int i, type, reloc_type, sym_index; for(i = 1; i < s1->nb_sections; i++) { s = s1->sections[i]; if (s->sh_type != SHT_REL) continue; /* no need to handle got relocations */ if (s->link != symtab_section) continue; symtab = s->link; rel_end = (Elf32_Rel *)(s->data + s->data_offset); for(rel = (Elf32_Rel *)s->data; rel < rel_end; rel++) { type = ELF32_R_TYPE(rel->r_info); switch(type) {#if defined(TCC_TARGET_I386) case R_386_GOT32: case R_386_GOTOFF: case R_386_GOTPC: case R_386_PLT32: if (!s1->got) build_got(s1); if (type == R_386_GOT32 || type == R_386_PLT32) { sym_index = ELF32_R_SYM(rel->r_info); sym = &((Elf32_Sym *)symtab_section->data)[sym_index]; /* look at the symbol got offset. If none, then add one */ if (type == R_386_GOT32) reloc_type = R_386_GLOB_DAT; else reloc_type = R_386_JMP_SLOT; put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, sym_index); } break;#elif defined(TCC_TARGET_ARM) case R_ARM_GOT32: case R_ARM_GOTOFF: case R_ARM_GOTPC: case R_ARM_PLT32: if (!s1->got) build_got(s1); if (type == R_ARM_GOT32 || type == R_ARM_PLT32) { sym_index = ELF32_R_SYM(rel->r_info); sym = &((Elf32_Sym *)symtab_section->data)[sym_index]; /* look at the symbol got offset. If none, then add one */ if (type == R_ARM_GOT32) reloc_type = R_ARM_GLOB_DAT; else reloc_type = R_ARM_JUMP_SLOT; put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, sym_index); } break;#elif defined(TCC_TARGET_C67) case R_C60_GOT32: case R_C60_GOTOFF: case R_C60_GOTPC: case R_C60_PLT32: if (!s1->got) build_got(s1); if (type == R_C60_GOT32 || type == R_C60_PLT32) { sym_index = ELF32_R_SYM(rel->r_info); sym = &((Elf32_Sym *)symtab_section->data)[sym_index]; /* look at the symbol got offset. If none, then add one */ if (type == R_C60_GOT32) reloc_type = R_C60_GLOB_DAT; else reloc_type = R_C60_JMP_SLOT; put_got_entry(s1, reloc_type, sym->st_size, sym->st_info, sym_index); } break;#else#error unsupported CPU#endif default: break; } } }}static Section *new_symtab(TCCState *s1, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags){ Section *symtab, *strtab, *hash; int *ptr, nb_buckets; symtab = new_section(s1, symtab_name, sh_type, sh_flags); symtab->sh_entsize = sizeof(Elf32_Sym); strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags); put_elf_str(strtab, ""); symtab->link = strtab; put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL); nb_buckets = 1; hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags); hash->sh_entsize = sizeof(int); symtab->hash = hash; hash->link = symtab; ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int)); ptr[0] = nb_buckets; ptr[1] = 1; memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int)); return symtab;}/* put dynamic tag */static void put_dt(Section *dynamic, int dt, unsigned long val){ Elf32_Dyn *dyn; dyn = section_ptr_add(dynamic, sizeof(Elf32_Dyn)); dyn->d_tag = dt; dyn->d_un.d_val = val;}static void add_init_array_defines(TCCState *s1, const char *section_name){ 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];#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"); snprintf(buf, sizeof(buf), "%s/%s", tcc_lib_path, "libtcc1.a"); tcc_add_file(s1, buf); } /* 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 (must be done after the sections are filled (for example after allocating common symbols)) */static void tcc_add_linker_symbols(TCCState *s1){ char buf[1024]; int i; Section *s; 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";#endifstatic void tcc_output_binary(TCCState *s1, FILE *f, const int *section_order){ Section *s; int i, offset, size; offset = 0; for(i=1;i<s1->nb_sections;i++) { s = s1->sections[section_order[i]]; if (s->sh_type != SHT_NOBITS && (s->sh_flags & SHF_ALLOC)) { while (offset < s->sh_offset) { fputc(0, f); offset++; } size = s->sh_size; fwrite(s->data, 1, size, f); offset += size; } }}/* 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(); tcc_add_linker_symbols(s1); 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -