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