elf_object.cc revision 11389:1e55f16160cb
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 63using namespace std; 64 65ObjectFile * 66ElfObject::tryFile(const string &fname, size_t len, uint8_t *data, 67 bool skip_interp_check) 68{ 69 Elf *elf; 70 GElf_Ehdr ehdr; 71 Arch arch = UnknownArch; 72 OpSys opSys = UnknownOpSys; 73 74 // check that header matches library version 75 if (elf_version(EV_CURRENT) == EV_NONE) 76 panic("wrong elf version number!"); 77 78 // get a pointer to elf structure 79 elf = elf_memory((char*)data,len); 80 assert(elf != NULL); 81 82 // Check that we actually have a elf file 83 if (gelf_getehdr(elf, &ehdr) == 0) { 84 DPRINTFR(Loader, "Not ELF\n"); 85 elf_end(elf); 86 return NULL; 87 } else { 88 //Detect the architecture 89 //Since we don't know how to check for alpha right now, we'll 90 //just assume if it wasn't something else and it's 64 bit, that's 91 //what it must be. 92 if (ehdr.e_machine == EM_SPARC64 || 93 (ehdr.e_machine == EM_SPARC && 94 ehdr.e_ident[EI_CLASS] == ELFCLASS64)|| 95 ehdr.e_machine == EM_SPARCV9) { 96 arch = ObjectFile::SPARC64; 97 } else if (ehdr.e_machine == EM_SPARC32PLUS || 98 (ehdr.e_machine == EM_SPARC && 99 ehdr.e_ident[EI_CLASS] == ELFCLASS32)) { 100 arch = ObjectFile::SPARC32; 101 } else if (ehdr.e_machine == EM_MIPS 102 && ehdr.e_ident[EI_CLASS] == ELFCLASS32) { 103 if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) { 104 arch = ObjectFile::Mips; 105 } else { 106 fatal("The binary you're trying to load is compiled for big " 107 "endian MIPS. M5\nonly supports little endian MIPS. " 108 "Please recompile your binary.\n"); 109 } 110 } else if (ehdr.e_machine == EM_X86_64 && 111 ehdr.e_ident[EI_CLASS] == ELFCLASS64) { 112 arch = ObjectFile::X86_64; 113 } else if (ehdr.e_machine == EM_386 && 114 ehdr.e_ident[EI_CLASS] == ELFCLASS32) { 115 arch = ObjectFile::I386; 116 } else if (ehdr.e_machine == EM_ARM && 117 ehdr.e_ident[EI_CLASS] == ELFCLASS32) { 118 if (bits(ehdr.e_entry, 0)) { 119 arch = ObjectFile::Thumb; 120 } else { 121 arch = ObjectFile::Arm; 122 } 123 } else if ((ehdr.e_machine == EM_AARCH64) && 124 ehdr.e_ident[EI_CLASS] == ELFCLASS64) { 125 arch = ObjectFile::Arm64; 126 } else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) { 127 arch = ObjectFile::Alpha; 128 } else if (ehdr.e_machine == EM_PPC && 129 ehdr.e_ident[EI_CLASS] == ELFCLASS32) { 130 if (ehdr.e_ident[EI_DATA] == ELFDATA2MSB) { 131 arch = ObjectFile::Power; 132 } else { 133 fatal("The binary you're trying to load is compiled for " 134 "little endian Power.\nM5 only supports big " 135 "endian Power. Please recompile your binary.\n"); 136 } 137 } else if (ehdr.e_machine == EM_PPC64) { 138 fatal("The binary you're trying to load is compiled for 64-bit " 139 "Power. M5\n only supports 32-bit Power. Please " 140 "recompile your binary.\n"); 141 } else { 142 warn("Unknown architecture: %d\n", ehdr.e_machine); 143 arch = ObjectFile::UnknownArch; 144 } 145 146 //Detect the operating system 147 switch (ehdr.e_ident[EI_OSABI]) { 148 case ELFOSABI_LINUX: 149 opSys = ObjectFile::Linux; 150 break; 151 case ELFOSABI_SOLARIS: 152 opSys = ObjectFile::Solaris; 153 break; 154 case ELFOSABI_TRU64: 155 opSys = ObjectFile::Tru64; 156 break; 157 case ELFOSABI_ARM: 158 opSys = ObjectFile::LinuxArmOABI; 159 break; 160 case ELFOSABI_FREEBSD: 161 opSys = ObjectFile::FreeBSD; 162 break; 163 default: 164 opSys = ObjectFile::UnknownOpSys; 165 } 166 167 //take a look at the .note.ABI section 168 //It can let us know what's what. 169 if (opSys == ObjectFile::UnknownOpSys) { 170 Elf_Scn *section; 171 GElf_Shdr shdr; 172 Elf_Data *data; 173 uint32_t osAbi; 174 uint32_t *elem; 175 int secIdx = 1; 176 177 // Get the first section 178 section = elf_getscn(elf, secIdx); 179 180 // While there are no more sections 181 while (section != NULL && opSys == ObjectFile::UnknownOpSys) { 182 gelf_getshdr(section, &shdr); 183 if (shdr.sh_type == SHT_NOTE && !strcmp(".note.ABI-tag", 184 elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) { 185 // we have found a ABI note section 186 // Check the 5th 32bit word for OS 0 == linux, 1 == hurd, 187 // 2 == solaris, 3 == freebsd 188 data = elf_rawdata(section, NULL); 189 assert(data->d_buf); 190 if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) 191 osAbi = htole(((uint32_t*)data->d_buf)[4]); 192 else 193 osAbi = htobe(((uint32_t*)data->d_buf)[4]); 194 195 switch(osAbi) { 196 case 0: 197 opSys = ObjectFile::Linux; 198 break; 199 case 2: 200 opSys = ObjectFile::Solaris; 201 break; 202 } 203 } // if section found 204 if (!strcmp(".SUNW_version", elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) 205 opSys = ObjectFile::Solaris; 206 if (!strcmp(".stab.index", elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) 207 opSys = ObjectFile::Solaris; 208 if (shdr.sh_type == SHT_NOTE && !strcmp(".note.tag", 209 elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) { 210 data = elf_rawdata(section, NULL); 211 assert(data->d_buf); 212 elem = (uint32_t *)data->d_buf; 213 if (elem[0] == 0x8) { //size of name 214 if (memcmp((void *)&elem[3], "FreeBSD", 0x8) == 0) 215 opSys = ObjectFile::FreeBSD; 216 } 217 } 218 219 section = elf_getscn(elf, ++secIdx); 220 } // while sections 221 } 222 223 ElfObject * result = new ElfObject(fname, len, data, arch, opSys); 224 225 //The number of headers in the file 226 result->_programHeaderCount = ehdr.e_phnum; 227 //Record the size of each entry 228 result->_programHeaderSize = ehdr.e_phentsize; 229 if (result->_programHeaderCount) //If there is a program header table 230 { 231 //Figure out the virtual address of the header table in the 232 //final memory image. We use the program headers themselves 233 //to translate from a file offset to the address in the image. 234 GElf_Phdr phdr; 235 uint64_t e_phoff = ehdr.e_phoff; 236 result->_programHeaderTable = 0; 237 for (int hdrnum = 0; hdrnum < result->_programHeaderCount; hdrnum++) 238 { 239 gelf_getphdr(elf, hdrnum, &phdr); 240 //Check if we've found the segment with the headers in it 241 if (phdr.p_offset <= e_phoff && 242 phdr.p_offset + phdr.p_filesz > e_phoff) 243 { 244 result->_programHeaderTable = 245 phdr.p_paddr + (e_phoff - phdr.p_offset); 246 break; 247 } 248 } 249 } 250 else 251 result->_programHeaderTable = 0; 252 253 254 if (!skip_interp_check) { 255 for (int i = 0; i < ehdr.e_phnum; i++) { 256 GElf_Phdr phdr; 257 M5_VAR_USED void *check_p = gelf_getphdr(elf, i, &phdr); 258 assert(check_p != nullptr); 259 260 if (phdr.p_type != PT_INTERP) 261 continue; 262 263 char *interp_path = (char*)data + phdr.p_offset; 264 int fd = open(interp_path, O_RDONLY); 265 if (fd == -1) { 266 fatal("Unable to open dynamic executable's " 267 "interpreter.\n"); 268 } 269 270 struct stat sb; 271 M5_VAR_USED int check_i = fstat(fd, &sb); 272 assert(check_i == 0); 273 274 void *mm = mmap(nullptr, sb.st_size, PROT_READ, 275 MAP_PRIVATE, fd, 0); 276 assert(mm != MAP_FAILED); 277 ::close(fd); 278 279 uint8_t *interp_image = (uint8_t*)mm; 280 ObjectFile *obj = tryFile(interp_path, sb.st_size, 281 interp_image, true); 282 assert(obj != nullptr); 283 result->interpreter = dynamic_cast<ElfObject*>(obj); 284 assert(result->interpreter != nullptr); 285 break; 286 } 287 } 288 289 elf_end(elf); 290 return result; 291 } 292} 293 294 295ElfObject::ElfObject(const string &_filename, size_t _len, uint8_t *_data, 296 Arch _arch, OpSys _opSys) 297 : ObjectFile(_filename, _len, _data, _arch, _opSys), 298 _programHeaderTable(0), _programHeaderSize(0), _programHeaderCount(0), 299 interpreter(nullptr), ldBias(0), relocate(true), 300 ldMin(std::numeric_limits<Addr>::max()), 301 ldMax(std::numeric_limits<Addr>::min()) 302{ 303 Elf *elf; 304 GElf_Ehdr ehdr; 305 306 // check that header matches library version 307 if (elf_version(EV_CURRENT) == EV_NONE) 308 panic("wrong elf version number!"); 309 310 // get a pointer to elf structure 311 elf = elf_memory((char*)fileData,len); 312 assert(elf != NULL); 313 314 // Check that we actually have a elf file 315 if (gelf_getehdr(elf, &ehdr) ==0) { 316 panic("Not ELF, shouldn't be here"); 317 } 318 319 entry = ehdr.e_entry; 320 321 // initialize segment sizes to 0 in case they're not present 322 text.size = data.size = bss.size = 0; 323 text.baseAddr = data.baseAddr = bss.baseAddr = 0; 324 325 int secIdx = 1; 326 Elf_Scn *section; 327 GElf_Shdr shdr; 328 329 // The first address of some important sections. 330 Addr textSecStart = 0; 331 Addr dataSecStart = 0; 332 Addr bssSecStart = 0; 333 334 // Get the first section 335 section = elf_getscn(elf, secIdx); 336 337 // Find the beginning of the most interesting sections. 338 while (section != NULL) { 339 gelf_getshdr(section, &shdr); 340 char * secName = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name); 341 342 if (secName) { 343 if (!strcmp(".text", secName)) { 344 textSecStart = shdr.sh_addr; 345 } else if (!strcmp(".data", secName)) { 346 dataSecStart = shdr.sh_addr; 347 } else if (!strcmp(".bss", secName)) { 348 bssSecStart = shdr.sh_addr; 349 } 350 } else { 351 Elf_Error errorNum = (Elf_Error)elf_errno(); 352 if (errorNum != ELF_E_NONE) { 353 const char *errorMessage = elf_errmsg(errorNum); 354 fatal("Error from libelf: %s.\n", errorMessage); 355 } 356 } 357 358 section = elf_getscn(elf, ++secIdx); 359 } 360 361 // Go through all the segments in the program, record them, and scrape 362 // out information about the text, data, and bss areas needed by other 363 // code. 364 for (int i = 0; i < ehdr.e_phnum; ++i) { 365 GElf_Phdr phdr; 366 if (gelf_getphdr(elf, i, &phdr) == 0) { 367 panic("gelf_getphdr failed for segment %d.", i); 368 } 369 370 // for now we don't care about non-loadable segments 371 if (!(phdr.p_type & PT_LOAD)) 372 continue; 373 374 ldMin = std::min(ldMin, phdr.p_vaddr); 375 ldMax = std::max(ldMax, phdr.p_vaddr + phdr.p_memsz); 376 377 // Check to see if this segment contains the bss section. 378 if (phdr.p_paddr <= bssSecStart && 379 phdr.p_paddr + phdr.p_memsz > bssSecStart && 380 phdr.p_memsz - phdr.p_filesz > 0) { 381 bss.baseAddr = phdr.p_paddr + phdr.p_filesz; 382 bss.size = phdr.p_memsz - phdr.p_filesz; 383 bss.fileImage = NULL; 384 } 385 386 // Check to see if this is the text or data segment 387 if (phdr.p_vaddr <= textSecStart && 388 phdr.p_vaddr + phdr.p_filesz > textSecStart) { 389 390 // If this value is nonzero, we need to flip the relocate flag. 391 if (phdr.p_vaddr != 0) 392 relocate = false; 393 394 text.baseAddr = phdr.p_paddr; 395 text.size = phdr.p_filesz; 396 text.fileImage = fileData + phdr.p_offset; 397 } else if (phdr.p_vaddr <= dataSecStart && 398 phdr.p_vaddr + phdr.p_filesz > dataSecStart) { 399 data.baseAddr = phdr.p_paddr; 400 data.size = phdr.p_filesz; 401 data.fileImage = fileData + phdr.p_offset; 402 } else { 403 // If it's none of the above but is loadable, 404 // load the filesize worth of data 405 Segment extra; 406 extra.baseAddr = phdr.p_paddr; 407 extra.size = phdr.p_filesz; 408 extra.fileImage = fileData + phdr.p_offset; 409 extraSegments.push_back(extra); 410 } 411 } 412 413 // should have found at least one loadable segment 414 assert(text.size != 0); 415 416 DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n", 417 text.baseAddr, text.size, data.baseAddr, data.size, 418 bss.baseAddr, bss.size); 419 420 elf_end(elf); 421 422 // We will actually read the sections when we need to load them 423} 424 425 426bool 427ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding, Addr mask) 428{ 429 Elf *elf; 430 int sec_idx = 1; // there is a 0 but it is nothing, go figure 431 Elf_Scn *section; 432 GElf_Shdr shdr; 433 Elf_Data *data; 434 int count, ii; 435 bool found = false; 436 GElf_Sym sym; 437 438 if (!symtab) 439 return false; 440 441 // check that header matches library version 442 if (elf_version(EV_CURRENT) == EV_NONE) 443 panic("wrong elf version number!"); 444 445 // get a pointer to elf structure 446 elf = elf_memory((char*)fileData,len); 447 448 assert(elf != NULL); 449 450 // Get the first section 451 section = elf_getscn(elf, sec_idx); 452 453 // While there are no more sections 454 while (section != NULL) { 455 gelf_getshdr(section, &shdr); 456 457 if (shdr.sh_type == SHT_SYMTAB) { 458 found = true; 459 data = elf_getdata(section, NULL); 460 count = shdr.sh_size / shdr.sh_entsize; 461 DPRINTF(Loader, "Found Symbol Table, %d symbols present\n", count); 462 463 // loop through all the symbols, only loading global ones 464 for (ii = 0; ii < count; ++ii) { 465 gelf_getsym(data, ii, &sym); 466 if (GELF_ST_BIND(sym.st_info) == binding) { 467 char *sym_name = elf_strptr(elf, shdr.sh_link, sym.st_name); 468 if (sym_name && sym_name[0] != '$') { 469 DPRINTF(Loader, "Symbol: %-40s value %#x\n", 470 sym_name, sym.st_value); 471 symtab->insert(sym.st_value & mask, sym_name); 472 } 473 } 474 } 475 } 476 ++sec_idx; 477 section = elf_getscn(elf, sec_idx); 478 } 479 480 elf_end(elf); 481 482 return found; 483} 484 485bool 486ElfObject::loadGlobalSymbols(SymbolTable *symtab, Addr addrMask) 487{ 488 return loadSomeSymbols(symtab, STB_GLOBAL, addrMask); 489} 490 491bool 492ElfObject::loadLocalSymbols(SymbolTable *symtab, Addr addrMask) 493{ 494 bool found_local = loadSomeSymbols(symtab, STB_LOCAL, addrMask); 495 bool found_weak = loadSomeSymbols(symtab, STB_WEAK, addrMask); 496 return found_local || found_weak; 497} 498 499bool 500ElfObject::loadWeakSymbols(SymbolTable *symtab, Addr addrMask) 501{ 502 return loadSomeSymbols(symtab, STB_WEAK, addrMask); 503} 504 505bool 506ElfObject::loadSections(PortProxy& memProxy, Addr addrMask, Addr offset) 507{ 508 if (!ObjectFile::loadSections(memProxy, addrMask, offset)) 509 return false; 510 511 vector<Segment>::iterator extraIt; 512 for (extraIt = extraSegments.begin(); 513 extraIt != extraSegments.end(); extraIt++) { 514 if (!loadSection(&(*extraIt), memProxy, addrMask, offset)) { 515 return false; 516 } 517 } 518 519 if (interpreter) 520 interpreter->loadSections(memProxy, addrMask, offset); 521 522 return true; 523} 524 525void 526ElfObject::getSections() 527{ 528 Elf *elf; 529 int sec_idx = 1; // there is a 0 but it is nothing, go figure 530 Elf_Scn *section; 531 GElf_Shdr shdr; 532 533 GElf_Ehdr ehdr; 534 535 assert(!sectionNames.size()); 536 537 // check that header matches library version 538 if (elf_version(EV_CURRENT) == EV_NONE) 539 panic("wrong elf version number!"); 540 541 // get a pointer to elf structure 542 elf = elf_memory((char*)fileData,len); 543 assert(elf != NULL); 544 545 // Check that we actually have a elf file 546 if (gelf_getehdr(elf, &ehdr) ==0) { 547 panic("Not ELF, shouldn't be here"); 548 } 549 550 // Get the first section 551 section = elf_getscn(elf, sec_idx); 552 553 // While there are no more sections 554 while (section != NULL) { 555 gelf_getshdr(section, &shdr); 556 sectionNames.insert(elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name)); 557 section = elf_getscn(elf, ++sec_idx); 558 } // while sections 559} 560 561bool 562ElfObject::sectionExists(string sec) 563{ 564 if (!sectionNames.size()) 565 getSections(); 566 return sectionNames.find(sec) != sectionNames.end(); 567} 568 569 570void 571ElfObject::updateBias(Addr bias_addr) 572{ 573 // Record the bias. 574 ldBias = bias_addr; 575 576 // Patch the entry point with bias_addr. 577 entry += bias_addr; 578 579 // Patch segments with the bias_addr. 580 text.baseAddr += bias_addr; 581 data.baseAddr += bias_addr; 582 bss.baseAddr += bias_addr; 583 for (auto &segment : extraSegments) 584 segment.baseAddr += bias_addr; 585} 586