/* Output the object file's symbol table, containing one section * symbol, one file symbol for each input file, and one exported * symbol for each binary object. */ static void outputsymtab(void) { Elf64_Sym sym; int i; sym.st_name = 0; sym.st_info = 0; sym.st_other = 0; sym.st_shndx = SHN_UNDEF; sym.st_value = 0; sym.st_size = 0; if (!elfrw_write_Sym(destfile, &sym)) ferr(); sym.st_info = ELF64_ST_INFO(STB_LOCAL, STT_SECTION); sym.st_shndx = piece_data->shndx; if (!elfrw_write_Sym(destfile, &sym)) ferr(); sym.st_shndx = SHN_UNDEF; for (i = 0 ; i < objectcount ; ++i) { sym.st_name = objects[i].filenamestrpos; sym.st_info = ELF64_ST_INFO(STB_LOCAL, STT_FILE); if (!elfrw_write_Sym(destfile, &sym)) ferr(); } for (i = 0 ; i < objectcount ; ++i) { sym.st_name = objects[i].objectnamestrpos; sym.st_info = ELF64_ST_INFO(STB_GLOBAL, STT_OBJECT); sym.st_shndx = piece_data->shndx; sym.st_value = objects[i].offset; sym.st_size = objects[i].size; if (!elfrw_write_Sym(destfile, &sym)) ferr(); } }
void Elf64Output::sym(String* label, SymType type) { // Finds the symbol table entry for 'label' and updates it to the current // offset of the text or data segment. std::map<String::Ptr,size_t>::iterator i = symbol_.find(label); Elf64_Sym* sym = 0; if (i == symbol_.end()) { symbol_.insert(std::make_pair(label, sym_.size())); sym_.resize(sym_.size()+1); sym = &sym_.back(); sym->st_name = string_->bytes(); sym->st_other = 0; sym->st_size = 0; // FixMe: May need to set this explicitly // Offset to name in string table (+4 for strtab size header) string_->buffer(label->string().c_str(), label->string().size()+1); } else { sym = &sym_[i->second]; assert("Duplicate label"&&(sym->st_shndx==0)); } if (type & SYM_TEXT) { sym->st_value = text_->bytes(); sym->st_shndx = OUT_SECT_TEXT; } else if (type & SYM_DATA) { sym->st_value = data_->bytes(); sym->st_shndx = OUT_SECT_DATA; } else { assert(!"Unknown section type"); } if (type & SYM_LOCAL) { sym->st_info = ELF64_ST_INFO(STB_LOCAL, STT_NOTYPE); } else { sym->st_info = ELF64_ST_INFO(STB_GLOBAL, STT_NOTYPE); } }
GElf_Sym * gelf_getsym(Elf_Data *d, int ndx, GElf_Sym *dst) { int ec; Elf *e; Elf_Scn *scn; Elf32_Sym *sym32; Elf64_Sym *sym64; size_t msz; uint32_t sh_type; if (d == NULL || ndx < 0 || dst == NULL || (scn = d->d_scn) == NULL || (e = scn->s_elf) == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } ec = e->e_class; assert(ec == ELFCLASS32 || ec == ELFCLASS64); if (ec == ELFCLASS32) sh_type = scn->s_shdr.s_shdr32.sh_type; else sh_type = scn->s_shdr.s_shdr64.sh_type; if (_libelf_xlate_shtype(sh_type) != ELF_T_SYM) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } msz = _libelf_msize(ELF_T_SYM, ec, e->e_version); assert(msz > 0); if (msz * ndx >= d->d_size) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if (ec == ELFCLASS32) { sym32 = (Elf32_Sym *) d->d_buf + ndx; dst->st_name = sym32->st_name; dst->st_value = (Elf64_Addr) sym32->st_value; dst->st_size = (Elf64_Xword) sym32->st_size; dst->st_info = ELF64_ST_INFO(ELF32_ST_BIND(sym32->st_info), ELF32_ST_TYPE(sym32->st_info)); dst->st_other = sym32->st_other; dst->st_shndx = sym32->st_shndx; } else { sym64 = (Elf64_Sym *) d->d_buf + ndx; *dst = *sym64; } return (dst); }
static void add_symtab(Elf *elf) { String *symtabb = make_string(); String *strtabb = make_string(); o1(strtabb, 0); // Null symbol for (int i = 0; i < 24; i++) o1(symtabb, 0); // File symbol o4(symtabb, STRING_LEN(strtabb)); // st_name ostr(strtabb, "noname"); o1(symtabb, ELF64_ST_INFO(STB_LOCAL, STT_FILE)); // st_info o1(symtabb, 0); // other o2(symtabb, SHN_ABS); // st_shndx o8(symtabb, 0); // st_value o8(symtabb, 0); // st_size int index = 2; write_sym_to_buf(elf, &index, symtabb, strtabb, true); int localidx = index; write_section_sym(elf, &index, symtabb, strtabb); write_sym_to_buf(elf, &index, symtabb, strtabb, false); elf->symtabnum = LIST_LEN(elf->sections) + 1; Section *symtab = make_section(".symtab", SHT_SYMTAB); symtab->body = symtabb; symtab->link = LIST_LEN(elf->sections) + 2; symtab->info = localidx + 2; symtab->entsize = 24; symtab->align = 4; add_section(elf, symtab); Section *strtab = make_section(".strtab", SHT_STRTAB); strtab->body = strtabb; add_section(elf, strtab); }
uint32_t SymbolTable::addSymbol(uint32_t name, uint64_t value, uint64_t size, uint8_t bind, uint8_t type, uint32_t other, uint16_t shndx){ if (elfFile->is64Bit()){ Symbol64* sym = new Symbol64(this, NULL, symbols.size()); Elf64_Sym symEntry; symEntry.st_name = name; symEntry.st_value = value; symEntry.st_size = size; symEntry.st_info = ELF64_ST_INFO(bind,type); symEntry.st_other = other; symEntry.st_shndx = shndx; memcpy(sym->charStream(), &symEntry, Size__64_bit_Symbol); symbols.append(sym); sizeInBytes += Size__64_bit_Symbol; } else { Symbol32* sym = new Symbol32(this, NULL, symbols.size()); Elf32_Sym symEntry; symEntry.st_name = name; symEntry.st_value = (uint32_t)value; symEntry.st_size = (uint32_t)size; symEntry.st_info = ELF32_ST_INFO(bind,type); symEntry.st_other = other; symEntry.st_shndx = shndx; memcpy(sym->charStream(), &symEntry, Size__32_bit_Symbol); symbols.append(sym); sizeInBytes += Size__32_bit_Symbol; } // sortSymbols(); verify(); return symbols.size()-1; }
static Elf64_Sym * sym_to_gelf_macho_64(const ctf_sect_t *sp, const Elf32_Sym *src, Elf64_Sym * sym, const char *base) { const struct nlist_64 *nsym = (const struct nlist_64 *)src; const char *name = base + nsym->n_un.n_strx; char *tmp; if (0 == nsym->n_un.n_strx) { // iff a null, "", name. sym->st_name = 0; return sym; } if ('_' == name[0]) name++; // Lop off omnipresent underscore to match DWARF convention sym->st_name = (Elf64_Word)(name - base); sym->st_value = nsym->n_value; sym->st_size = 0; sym->st_info = STT_NOTYPE; sym->st_other = 0; sym->st_shndx = SHN_MACHO_64; if (nsym->n_type & N_STAB) { switch(nsym->n_type) { case N_FUN: sym->st_info = ELF64_ST_INFO((STB_GLOBAL), (STT_FUNC)); break; case N_GSYM: sym->st_info = ELF64_ST_INFO((STB_GLOBAL), (STT_OBJECT)); break; default: break; } } else if ((N_ABS | N_EXT) == (nsym->n_type & (N_TYPE | N_EXT)) || (N_SECT | N_EXT) == (nsym->n_type & (N_TYPE | N_EXT))) { sym->st_info = ELF64_ST_INFO((STB_GLOBAL), (nsym->n_desc)); } else if ((N_UNDF | N_EXT) == (nsym->n_type & (N_TYPE | N_EXT)) && nsym->n_sect == NO_SECT) { sym->st_info = ELF64_ST_INFO((STB_GLOBAL), (STT_OBJECT)); /* Common */ } return sym; }
static void newSym64(char *name,elfull value,elfull size,uint8_t bind, uint8_t type,unsigned shndx) { struct Symbol64Node *elfsym = addSymbol64(name); setval(be,elfsym->s.st_value,8,value); setval(be,elfsym->s.st_size,8,size); elfsym->s.st_info[0] = ELF64_ST_INFO(bind,type); setval(be,elfsym->s.st_shndx,2,shndx); }
void prepare_symentry(Sym *symentry) { symentry->st_name = 1; symentry->st_value = 0; symentry->st_size = fs.st_size; #ifdef BIT32 symentry->st_info = ELF32_ST_INFO(STB_GLOBAL, STT_OBJECT); #else symentry->st_info = ELF64_ST_INFO(STB_GLOBAL, STT_OBJECT); #endif symentry->st_other = STV_DEFAULT; symentry->st_shndx = IDX_DATA; }
void Elf64Output::ref(String* label, RelocType rtype) { // Refer to a symbol by name at the current text/data output location. // This function adds an entry to the relocation table. The size can be // either 4 or 8 bytes. A 4-byte entry indicates the instruction uses // RIP-relative addressing for x64. std::map<String::Ptr,size_t>::iterator i = symbol_.find(label); size_t symnum = 0; if (i == symbol_.end()) { symbol_.insert(std::make_pair(label, sym_.size())); sym_.resize(sym_.size()+1); Elf64_Sym* const sym = &sym_.back(); sym->st_name = string_->bytes(); sym->st_info = ELF64_ST_INFO(STB_GLOBAL, STT_NOTYPE); sym->st_other = 0; sym->st_shndx = SHN_UNDEF; sym->st_value = 0; sym->st_size = 0; // Unknown size string_->buffer(label->string().c_str(), label->string().size()+1); symnum = sym_.size()-1; } else { symnum = i->second; } Elf64_Rela reloc; if (REF_TEXT == rtype) { reloc.r_offset = text_->bytes(); reloc.r_info = ELF64_R_INFO(symnum, R_X86_64_64); reloc.r_addend = 0; text_reloc_.push_back(reloc); } else if (REF_DATA == rtype || REF_VTABLE == rtype) { reloc.r_offset = data_->bytes(); reloc.r_info = ELF64_R_INFO(symnum, R_X86_64_64); reloc.r_addend = 0; data_reloc_.push_back(reloc); } else if (REF_BRANCH == rtype || REF_CALL == rtype) { reloc.r_offset = text_->bytes(); reloc.r_info = ELF64_R_INFO(symnum, R_X86_64_PC32); reloc.r_addend = -sizeof(uint32_t); text_reloc_.push_back(reloc); } else if (REF_SIGNED == rtype) { reloc.r_offset = text_->bytes(); reloc.r_info = ELF64_R_INFO(symnum, R_X86_64_PC32); reloc.r_addend = -sizeof(uint32_t); text_reloc_.push_back(reloc); } }
static void write_one_symbol(Symbol *sym, int *index, String *symtab, String *strtab) { if (sym->name) { o4(symtab, STRING_LEN(strtab)); // st_name ostr(strtab, STRING_BODY(sym->name)); } else { o4(symtab, 0); // st_name } o1(symtab, ELF64_ST_INFO(sym->bind, sym->type)); // st_info; o1(symtab, 0); // st_other; if (sym->defined) { o2(symtab, sym->section->shndx); // st_shndx } else { o2(symtab, 0); // st_shndx } o8(symtab, sym->value); // st_value o8(symtab, 0); // st_size sym->index = (*index)++; }
static void elf_x86_amd64_write_symtab_entry(unsigned char *bufp, elf_symtab_entry *entry, yasm_intnum *value_intn, yasm_intnum *size_intn) { YASM_WRITE_32_L(bufp, entry->name ? entry->name->index : 0); YASM_WRITE_8(bufp, ELF64_ST_INFO(entry->bind, entry->type)); YASM_WRITE_8(bufp, ELF64_ST_OTHER(entry->vis)); if (entry->sect) { elf_secthead *shead = yasm_section_get_data(entry->sect, &elf_section_data); if (!shead) yasm_internal_error(N_("symbol references section without data")); YASM_WRITE_16_L(bufp, shead->index); } else { YASM_WRITE_16_L(bufp, entry->index); } YASM_WRITE_64I_L(bufp, value_intn); YASM_WRITE_64I_L(bufp, size_intn); }