this repo has no description
1
fork

Configure Feed

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

Moved more code out of ld-mac.cc, implemented more functionality in ld.cpp

+796 -501
+1 -1
CMakeLists.txt
··· 31 31 32 32 set(dyld_SRCS 33 33 src/dyld/FileMap.cpp 34 - src/dyld/ld-mac.cc 34 + src/dyld/MachOLoader.cpp 35 35 src/util/log.cc 36 36 src/util/trace.cpp 37 37 )
+608
src/dyld/MachOLoader.cpp
··· 1 + #include "MachOLoader.h" 2 + #include "MachO.h" 3 + #include "ld.h" 4 + #include "log.h" 5 + #include "trace.h" 6 + #include <cstdio> 7 + #include <cassert> 8 + #include <algorithm> 9 + #include <sstream> 10 + #include <stdexcept> 11 + #include <sys/mman.h> 12 + 13 + #define FLAGS_TRACE_FUNCTIONS 0 14 + 15 + FileMap g_file_map; 16 + static std::map<std::string, std::string> g_rename; 17 + static std::vector<std::string> g_bound_names; 18 + static std::set<std::string> g_no_trampoline; 19 + 20 + extern char g_darwin_executable_path[PATH_MAX]; 21 + 22 + static void initNoTrampoline() __attribute__((constructor)) 23 + { 24 + #define NO_TRAMPOLINE(name) g_no_trampoline.insert(#name); 25 + #include "no_trampoline.tab" 26 + #undef NO_TRAMPOLINE 27 + } 28 + 29 + static void* undefinedFunction() 30 + { 31 + fprintf(stderr, "Undefined function called, returning NULL\n"); 32 + //abort(); 33 + return 0; 34 + } 35 + 36 + static void doNothing() 37 + { 38 + } 39 + 40 + static bool lookupDyldFunction(const char* name, uint64_t* addr) 41 + { 42 + LOG << "lookupDyldFunction: " << name <<std::endl; 43 + *addr = (int64_t)&doNothing; 44 + return true; 45 + } 46 + 47 + static uint64_t alignMem(uint64_t p, uint64_t a) 48 + { 49 + a--; 50 + return (p + a) & ~a; 51 + } 52 + 53 + static void dumpInt(int bound_name_id) 54 + { 55 + if (bound_name_id < 0) 56 + { 57 + fprintf(stderr, "%d: negative bound function id\n", bound_name_id); 58 + return; 59 + } 60 + if (bound_name_id >= (int)g_bound_names.size()) 61 + { 62 + fprintf(stderr, "%d: bound function id overflow\n", bound_name_id); 63 + return; 64 + } 65 + if (g_bound_names[bound_name_id].empty()) 66 + { 67 + fprintf(stderr, "%d: unbound function id\n", bound_name_id); 68 + return; 69 + } 70 + printf("calling %s(%d)\n", 71 + g_bound_names[bound_name_id].c_str(), bound_name_id); 72 + fflush(stdout); 73 + } 74 + 75 + MachOLoader::MachOLoader() 76 + : m_last_addr(0) 77 + { 78 + if (FLAGS_TRACE_FUNCTIONS) 79 + { 80 + // Push all arguments into stack. 81 + 82 + // push %rax 83 + pushTrampolineCode(0x50); 84 + // push %rdi 85 + pushTrampolineCode(0x57); 86 + // push %rsi 87 + pushTrampolineCode(0x56); 88 + // push %rdx 89 + pushTrampolineCode(0x52); 90 + // push %rcx 91 + pushTrampolineCode(0x51); 92 + // push %r8 93 + pushTrampolineCode(0x5041); 94 + // push %r9 95 + pushTrampolineCode(0x5141); 96 + 97 + // push %xmm0..%xmm7 98 + for (int i = 0; i < 8; i++) 99 + { 100 + // sub $8, %rsp 101 + pushTrampolineCode(0x08ec8348); 102 + 103 + // movq %xmmN, (%rsp) 104 + pushTrampolineCode(0xd60f66); 105 + pushTrampolineCode(4 + i * 8); 106 + pushTrampolineCode(0x24); 107 + } 108 + 109 + // mov %r10, %rdi 110 + pushTrampolineCode(0xd7894c); 111 + 112 + // mov $func, %rdx 113 + pushTrampolineCode(0xba48); 114 + pushTrampolineCode64((unsigned long long)(void*)&dumpInt); 115 + 116 + // call *%rdx 117 + pushTrampolineCode(0xd2ff); 118 + 119 + // pop %xmm7..%xmm0 120 + for (int i = 7; i >= 0; i--) 121 + { 122 + // movq (%rsp), %xmmN 123 + pushTrampolineCode(0x7e0ff3); 124 + pushTrampolineCode(4 + i * 8); 125 + pushTrampolineCode(0x24); 126 + 127 + // add $8, %rsp 128 + pushTrampolineCode(0x08c48348); 129 + } 130 + 131 + // pop %r9 132 + pushTrampolineCode(0x5941); 133 + // pop %r8 134 + pushTrampolineCode(0x5841); 135 + // pop %rcx 136 + pushTrampolineCode(0x59); 137 + // pop %rdx 138 + pushTrampolineCode(0x5a); 139 + // pop %rsi 140 + pushTrampolineCode(0x5e); 141 + // pop %rdi 142 + pushTrampolineCode(0x5f); 143 + // pop %rax 144 + pushTrampolineCode(0x58); 145 + 146 + // ret 147 + pushTrampolineCode(0xc3); 148 + } 149 + } 150 + 151 + void MachOLoader::loadDylibs(const MachO& mach) 152 + { 153 + for (size_t i = 0; i < mach.dylibs().size(); i++) 154 + { 155 + std::string dylib = mach.dylibs()[i]; 156 + 157 + // __darwin_dlopen checks if already loaded 158 + // automatically adds a reference if so 159 + if (!__darwin_dlopen(dylib.c_str(), DARWIN_RTLD_GLOBAL)) 160 + throw std::runtime_error("Cannot load " + dylib + "!"); 161 + } 162 + } 163 + 164 + 165 + void MachOLoader::loadSegments(const MachO& mach, intptr* slide, intptr* base) 166 + { 167 + *base = 0; 168 + --*base; 169 + 170 + const std::vector<Segment*>& segments = getSegments(mach); 171 + for (size_t i = 0; i < segments.size(); i++) 172 + { 173 + Segment* seg = segments[i]; 174 + const char* name = seg->segname; 175 + if (!strcmp(name, SEG_PAGEZERO)) 176 + continue; 177 + 178 + LOG << seg->segname << ": " 179 + << "fileoff=" << seg->fileoff 180 + << ", vmaddr=" << seg->vmaddr <<std::endl; 181 + 182 + int prot = 0; 183 + if (seg->initprot & VM_PROT_READ) 184 + prot |= PROT_READ; 185 + 186 + if (seg->initprot & VM_PROT_WRITE) 187 + prot |= PROT_WRITE; 188 + 189 + if (seg->initprot & VM_PROT_EXECUTE) 190 + prot |= PROT_EXEC; 191 + 192 + 193 + intptr filesize = alignMem(seg->filesize, 0x1000); 194 + intptr vmaddr = seg->vmaddr + *slide; 195 + 196 + if (vmaddr < m_last_addr) 197 + { 198 + LOG << "will rebase: filename=" << mach.filename() 199 + << ", vmaddr=" << (void*)vmaddr 200 + << ", last_addr=" << (void*)last_addr_ <<std::endl; 201 + assert(i == 0); 202 + vmaddr = last_addr_; 203 + *slide = vmaddr - seg->vmaddr; 204 + } 205 + *base = std::min(*base, vmaddr); 206 + 207 + intptr vmsize = alignMem(seg->vmsize, 0x1000); 208 + LOG << "mmap(file) " << mach.filename() << ' ' << name 209 + << ": " << (void*)vmaddr << "-" << (void*)(vmaddr + filesize) 210 + << " offset=" << mach.offset() + seg->fileoff <<std::endl; 211 + 212 + if (filesize == 0) 213 + continue; 214 + 215 + void* mapped = ::mmap((void*)vmaddr, filesize, prot, 216 + MAP_PRIVATE | MAP_FIXED, 217 + mach.fd(), mach.offset() + seg->fileoff); 218 + 219 + if (mapped == MAP_FAILED) 220 + err(1, "%s mmap(file) failed", mach.filename().c_str()); 221 + 222 + if (vmsize != filesize) 223 + { 224 + LOG << "mmap(anon) " << mach.filename() << ' ' << name 225 + << ": " << (void*)(vmaddr + filesize) << "-" 226 + << (void*)(vmaddr + vmsize) 227 + <<std::endl; 228 + 229 + assert(vmsize > filesize); 230 + 231 + void* mapped = ::mmap((void*)(vmaddr + filesize), 232 + vmsize - filesize, prot, 233 + MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, 234 + 0, 0); 235 + 236 + if (mapped == MAP_FAILED) 237 + { 238 + // TODO: insert a suggestion for a fix on 32bit systems 239 + err(1, "%s mmap(anon) failed", mach.filename().c_str()); 240 + } 241 + } 242 + 243 + m_last_addr = std::max(m_last_addr, (intptr)vmaddr + vmsize); 244 + } 245 + } 246 + 247 + void MachOLoader::doRebase(const MachO& mach, intptr slide) 248 + { 249 + for (size_t i = 0; i < mach.rebases().size(); i++) 250 + { 251 + const MachO::Rebase& rebase = *mach.rebases()[i]; 252 + switch (rebase.type) 253 + { 254 + case REBASE_TYPE_POINTER: 255 + { 256 + char** ptr = (char**)(rebase.vmaddr + slide); 257 + LOG << "rebase: " << i << ": " << (void*)rebase.vmaddr << ' ' 258 + << (void*)*ptr << " => " 259 + << (void*)(*ptr + slide) << " @" << ptr <<std::endl; 260 + *ptr += slide; 261 + break; 262 + } 263 + 264 + default: 265 + { 266 + std::stringstream ss; 267 + ss << "Unknown rebase type: " << rebase.type; 268 + 269 + throw std::runtime_error(ss.str()); 270 + } 271 + } 272 + } 273 + } 274 + 275 + void MachOLoader::loadInitFuncs(const MachO& mach, intptr slide) 276 + { 277 + for (size_t i = 0; i < mach.init_funcs().size(); i++) 278 + { 279 + intptr addr = mach.init_funcs()[i] + slide; 280 + LOG << "Registering init func " << (void*)addr 281 + << " from " << mach.filename() << std::endl; 282 + m_init_funcs.push_back(addr); 283 + } 284 + } 285 + 286 + void MachOLoader::doBind(const MachO& mach, intptr slide) 287 + { 288 + std::string last_weak_name; 289 + char* last_weak_sym = 0; 290 + size_t seen_weak_bind_index = 0; 291 + size_t seen_weak_binds_orig_size = m_seen_weak_binds.size(); 292 + 293 + unsigned int common_code_size = (unsigned int)m_trampoline.size(); 294 + // Ensure that we won't change the address. 295 + m_trampoline.reserve(common_code_size + 296 + (1 + 6 + 5 + 10 + 3 + 2 + 1) * mach.binds().size()); 297 + g_bound_names.resize(mach.binds().size()); 298 + 299 + for (size_t i = 0; i < mach.binds().size(); i++) 300 + { 301 + MachO::Bind* bind = mach.binds()[i]; 302 + if (bind->name[0] != '_') 303 + { 304 + LOG << bind->name << ": skipping" << endl; 305 + continue; 306 + } 307 + 308 + if (bind->type == BIND_TYPE_POINTER) 309 + { 310 + string name = bind->name.substr(1); 311 + void** ptr = (void**)(bind->vmaddr + slide); 312 + char* sym = 0; 313 + 314 + if (bind->is_weak) 315 + { 316 + if (last_weak_name == name) 317 + { 318 + sym = last_weak_sym; 319 + } 320 + else 321 + { 322 + last_weak_name = name; 323 + if (seen_weak_bind_index != seen_weak_binds_orig_size && !strcmp(seen_weak_binds_[seen_weak_bind_index].first.c_str(), name.c_str())) 324 + { 325 + last_weak_sym = sym = 326 + seen_weak_binds_[seen_weak_bind_index].second; 327 + seen_weak_bind_index++; 328 + } 329 + else 330 + { 331 + if (bind->is_classic) 332 + { 333 + *ptr = last_weak_sym = (char*)bind->value; 334 + } 335 + else 336 + { 337 + const Exports::const_iterator export_found = exports_.find(bind->name); 338 + if (export_found != exports_.end()) 339 + *ptr = last_weak_sym = (char*)export_found->second.addr; 340 + else 341 + last_weak_sym = (char*)*ptr; 342 + } 343 + } 344 + 345 + seen_weak_binds_.push_back(make_pair(name, last_weak_sym)); 346 + while (seen_weak_bind_index != seen_weak_binds_orig_size && strcmp(seen_weak_binds_[seen_weak_bind_index].first.c_str(), name.c_str()) <= 0) 347 + seen_weak_bind_index++; 348 + 349 + continue; 350 + } 351 + } 352 + else // not weak 353 + { 354 + // TODO: remove, replace with aliases 355 + #ifndef __x86_64__ 356 + static const char* SUF_UNIX03 = "$UNIX2003"; 357 + static const size_t SUF_UNIX03_LEN = strlen(SUF_UNIX03); 358 + if (name.size() > SUF_UNIX03_LEN && 359 + !strcmp(name.c_str() + name.size() - SUF_UNIX03_LEN, 360 + SUF_UNIX03)) { 361 + name = name.substr(0, name.size() - SUF_UNIX03_LEN); 362 + } 363 + #endif 364 + 365 + sym = reinterpret_cast<char*>(__darwin_dlsym(DARWIN_RTLD_GLOBAL, name.c_str())); 366 + if (!sym) 367 + { 368 + std::stringstream ss; 369 + ss << "Undefined symbol: " << name; 370 + throw std::runtime_error(ss); 371 + } 372 + 373 + sym += bind->addend; 374 + } 375 + 376 + LOG << "bind " << name << ": " 377 + << *ptr << " => " << (void*)sym << " @" << ptr << endl; 378 + 379 + if (FLAGS_TRACE_FUNCTIONS && !g_no_trampoline.count(name)) 380 + { 381 + LOG << "Generating trampoline for " << name << "..." << endl; 382 + 383 + *ptr = &m_trampoline[0] + m_trampoline.size(); 384 + g_bound_names[i] = name; 385 + 386 + // push %rax ; to adjust alignment for sse 387 + pushTrampolineCode(0x50); 388 + 389 + // mov $i, %r10d 390 + pushTrampolineCode(0xba41); 391 + pushTrampolineCode32((unsigned int)i); 392 + 393 + // call &m_trampoline[0] 394 + pushTrampolineCode(0xe8); 395 + pushTrampolineCode32((unsigned int)(-4-m_trampoline.size())); 396 + 397 + // mov $sym, %r10 398 + pushTrampolineCode(0xba49); 399 + pushTrampolineCode64((unsigned long long)(void*)sym); 400 + // call *%r10 401 + pushTrampolineCode(0xd2ff41); 402 + 403 + // pop %r10 404 + pushTrampolineCode(0x5a41); 405 + 406 + // ret 407 + pushTrampolineCode(0xc3); 408 + } 409 + else 410 + { 411 + *ptr = sym; 412 + } 413 + } 414 + else 415 + { 416 + std::stringstream ss; 417 + ss << "Unknown bind type: " << bind->type; 418 + throw std::runtime_exception(ss.str()); 419 + } 420 + } 421 + 422 + std::inplace_merge(m_seen_weak_binds.begin(), m_seen_weak_binds.begin() + seen_weak_binds_orig_size, m_seen_weak_binds.end()); 423 + } 424 + 425 + 426 + 427 + void MachOLoader::loadExports(const MachO& mach, intptr base, Exports* exports) 428 + { 429 + exports->rehash(exports->size() + mach.exports().size()); 430 + 431 + for (size_t i = 0; i < mach.exports().size(); i++) 432 + { 433 + MachO::Export exp = *mach.exports()[i]; 434 + exp.addr += base; 435 + // TODO(hamaji): Not 100% sure, but we may need to consider weak symbols. 436 + if (!exports->insert(make_pair(exp.name, exp)).second) 437 + fprintf(stderr, "duplicated exported symbol: %s\n", exp.name.c_str()); 438 + } 439 + } 440 + 441 + 442 + void MachOLoader::loadSymbols(const MachO& mach, intptr slide, intptr base) 443 + { 444 + g_file_map.add(mach, slide, base); 445 + } 446 + 447 + 448 + void MachOLoader::load(const MachO& mach, Exports* exports) 449 + { 450 + if (!exports) 451 + exports = m_exports; 452 + 453 + intptr slide = 0; 454 + intptr base = 0; 455 + 456 + loadSegments(mach, &slide, &base); 457 + 458 + doRebase(mach, slide); 459 + 460 + runPendingInitFuncs(mach, slide); 461 + 462 + loadDylibs(mach); 463 + 464 + loadExports(mach, base, exports); 465 + 466 + doBind(mach, slide); 467 + 468 + loadSymbols(mach, slide, base); 469 + } 470 + 471 + 472 + void MachOLoader::setupDyldData(const MachO& mach) 473 + { 474 + if (!mach.dyld_data()) 475 + return; 476 + 477 + void** dyld_data = (void**)mach.dyld_data(); 478 + dyld_data[1] = reinterpret_cast<void*>(&lookupDyldFunction); 479 + } 480 + 481 + void MachOLoader::runPendingInitFuncs(int argc, char** argv, char** envp, char** apple) 482 + { 483 + for (size_t i = 0; i < m_init_funcs.size(); i++) 484 + { 485 + void** init_func = (void**) m_init_funcs[i]; 486 + LOG << "calling initializer function " << *init_func << std::endl; 487 + 488 + if (argc >= 0) 489 + ((void(*)(int, char**, char**, char**))*init_func)(argc, argv, envp, apple); 490 + else 491 + ((void(*)())*init_func)(); 492 + } 493 + m_init_funcs.clear(); 494 + } 495 + 496 + 497 + void MachOLoader::run(MachO& mach, int argc, char** argv, char** envp) 498 + { 499 + char* apple[2] = { g_darwin_executable_path, 0 }; 500 + 501 + load(mach); 502 + setupDyldData(mach); 503 + 504 + g_file_map.addWatchDog(m_last_addr + 1); 505 + 506 + char* trampoline_start_addr = (char*)(((uintptr_t)&m_trampoline[0]) & ~0xfff); 507 + uint64_t trampoline_size = alignMem(&trampoline_[0] + m_trampoline.size() - trampoline_start_addr, 0x1000); 508 + 509 + ::mprotect(trampoline_start_addr, trampoline_size, PROT_READ | PROT_WRITE | PROT_EXEC); 510 + 511 + //g_timer.print(mach.filename().c_str()); 512 + 513 + mach.close(); 514 + 515 + runInitFuncs(argc, argv, envp, apple); 516 + 517 + LOG << "booting from " << (void*)mach.entry() << "..." << std::endl; 518 + 519 + fflush(stdout); 520 + assert(argc > 0); 521 + 522 + boot(mach.entry(), argc, argv, envp); 523 + 524 + /* 525 + int (*fp)(int, char**, char**) = 526 + (int(*)(int, char**, char**))mach.entry(); 527 + int ret = fp(argc, argv, envp); 528 + exit(ret); 529 + */ 530 + } 531 + 532 + void MachOLoader::pushTrampolineCode(unsigned int c) 533 + { 534 + while (c) 535 + { 536 + m_trampoline.push_back(c & 255); 537 + c >>= 8; 538 + } 539 + } 540 + 541 + void MachOLoader::pushTrampolineCode64(uint64_t c) 542 + { 543 + for (int i = 0; i < 8; i++) 544 + { 545 + m_trampoline.push_back(c & 255); 546 + c >>= 8; 547 + } 548 + } 549 + 550 + void MachOLoader::pushTrampolineCode32(uint32_t c) 551 + { 552 + for (int i = 0; i < 4; i++) 553 + { 554 + m_trampoline.push_back(c & 255); 555 + c >>= 8; 556 + } 557 + } 558 + 559 + void MachOLoader::boot( uint64_t entry, int argc, char** argv, char** envp) 560 + { 561 + #ifdef __x86_64__ 562 + // 0x08: argc 563 + // 0x10: argv[0] 564 + // 0x18: argv[1] 565 + // ...: argv[n] 566 + // 0 567 + // envp[0] 568 + // envp[1] 569 + // envp[n] 570 + 571 + // TODO: add 'apple'! 572 + 573 + __asm__ volatile(" mov %1, %%rax;\n" 574 + " mov %2, %%rdx;\n" 575 + " push $0;\n" 576 + // TODO(hamaji): envp 577 + " push $0;\n" 578 + ".loop64:\n" 579 + " sub $8, %%rdx;\n" 580 + " push (%%rdx);\n" 581 + " dec %%eax;\n" 582 + " jnz .loop64;\n" 583 + " mov %1, %%eax;\n" 584 + " push %%rax;\n" 585 + " jmp *%0;\n" 586 + ::"r"(entry), "r"(argc), "r"(argv + argc), "r"(envp) 587 + :"%rax", "%rdx"); 588 + //fprintf(stderr, "done!\n"); 589 + #else 590 + __asm__ volatile(" mov %1, %%eax;\n" 591 + " mov %2, %%edx;\n" 592 + " push $0;\n" 593 + ".loop32:\n" 594 + " sub $4, %%edx;\n" 595 + " push (%%edx);\n" 596 + " dec %%eax;\n" 597 + " jnz .loop32;\n" 598 + " mov %1, %%eax;\n" 599 + " push %%eax;\n" 600 + " jmp *%0;\n" 601 + // TODO(hamaji): Fix parameters 602 + ::"r"(entry), "r"(argc), "r"(argv + argc), "g"(envp) 603 + :"%eax", "%edx"); 604 + #endif 605 + } 606 + 607 + 608 +
+47 -8
src/dyld/MachOLoader.h
··· 1 1 #ifndef MACHOLOADER_H 2 2 #define MACHOLOADER_H 3 + #include <vector> 4 + #include <string> 5 + #include <map> 6 + #include <pair> 7 + #include <stdint.h> 8 + #include "arch.h" 3 9 4 10 class MachOLoader 5 11 { 6 12 #ifdef __x86_64__ 7 - typedef uint64_t intptr; 13 + public: 8 14 typedef segment_command_64 Segment; 9 - 15 + private: 10 16 static inline const vector<Segment*>& getSegments(const MachO& mach) { 11 17 return mach.segments64(); 12 18 } 13 19 #else 14 - typedef uint32_t intptr; 20 + public: 15 21 typedef segment_command Segment; 16 - 22 + private: 17 23 static inline const vector<Segment*>& getSegments(const MachO& mach) { 18 24 return mach.segments(); 19 25 } ··· 21 27 22 28 public: 23 29 MachOLoader(); 30 + 31 + // Maps module segments into the memory 24 32 void loadSegments(const MachO& mach, intptr* slide, intptr* base); 33 + 34 + 25 35 void doRebase(const MachO& mach, intptr slide); 36 + 37 + // Puts initializer functions of that module into the list of initializers to be run 26 38 void loadInitFuncs(const MachO& mach, intptr slide); 39 + 40 + // Loads libraries this module depends on 27 41 void loadDylibs(const MachO& mach); 42 + 43 + // Resolves all external symbols required by this module 28 44 void doBind(const MachO& mach, intptr slide); 45 + 46 + // Creates a list of publicly visible functions in this module 29 47 void loadExports(const MachO& mach, intptr base, Exports* exports); 48 + 49 + // Puts all symbol addresses into a global map 30 50 void loadSymbols(const MachO& mach, intptr slide, intptr base); 31 - void load(const MachO& mach, Exports* exports = NULL); 51 + 52 + // Loads a Mach-O file and does all the processing 53 + void load(const MachO& mach, Exports* exports = 0); 54 + 55 + // Dyld data contains an accessor to internal dyld functionality. This stores the accessor pointer. 32 56 void setupDyldData(const MachO& mach); 33 - void runInitFuncs(int argc, char** argv, char** envp, char** apple); 57 + 58 + // Runs initializer functions that have not been run yet 59 + void runPendingInitFuncs(int argc, char** argv, char** envp, char** apple); 60 + 61 + // Starts an application 34 62 void run(MachO& mach, int argc, char** argv, char** envp); 63 + 64 + const Exports& getExports() const { return m_exports; } 35 65 private: 66 + // Jumps to the application entry 36 67 void boot(uint64_t entry, int argc, char** argv, char** envp); 68 + 37 69 void pushTrampolineCode(unsigned int c); 38 - void pushTrampolineCode64(unsigned long long c); 39 - void pushTrampolineCode32(unsigned int c); 70 + void pushTrampolineCode64(uint64_t c); 71 + void pushTrampolineCode32(uint32_t c); 72 + private: 73 + std::string m_trampoline; 74 + intptr m_last_addr; 75 + std::vector<uint64_t> m_init_funcs; 76 + Exports m_exports; 77 + std::vector<std::pair<std::string, char*> > m_seen_weak_binds; 78 + 40 79 }; 41 80 42 81 #endif
+6
src/dyld/arch.h
··· 3 3 4 4 #if defined(__x86_64__) 5 5 # define ARCH_NAME "x86-64" 6 + 7 + typedef uint64_t intptr; 8 + 6 9 #elif defined(__i386__) 7 10 # define ARCH_NAME "i386" 11 + 12 + typedef uint32_t intptr; 13 + 8 14 #else 9 15 # error Unsupported platform 10 16 #endif
+1 -485
src/dyld/ld-mac.cc
··· 89 89 } 90 90 */ 91 91 92 - static void initNoTrampoline() { 93 - #define NO_TRAMPOLINE(name) g_no_trampoline.insert(#name); 94 - #include "no_trampoline.tab" 95 - #undef NO_TRAMPOLINE 96 - } 97 92 98 - static void* undefinedFunction() { 99 - fprintf(stderr, "Undefined function called, returning NULL\n"); 100 - //abort(); 101 - return 0; 102 - } 103 93 104 - static void doNothing() { 105 - } 106 94 107 - static bool lookupDyldFunction(const char* name, uint64_t* addr) { 108 - LOG << "lookupDyldFunction: " << name << endl; 109 - *addr = (int64_t)&doNothing; 110 - return true; 111 - } 112 95 113 - static uint64_t alignMem(uint64_t p, uint64_t a) { 114 - a--; 115 - return (p + a) & ~a; 116 - } 117 96 118 - static void dumpInt(int bound_name_id) { 119 - if (bound_name_id < 0) { 120 - fprintf(stderr, "%d: negative bound function id\n", bound_name_id); 121 - return; 122 - } 123 - if (bound_name_id >= (int)g_bound_names.size()) { 124 - fprintf(stderr, "%d: bound function id overflow\n", bound_name_id); 125 - return; 126 - } 127 - if (g_bound_names[bound_name_id].empty()) { 128 - fprintf(stderr, "%d: unbound function id\n", bound_name_id); 129 - return; 130 - } 131 - printf("calling %s(%d)\n", 132 - g_bound_names[bound_name_id].c_str(), bound_name_id); 133 - fflush(stdout); 134 - } 135 - 136 - static MachO* loadDylib(string dylib) { 137 - static const char executable_str[] = "@executable_path"; 138 - static const size_t executable_str_len = strlen(executable_str); 139 - if (!strncmp(dylib.c_str(), executable_str, executable_str_len)) { 140 - string dir = g_darwin_executable_path; 141 - size_t found = dir.rfind('/'); 142 - if (found == string::npos) { 143 - dir = "."; 144 - } else { 145 - dir = dir.substr(0, found); 146 - } 147 - dylib.replace(0, executable_str_len, dir); 148 - } 149 - 150 - return MachO::readFile(dylib.c_str(), ARCH_NAME); 151 - } 152 - 153 - typedef unordered_map<string, MachO::Export> Exports; 154 97 155 98 class MachOLoader { 156 99 #ifdef __x86_64__ ··· 197 140 symbol_to_so_.insert(make_pair("uuid_unparse_upper", "libuuid.so")); 198 141 */ 199 142 200 - if (FLAGS_TRACE_FUNCTIONS) { 201 - // Push all arguments into stack. 202 - 203 - // push %rax 204 - pushTrampolineCode(0x50); 205 - // push %rdi 206 - pushTrampolineCode(0x57); 207 - // push %rsi 208 - pushTrampolineCode(0x56); 209 - // push %rdx 210 - pushTrampolineCode(0x52); 211 - // push %rcx 212 - pushTrampolineCode(0x51); 213 - // push %r8 214 - pushTrampolineCode(0x5041); 215 - // push %r9 216 - pushTrampolineCode(0x5141); 217 - 218 - // push %xmm0..%xmm7 219 - for (int i = 0; i < 8; i++) { 220 - // sub $8, %rsp 221 - pushTrampolineCode(0x08ec8348); 222 - 223 - // movq %xmmN, (%rsp) 224 - pushTrampolineCode(0xd60f66); 225 - pushTrampolineCode(4 + i * 8); 226 - pushTrampolineCode(0x24); 227 - } 228 - 229 - // mov %r10, %rdi 230 - pushTrampolineCode(0xd7894c); 231 - 232 - // mov $func, %rdx 233 - pushTrampolineCode(0xba48); 234 - pushTrampolineCode64((unsigned long long)(void*)&dumpInt); 235 - 236 - // call *%rdx 237 - pushTrampolineCode(0xd2ff); 238 - 239 - // pop %xmm7..%xmm0 240 - for (int i = 7; i >= 0; i--) { 241 - // movq (%rsp), %xmmN 242 - pushTrampolineCode(0x7e0ff3); 243 - pushTrampolineCode(4 + i * 8); 244 - pushTrampolineCode(0x24); 245 - 246 - // add $8, %rsp 247 - pushTrampolineCode(0x08c48348); 248 - } 249 - 250 - // pop %r9 251 - pushTrampolineCode(0x5941); 252 - // pop %r8 253 - pushTrampolineCode(0x5841); 254 - // pop %rcx 255 - pushTrampolineCode(0x59); 256 - // pop %rdx 257 - pushTrampolineCode(0x5a); 258 - // pop %rsi 259 - pushTrampolineCode(0x5e); 260 - // pop %rdi 261 - pushTrampolineCode(0x5f); 262 - // pop %rax 263 - pushTrampolineCode(0x58); 264 - 265 - // ret 266 - pushTrampolineCode(0xc3); 267 - } 268 - } 269 - 270 - void loadSegments(const MachO& mach, intptr* slide, intptr* base) { 271 - *base = 0; 272 - --*base; 273 - 274 - const vector<Segment*>& segments = getSegments(mach); 275 - for (size_t i = 0; i < segments.size(); i++) { 276 - Segment* seg = segments[i]; 277 - const char* name = seg->segname; 278 - if (!strcmp(name, SEG_PAGEZERO)) { 279 - continue; 280 - } 281 - 282 - LOG << seg->segname << ": " 283 - << "fileoff=" << seg->fileoff 284 - << ", vmaddr=" << seg->vmaddr << endl; 285 - 286 - int prot = 0; 287 - if (seg->initprot & VM_PROT_READ) { 288 - prot |= PROT_READ; 289 - } 290 - if (seg->initprot & VM_PROT_WRITE) { 291 - prot |= PROT_WRITE; 292 - } 293 - if (seg->initprot & VM_PROT_EXECUTE) { 294 - prot |= PROT_EXEC; 295 - } 296 - 297 - intptr filesize = alignMem(seg->filesize, 0x1000); 298 - intptr vmaddr = seg->vmaddr + *slide; 299 - if (vmaddr < last_addr_) { 300 - LOG << "will rebase: filename=" << mach.filename() 301 - << ", vmaddr=" << (void*)vmaddr 302 - << ", last_addr=" << (void*)last_addr_ << endl; 303 - CHECK(i == 0); 304 - vmaddr = last_addr_; 305 - *slide = vmaddr - seg->vmaddr; 306 - } 307 - *base = min(*base, vmaddr); 308 - 309 - intptr vmsize = alignMem(seg->vmsize, 0x1000); 310 - LOG << "mmap(file) " << mach.filename() << ' ' << name 311 - << ": " << (void*)vmaddr << "-" << (void*)(vmaddr + filesize) 312 - << " offset=" << mach.offset() + seg->fileoff << endl; 313 - if (filesize == 0) { 314 - continue; 315 - } 316 - void* mapped = mmap((void*)vmaddr, filesize, prot, 317 - MAP_PRIVATE | MAP_FIXED, 318 - mach.fd(), mach.offset() + seg->fileoff); 319 - if (mapped == MAP_FAILED) { 320 - err(1, "%s mmap(file) failed", mach.filename().c_str()); 321 - } 322 - 323 - if (vmsize != filesize) { 324 - LOG << "mmap(anon) " << mach.filename() << ' ' << name 325 - << ": " << (void*)(vmaddr + filesize) << "-" 326 - << (void*)(vmaddr + vmsize) 327 - << endl; 328 - CHECK(vmsize > filesize); 329 - void* mapped = mmap((void*)(vmaddr + filesize), 330 - vmsize - filesize, prot, 331 - MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, 332 - 0, 0); 333 - if (mapped == MAP_FAILED) { 334 - // TODO: insert a suggestion for a fix on 32bit systems 335 - err(1, "%s mmap(anon) failed", mach.filename().c_str()); 336 - } 337 - } 338 - 339 - last_addr_ = max(last_addr_, (intptr)vmaddr + vmsize); 340 - } 341 - } 342 - 343 - void doRebase(const MachO& mach, intptr slide) { 344 - for (size_t i = 0; i < mach.rebases().size(); i++) { 345 - const MachO::Rebase& rebase = *mach.rebases()[i]; 346 - switch (rebase.type) { 347 - case REBASE_TYPE_POINTER: { 348 - char** ptr = (char**)(rebase.vmaddr + slide); 349 - LOG << "rebase: " << i << ": " << (void*)rebase.vmaddr << ' ' 350 - << (void*)*ptr << " => " 351 - << (void*)(*ptr + slide) << " @" << ptr << endl; 352 - *ptr += slide; 353 - break; 354 - } 355 - 356 - default: 357 - fprintf(stderr, "Unknown rebase type: %d\n", rebase.type); 358 - exit(1); 359 - } 360 - } 361 - } 362 - 363 - // FIXME: this is wrong 364 - // init funcs must be kept separate for every MachO for later init support (dlopen()) 365 - void loadInitFuncs(const MachO& mach, intptr slide) { 366 - for (size_t i = 0; i < mach.init_funcs().size(); i++) { 367 - intptr addr = mach.init_funcs()[i] + slide; 368 - LOG << "Registering init func " << (void*)addr 369 - << " from " << mach.filename() << endl; 370 - init_funcs_.push_back(addr); 371 - } 372 - } 373 - 374 - void loadDylibs(const MachO& mach) { 375 - for (size_t i = 0; i < mach.dylibs().size(); i++) { 376 - string dylib = mach.dylibs()[i]; 377 - 378 - // TODO: replace whole loop body with __darwin_dlopen() 379 - if (!loaded_dylibs_.insert(dylib).second) 380 - continue; 381 - 382 - // TODO: remove this 383 - const string so = dylib_to_so_[dylib]; 384 - if (!so.empty()) { 385 - LOG << "Loading " << so << " for " << dylib << endl; 386 - if (!dlopen(so.c_str(), RTLD_LAZY | RTLD_GLOBAL)) { 387 - fprintf(stderr, "Couldn't load %s for %s\n", 388 - so.c_str(), dylib.c_str()); 389 - } 390 - } 391 - 392 - // For now, we assume a dylib is a system library if its path 393 - // starts with / 394 - // TODO: try loading a .so, then try a .dylib. First try with a prefix. 395 - if (dylib[0] == '/') { 396 - continue; 397 - } 398 - 399 - // TODO: we cannot consider . as the @executable_path 400 - static const char executable_str[] = "@executable_path"; 401 - static const size_t executable_str_len = strlen(executable_str); 402 - if (!strncmp(dylib.c_str(), executable_str, executable_str_len)) { 403 - string dir = g_darwin_executable_path; 404 - size_t found = dir.rfind('/'); 405 - if (found == string::npos) { 406 - dir = "."; 407 - } else { 408 - dir = dir.substr(0, found); 409 - } 410 - dylib.replace(0, executable_str_len, dir); 411 - } 412 - 413 - auto_ptr<MachO> dylib_mach(loadDylib(dylib.c_str())); 414 - load(*dylib_mach); 415 - } 143 + 416 144 } 417 145 418 - void doBind(const MachO& mach, intptr slide) { 419 - string last_weak_name = ""; 420 - char* last_weak_sym = NULL; 421 - size_t seen_weak_bind_index = 0; 422 - size_t seen_weak_binds_orig_size = seen_weak_binds_.size(); 423 146 424 - unsigned int common_code_size = (unsigned int)trampoline_.size(); 425 - // Ensure that we won't change the address. 426 - trampoline_.reserve(common_code_size + 427 - (1 + 6 + 5 + 10 + 3 + 2 + 1) * mach.binds().size()); 428 - g_bound_names.resize(mach.binds().size()); 429 147 430 - for (size_t i = 0; i < mach.binds().size(); i++) { 431 - MachO::Bind* bind = mach.binds()[i]; 432 - if (bind->name[0] != '_') { 433 - LOG << bind->name << ": skipping" << endl; 434 - continue; 435 - } 436 - 437 - if (bind->type == BIND_TYPE_POINTER) { 438 - string name = bind->name.substr(1); 439 - void** ptr = (void**)(bind->vmaddr + slide); 440 - char* sym = NULL; 441 - 442 - if (bind->is_weak) { 443 - if (last_weak_name == name) { 444 - sym = last_weak_sym; 445 - } else { 446 - last_weak_name = name; 447 - if (seen_weak_bind_index != seen_weak_binds_orig_size && 448 - !strcmp(seen_weak_binds_[seen_weak_bind_index].first.c_str(), 449 - name.c_str())) { 450 - last_weak_sym = sym = 451 - seen_weak_binds_[seen_weak_bind_index].second; 452 - seen_weak_bind_index++; 453 - } else { 454 - if (bind->is_classic) { 455 - *ptr = last_weak_sym = (char*)bind->value; 456 - } else { 457 - const Exports::const_iterator export_found = 458 - exports_.find(bind->name); 459 - if (export_found != exports_.end()) { 460 - *ptr = last_weak_sym = (char*)export_found->second.addr; 461 - } else { 462 - last_weak_sym = (char*)*ptr; 463 - } 464 - } 465 - seen_weak_binds_.push_back(make_pair(name, last_weak_sym)); 466 - while (seen_weak_bind_index != seen_weak_binds_orig_size && 467 - strcmp( 468 - seen_weak_binds_[seen_weak_bind_index].first.c_str(), 469 - name.c_str()) <= 0) { 470 - seen_weak_bind_index++; 471 - } 472 - continue; 473 - } 474 - } 475 - } else { 476 - // TODO: remove, replace with aliases 477 - #ifndef __x86_64__ 478 - static const char* SUF_UNIX03 = "$UNIX2003"; 479 - static const size_t SUF_UNIX03_LEN = strlen(SUF_UNIX03); 480 - if (name.size() > SUF_UNIX03_LEN && 481 - !strcmp(name.c_str() + name.size() - SUF_UNIX03_LEN, 482 - SUF_UNIX03)) { 483 - name = name.substr(0, name.size() - SUF_UNIX03_LEN); 484 - } 485 - #endif 486 - 487 - // TODO: no renaming 488 - map<string, string>::const_iterator found = 489 - g_rename.find(name); 490 - if (found != g_rename.end()) { 491 - LOG << "Applying renaming: " << name 492 - << " => " << found->second.c_str() << endl; 493 - name = found->second.c_str(); 494 - } 495 - 496 - // TODO: use __darwin_dlsym instead 497 - const Exports::const_iterator export_found = 498 - exports_.find(bind->name); 499 - if (export_found != exports_.end()) { 500 - sym = (char*)export_found->second.addr; 501 - } 502 - if (!sym) { 503 - // TODO: try prefixes 504 - sym = (char*)dlsym(RTLD_DEFAULT, name.c_str()); 505 - // TODO: remove this 506 - if (!sym) { 507 - map<string, string>::const_iterator iter = 508 - symbol_to_so_.find(name); 509 - if (iter != symbol_to_so_.end()) { 510 - if (dlopen(iter->second.c_str(), RTLD_LAZY | RTLD_GLOBAL)) { 511 - sym = (char*)dlsym(RTLD_DEFAULT, name.c_str()); 512 - } else { 513 - fprintf(stderr, "Couldn't load %s for %s\n", 514 - iter->second.c_str(), name.c_str()); 515 - } 516 - } 517 - } 518 - } 519 - 520 - // TODO: idea: dynamically create undefined functions that would print out their name when called 521 - if (!sym) { 522 - ERR << name << ": undefined symbol" << endl; 523 - sym = (char*)&undefinedFunction; 524 - } 525 - sym += bind->addend; 526 - } 527 - 528 - LOG << "bind " << name << ": " 529 - << *ptr << " => " << (void*)sym << " @" << ptr << endl; 530 - 531 - if (FLAGS_TRACE_FUNCTIONS && !g_no_trampoline.count(name)) { 532 - LOG << "Generating trampoline for " << name << "..." << endl; 533 - 534 - *ptr = &trampoline_[0] + trampoline_.size(); 535 - g_bound_names[i] = name; 536 - 537 - // push %rax ; to adjust alignment for sse 538 - pushTrampolineCode(0x50); 539 - 540 - // mov $i, %r10d 541 - pushTrampolineCode(0xba41); 542 - pushTrampolineCode32((unsigned int)i); 543 - 544 - // call &trampoline_[0] 545 - pushTrampolineCode(0xe8); 546 - pushTrampolineCode32((unsigned int)(-4-trampoline_.size())); 547 - 548 - // mov $sym, %r10 549 - pushTrampolineCode(0xba49); 550 - pushTrampolineCode64((unsigned long long)(void*)sym); 551 - // call *%r10 552 - pushTrampolineCode(0xd2ff41); 553 - 554 - // pop %r10 555 - pushTrampolineCode(0x5a41); 556 - 557 - // ret 558 - pushTrampolineCode(0xc3); 559 - } else { 560 - *ptr = sym; 561 - } 562 - } else { 563 - fprintf(stderr, "Unknown bind type: %d\n", bind->type); 564 - abort(); 565 - } 566 - } 567 - 568 - inplace_merge(seen_weak_binds_.begin(), 569 - seen_weak_binds_.begin() + seen_weak_binds_orig_size, 570 - seen_weak_binds_.end()); 571 - } 572 - 573 - void loadExports(const MachO& mach, intptr base, Exports* exports) { 574 - exports->rehash(exports->size() + mach.exports().size()); 575 - for (size_t i = 0; i < mach.exports().size(); i++) { 576 - MachO::Export exp = *mach.exports()[i]; 577 - exp.addr += base; 578 - // TODO(hamaji): Not 100% sure, but we may need to consider weak symbols. 579 - if (!exports->insert(make_pair(exp.name, exp)).second) { 580 - fprintf(stderr, "duplicated exported symbol: %s\n", exp.name.c_str()); 581 - } 582 - } 583 - } 584 - 585 - void loadSymbols(const MachO& mach, intptr slide, intptr base) { 586 - g_file_map.add(mach, slide, base); 587 - } 588 - 589 - void load(const MachO& mach, Exports* exports = NULL) { 590 - if (!exports) { 591 - exports = &exports_; 592 - } 593 - intptr slide = 0; 594 - intptr base = 0; 595 - 596 - loadSegments(mach, &slide, &base); 597 - 598 - doRebase(mach, slide); 599 - 600 - loadInitFuncs(mach, slide); 601 - 602 - loadDylibs(mach); 603 - 604 - loadExports(mach, base, exports); 605 - 606 - doBind(mach, slide); 607 - 608 - loadSymbols(mach, slide, base); 609 - } 610 - 611 - void setupDyldData(const MachO& mach) { 612 - if (!mach.dyld_data()) 613 - return; 614 - 615 - void** dyld_data = (void**)mach.dyld_data(); 616 - dyld_data[1] = reinterpret_cast<void*>(&lookupDyldFunction); 617 - } 618 - 619 - void runInitFuncs(int argc, char** argv, char** envp, char** apple) { 620 - for (size_t i = 0; i < init_funcs_.size(); i++) { 621 - void** init_func = (void**)init_funcs_[i]; 622 - LOG << "calling initializer function " << *init_func << endl; 623 - if (argc >= 0) { 624 - ((void(*)(int, char**, char**, char**))*init_func)( 625 - argc, argv, envp, apple); 626 - } else { 627 - ((void(*)())*init_func)(); 628 - } 629 - } 630 - init_funcs_.clear(); 631 - } 632 148 633 149 void run(MachO& mach, int argc, char** argv, char** envp) { 634 150 // I don't understand what it is.
+127 -5
src/dyld/ld.cpp
··· 4 4 #include "MachO.h" 5 5 #include "mutex.h" 6 6 #include "trace.h" 7 + #include "FileMap.h" 7 8 #include <config.h> 8 9 #include <unistd.h> 9 10 #include <map> 10 11 #include <string> 12 + #include <limits.h> 11 13 12 14 static Mutex g_ldMutex; 13 - static std::map<string, LoadedLibrary> g_ldLibraries; 15 + static std::map<std::string, LoadedLibrary> g_ldLibraries; 14 16 static __thread char g_ldError[256] = ""; 17 + 18 + extern char g_darwin_executable_path[PATH_MAX]; 15 19 16 20 // TODO: this may need a rework for a 32bit loader on a 64bit system 17 21 static const char* g_searchPath[] = { ··· 25 29 extern char g_darwin_executable_path[PATH_MAX]; 26 30 extern int g_argc; 27 31 extern char** g_argv; 32 + extern FileMap g_file_map; 28 33 29 34 #define RET_IF(x) { if (void* p = x) return p; } 30 35 ··· 162 167 lib->refCount = 1; 163 168 lib->type = LoadedLibraryNative; 164 169 lib->nativeRef = d; 170 + lib->slide = lib->base = 0; 165 171 166 172 g_ldLibraries[name] = lib; 167 173 return lib; ··· 186 192 lib->machoRef = machO; 187 193 188 194 bool global = flags & RTLD_GLOBAL && !(flags & RTLD_LOCAL); 189 - // TODO: deal with global 190 - g_loader->load(*dylib_mach, exports, true); 191 - //g_loader-> 192 - // TODO: run initializers 195 + 196 + if (!global) 197 + { 198 + lib->exports = new Exports; 199 + g_loader->load(*dylib_mach, lib->exports, true); 200 + } 201 + else 202 + g_loader->load(*dylib_mach, 0, true); 203 + 204 + const char* apple[2] = { g_darwin_executable_path, 0 }; 205 + g_loader->runPendingInitFuncs(g_argc, g_argv, environ, apple); 193 206 194 207 g_ldLibraries[name] = lib; 195 208 return lib; ··· 210 223 MutexLock l(g_ldMutex); 211 224 g_ldError[0] = 0; 212 225 226 + if (!handle) 227 + return 0; 228 + 229 + LoadedLibrary* lib = dynamic_cast<LoadedLibrary*>(handle); 230 + if (!lib) 231 + { 232 + strcpy(g_ldError, "Invalid handle passed to __darwin_dlclose()"); 233 + return -1; 234 + } 235 + 236 + lib->refCount--; 237 + 238 + if (lib->type == LoadedLibraryNative) 239 + ::dlclose(lib->nativeRef); 240 + if (!lib->refCount) 241 + { 242 + if (lib->type == LoadedLibraryDylib) 243 + { 244 + // TODO: unmap in g_loader! 245 + delete lib->exports; 246 + 247 + for (std::map<std::string,LoadedLibrary>::iterator it = g_ldLibraries.begin(); it != g_ldLibraries.end(); it++) 248 + { 249 + if (it->second == lib) 250 + { 251 + g_ldLibraries.erase(it); 252 + delete lib; 253 + break; 254 + } 255 + } 256 + } 257 + } 258 + 213 259 return 0; 214 260 } 215 261 ··· 226 272 227 273 MutexLock l(g_ldMutex); 228 274 g_ldError[0] = 0; 275 + 276 + if (handle == DARWIN_RTLD_NEXT || handle == DARWIN_RTLD_SELF || handle == DARWIN_RTLD_MAIN_ONLY || !handle) 277 + { 278 + LOG("Cannot yet handle certain DARWIN_RTLD_* search strategies, falling back to RTLD_DEFAULT"); 279 + handle = DARWIN_RTLD_DEFAULT; 280 + } 281 + 282 + handling: 283 + if (handle == DARWIN_RTLD_DEFAULT) 284 + { 285 + // First try native with the __darwin prefix 286 + void* sym; 287 + char* buf = reinterpret_cast<char*>(malloc(strlen(symbol+20))); 288 + strcpy(buf, "__darwin_"); 289 + strcat(buf, symbol); 290 + 291 + sym = ::dlsym(RTLD_DEFAULT, buf); 292 + if (sym) 293 + return sym; 294 + 295 + // Now try Darwin libraries 296 + const Exports& e = g_loader.getExports(); 297 + Exports::const_iterator itSym = lib->exports->find(symbol); 298 + if (itSym == e.const_end()) 299 + { 300 + // Now try without a prefix 301 + sym = ::dlsym(RTLD_DEFAULT, symbol); 302 + if (sym) 303 + return sym; 304 + 305 + // Now we fail 306 + snprintf(g_ldError, sizeof(g_ldError)-1, "Cannot find symbol '%s'", symbol); 307 + return 0; 308 + } 309 + else 310 + return itSym->second.addr; 311 + } 312 + else 313 + { 314 + LoadedLibrary* lib = dynamic_cast<LoadedLibrary*>(handle); 315 + if (!lib) 316 + { 317 + strcpy(g_ldError, "Invalid handle passed to __darwin_dlsym()"); 318 + return 0; 319 + } 320 + 321 + if (lib->type == LoadedLibraryNative) 322 + { 323 + void* rv = ::dlsym(lib->nativeRef, symbol); 324 + if (!rv) 325 + strcpy(g_ldError, ::dlerror()); 326 + return rv; 327 + } 328 + else if (!lib->exports) 329 + { 330 + // TODO: this isn't 100% correct 331 + handle = DARWIN_RTLD_DEFAULT; 332 + goto handling; 333 + } 334 + else 335 + { 336 + Exports::iterator itSym = lib->exports->find(symbol); 337 + if (itSym == lib->exports->end()) 338 + { 339 + snprintf(g_ldError, sizeof(g_ldError)-1, "Cannot find symbol '%s'", symbol); 340 + return 0; 341 + } 342 + else 343 + return itSym->second.addr; 344 + } 345 + } 229 346 } 230 347 231 348 int __darwin_dladdr(void *addr, Dl_info *info) ··· 234 351 235 352 MutexLock l(g_ldMutex); 236 353 g_ldError[0] = 0; 354 + 355 + 356 + // TODO: implement - examine g_file_map 357 + strcpy(g_ldError, "Not implemented yet"); 358 + return -1; 237 359 }
+6 -2
src/dyld/ld.h
··· 1 1 #ifndef DARWIN_LD_H 2 2 #define DARWIN_LD_H 3 3 #include <dlfcn.h> 4 + #include "MachOLoader.h" 4 5 5 6 #define DARWIN_RTLD_LAZY 0x1 6 7 #define DARWIN_RTLD_NOW 0x2 ··· 26 27 27 28 } 28 29 29 - #ifdef DARWIN_LD_INTERNAL 30 30 enum LoadedLibraryType { LoadedLibraryDylib, LoadedLibraryNative }; 31 + 32 + typedef std::unordered_map<std::string, MachO::Export> Exports; 31 33 32 34 struct LoadedLibrary 33 35 { ··· 39 41 void* nativeRef; 40 42 MachO* machoRef; 41 43 }; 44 + //intptr slide; 45 + //intptr base; 46 + Exports* exports; 42 47 }; 43 - #endif 44 48 45 49 #endif