Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2011 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2011 The Native Client Authors. All rights reserved. |
| 3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 /* | 7 /* |
| 8 * NaCl helper functions to deal with elf images | 8 * NaCl helper functions to deal with elf images |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 148 | 148 |
| 149 | 149 |
| 150 NaClErrorCode NaClElfImageValidateElfHeader(struct NaClElfImage *image) { | 150 NaClErrorCode NaClElfImageValidateElfHeader(struct NaClElfImage *image) { |
| 151 const Elf_Ehdr *hdr = &image->ehdr; | 151 const Elf_Ehdr *hdr = &image->ehdr; |
| 152 | 152 |
| 153 if (memcmp(hdr->e_ident, ELFMAG, SELFMAG)) { | 153 if (memcmp(hdr->e_ident, ELFMAG, SELFMAG)) { |
| 154 NaClLog(LOG_ERROR, "bad elf magic\n"); | 154 NaClLog(LOG_ERROR, "bad elf magic\n"); |
| 155 return LOAD_BAD_ELF_MAGIC; | 155 return LOAD_BAD_ELF_MAGIC; |
| 156 } | 156 } |
| 157 | 157 |
| 158 #if NACL_TARGET_SUBARCH == 64 | |
| 159 if (ELFCLASS64 != hdr->e_ident[EI_CLASS]) { | |
| 160 NaClLog(LOG_ERROR, "bad elf class\n"); | |
| 161 return LOAD_NOT_64_BIT; | |
| 162 } | |
| 163 #else | |
| 164 if (ELFCLASS32 != hdr->e_ident[EI_CLASS]) { | 158 if (ELFCLASS32 != hdr->e_ident[EI_CLASS]) { |
| 165 NaClLog(LOG_ERROR, "bad elf class\n"); | 159 NaClLog(LOG_ERROR, "bad elf class\n"); |
| 166 return LOAD_NOT_32_BIT; | 160 return LOAD_NOT_32_BIT; |
| 167 } | 161 } |
| 168 #endif | |
| 169 | 162 |
| 170 if (ET_EXEC != hdr->e_type) { | 163 if (ET_EXEC != hdr->e_type) { |
| 171 NaClLog(LOG_ERROR, "non executable\n"); | 164 NaClLog(LOG_ERROR, "non executable\n"); |
| 172 return LOAD_NOT_EXEC; | 165 return LOAD_NOT_EXEC; |
| 173 } | 166 } |
| 174 | 167 |
| 175 if (EM_EXPECTED_BY_NACL != hdr->e_machine) { | 168 if (EM_EXPECTED_BY_NACL != hdr->e_machine) { |
| 176 NaClLog(LOG_ERROR, "bad machine: %"NACL_PRIxElf_Half"\n", hdr->e_machine); | 169 NaClLog(LOG_ERROR, "bad machine: %"NACL_PRIxElf_Half"\n", hdr->e_machine); |
| 177 return LOAD_BAD_MACHINE; | 170 return LOAD_BAD_MACHINE; |
| 178 } | 171 } |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 275 } | 268 } |
| 276 if (php->p_vaddr < NACL_TRAMPOLINE_END) { | 269 if (php->p_vaddr < NACL_TRAMPOLINE_END) { |
| 277 NaClLog(2, | 270 NaClLog(2, |
| 278 ("Segment %d: virtual address (0x%08"NACL_PRIxElf_Addr | 271 ("Segment %d: virtual address (0x%08"NACL_PRIxElf_Addr |
| 279 ") too low\n"), | 272 ") too low\n"), |
| 280 segnum, | 273 segnum, |
| 281 php->p_vaddr); | 274 php->p_vaddr); |
| 282 return LOAD_SEGMENT_OUTSIDE_ADDRSPACE; | 275 return LOAD_SEGMENT_OUTSIDE_ADDRSPACE; |
| 283 } | 276 } |
| 284 /* | 277 /* |
| 285 * integer overflow? Elf_Addr and Elf_Word are uint32_t or | 278 * integer overflow? Elf_Addr and Elf_Word are always uint32_t, |
| 286 * uint64_t, so the addition/comparison is well defined. | 279 * so the addition/comparison is well defined but we need to do |
| 280 * a 64-bit comparison when addr_bits is 32. | |
| 287 */ | 281 */ |
| 288 if (php->p_vaddr + php->p_memsz < php->p_vaddr) { | 282 if (php->p_vaddr + php->p_memsz < php->p_vaddr) { |
| 289 NaClLog(2, | 283 NaClLog(2, |
| 290 "Segment %d: p_memsz caused integer overflow\n", | 284 "Segment %d: p_memsz caused integer overflow\n", |
| 291 segnum); | 285 segnum); |
| 292 return LOAD_SEGMENT_OUTSIDE_ADDRSPACE; | 286 return LOAD_SEGMENT_OUTSIDE_ADDRSPACE; |
| 293 } | 287 } |
| 294 if (php->p_vaddr + php->p_memsz >= ((Elf_Addr) 1U << addr_bits)) { | 288 if (php->p_vaddr + php->p_memsz >= ((uint64_t) 1U << addr_bits)) { |
|
bsy
2011/10/11 00:26:52
the sum can overflow since the add is done as uint
| |
| 295 NaClLog(2, | 289 NaClLog(2, |
| 296 "Segment %d: too large, ends at 0x%08"NACL_PRIxElf_Addr"\n", | 290 "Segment %d: too large, ends at 0x%08"NACL_PRIxElf_Addr"\n", |
| 297 segnum, | 291 segnum, |
| 298 php->p_vaddr + php->p_memsz); | 292 php->p_vaddr + php->p_memsz); |
| 299 return LOAD_SEGMENT_OUTSIDE_ADDRSPACE; | 293 return LOAD_SEGMENT_OUTSIDE_ADDRSPACE; |
| 300 } | 294 } |
| 301 if (php->p_filesz > php->p_memsz) { | 295 if (php->p_filesz > php->p_memsz) { |
| 302 NaClLog(2, | 296 NaClLog(2, |
| 303 ("Segment %d: file size 0x%08"NACL_PRIxElf_Xword" larger" | 297 ("Segment %d: file size 0x%08"NACL_PRIxElf_Xword" larger" |
| 304 " than memory size 0x%08"NACL_PRIxElf_Xword"\n"), | 298 " than memory size 0x%08"NACL_PRIxElf_Xword"\n"), |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 356 */ | 350 */ |
| 357 | 351 |
| 358 return LOAD_OK; | 352 return LOAD_OK; |
| 359 } | 353 } |
| 360 | 354 |
| 361 | 355 |
| 362 struct NaClElfImage *NaClElfImageNew(struct Gio *gp, | 356 struct NaClElfImage *NaClElfImageNew(struct Gio *gp, |
| 363 NaClErrorCode *err_code) { | 357 NaClErrorCode *err_code) { |
| 364 struct NaClElfImage *result; | 358 struct NaClElfImage *result; |
| 365 struct NaClElfImage image; | 359 struct NaClElfImage image; |
| 360 union { | |
| 361 Elf32_Ehdr ehdr32; | |
| 362 #if NACL_TARGET_SUBARCH == 64 | |
| 363 Elf64_Ehdr ehdr64; | |
| 364 #endif | |
| 365 } ehdr; | |
| 366 int cur_ph; | 366 int cur_ph; |
| 367 | 367 |
| 368 memset(image.loadable, 0, sizeof image.loadable); | 368 memset(image.loadable, 0, sizeof image.loadable); |
| 369 if (-1 == (*gp->vtbl->Seek)(gp, 0, 0)) { | 369 if (-1 == (*gp->vtbl->Seek)(gp, 0, 0)) { |
| 370 NaClLog(2, "could not seek to beginning of Gio object containing nexe\n"); | 370 NaClLog(2, "could not seek to beginning of Gio object containing nexe\n"); |
| 371 if (NULL != err_code) { | 371 if (NULL != err_code) { |
| 372 *err_code = LOAD_READ_ERROR; | 372 *err_code = LOAD_READ_ERROR; |
| 373 } | 373 } |
| 374 return 0; | 374 return 0; |
| 375 } | 375 } |
| 376 if ((*gp->vtbl->Read)(gp, | 376 if ((*gp->vtbl->Read)(gp, |
| 377 &image.ehdr, | 377 &ehdr, |
| 378 sizeof image.ehdr) | 378 sizeof ehdr) |
|
bsy
2011/10/11 00:26:52
maybe a comment here that reading the size of the
| |
| 379 != sizeof image.ehdr) { | 379 != sizeof ehdr) { |
| 380 if (NULL != err_code) { | 380 if (NULL != err_code) { |
| 381 *err_code = LOAD_READ_ERROR; | 381 *err_code = LOAD_READ_ERROR; |
| 382 } | 382 } |
| 383 NaClLog(2, "could not load elf headers\n"); | 383 NaClLog(2, "could not load elf headers\n"); |
| 384 return 0; | 384 return 0; |
| 385 } | 385 } |
| 386 | 386 |
| 387 #if NACL_TARGET_SUBARCH == 64 | |
| 388 if (ELFCLASS64 == ehdr.ehdr64.e_ident[EI_CLASS]) { | |
| 389 /* | |
| 390 * Convert ELFCLASS64 format to ELFCLASS32 format. | |
| 391 * The initial four fields are the same in both classes. | |
| 392 */ | |
| 393 memcpy(image.ehdr.e_ident, ehdr.ehdr64.e_ident, EI_NIDENT); | |
| 394 image.ehdr.e_ident[EI_CLASS] = ELFCLASS32; | |
| 395 image.ehdr.e_type = ehdr.ehdr64.e_type; | |
| 396 image.ehdr.e_machine = ehdr.ehdr64.e_machine; | |
| 397 image.ehdr.e_version = ehdr.ehdr64.e_version; | |
| 398 if (ehdr.ehdr64.e_entry > 0xffffffffU || | |
| 399 ehdr.ehdr64.e_phoff > 0xffffffffU || | |
| 400 ehdr.ehdr64.e_shoff > 0xffffffffU) { | |
| 401 if (NULL != err_code) { | |
| 402 *err_code = LOAD_EHDR_OVERFLOW; | |
| 403 } | |
| 404 NaClLog(2, "ELFCLASS64 file header fields overflow 32 bits\n"); | |
| 405 return 0; | |
| 406 } | |
| 407 image.ehdr.e_entry = (Elf32_Addr) ehdr.ehdr64.e_entry; | |
| 408 image.ehdr.e_phoff = (Elf32_Off) ehdr.ehdr64.e_phoff; | |
| 409 image.ehdr.e_shoff = (Elf32_Off) ehdr.ehdr64.e_shoff; | |
| 410 image.ehdr.e_flags = ehdr.ehdr64.e_flags; | |
| 411 if (ehdr.ehdr64.e_ehsize < sizeof(ehdr.ehdr64)) { | |
| 412 if (NULL != err_code) { | |
| 413 *err_code = LOAD_BAD_EHSIZE; | |
| 414 } | |
| 415 NaClLog(2, "ELFCLASS64 file e_ehsize != %d\n", (int) sizeof(ehdr.ehdr64)); | |
| 416 return 0; | |
| 417 } | |
| 418 image.ehdr.e_ehsize = sizeof(image.ehdr); | |
| 419 image.ehdr.e_phentsize = sizeof(image.phdrs[0]); | |
| 420 image.ehdr.e_phnum = ehdr.ehdr64.e_phnum; | |
| 421 image.ehdr.e_shentsize = ehdr.ehdr64.e_shentsize; | |
| 422 image.ehdr.e_shnum = ehdr.ehdr64.e_shnum; | |
| 423 image.ehdr.e_shstrndx = ehdr.ehdr64.e_shstrndx; | |
| 424 } else | |
| 425 #endif | |
| 426 { | |
| 427 image.ehdr = ehdr.ehdr32; | |
| 428 } | |
| 429 | |
| 387 NaClDumpElfHeader(2, &image.ehdr); | 430 NaClDumpElfHeader(2, &image.ehdr); |
| 388 | 431 |
| 389 /* read program headers */ | 432 /* read program headers */ |
| 390 if (image.ehdr.e_phnum > NACL_MAX_PROGRAM_HEADERS) { | 433 if (image.ehdr.e_phnum > NACL_MAX_PROGRAM_HEADERS) { |
| 391 if (NULL != err_code) | 434 if (NULL != err_code) |
| 392 *err_code = LOAD_TOO_MANY_PROG_HDRS; | 435 *err_code = LOAD_TOO_MANY_PROG_HDRS; |
| 393 NaClLog(2, "too many prog headers\n"); | 436 NaClLog(2, "too many prog headers\n"); |
| 394 return 0; | 437 return 0; |
| 395 } | 438 } |
| 396 | 439 |
| 397 if (image.ehdr.e_phentsize < sizeof image.phdrs[0]) { | |
| 398 if (NULL != err_code) { | |
| 399 *err_code = LOAD_PROG_HDR_SIZE_TOO_SMALL; | |
| 400 } | |
| 401 NaClLog(2, "bad prog headers size\n"); | |
| 402 NaClLog(2, " image.ehdr.e_phentsize = 0x%"NACL_PRIxElf_Half"\n", | |
| 403 image.ehdr.e_phentsize); | |
| 404 NaClLog(2, " sizeof image.phdrs[0] = 0x%"NACL_PRIxS"\n", | |
| 405 sizeof image.phdrs[0]); | |
| 406 return 0; | |
| 407 } | |
| 408 | |
| 409 /* | 440 /* |
| 410 * NB: cast from e_phoff to off_t may not be valid, since off_t can be | 441 * NB: cast from e_phoff to off_t may not be valid, since off_t can be |
| 411 * smaller than Elf64_off, but since invalid values will be rejected | 442 * smaller than Elf64_off, but since invalid values will be rejected |
| 412 * by Seek() the cast is safe (cf bsy) | 443 * by Seek() the cast is safe (cf bsy) |
| 413 */ | 444 */ |
| 414 if ((*gp->vtbl->Seek)(gp, | 445 if ((*gp->vtbl->Seek)(gp, |
| 415 (off_t) image.ehdr.e_phoff, | 446 (off_t) image.ehdr.e_phoff, |
| 416 SEEK_SET) == (off_t) -1) { | 447 SEEK_SET) == (off_t) -1) { |
| 417 if (NULL != err_code) { | 448 if (NULL != err_code) { |
| 418 *err_code = LOAD_READ_ERROR; | 449 *err_code = LOAD_READ_ERROR; |
| 419 } | 450 } |
| 420 NaClLog(2, "cannot seek tp prog headers\n"); | 451 NaClLog(2, "cannot seek tp prog headers\n"); |
| 421 return 0; | 452 return 0; |
| 422 } | 453 } |
| 423 | 454 |
| 424 if ((size_t) (*gp->vtbl->Read)(gp, | 455 #if NACL_TARGET_SUBARCH == 64 |
| 425 &image.phdrs[0], | 456 if (ELFCLASS64 == ehdr.ehdr64.e_ident[EI_CLASS]) { |
| 426 image.ehdr.e_phnum * sizeof image.phdrs[0]) | 457 /* |
| 427 != (image.ehdr.e_phnum * sizeof image.phdrs[0])) { | 458 * We'll load the 64-bit phdrs and convert them to 32-bit format. |
| 428 if (NULL != err_code) { | 459 */ |
| 429 *err_code = LOAD_READ_ERROR; | 460 Elf64_Phdr phdr64[NACL_MAX_PROGRAM_HEADERS]; |
| 461 | |
| 462 if (ehdr.ehdr64.e_phentsize < sizeof(Elf64_Phdr)) { | |
| 463 if (NULL != err_code) { | |
| 464 *err_code = LOAD_PROG_HDR_SIZE_TOO_SMALL; | |
| 465 } | |
| 466 NaClLog(2, "bad prog headers size\n"); | |
| 467 NaClLog(2, " ehdr64.e_phentsize = 0x%"NACL_PRIxElf_Half"\n", | |
| 468 ehdr.ehdr64.e_phentsize); | |
| 469 NaClLog(2, " sizeof(Elf64_Phdr) = 0x%"NACL_PRIxS"\n", | |
| 470 sizeof(Elf64_Phdr)); | |
| 471 return 0; | |
| 430 } | 472 } |
| 431 NaClLog(2, "cannot load tp prog headers\n"); | 473 |
| 432 return 0; | 474 if ((size_t) (*gp->vtbl->Read)(gp, |
| 475 &phdr64[0], | |
| 476 image.ehdr.e_phnum * sizeof phdr64[0]) | |
| 477 != (image.ehdr.e_phnum * sizeof phdr64[0])) { | |
| 478 if (NULL != err_code) { | |
| 479 *err_code = LOAD_READ_ERROR; | |
| 480 } | |
| 481 NaClLog(2, "cannot load tp prog headers\n"); | |
| 482 return 0; | |
| 483 } | |
| 484 | |
| 485 for (cur_ph = 0; cur_ph < image.ehdr.e_phnum; ++cur_ph) { | |
| 486 if (phdr64[cur_ph].p_offset > 0xffffffffU || | |
| 487 phdr64[cur_ph].p_vaddr > 0xffffffffU || | |
| 488 phdr64[cur_ph].p_paddr > 0xffffffffU || | |
| 489 phdr64[cur_ph].p_filesz > 0xffffffffU || | |
| 490 phdr64[cur_ph].p_memsz > 0xffffffffU || | |
| 491 phdr64[cur_ph].p_align > 0xffffffffU) { | |
| 492 if (NULL != err_code) { | |
| 493 *err_code = LOAD_PHDR_OVERFLOW; | |
| 494 } | |
| 495 NaClLog(2, "ELFCLASS64 program header fields overflow 32 bits\n"); | |
| 496 return 0; | |
| 497 } | |
| 498 image.phdrs[cur_ph].p_type = phdr64[cur_ph].p_type; | |
| 499 image.phdrs[cur_ph].p_offset = (Elf32_Off) phdr64[cur_ph].p_offset; | |
| 500 image.phdrs[cur_ph].p_vaddr = (Elf32_Addr) phdr64[cur_ph].p_vaddr; | |
| 501 image.phdrs[cur_ph].p_paddr = (Elf32_Addr) phdr64[cur_ph].p_paddr; | |
| 502 image.phdrs[cur_ph].p_filesz = (Elf32_Word) phdr64[cur_ph].p_filesz; | |
| 503 image.phdrs[cur_ph].p_memsz = (Elf32_Word) phdr64[cur_ph].p_memsz; | |
| 504 image.phdrs[cur_ph].p_flags = phdr64[cur_ph].p_flags; | |
| 505 image.phdrs[cur_ph].p_align = (Elf32_Word) phdr64[cur_ph].p_align; | |
| 506 } | |
| 507 } else | |
| 508 #endif | |
| 509 { | |
| 510 if (image.ehdr.e_phentsize < sizeof image.phdrs[0]) { | |
| 511 if (NULL != err_code) { | |
| 512 *err_code = LOAD_PROG_HDR_SIZE_TOO_SMALL; | |
| 513 } | |
| 514 NaClLog(2, "bad prog headers size\n"); | |
| 515 NaClLog(2, " image.ehdr.e_phentsize = 0x%"NACL_PRIxElf_Half"\n", | |
| 516 image.ehdr.e_phentsize); | |
| 517 NaClLog(2, " sizeof image.phdrs[0] = 0x%"NACL_PRIxS"\n", | |
| 518 sizeof image.phdrs[0]); | |
| 519 return 0; | |
| 520 } | |
| 521 | |
| 522 if ((size_t) (*gp->vtbl->Read)(gp, | |
| 523 &image.phdrs[0], | |
| 524 image.ehdr.e_phnum * sizeof image.phdrs[0]) | |
| 525 != (image.ehdr.e_phnum * sizeof image.phdrs[0])) { | |
| 526 if (NULL != err_code) { | |
| 527 *err_code = LOAD_READ_ERROR; | |
| 528 } | |
| 529 NaClLog(2, "cannot load tp prog headers\n"); | |
| 530 return 0; | |
| 531 } | |
| 433 } | 532 } |
| 434 | 533 |
| 435 NaClLog(2, "=================================================\n"); | 534 NaClLog(2, "=================================================\n"); |
| 436 NaClLog(2, "Elf Program headers\n"); | 535 NaClLog(2, "Elf Program headers\n"); |
| 437 NaClLog(2, "==================================================\n"); | 536 NaClLog(2, "==================================================\n"); |
| 438 for (cur_ph = 0; cur_ph < image.ehdr.e_phnum; ++cur_ph) { | 537 for (cur_ph = 0; cur_ph < image.ehdr.e_phnum; ++cur_ph) { |
| 439 NaClDumpElfProgramHeader(2, &image.phdrs[cur_ph]); | 538 NaClDumpElfProgramHeader(2, &image.phdrs[cur_ph]); |
| 440 } | 539 } |
| 441 | 540 |
| 442 /* we delay allocating till the end to avoid cleanup code */ | 541 /* we delay allocating till the end to avoid cleanup code */ |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 601 size_t mapping_size = NaClRoundAllocPage(php->p_memsz); | 700 size_t mapping_size = NaClRoundAllocPage(php->p_memsz); |
| 602 /* | 701 /* |
| 603 * Note that we do not used NACL_ABI_MAP_FIXED because we do not | 702 * Note that we do not used NACL_ABI_MAP_FIXED because we do not |
| 604 * want to silently overwrite any existing mappings, such as the | 703 * want to silently overwrite any existing mappings, such as the |
| 605 * user app's data segment or the stack. We detect overmapping | 704 * user app's data segment or the stack. We detect overmapping |
| 606 * when mmap chooses not to use the preferred address we supply. | 705 * when mmap chooses not to use the preferred address we supply. |
| 607 * (Ideally mmap would provide a MAP_EXCL option for this | 706 * (Ideally mmap would provide a MAP_EXCL option for this |
| 608 * instead.) | 707 * instead.) |
| 609 */ | 708 */ |
| 610 result = NaClCommonSysMmapIntern( | 709 result = NaClCommonSysMmapIntern( |
| 611 nap, (void *) php->p_vaddr, mapping_size, | 710 nap, (void *) (uintptr_t) php->p_vaddr, mapping_size, |
| 612 NACL_ABI_PROT_READ | NACL_ABI_PROT_WRITE, | 711 NACL_ABI_PROT_READ | NACL_ABI_PROT_WRITE, |
| 613 NACL_ABI_MAP_ANONYMOUS | NACL_ABI_MAP_PRIVATE, | 712 NACL_ABI_MAP_ANONYMOUS | NACL_ABI_MAP_PRIVATE, |
| 614 -1, 0); | 713 -1, 0); |
| 615 if ((int32_t) php->p_vaddr != result) { | 714 if ((int32_t) php->p_vaddr != result) { |
| 616 NaClLog(1, "NaClElfImageLoadDynamically: failed to map data segment\n"); | 715 NaClLog(1, "NaClElfImageLoadDynamically: failed to map data segment\n"); |
| 617 return LOAD_UNLOADABLE; | 716 return LOAD_UNLOADABLE; |
| 618 } | 717 } |
| 619 if ((Elf_Word) (*gfile->vtbl->Read)(gfile, paddr, php->p_filesz) | 718 if ((Elf_Word) (*gfile->vtbl->Read)(gfile, paddr, php->p_filesz) |
| 620 != php->p_filesz) { | 719 != php->p_filesz) { |
| 621 NaClLog(1, "NaClElfImageLoadDynamically: " | 720 NaClLog(1, "NaClElfImageLoadDynamically: " |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 652 | 751 |
| 653 | 752 |
| 654 void NaClElfImageDelete(struct NaClElfImage *image) { | 753 void NaClElfImageDelete(struct NaClElfImage *image) { |
| 655 free(image); | 754 free(image); |
| 656 } | 755 } |
| 657 | 756 |
| 658 | 757 |
| 659 uintptr_t NaClElfImageGetEntryPoint(struct NaClElfImage *image) { | 758 uintptr_t NaClElfImageGetEntryPoint(struct NaClElfImage *image) { |
| 660 return image->ehdr.e_entry; | 759 return image->ehdr.e_entry; |
| 661 } | 760 } |
| OLD | NEW |