1 /* 2 * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2003-2008, Axel Dörfler, axeld@pinc-software.de. 4 * Distributed under the terms of the MIT License. 5 * 6 * Copyright 2002, Manuel J. Petit. All rights reserved. 7 * Copyright 2001, Travis Geiselbrecht. All rights reserved. 8 * Distributed under the terms of the NewOS License. 9 */ 10 11 #include "elf_load_image.h" 12 13 #include <stdio.h> 14 #include <string.h> 15 16 #include <syscalls.h> 17 18 #include "add_ons.h" 19 #include "elf_haiku_version.h" 20 #include "elf_symbol_lookup.h" 21 #include "elf_versioning.h" 22 #include "images.h" 23 #include "runtime_loader_private.h" 24 25 26 static const char* sSearchPathSubDir = NULL; 27 28 29 static const char* 30 get_program_path() 31 { 32 return gProgramImage != NULL ? gProgramImage->path : NULL; 33 } 34 35 36 static int32 37 count_regions(const char* imagePath, char const* buff, int phnum, int phentsize) 38 { 39 struct Elf32_Phdr* pheaders; 40 int32 count = 0; 41 int i; 42 43 for (i = 0; i < phnum; i++) { 44 pheaders = (struct Elf32_Phdr*)(buff + i * phentsize); 45 46 switch (pheaders->p_type) { 47 case PT_NULL: 48 // NOP header 49 break; 50 case PT_LOAD: 51 count += 1; 52 if (pheaders->p_memsz != pheaders->p_filesz) { 53 addr_t A = TO_PAGE_SIZE(pheaders->p_vaddr 54 + pheaders->p_memsz); 55 addr_t B = TO_PAGE_SIZE(pheaders->p_vaddr 56 + pheaders->p_filesz); 57 58 if (A != B) 59 count += 1; 60 } 61 break; 62 case PT_DYNAMIC: 63 // will be handled at some other place 64 break; 65 case PT_INTERP: 66 // should check here for appropiate interpreter 67 break; 68 case PT_NOTE: 69 // unsupported 70 break; 71 case PT_SHLIB: 72 // undefined semantics 73 break; 74 case PT_PHDR: 75 // we don't use it 76 break; 77 case PT_STACK: 78 // we don't use it 79 break; 80 default: 81 FATAL("%s: Unhandled pheader type in count 0x%lx\n", 82 imagePath, pheaders->p_type); 83 return B_BAD_DATA; 84 } 85 } 86 87 return count; 88 } 89 90 91 static status_t 92 parse_program_headers(image_t* image, char* buff, int phnum, int phentsize) 93 { 94 struct Elf32_Phdr* pheader; 95 int regcount; 96 int i; 97 98 regcount = 0; 99 for (i = 0; i < phnum; i++) { 100 pheader = (struct Elf32_Phdr*)(buff + i * phentsize); 101 102 switch (pheader->p_type) { 103 case PT_NULL: 104 /* NOP header */ 105 break; 106 case PT_LOAD: 107 if (pheader->p_memsz == pheader->p_filesz) { 108 /* 109 * everything in one area 110 */ 111 image->regions[regcount].start = pheader->p_vaddr; 112 image->regions[regcount].size = pheader->p_memsz; 113 image->regions[regcount].vmstart 114 = PAGE_BASE(pheader->p_vaddr); 115 image->regions[regcount].vmsize 116 = TO_PAGE_SIZE(pheader->p_memsz 117 + PAGE_OFFSET(pheader->p_vaddr)); 118 image->regions[regcount].fdstart = pheader->p_offset; 119 image->regions[regcount].fdsize = pheader->p_filesz; 120 image->regions[regcount].delta = 0; 121 image->regions[regcount].flags = 0; 122 if (pheader->p_flags & PF_WRITE) { 123 // this is a writable segment 124 image->regions[regcount].flags |= RFLAG_RW; 125 } 126 } else { 127 /* 128 * may require splitting 129 */ 130 addr_t A = TO_PAGE_SIZE(pheader->p_vaddr 131 + pheader->p_memsz); 132 addr_t B = TO_PAGE_SIZE(pheader->p_vaddr 133 + pheader->p_filesz); 134 135 image->regions[regcount].start = pheader->p_vaddr; 136 image->regions[regcount].size = pheader->p_filesz; 137 image->regions[regcount].vmstart 138 = PAGE_BASE(pheader->p_vaddr); 139 image->regions[regcount].vmsize 140 = TO_PAGE_SIZE(pheader->p_filesz 141 + PAGE_OFFSET(pheader->p_vaddr)); 142 image->regions[regcount].fdstart = pheader->p_offset; 143 image->regions[regcount].fdsize = pheader->p_filesz; 144 image->regions[regcount].delta = 0; 145 image->regions[regcount].flags = 0; 146 if (pheader->p_flags & PF_WRITE) { 147 // this is a writable segment 148 image->regions[regcount].flags |= RFLAG_RW; 149 } 150 151 if (A != B) { 152 /* 153 * yeah, it requires splitting 154 */ 155 regcount += 1; 156 image->regions[regcount].start = pheader->p_vaddr; 157 image->regions[regcount].size 158 = pheader->p_memsz - pheader->p_filesz; 159 image->regions[regcount].vmstart 160 = image->regions[regcount-1].vmstart 161 + image->regions[regcount-1].vmsize; 162 image->regions[regcount].vmsize 163 = TO_PAGE_SIZE(pheader->p_memsz 164 + PAGE_OFFSET(pheader->p_vaddr)) 165 - image->regions[regcount-1].vmsize; 166 image->regions[regcount].fdstart = 0; 167 image->regions[regcount].fdsize = 0; 168 image->regions[regcount].delta = 0; 169 image->regions[regcount].flags = RFLAG_ANON; 170 if (pheader->p_flags & PF_WRITE) { 171 // this is a writable segment 172 image->regions[regcount].flags |= RFLAG_RW; 173 } 174 } 175 } 176 regcount += 1; 177 break; 178 case PT_DYNAMIC: 179 image->dynamic_ptr = pheader->p_vaddr; 180 break; 181 case PT_INTERP: 182 // should check here for appropiate interpreter 183 break; 184 case PT_NOTE: 185 // unsupported 186 break; 187 case PT_SHLIB: 188 // undefined semantics 189 break; 190 case PT_PHDR: 191 // we don't use it 192 break; 193 case PT_STACK: 194 // we don't use it 195 break; 196 default: 197 FATAL("%s: Unhandled pheader type in parse 0x%lx\n", 198 image->path, pheader->p_type); 199 return B_BAD_DATA; 200 } 201 } 202 203 return B_OK; 204 } 205 206 207 static bool 208 assert_dynamic_loadable(image_t* image) 209 { 210 uint32 i; 211 212 if (!image->dynamic_ptr) 213 return true; 214 215 for (i = 0; i < image->num_regions; i++) { 216 if (image->dynamic_ptr >= image->regions[i].start 217 && image->dynamic_ptr 218 < image->regions[i].start + image->regions[i].size) { 219 return true; 220 } 221 } 222 223 return false; 224 } 225 226 227 static bool 228 parse_dynamic_segment(image_t* image) 229 { 230 struct Elf32_Dyn* d; 231 int i; 232 int sonameOffset = -1; 233 234 image->symhash = 0; 235 image->syms = 0; 236 image->strtab = 0; 237 238 d = (struct Elf32_Dyn*)image->dynamic_ptr; 239 if (!d) 240 return true; 241 242 for (i = 0; d[i].d_tag != DT_NULL; i++) { 243 switch (d[i].d_tag) { 244 case DT_NEEDED: 245 image->num_needed += 1; 246 break; 247 case DT_HASH: 248 image->symhash 249 = (uint32*)(d[i].d_un.d_ptr + image->regions[0].delta); 250 break; 251 case DT_STRTAB: 252 image->strtab 253 = (char*)(d[i].d_un.d_ptr + image->regions[0].delta); 254 break; 255 case DT_SYMTAB: 256 image->syms = (struct Elf32_Sym*) 257 (d[i].d_un.d_ptr + image->regions[0].delta); 258 break; 259 case DT_REL: 260 image->rel = (struct Elf32_Rel*) 261 (d[i].d_un.d_ptr + image->regions[0].delta); 262 break; 263 case DT_RELSZ: 264 image->rel_len = d[i].d_un.d_val; 265 break; 266 case DT_RELA: 267 image->rela = (struct Elf32_Rela*) 268 (d[i].d_un.d_ptr + image->regions[0].delta); 269 break; 270 case DT_RELASZ: 271 image->rela_len = d[i].d_un.d_val; 272 break; 273 // TK: procedure linkage table 274 case DT_JMPREL: 275 image->pltrel = (struct Elf32_Rel*) 276 (d[i].d_un.d_ptr + image->regions[0].delta); 277 break; 278 case DT_PLTRELSZ: 279 image->pltrel_len = d[i].d_un.d_val; 280 break; 281 case DT_INIT: 282 image->init_routine 283 = (d[i].d_un.d_ptr + image->regions[0].delta); 284 break; 285 case DT_FINI: 286 image->term_routine 287 = (d[i].d_un.d_ptr + image->regions[0].delta); 288 break; 289 case DT_SONAME: 290 sonameOffset = d[i].d_un.d_val; 291 break; 292 case DT_VERSYM: 293 image->symbol_versions = (Elf32_Versym*) 294 (d[i].d_un.d_ptr + image->regions[0].delta); 295 break; 296 case DT_VERDEF: 297 image->version_definitions = (Elf32_Verdef*) 298 (d[i].d_un.d_ptr + image->regions[0].delta); 299 break; 300 case DT_VERDEFNUM: 301 image->num_version_definitions = d[i].d_un.d_val; 302 break; 303 case DT_VERNEED: 304 image->needed_versions = (Elf32_Verneed*) 305 (d[i].d_un.d_ptr + image->regions[0].delta); 306 break; 307 case DT_VERNEEDNUM: 308 image->num_needed_versions = d[i].d_un.d_val; 309 break; 310 default: 311 continue; 312 } 313 } 314 315 // lets make sure we found all the required sections 316 if (!image->symhash || !image->syms || !image->strtab) 317 return false; 318 319 if (sonameOffset >= 0) 320 strlcpy(image->name, STRING(image, sonameOffset), sizeof(image->name)); 321 322 return true; 323 } 324 325 326 // #pragma mark - 327 328 329 status_t 330 parse_elf_header(struct Elf32_Ehdr* eheader, int32* _pheaderSize, 331 int32* _sheaderSize) 332 { 333 if (memcmp(eheader->e_ident, ELF_MAGIC, 4) != 0) 334 return B_NOT_AN_EXECUTABLE; 335 336 if (eheader->e_ident[4] != ELFCLASS32) 337 return B_NOT_AN_EXECUTABLE; 338 339 if (eheader->e_phoff == 0) 340 return B_NOT_AN_EXECUTABLE; 341 342 if (eheader->e_phentsize < sizeof(struct Elf32_Phdr)) 343 return B_NOT_AN_EXECUTABLE; 344 345 *_pheaderSize = eheader->e_phentsize * eheader->e_phnum; 346 *_sheaderSize = eheader->e_shentsize * eheader->e_shnum; 347 348 if (*_pheaderSize <= 0 || *_sheaderSize <= 0) 349 return B_NOT_AN_EXECUTABLE; 350 351 return B_OK; 352 } 353 354 355 status_t 356 load_image(char const* name, image_type type, const char* rpath, 357 image_t** _image) 358 { 359 int32 pheaderSize, sheaderSize; 360 char path[PATH_MAX]; 361 ssize_t length; 362 char pheaderBuffer[4096]; 363 int32 numRegions; 364 image_t* found; 365 image_t* image; 366 status_t status; 367 int fd; 368 369 struct Elf32_Ehdr eheader; 370 371 // Have we already loaded that image? Don't check for add-ons -- we always 372 // reload them. 373 if (type != B_ADD_ON_IMAGE) { 374 found = find_loaded_image_by_name(name, APP_OR_LIBRARY_TYPE); 375 376 if (found == NULL && type != B_APP_IMAGE && gProgramImage != NULL) { 377 // Special case for add-ons that link against the application 378 // executable, with the executable not having a soname set. 379 if (const char* lastSlash = strrchr(name, '/')) { 380 if (strcmp(gProgramImage->name, lastSlash + 1) == 0) 381 found = gProgramImage; 382 } 383 } 384 385 if (found) { 386 atomic_add(&found->ref_count, 1); 387 *_image = found; 388 KTRACE("rld: load_container(\"%s\", type: %d, rpath: \"%s\") " 389 "already loaded", name, type, rpath); 390 return B_OK; 391 } 392 } 393 394 KTRACE("rld: load_container(\"%s\", type: %d, rpath: \"%s\")", name, type, 395 rpath); 396 397 strlcpy(path, name, sizeof(path)); 398 399 // find and open the file 400 fd = open_executable(path, type, rpath, get_program_path(), 401 sSearchPathSubDir); 402 if (fd < 0) { 403 FATAL("Cannot open file %s: %s\n", name, strerror(fd)); 404 KTRACE("rld: load_container(\"%s\"): failed to open file", name); 405 return fd; 406 } 407 408 // normalize the image path 409 status = _kern_normalize_path(path, true, path); 410 if (status != B_OK) 411 goto err1; 412 413 // Test again if this image has been registered already - this time, 414 // we can check the full path, not just its name as noted. 415 // You could end up loading an image twice with symbolic links, else. 416 if (type != B_ADD_ON_IMAGE) { 417 found = find_loaded_image_by_name(path, APP_OR_LIBRARY_TYPE); 418 if (found) { 419 atomic_add(&found->ref_count, 1); 420 *_image = found; 421 _kern_close(fd); 422 KTRACE("rld: load_container(\"%s\"): already loaded after all", 423 name); 424 return B_OK; 425 } 426 } 427 428 length = _kern_read(fd, 0, &eheader, sizeof(eheader)); 429 if (length != sizeof(eheader)) { 430 status = B_NOT_AN_EXECUTABLE; 431 FATAL("%s: Troubles reading ELF header\n", path); 432 goto err1; 433 } 434 435 status = parse_elf_header(&eheader, &pheaderSize, &sheaderSize); 436 if (status < B_OK) { 437 FATAL("%s: Incorrect ELF header\n", path); 438 goto err1; 439 } 440 441 // ToDo: what to do about this restriction?? 442 if (pheaderSize > (int)sizeof(pheaderBuffer)) { 443 FATAL("%s: Cannot handle program headers bigger than %lu\n", 444 path, sizeof(pheaderBuffer)); 445 status = B_UNSUPPORTED; 446 goto err1; 447 } 448 449 length = _kern_read(fd, eheader.e_phoff, pheaderBuffer, pheaderSize); 450 if (length != pheaderSize) { 451 FATAL("%s: Could not read program headers: %s\n", path, 452 strerror(length)); 453 status = B_BAD_DATA; 454 goto err1; 455 } 456 457 numRegions = count_regions(path, pheaderBuffer, eheader.e_phnum, 458 eheader.e_phentsize); 459 if (numRegions <= 0) { 460 FATAL("%s: Troubles parsing Program headers, numRegions = %ld\n", 461 path, numRegions); 462 status = B_BAD_DATA; 463 goto err1; 464 } 465 466 image = create_image(name, path, numRegions); 467 if (image == NULL) { 468 FATAL("%s: Failed to allocate image_t object\n", path); 469 status = B_NO_MEMORY; 470 goto err1; 471 } 472 473 status = parse_program_headers(image, pheaderBuffer, eheader.e_phnum, 474 eheader.e_phentsize); 475 if (status < B_OK) 476 goto err2; 477 478 if (!assert_dynamic_loadable(image)) { 479 FATAL("%s: Dynamic segment must be loadable (implementation " 480 "restriction)\n", image->path); 481 status = B_UNSUPPORTED; 482 goto err2; 483 } 484 485 status = map_image(fd, path, image, type == B_APP_IMAGE); 486 if (status < B_OK) { 487 FATAL("%s: Could not map image: %s\n", image->path, strerror(status)); 488 status = B_ERROR; 489 goto err2; 490 } 491 492 if (!parse_dynamic_segment(image)) { 493 FATAL("%s: Troubles handling dynamic section\n", image->path); 494 status = B_BAD_DATA; 495 goto err3; 496 } 497 498 if (eheader.e_entry != 0) 499 image->entry_point = eheader.e_entry + image->regions[0].delta; 500 501 analyze_image_haiku_version_and_abi(fd, image, eheader, sheaderSize, 502 pheaderBuffer, sizeof(pheaderBuffer)); 503 504 // If this is the executable image, we init the search path 505 // subdir, if the compiler version doesn't match ours. 506 if (type == B_APP_IMAGE) { 507 #if __GNUC__ == 2 508 if ((image->abi & B_HAIKU_ABI_MAJOR) == B_HAIKU_ABI_GCC_4) 509 sSearchPathSubDir = "gcc4"; 510 #elif __GNUC__ == 4 511 if ((image->abi & B_HAIKU_ABI_MAJOR) == B_HAIKU_ABI_GCC_2) 512 sSearchPathSubDir = "gcc2"; 513 #endif 514 } 515 516 // init gcc version dependent image flags 517 // symbol resolution strategy 518 if (image->abi == B_HAIKU_ABI_GCC_2_ANCIENT) 519 image->find_undefined_symbol = find_undefined_symbol_beos; 520 521 // init version infos 522 status = init_image_version_infos(image); 523 524 image->type = type; 525 register_image(image, fd, path); 526 image_event(image, IMAGE_EVENT_LOADED); 527 528 _kern_close(fd); 529 530 enqueue_loaded_image(image); 531 532 *_image = image; 533 534 KTRACE("rld: load_container(\"%s\"): done: id: %ld (ABI: %#lx)", name, 535 image->id, image->abi); 536 537 return B_OK; 538 539 err3: 540 unmap_image(image); 541 err2: 542 delete_image_struct(image); 543 err1: 544 _kern_close(fd); 545 546 KTRACE("rld: load_container(\"%s\"): failed: %s", name, 547 strerror(status)); 548 549 return status; 550 } 551