elf_object.cc revision 11561:704b0198f747
1/* 2 * Copyright (c) 2011-2013 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2003-2005 The Regents of The University of Michigan 15 * All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions are 19 * met: redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer; 21 * redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution; 24 * neither the name of the copyright holders nor the names of its 25 * contributors may be used to endorse or promote products derived from 26 * this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 * 40 * Authors: Steve Reinhardt 41 * Ali Saidi 42 */ 43 44#include "base/loader/elf_object.hh" 45 46#include <fcntl.h> 47#include <sys/mman.h> 48#include <sys/stat.h> 49#include <sys/types.h> 50#include <unistd.h> 51 52#include <cassert> 53#include <string> 54 55#include "base/bitfield.hh" 56#include "base/loader/symtab.hh" 57#include "base/misc.hh" 58#include "base/trace.hh" 59#include "debug/Loader.hh" 60#include "gelf.h" 61#include "sim/byteswap.hh" 62 63ObjectFile * 64ElfObject::tryFile(const std::string &fname, size_t len, uint8_t *data, 65 bool skip_interp_check) 66{ 67 // check that header matches library version 68 if (elf_version(EV_CURRENT) == EV_NONE) 69 panic("wrong elf version number!"); 70 71 // get a pointer to elf structure 72 // Check that we actually have a elf file 73 Elf *elf = elf_memory((char*)data, len); 74 assert(elf); 75 76 GElf_Ehdr ehdr; 77 if (gelf_getehdr(elf, &ehdr) == 0) { 78 DPRINTFR(Loader, "Not ELF\n"); 79 elf_end(elf); 80 return NULL; 81 } 82 83 // Detect the architecture 84 Arch arch = UnknownArch; 85 if (ehdr.e_machine == EM_SPARC64 || 86 (ehdr.e_machine == EM_SPARC && 87 ehdr.e_ident[EI_CLASS] == ELFCLASS64) || 88 ehdr.e_machine == EM_SPARCV9) { 89 arch = SPARC64; 90 } else if (ehdr.e_machine == EM_SPARC32PLUS || 91 (ehdr.e_machine == EM_SPARC && 92 ehdr.e_ident[EI_CLASS] == ELFCLASS32)) { 93 arch = SPARC32; 94 } else if (ehdr.e_machine == EM_MIPS && 95 ehdr.e_ident[EI_CLASS] == ELFCLASS32) { 96 arch = Mips; 97 if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB) { 98 fatal("The binary you're trying to load is compiled for big " 99 "endian MIPS. gem5\nonly supports little endian MIPS. " 100 "Please recompile your binary.\n"); 101 } 102 } else if (ehdr.e_machine == EM_X86_64 && 103 ehdr.e_ident[EI_CLASS] == ELFCLASS64) { 104 arch = X86_64; 105 } else if (ehdr.e_machine == EM_386 && 106 ehdr.e_ident[EI_CLASS] == ELFCLASS32) { 107 arch = I386; 108 } else if (ehdr.e_machine == EM_ARM && 109 ehdr.e_ident[EI_CLASS] == ELFCLASS32) { 110 arch = bits(ehdr.e_entry, 0) ? Thumb : Arm; 111 } else if (ehdr.e_machine == EM_AARCH64 && 112 ehdr.e_ident[EI_CLASS] == ELFCLASS64) { 113 arch = Arm64; 114 } else if (ehdr.e_machine == EM_PPC && 115 ehdr.e_ident[EI_CLASS] == ELFCLASS32) { 116 arch = Power; 117 if (ehdr.e_ident[EI_DATA] != ELFDATA2MSB) { 118 fatal("The binary you're trying to load is compiled for " 119 "little endian Power.\ngem5 only supports big " 120 "endian Power. Please recompile your binary.\n"); 121 } 122 } else if (ehdr.e_machine == EM_PPC64) { 123 fatal("The binary you're trying to load is compiled for 64-bit " 124 "Power. M5\n only supports 32-bit Power. Please " 125 "recompile your binary.\n"); 126 } else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) { 127 // Since we don't know how to check for alpha right now, we'll 128 // just assume if it wasn't something else and it's 64 bit, that's 129 // what it must be. 130 arch = Alpha; 131 } else { 132 warn("Unknown architecture: %d\n", ehdr.e_machine); 133 arch = UnknownArch; 134 } 135 136 // Detect the operating system 137 OpSys op_sys; 138 switch (ehdr.e_ident[EI_OSABI]) { 139 case ELFOSABI_LINUX: 140 op_sys = Linux; 141 break; 142 case ELFOSABI_SOLARIS: 143 op_sys = Solaris; 144 break; 145 case ELFOSABI_TRU64: 146 op_sys = Tru64; 147 break; 148 case ELFOSABI_ARM: 149 op_sys = LinuxArmOABI; 150 break; 151 case ELFOSABI_FREEBSD: 152 op_sys = FreeBSD; 153 break; 154 default: 155 op_sys = UnknownOpSys; 156 } 157 158 // Take a look at the .note.ABI section. 159 // It can let us know what's what. 160 if (op_sys == UnknownOpSys) { 161 int sec_idx = 1; 162 163 // Get the first section 164 Elf_Scn *section = elf_getscn(elf, sec_idx); 165 166 // While there are no more sections 167 while (section && op_sys == UnknownOpSys) { 168 GElf_Shdr shdr; 169 gelf_getshdr(section, &shdr); 170 171 char *e_str = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name); 172 if (shdr.sh_type == SHT_NOTE && 173 !strcmp(".note.ABI-tag", e_str)) { 174 // we have found a ABI note section 175 // Check the 5th 32bit word for OS 0 == linux, 1 == hurd, 176 // 2 == solaris, 3 == freebsd 177 Elf_Data *raw_data = elf_rawdata(section, NULL); 178 assert(raw_data && raw_data->d_buf); 179 180 uint32_t raw_abi = ((uint32_t*)raw_data->d_buf)[4]; 181 bool is_le = ehdr.e_ident[EI_DATA] == ELFDATA2LSB; 182 uint32_t os_abi = is_le ? htole(raw_abi) : htobe(raw_abi); 183 184 switch (os_abi) { 185 case 0: 186 op_sys = Linux; 187 break; 188 case 1: 189 fatal("gem5 does not support the HURD ABI.\n"); 190 case 2: 191 op_sys = Solaris; 192 break; 193 case 3: 194 op_sys = FreeBSD; 195 break; 196 } 197 } // if section found 198 199 if (!strcmp(".SUNW_version", e_str) || 200 !strcmp(".stab.index", e_str)) 201 op_sys = Solaris; 202 203 section = elf_getscn(elf, ++sec_idx); 204 } // while sections 205 } 206 207 ElfObject * result = new ElfObject(fname, len, data, arch, op_sys); 208 209 // The number of headers in the file 210 result->_programHeaderCount = ehdr.e_phnum; 211 // Record the size of each entry 212 result->_programHeaderSize = ehdr.e_phentsize; 213 result->_programHeaderTable = 0; 214 if (result->_programHeaderCount) { // If there is a program header table 215 // Figure out the virtual address of the header table in the 216 // final memory image. We use the program headers themselves 217 // to translate from a file offset to the address in the image. 218 GElf_Phdr phdr; 219 uint64_t e_phoff = ehdr.e_phoff; 220 221 for (int i = 0; i < result->_programHeaderCount; i++) { 222 gelf_getphdr(elf, i, &phdr); 223 // Check if we've found the segment with the headers in it 224 if (phdr.p_offset <= e_phoff && 225 phdr.p_offset + phdr.p_filesz > e_phoff) { 226 result->_programHeaderTable = 227 phdr.p_paddr + (e_phoff - phdr.p_offset); 228 break; 229 } 230 } 231 } 232 233 if (!skip_interp_check) { 234 for (int i = 0; i < ehdr.e_phnum; i++) { 235 GElf_Phdr phdr; 236 M5_VAR_USED void *check_p = gelf_getphdr(elf, i, &phdr); 237 assert(check_p != nullptr); 238 239 if (phdr.p_type != PT_INTERP) 240 continue; 241 242 char *interp_path = (char*)data + phdr.p_offset; 243 int fd = open(interp_path, O_RDONLY); 244 if (fd == -1) 245 fatal("Unable to open dynamic executable's interpreter.\n"); 246 247 struct stat sb; 248 M5_VAR_USED int check_i = fstat(fd, &sb); 249 assert(check_i == 0); 250 251 void *mm = mmap(nullptr, sb.st_size, PROT_READ, 252 MAP_PRIVATE, fd, 0); 253 assert(mm != MAP_FAILED); 254 close(fd); 255 256 uint8_t *interp_image = (uint8_t*)mm; 257 ObjectFile *obj = tryFile(interp_path, sb.st_size, 258 interp_image, true); 259 assert(obj != nullptr); 260 result->interpreter = dynamic_cast<ElfObject*>(obj); 261 assert(result->interpreter != nullptr); 262 break; 263 } 264 } 265 266 elf_end(elf); 267 return result; 268} 269 270ElfObject::ElfObject(const std::string &_filename, size_t _len, 271 uint8_t *_data, Arch _arch, OpSys _op_sys) 272 : ObjectFile(_filename, _len, _data, _arch, _op_sys), 273 _programHeaderTable(0), _programHeaderSize(0), _programHeaderCount(0), 274 interpreter(nullptr), ldBias(0), relocate(true), 275 ldMin(std::numeric_limits<Addr>::max()), 276 ldMax(std::numeric_limits<Addr>::min()) 277{ 278 // check that header matches library version 279 if (elf_version(EV_CURRENT) == EV_NONE) 280 panic("wrong elf version number!"); 281 282 // get a pointer to elf structure 283 Elf *elf = elf_memory((char*)fileData,len); 284 assert(elf); 285 286 // Check that we actually have a elf file 287 GElf_Ehdr ehdr; 288 if (gelf_getehdr(elf, &ehdr) ==0) { 289 panic("Not ELF, shouldn't be here"); 290 } 291 292 entry = ehdr.e_entry; 293 294 // initialize segment sizes to 0 in case they're not present 295 text.size = data.size = bss.size = 0; 296 text.baseAddr = data.baseAddr = bss.baseAddr = 0; 297 298 int sec_idx = 1; 299 300 // The first address of some important sections. 301 Addr text_sec_start = 0; 302 Addr data_sec_start = 0; 303 Addr bss_sec_start = 0; 304 305 // Get the first section 306 Elf_Scn *section = elf_getscn(elf, sec_idx); 307 308 // Find the beginning of the most interesting sections. 309 while (section) { 310 GElf_Shdr shdr; 311 gelf_getshdr(section, &shdr); 312 char *sec_name = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name); 313 314 if (sec_name) { 315 if (!strcmp(".text", sec_name)) { 316 text_sec_start = shdr.sh_addr; 317 } else if (!strcmp(".data", sec_name)) { 318 data_sec_start = shdr.sh_addr; 319 } else if (!strcmp(".bss", sec_name)) { 320 bss_sec_start = shdr.sh_addr; 321 } 322 } else { 323 Elf_Error errorNum = (Elf_Error)elf_errno(); 324 if (errorNum != ELF_E_NONE) { 325 const char *errorMessage = elf_errmsg(errorNum); 326 fatal("Error from libelf: %s.\n", errorMessage); 327 } 328 } 329 330 section = elf_getscn(elf, ++sec_idx); 331 } 332 333 // Go through all the segments in the program, record them, and scrape 334 // out information about the text, data, and bss areas needed by other 335 // code. 336 for (int i = 0; i < ehdr.e_phnum; ++i) { 337 GElf_Phdr phdr; 338 if (gelf_getphdr(elf, i, &phdr) == 0) { 339 panic("gelf_getphdr failed for segment %d.", i); 340 } 341 342 // for now we don't care about non-loadable segments 343 if (!(phdr.p_type & PT_LOAD)) 344 continue; 345 346 ldMin = std::min(ldMin, phdr.p_vaddr); 347 ldMax = std::max(ldMax, phdr.p_vaddr + phdr.p_memsz); 348 349 // Check to see if this segment contains the bss section. 350 if (phdr.p_paddr <= bss_sec_start && 351 phdr.p_paddr + phdr.p_memsz > bss_sec_start && 352 phdr.p_memsz - phdr.p_filesz > 0) { 353 bss.baseAddr = phdr.p_paddr + phdr.p_filesz; 354 bss.size = phdr.p_memsz - phdr.p_filesz; 355 bss.fileImage = NULL; 356 } 357 358 // Check to see if this is the text or data segment 359 if (phdr.p_vaddr <= text_sec_start && 360 phdr.p_vaddr + phdr.p_filesz > text_sec_start) { 361 362 // If this value is nonzero, we need to flip the relocate flag. 363 if (phdr.p_vaddr != 0) 364 relocate = false; 365 366 text.baseAddr = phdr.p_paddr; 367 text.size = phdr.p_filesz; 368 text.fileImage = fileData + phdr.p_offset; 369 } else if (phdr.p_vaddr <= data_sec_start && 370 phdr.p_vaddr + phdr.p_filesz > data_sec_start) { 371 data.baseAddr = phdr.p_paddr; 372 data.size = phdr.p_filesz; 373 data.fileImage = fileData + phdr.p_offset; 374 } else { 375 // If it's none of the above but is loadable, 376 // load the filesize worth of data 377 Segment extra; 378 extra.baseAddr = phdr.p_paddr; 379 extra.size = phdr.p_filesz; 380 extra.fileImage = fileData + phdr.p_offset; 381 extraSegments.push_back(extra); 382 } 383 } 384 385 // should have found at least one loadable segment 386 warn_if(text.size == 0, 387 "Empty .text segment in '%s'. ELF file corrupted?\n", 388 filename); 389 390 DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n", 391 text.baseAddr, text.size, data.baseAddr, data.size, 392 bss.baseAddr, bss.size); 393 394 elf_end(elf); 395 396 // We will actually read the sections when we need to load them 397} 398 399 400bool 401ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding, Addr mask, 402 Addr base, Addr offset) 403{ 404 if (!symtab) 405 return false; 406 407 // check that header matches library version 408 if (elf_version(EV_CURRENT) == EV_NONE) 409 panic("wrong elf version number!"); 410 411 // get a pointer to elf structure 412 Elf *elf = elf_memory((char*)fileData,len); 413 assert(elf != NULL); 414 415 // Get the first section 416 int sec_idx = 1; // there is a 0 but it is nothing, go figure 417 Elf_Scn *section = elf_getscn(elf, sec_idx); 418 419 // While there are no more sections 420 bool found = false; 421 while (section != NULL) { 422 GElf_Shdr shdr; 423 gelf_getshdr(section, &shdr); 424 425 if (shdr.sh_type == SHT_SYMTAB) { 426 found = true; 427 Elf_Data *data = elf_getdata(section, NULL); 428 int count = shdr.sh_size / shdr.sh_entsize; 429 DPRINTF(Loader, "Found Symbol Table, %d symbols present\n", count); 430 431 // loop through all the symbols, only loading global ones 432 for (int i = 0; i < count; ++i) { 433 GElf_Sym sym; 434 gelf_getsym(data, i, &sym); 435 if (GELF_ST_BIND(sym.st_info) == binding) { 436 char *sym_name = elf_strptr(elf, shdr.sh_link, sym.st_name); 437 if (sym_name && sym_name[0] != '$') { 438 Addr value = sym.st_value - base + offset; 439 if (symtab->insert(value & mask, sym_name)) { 440 DPRINTF(Loader, "Symbol: %-40s value %#x\n", 441 sym_name, value); 442 } 443 } 444 } 445 } 446 } 447 ++sec_idx; 448 section = elf_getscn(elf, sec_idx); 449 } 450 451 elf_end(elf); 452 453 return found; 454} 455 456bool 457ElfObject::loadAllSymbols(SymbolTable *symtab, Addr base, Addr offset, 458 Addr addr_mask) 459{ 460 return (loadGlobalSymbols(symtab, base, offset, addr_mask) && 461 loadLocalSymbols(symtab, base, offset, addr_mask) && 462 loadWeakSymbols(symtab, base, offset, addr_mask)); 463} 464 465bool 466ElfObject::loadGlobalSymbols(SymbolTable *symtab, Addr base, Addr offset, 467 Addr addr_mask) 468{ 469 if (interpreter) { 470 interpreter->loadSomeSymbols(symtab, STB_GLOBAL, addr_mask, 471 base, offset); 472 } 473 return loadSomeSymbols(symtab, STB_GLOBAL, addr_mask, base, offset); 474} 475 476bool 477ElfObject::loadLocalSymbols(SymbolTable *symtab, Addr base, Addr offset, 478 Addr addr_mask) 479{ 480 if (interpreter) { 481 interpreter->loadSomeSymbols(symtab, STB_LOCAL, addr_mask, 482 base, offset); 483 } 484 return loadSomeSymbols(symtab, STB_LOCAL, addr_mask, base, offset); 485} 486 487bool 488ElfObject::loadWeakSymbols(SymbolTable *symtab, Addr base, Addr offset, 489 Addr addr_mask) 490{ 491 if (interpreter) { 492 interpreter->loadSomeSymbols(symtab, STB_WEAK, addr_mask, 493 base, offset); 494 } 495 return loadSomeSymbols(symtab, STB_WEAK, addr_mask, base, offset); 496} 497 498bool 499ElfObject::loadSections(PortProxy& mem_proxy, Addr addr_mask, Addr offset) 500{ 501 if (!ObjectFile::loadSections(mem_proxy, addr_mask, offset)) 502 return false; 503 504 for (auto seg : extraSegments) { 505 if (!loadSection(&seg, mem_proxy, addr_mask, offset)) { 506 return false; 507 } 508 } 509 510 if (interpreter) 511 interpreter->loadSections(mem_proxy, addr_mask, offset); 512 513 return true; 514} 515 516void 517ElfObject::getSections() 518{ 519 assert(!sectionNames.size()); 520 521 // check that header matches library version 522 if (elf_version(EV_CURRENT) == EV_NONE) 523 panic("wrong elf version number!"); 524 525 // get a pointer to elf structure 526 Elf *elf = elf_memory((char*)fileData,len); 527 assert(elf != NULL); 528 529 // Check that we actually have a elf file 530 GElf_Ehdr ehdr; 531 if (gelf_getehdr(elf, &ehdr) ==0) { 532 panic("Not ELF, shouldn't be here"); 533 } 534 535 // Get the first section 536 int sec_idx = 1; // there is a 0 but it is nothing, go figure 537 Elf_Scn *section = elf_getscn(elf, sec_idx); 538 539 // While there are no more sections 540 while (section) { 541 GElf_Shdr shdr; 542 gelf_getshdr(section, &shdr); 543 sectionNames.insert(elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name)); 544 section = elf_getscn(elf, ++sec_idx); 545 } // while sections 546} 547 548bool 549ElfObject::sectionExists(std::string sec) 550{ 551 if (!sectionNames.size()) 552 getSections(); 553 554 return sectionNames.find(sec) != sectionNames.end(); 555} 556 557 558void 559ElfObject::updateBias(Addr bias_addr) 560{ 561 // Record the bias. 562 ldBias = bias_addr; 563 564 // Patch the entry point with bias_addr. 565 entry += bias_addr; 566 567 // Patch segments with the bias_addr. 568 text.baseAddr += bias_addr; 569 data.baseAddr += bias_addr; 570 bss.baseAddr += bias_addr; 571 for (auto &segment : extraSegments) 572 segment.baseAddr += bias_addr; 573} 574