this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

libmach-o/dyld: support for internal/external relocations on i386 and x86-64

+286 -61
+93 -49
src/dyld/MachOLoader.cpp
··· 1 1 /* 2 2 This file is part of Darling. 3 3 4 - Copyright (C) 2012 Lubos Dolezel 4 + Copyright (C) 2012-2013 Lubos Dolezel 5 5 Copyright (C) 2011 Shinichiro Hamaji 6 6 7 7 Darling is free software: you can redistribute it and/or modify ··· 317 317 } 318 318 } 319 319 320 + void MachOLoader::doRelocations(const std::vector<MachO::Relocation*>& rels, intptr base, intptr slide) 321 + { 322 + for (const MachO::Relocation* rel : rels) 323 + { 324 + uintptr_t* ptr = (uintptr_t*) (uintptr_t(rel->addr) /*+ base*/ + slide); 325 + uintptr_t symbol; 326 + uintptr_t value = *ptr; 327 + 328 + symbol = getSymbolAddress(rel->name); 329 + 330 + value += symbol; 331 + 332 + #ifdef __i386__ 333 + if (rel->pcrel) 334 + { 335 + LOG << "reloc(pcrel): @" << ptr << " " << std::hex << *ptr << " -> " << (value - uintptr_t(ptr) - 4) << std::dec << std::endl; 336 + *ptr = value - uintptr_t(ptr) - 4; 337 + } 338 + else 339 + #endif 340 + { 341 + LOG << "reloc: @" << ptr << " " << std::hex << *ptr << " -> " << value << std::dec << std::endl; 342 + *ptr = value; 343 + } 344 + } 345 + } 346 + 320 347 void MachOLoader::loadInitFuncs(const MachO& mach, intptr slide) 321 348 { 322 349 for (intptr addr : mach.init_funcs()) ··· 356 383 uintptr_t* ptr = (uintptr_t*)(bind->vmaddr + slide); 357 384 358 385 sym = 0; 359 - 386 + 387 + // FIXME: This unholy mess needs to be fixed, weak bind handling shouldn't be implemented separately like this 360 388 if (bind->is_weak) 361 389 { 362 390 if (g_noWeak) ··· 419 447 } 420 448 else // not weak 421 449 { 422 - // TODO: remove, replace with aliases 423 - #ifndef __x86_64__ 424 - static const char* SUF_UNIX03 = "$UNIX2003"; 425 - static const size_t SUF_UNIX03_LEN = strlen(SUF_UNIX03); 426 - if (name.size() > SUF_UNIX03_LEN && 427 - !strcmp(name.c_str() + name.size() - SUF_UNIX03_LEN, 428 - SUF_UNIX03)) { 429 - name = name.substr(0, name.size() - SUF_UNIX03_LEN); 430 - } 431 - #endif 450 + sym = getSymbolAddress(bind->name); 432 451 433 - if (bind->name[0] != '_') 434 - { 435 - // assume local (e.g. dyld_stub_binder) 436 - name = bind->name; // for correct error reporting 437 - sym = reinterpret_cast<uintptr_t>(dlsym(dlopen(0, 0), bind->name.c_str())); 438 - } 439 - else 440 - sym = reinterpret_cast<uintptr_t>(__darwin_dlsym(DARWIN_RTLD_DEFAULT, name.c_str())); 441 - 442 - if (!sym) 443 - { 444 - const char* ign_sym = getenv("DYLD_IGN_MISSING_SYMS"); 445 - //if (!bind->addend) 446 - { 447 - #ifdef __x86_64__ 448 - if (ign_sym && atoi(ign_sym)) 449 - { 450 - std::cerr << "!!! Undefined symbol: " << name << std::endl; 451 - 452 - char* dname = new char[name.size()+1]; 453 - strcpy(dname, name.c_str()); 454 - 455 - sym = reinterpret_cast<uintptr_t>(m_pUndefMgr->generateNew(dname)); 456 - } 457 - else 458 - #endif 459 - { 460 - std::stringstream ss; 461 - ss << "Undefined symbol: " << name; 462 - throw std::runtime_error(ss.str()); 463 - } 464 - } 465 - //else 466 - // sym = reinterpret_cast<char*>(bind->addend + slide); 467 - } 468 - else 452 + if (!bind->is_classic) 469 453 sym += bind->addend; 470 454 } 471 455 ··· 491 475 return reinterpret_cast<void*>(sym); 492 476 } 493 477 478 + uintptr_t MachOLoader::getSymbolAddress(const std::string& oname) 479 + { 480 + std::string name; 481 + uintptr_t sym; 482 + 483 + if (oname[0] != '_') 484 + { 485 + // assume local (e.g. dyld_stub_binder) 486 + name = oname; 487 + sym = reinterpret_cast<uintptr_t>(dlsym(dlopen(0, 0), name.c_str())); 488 + } 489 + else 490 + { 491 + name = oname.substr(1); 492 + 493 + // TODO: remove, replace with aliases 494 + #ifndef __x86_64__ 495 + static const char* SUF_UNIX03 = "$UNIX2003"; 496 + static const size_t SUF_UNIX03_LEN = strlen(SUF_UNIX03); 497 + if (name.size() > SUF_UNIX03_LEN && !strcmp(name.c_str() + name.size() - SUF_UNIX03_LEN, SUF_UNIX03)) 498 + name = name.substr(0, name.size() - SUF_UNIX03_LEN); 499 + #endif 500 + sym = reinterpret_cast<uintptr_t>(__darwin_dlsym(DARWIN_RTLD_DEFAULT, name.c_str())); 501 + } 502 + 503 + if (!sym) 504 + { 505 + static const char* ign_sym = getenv("DYLD_IGN_MISSING_SYMS"); 506 + //if (!bind->addend) 507 + { 508 + #ifdef __x86_64__ 509 + if (ign_sym && atoi(ign_sym)) 510 + { 511 + std::cerr << "!!! Undefined symbol: " << name << std::endl; 512 + 513 + char* dname = new char[name.size()+1]; 514 + strcpy(dname, name.c_str()); 515 + 516 + sym = reinterpret_cast<uintptr_t>(m_pUndefMgr->generateNew(dname)); 517 + } 518 + else 519 + #endif 520 + { 521 + std::stringstream ss; 522 + ss << "Undefined symbol: " << name; 523 + throw std::runtime_error(ss.str()); 524 + } 525 + } 526 + //else 527 + // sym = reinterpret_cast<char*>(bind->addend + slide); 528 + } 529 + 530 + return sym; 531 + } 532 + 494 533 void MachOLoader::writeBind(int type, uintptr_t* ptr, uintptr_t newAddr) 495 534 { 496 535 if (type == BIND_TYPE_POINTER) ··· 585 624 586 625 if (!bindLater) 587 626 doBind(mach.binds(), slide, !bindLazy); 627 + doRelocations(mach.relocations(), base, slide); 588 628 589 629 if (!bindLater) 590 630 { ··· 607 647 LOG << "Perform " << b.macho->binds().size() << " binds\n"; 608 648 doBind(b.macho->binds(), b.slide, b.bindLazy); 609 649 if (b.macho->get_eh_frame().first) 610 - __register_frame(reinterpret_cast<void*>(b.macho->get_eh_frame().first + b.slide)); 650 + { 651 + void* frame = reinterpret_cast<void*>(b.macho->get_eh_frame().first + b.slide); 652 + LOG << "Registering EH frame at " << frame << std::endl; 653 + __register_frame(frame); 654 + } 611 655 for (LoaderHookFunc* func : g_machoLoaderHooks) 612 656 func(b.header, b.slide); 613 657 }
+5
src/dyld/MachOLoader.h
··· 64 64 65 65 // Resolves all external symbols required by this module 66 66 void* doBind(const std::vector<MachO::Bind*>& binds, intptr slide, bool resolveLazy = false); 67 + 68 + // Binds external relocations 69 + void doRelocations(const std::vector<MachO::Relocation*>& rels, intptr base, intptr slide); 67 70 68 71 // Calls mprotect() to switch segment protections to the "initial" value. 69 72 // We initially set the maximum value. ··· 98 101 void boot(uint64_t entry, int argc, char** argv, char** envp, char** apple); 99 102 100 103 void writeBind(int type, uintptr_t* ptr, uintptr_t newAddr); 104 + // The name should include the extra underscore at the beginning 105 + uintptr_t getSymbolAddress(const std::string& name); 101 106 102 107 // checks sysctl mmap_min_addr 103 108 static void checkMmapMinAddr(intptr addr);
+9
src/libmach-o/MachO.h
··· 83 83 uintptr_t addr, size; 84 84 }; 85 85 86 + struct Relocation 87 + { 88 + uint64_t addr; 89 + std::string name; // symbol name 90 + bool pcrel; // i386 91 + }; 92 + 86 93 const std::vector<segment_command_64*>& segments64() const { return m_segments64; } 87 94 88 95 const std::vector<segment_command*>& segments() const { return m_segments; } ··· 98 105 const std::vector<Export*>& exports() const { return m_exports; } 99 106 100 107 const std::vector<Symbol>& symbols() const { return m_symbols; } 108 + const std::vector<Relocation*>& relocations() const { return m_relocations; } 101 109 102 110 uintptr_t base() const { return m_base; } 103 111 ··· 133 141 std::vector<Bind*> m_binds; 134 142 std::vector<Export*> m_exports; 135 143 std::vector<Symbol> m_symbols; 144 + std::vector<Relocation*> m_relocations; 136 145 uintptr_t m_base; 137 146 uint64_t m_entry, m_main; 138 147 std::vector<uint64_t> m_init_funcs;
+172 -11
src/libmach-o/MachOImpl.cpp
··· 1 1 /* 2 2 This file is part of Darling. 3 3 4 - Copyright (C) 2012 Lubos Dolezel 4 + Copyright (C) 2012-2013 Lubos Dolezel 5 5 Copyright (C) 2011 Shinichiro Hamaji 6 6 7 7 Darling is free software: you can redistribute it and/or modify ··· 56 56 bind->ordinal = 1; 57 57 bind->is_weak = ((sym->n_desc & N_WEAK_DEF) != 0); 58 58 bind->is_classic = true; 59 - LOG << "add classic bind: " << bind->name << " type=" << sym->n_type << " sect=" << sym->n_sect 59 + LOG << "add classic bind: " << bind->name << " type=" << int(sym->n_type) << " sect=" << int(sym->n_sect) 60 60 << " desc=" << sym->n_desc << " value=" << sym->n_value << " vmaddr=" << (void*)(bind->vmaddr) 61 61 << " is_weak=" << bind->is_weak << std::endl; 62 62 m_binds.push_back(bind); ··· 330 330 uint32_t* dysyms = 0; 331 331 const char* symstrtab = 0; 332 332 dyld_info_command* dyinfo = 0; 333 + 334 + struct relocation_info *ext_relocinfo = 0, *loc_relocinfo = 0; 335 + uint32_t ext_reloccount = 0, loc_reloccount = 0; 336 + 333 337 std::vector<section_64*> bind_sections_64; 334 338 std::vector<section*> bind_sections_32; 335 339 ··· 479 483 dysyms = reinterpret_cast<uint32_t*>( 480 484 m_base + dysymtab_cmd->indirectsymoff); 481 485 } 486 + if (dysymtab_cmd->nextrel) 487 + { 488 + ext_reloccount = dysymtab_cmd->nextrel; 489 + ext_relocinfo = reinterpret_cast<relocation_info*>(m_base + dysymtab_cmd->extreloff); 490 + } 491 + if (dysymtab_cmd->nlocrel) 492 + { 493 + loc_reloccount = dysymtab_cmd->nlocrel; 494 + loc_relocinfo = reinterpret_cast<relocation_info*>(m_base + dysymtab_cmd->locreloff); 495 + } 496 + 482 497 if (FLAGS_READ_DYSYMTAB) 483 498 { 484 499 for (uint32_t j = 0; j < dysymtab_cmd->nindirectsyms; j++) ··· 578 593 readClassicBind<section>(*bind_sections_32[i], dysyms, symtab, symstrtab); 579 594 } 580 595 } 596 + 597 + if (ext_relocinfo) 598 + { 599 + for (uint32_t i = 0; i < ext_reloccount; i++) 600 + readExternalRelocation(&ext_relocinfo[i], symtab, symstrtab); 601 + } 602 + if (loc_relocinfo) 603 + { 604 + for (uint32_t i = 0; i < loc_reloccount; i++) 605 + readInternalRelocation(&loc_relocinfo[i]); 606 + } 607 + } 608 + 609 + #if defined(__i386__) 610 + # define RELOC_VANILLA GENERIC_RELOC_VANILLA 611 + # define RELOC_PTRLEN 2 612 + #elif defined(__x86_64__) 613 + # define RELOC_VANILLA X86_64_RELOC_UNSIGNED 614 + # define RELOC_PTRLEN 3 615 + #endif 616 + 617 + void MachOImpl::readInternalRelocation(const struct relocation_info* reloc) 618 + { 619 + Rebase* rebase; 620 + 621 + #ifndef __x86_64__ // "In the OS X x86-64 environment scattered relocations are not used." 622 + if (reloc->r_address & R_SCATTERED) 623 + { 624 + const scattered_relocation_info* scattered = reinterpret_cast<const scattered_relocation_info*>(reloc); 625 + if (scattered->r_type != RELOC_VANILLA) 626 + { 627 + LOG << "Unhandled internal reloc type " << scattered->r_type << std::endl; 628 + return; 629 + } 630 + 631 + if (scattered->r_length != RELOC_PTRLEN) 632 + { 633 + LOG << "Unsupported relocation length: " << reloc->r_length << std::endl; 634 + return; 635 + } 636 + 637 + rebase = new Rebase { scattered->r_address, REBASE_TYPE_POINTER }; 638 + } 639 + else 640 + #endif 641 + { 642 + if (reloc->r_symbolnum == R_ABS) 643 + return; 644 + if (reloc->r_type != RELOC_VANILLA) 645 + { 646 + LOG << "Unhandled internal reloc type " << reloc->r_type << std::endl; 647 + return; 648 + } 649 + 650 + if (reloc->r_length != RELOC_PTRLEN) 651 + { 652 + LOG << "Unsupported relocation length: " << reloc->r_length << std::endl; 653 + return; 654 + } 655 + 656 + rebase = new Rebase { reloc->r_address, REBASE_TYPE_POINTER }; 657 + } 658 + 659 + if (rebase) 660 + m_rebases.push_back(rebase); 661 + } 662 + 663 + void MachOImpl::readExternalRelocation(const struct relocation_info* reloc, uint32_t* symtab, const char* symstrtab) 664 + { 665 + if (!reloc->r_extern) 666 + throw std::runtime_error("Invalid external relocation"); 667 + 668 + // Disabled, not implemented in original dyld 669 + #if !defined(__x86_64__) && 0 // "In the OS X x86-64 environment scattered relocations are not used." 670 + if (reloc->r_address & R_SCATTERED) 671 + { 672 + const scattered_relocation_info* scattered = reinterpret_cast<const scattered_relocation_info*>(reloc); 673 + LOG << "Scattered relocation not handled!\n"; 674 + } 675 + else 676 + #endif 677 + { 678 + if (reloc->r_length != RELOC_PTRLEN) 679 + { 680 + LOG << "Unsupported relocation length: " << reloc->r_length << std::endl; 681 + return; 682 + } 683 + 684 + if (reloc->r_type == RELOC_VANILLA) 685 + { 686 + Relocation* relocation = new Relocation; 687 + nlist* sym = (nlist*)(symtab + reloc->r_symbolnum * (m_is64 ? 4 : 3)); 688 + 689 + relocation->addr = reloc->r_address; 690 + relocation->name = symstrtab + sym->n_strx; 691 + relocation->pcrel = reloc->r_pcrel != 0; 692 + 693 + m_relocations.push_back(relocation); 694 + } 695 + else 696 + LOG << "Unsupported relocation type: " << reloc->r_type << std::endl; 697 + 698 + // At least on i386 and x86-64, this is not implemented in original dyld 699 + /* 700 + switch (reloc->r_type) 701 + { 702 + #if defined(__i386__) 703 + case GENERIC_RELOC_VANILLA: 704 + case GENERIC_RELOC_PAIR: 705 + case GENERIC_RELOC_SECTDIFF: 706 + case GENERIC_RELOC_LOCAL_SECTDIFF: 707 + case GENERIC_RELOC_PB_LA_PTR: 708 + #elif defined(__x86_64__) 709 + case X86_64_RELOC_BRANCH: 710 + case X86_64_RELOC_GOT_LOAD: 711 + case X86_64_RELOC_GOT: 712 + case X86_64_RELOC_SIGNED: 713 + case X86_64_RELOC_UNSIGNED: 714 + case X86_64_RELOC_SUBTRACTOR: 715 + #elif defined (__powerpc__) 716 + case PPC_RELOC_VANILLA: 717 + case PPC_RELOC_PAIR: 718 + case PPC_RELOC_BR14: 719 + case PPC_RELOC_BR24: 720 + case PPC_RELOC_HI16: 721 + case PPC_RELOC_LO16: 722 + case PPC_RELOC_HA16: 723 + case PPC_RELOC_LO14: 724 + case PPC_RELOC_SECTDIFF: 725 + case PPC_RELOC_LOCAL_SECTDIFF: 726 + case PPC_RELOC_PB_LA_PTR: 727 + case PPC_RELOC_HI16_SECTDIFF: 728 + case PPC_RELOC_LO16_SECTDIFF: 729 + case PPC_RELOC_HA16_SECTDIFF: 730 + case PPC_RELOC_JBSR: 731 + case PPC_RELOC_LO14_SECTDIFF: 732 + // TODO: ppc 733 + LOG << "PowerPC relocations not handled!\n"; 734 + break; 735 + #endif 736 + } 737 + */ 738 + } 581 739 } 582 740 583 741 MachOImpl::~MachOImpl() ··· 587 745 588 746 void MachOImpl::close() 589 747 { 590 - for (size_t i = 0; i < m_binds.size(); i++) 591 - delete m_binds[i]; 592 - 748 + for (auto* b : m_binds) 749 + delete b; 593 750 m_binds.clear(); 594 - for (size_t i = 0; i < m_rebases.size(); i++) 595 - delete m_rebases[i]; 596 - 751 + 752 + for (auto* r : m_rebases) 753 + delete r; 597 754 m_rebases.clear(); 598 - for (size_t i = 0; i < m_exports.size(); i++) 599 - delete m_exports[i]; 600 - 755 + 756 + for (auto* e : m_exports) 757 + delete e; 601 758 m_exports.clear(); 759 + 760 + for (auto* r : m_relocations) 761 + delete r; 762 + m_relocations.clear(); 602 763 603 764 if (m_mapped) 604 765 {
+7 -1
src/libmach-o/MachOImpl.h
··· 1 1 /* 2 2 This file is part of Darling. 3 3 4 - Copyright (C) 2012 Lubos Dolezel 4 + Copyright (C) 2012-2013 Lubos Dolezel 5 5 Copyright (C) 2011 Shinichiro Hamaji 6 6 7 7 Darling is free software: you can redistribute it and/or modify ··· 22 22 #define MACHOIMPL_H 23 23 #include "MachO.h" 24 24 #include <mach-o/loader.h> 25 + #include <mach-o/reloc.h> 25 26 #include <stdint.h> 26 27 #include <vector> 27 28 #include <string> ··· 55 56 template <class section> 56 57 void readClassicBind(const section& sec, uint32_t* dysyms, uint32_t* symtab, const char* symstrtab); 57 58 void readStubBind(const section& sec, uint32_t* dysyms, uint32_t* symtab, const char* symstrtab); 59 + 60 + // classic 61 + void readExternalRelocation(const struct relocation_info* reloc, uint32_t* symtab, const char* symstrtab); 62 + // classic 63 + void readInternalRelocation(const struct relocation_info* reloc); 58 64 59 65 char* m_mapped; 60 66 size_t m_mapped_size;