1 /* 2 * File macho_module.c - processing of Mach-O files 3 * Originally based on elf_module.c 4 * 5 * Copyright (C) 1996, Eric Youngdale. 6 * 1999-2007 Eric Pouech 7 * 2009 Ken Thomases, CodeWeavers Inc. 8 * 9 * This library is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Lesser General Public 11 * License as published by the Free Software Foundation; either 12 * version 2.1 of the License, or (at your option) any later version. 13 * 14 * This library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public 20 * License along with this library; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 22 */ 23 24 #include "config.h" 25 #include "wine/port.h" 26 27 #ifdef HAVE_MACH_O_LOADER_H 28 #include <CoreFoundation/CFString.h> 29 #define LoadResource mac_LoadResource 30 #define GetCurrentThread mac_GetCurrentThread 31 #include <CoreServices/CoreServices.h> 32 #undef LoadResource 33 #undef GetCurrentThread 34 #undef DPRINTF 35 #endif 36 37 #include <stdio.h> 38 #include <assert.h> 39 #include <stdarg.h> 40 #include <errno.h> 41 #ifdef HAVE_SYS_STAT_H 42 # include <sys/stat.h> 43 #endif 44 #ifdef HAVE_SYS_MMAN_H 45 # include <sys/mman.h> 46 #endif 47 48 #include "ntstatus.h" 49 #define WIN32_NO_STATUS 50 #include "dbghelp_private.h" 51 #include "winternl.h" 52 #include "wine/library.h" 53 #include "wine/debug.h" 54 #include "image_private.h" 55 56 #ifdef HAVE_MACH_O_LOADER_H 57 58 #include <mach-o/fat.h> 59 #include <mach-o/loader.h> 60 #include <mach-o/nlist.h> 61 #include <mach-o/dyld.h> 62 63 #ifdef HAVE_MACH_O_DYLD_IMAGES_H 64 #include <mach-o/dyld_images.h> 65 #else 66 struct dyld_image_info { 67 const struct mach_header *imageLoadAddress; 68 const char *imageFilePath; 69 uintptr_t imageFileModDate; 70 }; 71 72 struct dyld_all_image_infos { 73 uint32_t version; 74 uint32_t infoArrayCount; 75 const struct dyld_image_info *infoArray; 76 void* notification; 77 int processDetachedFromSharedRegion; 78 }; 79 #endif 80 81 #ifdef WORDS_BIGENDIAN 82 #define swap_ulong_be_to_host(n) (n) 83 #else 84 #define swap_ulong_be_to_host(n) (RtlUlongByteSwap(n)) 85 #endif 86 87 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_macho); 88 89 90 #ifdef _WIN64 91 typedef struct segment_command_64 macho_segment_command; 92 typedef struct nlist_64 macho_nlist; 93 94 #define TARGET_CPU_TYPE CPU_TYPE_X86_64 95 #define TARGET_MH_MAGIC MH_MAGIC_64 96 #define TARGET_SEGMENT_COMMAND LC_SEGMENT_64 97 #else 98 typedef struct segment_command macho_segment_command; 99 typedef struct nlist macho_nlist; 100 101 #define TARGET_CPU_TYPE CPU_TYPE_X86 102 #define TARGET_MH_MAGIC MH_MAGIC 103 #define TARGET_SEGMENT_COMMAND LC_SEGMENT 104 #endif 105 106 107 /* Bitmask for Mach-O image header flags indicating that the image is in dyld's 108 shared cached. That implies that its segments are mapped non-contiguously. 109 This value isn't defined anywhere in headers. It's used in dyld and in 110 debuggers which support OS X as a magic number. 111 112 The flag also isn't set in the on-disk image file. It's only set in 113 memory by dyld. */ 114 #define MACHO_DYLD_IN_SHARED_CACHE 0x80000000 115 116 117 #define UUID_STRING_LEN 37 /* 16 bytes at 2 hex digits apiece, 4 dashes, and the null terminator */ 118 119 120 struct macho_module_info 121 { 122 struct image_file_map file_map; 123 unsigned long load_addr; 124 unsigned short in_use : 1, 125 is_loader : 1; 126 }; 127 128 struct section_info 129 { 130 BOOL split_segs; 131 unsigned int section_index; 132 }; 133 134 #define MACHO_INFO_DEBUG_HEADER 0x0001 135 #define MACHO_INFO_MODULE 0x0002 136 #define MACHO_INFO_NAME 0x0004 137 138 struct macho_info 139 { 140 unsigned flags; /* IN one (or several) of the MACHO_INFO constants */ 141 unsigned long dbg_hdr_addr; /* OUT address of debug header (if MACHO_INFO_DEBUG_HEADER is set) */ 142 struct module* module; /* OUT loaded module (if MACHO_INFO_MODULE is set) */ 143 const WCHAR* module_name; /* OUT found module name (if MACHO_INFO_NAME is set) */ 144 }; 145 146 static void macho_unmap_file(struct image_file_map* fmap); 147 148 static char* format_uuid(const uint8_t uuid[16], char out[UUID_STRING_LEN]) 149 { 150 sprintf(out, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", 151 uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7], 152 uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]); 153 return out; 154 } 155 156 /****************************************************************** 157 * macho_calc_range 158 * 159 * For a range (offset & length) of a single architecture within 160 * a Mach-O file, calculate the page-aligned range of the whole file 161 * that encompasses it. For a fat binary, the architecture will 162 * itself be offset within the file, so take that into account. 163 */ 164 static void macho_calc_range(const struct macho_file_map* fmap, unsigned long offset, 165 unsigned long len, unsigned long* out_aligned_offset, 166 unsigned long* out_aligned_end, unsigned long* out_aligned_len, 167 unsigned long* out_misalign) 168 { 169 unsigned long pagemask = sysconf( _SC_PAGESIZE ) - 1; 170 unsigned long file_offset, misalign; 171 172 file_offset = fmap->arch_offset + offset; 173 misalign = file_offset & pagemask; 174 *out_aligned_offset = file_offset - misalign; 175 *out_aligned_end = (file_offset + len + pagemask) & ~pagemask; 176 if (out_aligned_len) 177 *out_aligned_len = *out_aligned_end - *out_aligned_offset; 178 if (out_misalign) 179 *out_misalign = misalign; 180 } 181 182 /****************************************************************** 183 * macho_map_range 184 * 185 * Maps a range (offset, length in bytes) from a Mach-O file into memory 186 */ 187 static const char* macho_map_range(const struct macho_file_map* fmap, unsigned long offset, unsigned long len, 188 const char** base) 189 { 190 unsigned long misalign, aligned_offset, aligned_map_end, map_size; 191 const void* aligned_ptr; 192 193 TRACE("(%p/%d, 0x%08lx, 0x%08lx)\n", fmap, fmap->fd, offset, len); 194 195 macho_calc_range(fmap, offset, len, &aligned_offset, &aligned_map_end, 196 &map_size, &misalign); 197 198 aligned_ptr = mmap(NULL, map_size, PROT_READ, MAP_PRIVATE, fmap->fd, aligned_offset); 199 200 TRACE("Mapped (0x%08lx - 0x%08lx) to %p\n", aligned_offset, aligned_map_end, aligned_ptr); 201 202 if (aligned_ptr == MAP_FAILED) return IMAGE_NO_MAP; 203 if (base) 204 *base = aligned_ptr; 205 return (const char*)aligned_ptr + misalign; 206 } 207 208 /****************************************************************** 209 * macho_unmap_range 210 * 211 * Unmaps a range (offset, length in bytes) of a Mach-O file from memory 212 */ 213 static void macho_unmap_range(const char** base, const void** mapped, const struct macho_file_map* fmap, 214 unsigned long offset, unsigned long len) 215 { 216 TRACE("(%p, %p, %p/%d, 0x%08lx, 0x%08lx)\n", base, mapped, fmap, fmap->fd, offset, len); 217 218 if ((mapped && *mapped != IMAGE_NO_MAP) || (base && *base != IMAGE_NO_MAP)) 219 { 220 unsigned long misalign, aligned_offset, aligned_map_end, map_size; 221 void* aligned_ptr; 222 223 macho_calc_range(fmap, offset, len, &aligned_offset, &aligned_map_end, 224 &map_size, &misalign); 225 226 if (mapped) 227 aligned_ptr = (char*)*mapped - misalign; 228 else 229 aligned_ptr = (void*)*base; 230 if (munmap(aligned_ptr, map_size) < 0) 231 WARN("Couldn't unmap the range\n"); 232 TRACE("Unmapped (0x%08lx - 0x%08lx) from %p - %p\n", aligned_offset, aligned_map_end, aligned_ptr, (char*)aligned_ptr + map_size); 233 if (mapped) 234 *mapped = IMAGE_NO_MAP; 235 if (base) 236 *base = IMAGE_NO_MAP; 237 } 238 } 239 240 /****************************************************************** 241 * macho_map_ranges 242 * 243 * Maps two ranges (offset, length in bytes) from a Mach-O file 244 * into memory. If the two ranges overlap, use one mmap so that 245 * the munmap doesn't fragment the mapping. 246 */ 247 static BOOL macho_map_ranges(const struct macho_file_map* fmap, 248 unsigned long offset1, unsigned long len1, 249 unsigned long offset2, unsigned long len2, 250 const void** mapped1, const void** mapped2) 251 { 252 unsigned long aligned_offset1, aligned_map_end1; 253 unsigned long aligned_offset2, aligned_map_end2; 254 255 TRACE("(%p/%d, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, %p, %p)\n", fmap, fmap->fd, 256 offset1, len1, offset2, len2, mapped1, mapped2); 257 258 macho_calc_range(fmap, offset1, len1, &aligned_offset1, &aligned_map_end1, NULL, NULL); 259 macho_calc_range(fmap, offset2, len2, &aligned_offset2, &aligned_map_end2, NULL, NULL); 260 261 if (aligned_map_end1 < aligned_offset2 || aligned_map_end2 < aligned_offset1) 262 { 263 *mapped1 = macho_map_range(fmap, offset1, len1, NULL); 264 if (*mapped1 != IMAGE_NO_MAP) 265 { 266 *mapped2 = macho_map_range(fmap, offset2, len2, NULL); 267 if (*mapped2 == IMAGE_NO_MAP) 268 macho_unmap_range(NULL, mapped1, fmap, offset1, len1); 269 } 270 } 271 else 272 { 273 if (offset1 < offset2) 274 { 275 *mapped1 = macho_map_range(fmap, offset1, offset2 + len2 - offset1, NULL); 276 if (*mapped1 != IMAGE_NO_MAP) 277 *mapped2 = (const char*)*mapped1 + offset2 - offset1; 278 } 279 else 280 { 281 *mapped2 = macho_map_range(fmap, offset2, offset1 + len1 - offset2, NULL); 282 if (*mapped2 != IMAGE_NO_MAP) 283 *mapped1 = (const char*)*mapped2 + offset1 - offset2; 284 } 285 } 286 287 TRACE(" => %p, %p\n", *mapped1, *mapped2); 288 289 return (*mapped1 != IMAGE_NO_MAP) && (*mapped2 != IMAGE_NO_MAP); 290 } 291 292 /****************************************************************** 293 * macho_unmap_ranges 294 * 295 * Unmaps two ranges (offset, length in bytes) of a Mach-O file 296 * from memory. Use for ranges which were mapped by 297 * macho_map_ranges. 298 */ 299 static void macho_unmap_ranges(const struct macho_file_map* fmap, 300 unsigned long offset1, unsigned long len1, 301 unsigned long offset2, unsigned long len2, 302 const void** mapped1, const void** mapped2) 303 { 304 unsigned long aligned_offset1, aligned_map_end1; 305 unsigned long aligned_offset2, aligned_map_end2; 306 307 TRACE("(%p/%d, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, %p/%p, %p/%p)\n", fmap, fmap->fd, 308 offset1, len1, offset2, len2, mapped1, *mapped1, mapped2, *mapped2); 309 310 macho_calc_range(fmap, offset1, len1, &aligned_offset1, &aligned_map_end1, NULL, NULL); 311 macho_calc_range(fmap, offset2, len2, &aligned_offset2, &aligned_map_end2, NULL, NULL); 312 313 if (aligned_map_end1 < aligned_offset2 || aligned_map_end2 < aligned_offset1) 314 { 315 macho_unmap_range(NULL, mapped1, fmap, offset1, len1); 316 macho_unmap_range(NULL, mapped2, fmap, offset2, len2); 317 } 318 else 319 { 320 if (offset1 < offset2) 321 { 322 macho_unmap_range(NULL, mapped1, fmap, offset1, offset2 + len2 - offset1); 323 *mapped2 = IMAGE_NO_MAP; 324 } 325 else 326 { 327 macho_unmap_range(NULL, mapped2, fmap, offset2, offset1 + len1 - offset2); 328 *mapped1 = IMAGE_NO_MAP; 329 } 330 } 331 } 332 333 /****************************************************************** 334 * macho_find_section 335 */ 336 BOOL macho_find_section(struct image_file_map* ifm, const char* segname, const char* sectname, struct image_section_map* ism) 337 { 338 struct macho_file_map* fmap; 339 unsigned i; 340 char tmp[sizeof(fmap->sect[0].section->sectname)]; 341 342 /* Other parts of dbghelp use section names like ".eh_frame". Mach-O uses 343 names like "__eh_frame". Convert those. */ 344 if (sectname[0] == '.') 345 { 346 lstrcpynA(tmp, "__", sizeof(tmp)); 347 lstrcpynA(tmp + 2, sectname + 1, sizeof(tmp) - 2); 348 sectname = tmp; 349 } 350 351 while (ifm) 352 { 353 fmap = &ifm->u.macho; 354 for (i = 0; i < fmap->num_sections; i++) 355 { 356 if (!fmap->sect[i].ignored && 357 strcmp(fmap->sect[i].section->sectname, sectname) == 0 && 358 (!segname || strcmp(fmap->sect[i].section->segname, segname) == 0)) 359 { 360 ism->fmap = ifm; 361 ism->sidx = i; 362 return TRUE; 363 } 364 } 365 ifm = fmap->dsym; 366 } 367 368 ism->fmap = NULL; 369 ism->sidx = -1; 370 return FALSE; 371 } 372 373 /****************************************************************** 374 * macho_map_section 375 */ 376 const char* macho_map_section(struct image_section_map* ism) 377 { 378 struct macho_file_map* fmap = &ism->fmap->u.macho; 379 380 assert(ism->fmap->modtype == DMT_MACHO); 381 if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.macho.num_sections || fmap->sect[ism->sidx].ignored) 382 return IMAGE_NO_MAP; 383 384 return macho_map_range(fmap, fmap->sect[ism->sidx].section->offset, fmap->sect[ism->sidx].section->size, 385 &fmap->sect[ism->sidx].mapped); 386 } 387 388 /****************************************************************** 389 * macho_unmap_section 390 */ 391 void macho_unmap_section(struct image_section_map* ism) 392 { 393 struct macho_file_map* fmap = &ism->fmap->u.macho; 394 395 if (ism->sidx >= 0 && ism->sidx < fmap->num_sections && fmap->sect[ism->sidx].mapped != IMAGE_NO_MAP) 396 { 397 macho_unmap_range(&fmap->sect[ism->sidx].mapped, NULL, fmap, fmap->sect[ism->sidx].section->offset, 398 fmap->sect[ism->sidx].section->size); 399 } 400 } 401 402 /****************************************************************** 403 * macho_get_map_rva 404 */ 405 DWORD_PTR macho_get_map_rva(const struct image_section_map* ism) 406 { 407 if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.macho.num_sections || 408 ism->fmap->u.macho.sect[ism->sidx].ignored) 409 return 0; 410 return ism->fmap->u.macho.sect[ism->sidx].section->addr - ism->fmap->u.macho.segs_start; 411 } 412 413 /****************************************************************** 414 * macho_get_map_size 415 */ 416 unsigned macho_get_map_size(const struct image_section_map* ism) 417 { 418 if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.macho.num_sections || 419 ism->fmap->u.macho.sect[ism->sidx].ignored) 420 return 0; 421 return ism->fmap->u.macho.sect[ism->sidx].section->size; 422 } 423 424 /****************************************************************** 425 * macho_map_load_commands 426 * 427 * Maps the load commands from a Mach-O file into memory 428 */ 429 static const struct load_command* macho_map_load_commands(struct macho_file_map* fmap) 430 { 431 if (fmap->load_commands == IMAGE_NO_MAP) 432 { 433 fmap->load_commands = (const struct load_command*) macho_map_range( 434 fmap, sizeof(fmap->mach_header), fmap->mach_header.sizeofcmds, NULL); 435 TRACE("Mapped load commands: %p\n", fmap->load_commands); 436 } 437 438 return fmap->load_commands; 439 } 440 441 /****************************************************************** 442 * macho_unmap_load_commands 443 * 444 * Unmaps the load commands of a Mach-O file from memory 445 */ 446 static void macho_unmap_load_commands(struct macho_file_map* fmap) 447 { 448 if (fmap->load_commands != IMAGE_NO_MAP) 449 { 450 TRACE("Unmapping load commands: %p\n", fmap->load_commands); 451 macho_unmap_range(NULL, (const void**)&fmap->load_commands, fmap, 452 sizeof(fmap->mach_header), fmap->mach_header.sizeofcmds); 453 } 454 } 455 456 /****************************************************************** 457 * macho_next_load_command 458 * 459 * Advance to the next load command 460 */ 461 static const struct load_command* macho_next_load_command(const struct load_command* lc) 462 { 463 return (const struct load_command*)((const char*)lc + lc->cmdsize); 464 } 465 466 /****************************************************************** 467 * macho_enum_load_commands 468 * 469 * Enumerates the load commands for a Mach-O file, selecting by 470 * the command type, calling a callback for each. If the callback 471 * returns <0, that indicates an error. If it returns >0, that means 472 * it's not interested in getting any more load commands. 473 * If this function returns <0, that's an error produced by the 474 * callback. If >=0, that's the count of load commands successfully 475 * processed. 476 */ 477 static int macho_enum_load_commands(struct macho_file_map* fmap, unsigned cmd, 478 int (*cb)(struct macho_file_map*, const struct load_command*, void*), 479 void* user) 480 { 481 const struct load_command* lc; 482 int i; 483 int count = 0; 484 485 TRACE("(%p/%d, %u, %p, %p)\n", fmap, fmap->fd, cmd, cb, user); 486 487 if ((lc = macho_map_load_commands(fmap)) == IMAGE_NO_MAP) return -1; 488 489 TRACE("%d total commands\n", fmap->mach_header.ncmds); 490 491 for (i = 0; i < fmap->mach_header.ncmds; i++, lc = macho_next_load_command(lc)) 492 { 493 int result; 494 495 if (cmd && cmd != lc->cmd) continue; 496 count++; 497 498 result = cb(fmap, lc, user); 499 TRACE("load_command[%d] (%p), cmd %u; callback => %d\n", i, lc, lc->cmd, result); 500 if (result) return (result < 0) ? result : count; 501 } 502 503 return count; 504 } 505 506 /****************************************************************** 507 * macho_count_sections 508 * 509 * Callback for macho_enum_load_commands. Counts the number of 510 * significant sections in a Mach-O file. All commands are 511 * expected to be of LC_SEGMENT[_64] type. 512 */ 513 static int macho_count_sections(struct macho_file_map* fmap, const struct load_command* lc, void* user) 514 { 515 const macho_segment_command* sc = (const macho_segment_command*)lc; 516 517 TRACE("(%p/%d, %p, %p) segment %s\n", fmap, fmap->fd, lc, user, debugstr_an(sc->segname, sizeof(sc->segname))); 518 519 fmap->num_sections += sc->nsects; 520 return 0; 521 } 522 523 /****************************************************************** 524 * macho_load_section_info 525 * 526 * Callback for macho_enum_load_commands. Accumulates the address 527 * range covered by the segments of a Mach-O file and builds the 528 * section map. All commands are expected to be of LC_SEGMENT[_64] type. 529 */ 530 static int macho_load_section_info(struct macho_file_map* fmap, const struct load_command* lc, void* user) 531 { 532 const macho_segment_command* sc = (const macho_segment_command*)lc; 533 struct section_info* info = user; 534 BOOL ignore; 535 const macho_section* section; 536 int i; 537 unsigned long tmp, page_mask = sysconf( _SC_PAGESIZE ) - 1; 538 539 TRACE("(%p/%d, %p, %p) before: 0x%08lx - 0x%08lx\n", fmap, fmap->fd, lc, user, 540 (unsigned long)fmap->segs_start, (unsigned long)fmap->segs_size); 541 TRACE("Segment command vm: 0x%08lx - 0x%08lx\n", (unsigned long)sc->vmaddr, 542 (unsigned long)(sc->vmaddr + sc->vmsize)); 543 544 /* Images in the dyld shared cache have their segments mapped non-contiguously. 545 We don't know how to properly locate any of the segments other than __TEXT, 546 so ignore them. */ 547 ignore = (info->split_segs && strcmp(sc->segname, SEG_TEXT)); 548 549 if (!strncmp(sc->segname, "WINE_", 5)) 550 TRACE("Ignoring special Wine segment %s\n", debugstr_an(sc->segname, sizeof(sc->segname))); 551 else if (!strncmp(sc->segname, "__PAGEZERO", 10)) 552 TRACE("Ignoring __PAGEZERO segment\n"); 553 else if (ignore) 554 TRACE("Ignoring %s segment because image has split segments\n", sc->segname); 555 else 556 { 557 /* If this segment starts before previously-known earliest, record new earliest. */ 558 if (sc->vmaddr < fmap->segs_start) 559 fmap->segs_start = sc->vmaddr; 560 561 /* If this segment extends beyond previously-known furthest, record new furthest. */ 562 tmp = (sc->vmaddr + sc->vmsize + page_mask) & ~page_mask; 563 if (fmap->segs_size < tmp) fmap->segs_size = tmp; 564 565 TRACE("after: 0x%08lx - 0x%08lx\n", (unsigned long)fmap->segs_start, (unsigned long)fmap->segs_size); 566 } 567 568 section = (const macho_section*)(sc + 1); 569 for (i = 0; i < sc->nsects; i++) 570 { 571 fmap->sect[info->section_index].section = §ion[i]; 572 fmap->sect[info->section_index].mapped = IMAGE_NO_MAP; 573 fmap->sect[info->section_index].ignored = ignore; 574 info->section_index++; 575 } 576 577 return 0; 578 } 579 580 /****************************************************************** 581 * find_uuid 582 * 583 * Callback for macho_enum_load_commands. Records the UUID load 584 * command of a Mach-O file. 585 */ 586 static int find_uuid(struct macho_file_map* fmap, const struct load_command* lc, void* user) 587 { 588 fmap->uuid = (const struct uuid_command*)lc; 589 return 1; 590 } 591 592 /****************************************************************** 593 * reset_file_map 594 */ 595 static inline void reset_file_map(struct image_file_map* ifm) 596 { 597 struct macho_file_map* fmap = &ifm->u.macho; 598 599 fmap->fd = -1; 600 fmap->dsym = NULL; 601 fmap->load_commands = IMAGE_NO_MAP; 602 fmap->uuid = NULL; 603 fmap->num_sections = 0; 604 fmap->sect = NULL; 605 } 606 607 /****************************************************************** 608 * macho_map_file 609 * 610 * Maps a Mach-O file into memory (and checks it's a real Mach-O file) 611 */ 612 static BOOL macho_map_file(const WCHAR* filenameW, BOOL split_segs, struct image_file_map* ifm) 613 { 614 struct macho_file_map* fmap = &ifm->u.macho; 615 struct fat_header fat_header; 616 struct stat statbuf; 617 int i; 618 char* filename; 619 unsigned len; 620 struct section_info info; 621 BOOL ret = FALSE; 622 623 TRACE("(%s, %p)\n", debugstr_w(filenameW), fmap); 624 625 reset_file_map(ifm); 626 627 ifm->modtype = DMT_MACHO; 628 #ifdef _WIN64 629 ifm->addr_size = 64; 630 #else 631 ifm->addr_size = 32; 632 #endif 633 634 len = WideCharToMultiByte(CP_UNIXCP, 0, filenameW, -1, NULL, 0, NULL, NULL); 635 if (!(filename = HeapAlloc(GetProcessHeap(), 0, len))) 636 { 637 WARN("failed to allocate filename buffer\n"); 638 return FALSE; 639 } 640 WideCharToMultiByte(CP_UNIXCP, 0, filenameW, -1, filename, len, NULL, NULL); 641 642 /* check that the file exists */ 643 if (stat(filename, &statbuf) == -1 || S_ISDIR(statbuf.st_mode)) 644 { 645 TRACE("stat() failed or %s is directory: %s\n", debugstr_a(filename), strerror(errno)); 646 goto done; 647 } 648 649 /* Now open the file, so that we can mmap() it. */ 650 if ((fmap->fd = open(filename, O_RDONLY)) == -1) 651 { 652 TRACE("failed to open file %s: %d\n", debugstr_a(filename), errno); 653 goto done; 654 } 655 656 if (read(fmap->fd, &fat_header, sizeof(fat_header)) != sizeof(fat_header)) 657 { 658 TRACE("failed to read fat header: %d\n", errno); 659 goto done; 660 } 661 TRACE("... got possible fat header\n"); 662 663 /* Fat header is always in big-endian order. */ 664 if (swap_ulong_be_to_host(fat_header.magic) == FAT_MAGIC) 665 { 666 int narch = swap_ulong_be_to_host(fat_header.nfat_arch); 667 for (i = 0; i < narch; i++) 668 { 669 struct fat_arch fat_arch; 670 if (read(fmap->fd, &fat_arch, sizeof(fat_arch)) != sizeof(fat_arch)) 671 goto done; 672 if (swap_ulong_be_to_host(fat_arch.cputype) == TARGET_CPU_TYPE) 673 { 674 fmap->arch_offset = swap_ulong_be_to_host(fat_arch.offset); 675 break; 676 } 677 } 678 if (i >= narch) goto done; 679 TRACE("... found target arch (%d)\n", TARGET_CPU_TYPE); 680 } 681 else 682 { 683 fmap->arch_offset = 0; 684 TRACE("... not a fat header\n"); 685 } 686 687 /* Individual architecture (standalone or within a fat file) is in its native byte order. */ 688 lseek(fmap->fd, fmap->arch_offset, SEEK_SET); 689 if (read(fmap->fd, &fmap->mach_header, sizeof(fmap->mach_header)) != sizeof(fmap->mach_header)) 690 goto done; 691 TRACE("... got possible Mach header\n"); 692 /* and check for a Mach-O header */ 693 if (fmap->mach_header.magic != TARGET_MH_MAGIC || 694 fmap->mach_header.cputype != TARGET_CPU_TYPE) goto done; 695 /* Make sure the file type is one of the ones we expect. */ 696 switch (fmap->mach_header.filetype) 697 { 698 case MH_EXECUTE: 699 case MH_DYLIB: 700 case MH_DYLINKER: 701 case MH_BUNDLE: 702 case MH_DSYM: 703 break; 704 default: 705 goto done; 706 } 707 TRACE("... verified Mach header\n"); 708 709 fmap->num_sections = 0; 710 if (macho_enum_load_commands(fmap, TARGET_SEGMENT_COMMAND, macho_count_sections, NULL) < 0) 711 goto done; 712 TRACE("%d sections\n", fmap->num_sections); 713 714 fmap->sect = HeapAlloc(GetProcessHeap(), 0, fmap->num_sections * sizeof(fmap->sect[0])); 715 if (!fmap->sect) 716 goto done; 717 718 fmap->segs_size = 0; 719 fmap->segs_start = ~0L; 720 721 info.split_segs = split_segs; 722 info.section_index = 0; 723 if (macho_enum_load_commands(fmap, TARGET_SEGMENT_COMMAND, macho_load_section_info, &info) < 0) 724 { 725 fmap->num_sections = 0; 726 goto done; 727 } 728 729 fmap->segs_size -= fmap->segs_start; 730 TRACE("segs_start: 0x%08lx, segs_size: 0x%08lx\n", (unsigned long)fmap->segs_start, 731 (unsigned long)fmap->segs_size); 732 733 if (macho_enum_load_commands(fmap, LC_UUID, find_uuid, NULL) < 0) 734 goto done; 735 if (fmap->uuid) 736 { 737 char uuid_string[UUID_STRING_LEN]; 738 TRACE("UUID %s\n", format_uuid(fmap->uuid->uuid, uuid_string)); 739 } 740 else 741 TRACE("no UUID found\n"); 742 743 ret = TRUE; 744 done: 745 if (!ret) 746 macho_unmap_file(ifm); 747 HeapFree(GetProcessHeap(), 0, filename); 748 return ret; 749 } 750 751 /****************************************************************** 752 * macho_unmap_file 753 * 754 * Unmaps a Mach-O file from memory (previously mapped with macho_map_file) 755 */ 756 static void macho_unmap_file(struct image_file_map* ifm) 757 { 758 struct image_file_map* cursor; 759 760 TRACE("(%p/%d)\n", ifm, ifm->u.macho.fd); 761 762 cursor = ifm; 763 while (cursor) 764 { 765 struct image_file_map* next; 766 767 if (ifm->u.macho.fd != -1) 768 { 769 struct image_section_map ism; 770 771 ism.fmap = ifm; 772 for (ism.sidx = 0; ism.sidx < ifm->u.macho.num_sections; ism.sidx++) 773 macho_unmap_section(&ism); 774 775 HeapFree(GetProcessHeap(), 0, ifm->u.macho.sect); 776 macho_unmap_load_commands(&ifm->u.macho); 777 close(ifm->u.macho.fd); 778 ifm->u.macho.fd = -1; 779 } 780 781 next = cursor->u.macho.dsym; 782 if (cursor != ifm) 783 HeapFree(GetProcessHeap(), 0, cursor); 784 cursor = next; 785 } 786 } 787 788 /****************************************************************** 789 * macho_sect_is_code 790 * 791 * Checks if a section, identified by sectidx which is a 1-based 792 * index into the sections of all segments, in order of load 793 * commands, contains code. 794 */ 795 static BOOL macho_sect_is_code(struct macho_file_map* fmap, unsigned char sectidx) 796 { 797 BOOL ret; 798 799 TRACE("(%p/%d, %u)\n", fmap, fmap->fd, sectidx); 800 801 if (!sectidx) return FALSE; 802 803 sectidx--; /* convert from 1-based to 0-based */ 804 if (sectidx >= fmap->num_sections || fmap->sect[sectidx].ignored) return FALSE; 805 806 ret = (!(fmap->sect[sectidx].section->flags & SECTION_TYPE) && 807 (fmap->sect[sectidx].section->flags & (S_ATTR_PURE_INSTRUCTIONS|S_ATTR_SOME_INSTRUCTIONS))); 808 TRACE("-> %d\n", ret); 809 return ret; 810 } 811 812 struct symtab_elt 813 { 814 struct hash_table_elt ht_elt; 815 struct symt_compiland* compiland; 816 unsigned long addr; 817 unsigned char is_code:1, 818 is_public:1, 819 is_global:1, 820 used:1; 821 }; 822 823 struct macho_debug_info 824 { 825 struct macho_file_map* fmap; 826 struct module* module; 827 struct pool pool; 828 struct hash_table ht_symtab; 829 }; 830 831 /****************************************************************** 832 * macho_stabs_def_cb 833 * 834 * Callback for stabs_parse. Collect symbol definitions. 835 */ 836 static void macho_stabs_def_cb(struct module* module, unsigned long load_offset, 837 const char* name, unsigned long offset, 838 BOOL is_public, BOOL is_global, unsigned char sectidx, 839 struct symt_compiland* compiland, void* user) 840 { 841 struct macho_debug_info* mdi = user; 842 struct symtab_elt* ste; 843 844 TRACE("(%p, 0x%08lx, %s, 0x%08lx, %d, %d, %u, %p, %p/%p/%d)\n", module, load_offset, 845 debugstr_a(name), offset, is_public, is_global, sectidx, 846 compiland, mdi, mdi->fmap, mdi->fmap->fd); 847 848 /* Defer the creation of new non-debugging symbols until after we've 849 * finished parsing the stabs. */ 850 ste = pool_alloc(&mdi->pool, sizeof(*ste)); 851 ste->ht_elt.name = pool_strdup(&mdi->pool, name); 852 ste->compiland = compiland; 853 ste->addr = load_offset + offset; 854 ste->is_code = !!macho_sect_is_code(mdi->fmap, sectidx); 855 ste->is_public = !!is_public; 856 ste->is_global = !!is_global; 857 ste->used = 0; 858 hash_table_add(&mdi->ht_symtab, &ste->ht_elt); 859 } 860 861 /****************************************************************** 862 * macho_parse_symtab 863 * 864 * Callback for macho_enum_load_commands. Processes the LC_SYMTAB 865 * load commands from the Mach-O file. 866 */ 867 static int macho_parse_symtab(struct macho_file_map* fmap, 868 const struct load_command* lc, void* user) 869 { 870 const struct symtab_command* sc = (const struct symtab_command*)lc; 871 struct macho_debug_info* mdi = user; 872 const macho_nlist* stab; 873 const char* stabstr; 874 int ret = 0; 875 876 TRACE("(%p/%d, %p, %p) %u syms at 0x%08x, strings 0x%08x - 0x%08x\n", fmap, fmap->fd, lc, 877 user, sc->nsyms, sc->symoff, sc->stroff, sc->stroff + sc->strsize); 878 879 if (!macho_map_ranges(fmap, sc->symoff, sc->nsyms * sizeof(macho_nlist), 880 sc->stroff, sc->strsize, (const void**)&stab, (const void**)&stabstr)) 881 return 0; 882 883 if (!stabs_parse(mdi->module, 884 mdi->module->format_info[DFI_MACHO]->u.macho_info->load_addr - fmap->segs_start, 885 stab, sc->nsyms * sizeof(macho_nlist), 886 stabstr, sc->strsize, macho_stabs_def_cb, mdi)) 887 ret = -1; 888 889 macho_unmap_ranges(fmap, sc->symoff, sc->nsyms * sizeof(macho_nlist), 890 sc->stroff, sc->strsize, (const void**)&stab, (const void**)&stabstr); 891 892 return ret; 893 } 894 895 /****************************************************************** 896 * macho_finish_stabs 897 * 898 * Integrate the non-debugging symbols we've gathered into the 899 * symbols that were generated during stabs parsing. 900 */ 901 static void macho_finish_stabs(struct module* module, struct hash_table* ht_symtab) 902 { 903 struct hash_table_iter hti_ours; 904 struct symtab_elt* ste; 905 BOOL adjusted = FALSE; 906 907 TRACE("(%p, %p)\n", module, ht_symtab); 908 909 /* For each of our non-debugging symbols, see if it can provide some 910 * missing details to one of the module's known symbols. */ 911 hash_table_iter_init(ht_symtab, &hti_ours, NULL); 912 while ((ste = hash_table_iter_up(&hti_ours))) 913 { 914 struct hash_table_iter hti_modules; 915 void* ptr; 916 struct symt_ht* sym; 917 struct symt_function* func; 918 struct symt_data* data; 919 920 hash_table_iter_init(&module->ht_symbols, &hti_modules, ste->ht_elt.name); 921 while ((ptr = hash_table_iter_up(&hti_modules))) 922 { 923 sym = CONTAINING_RECORD(ptr, struct symt_ht, hash_elt); 924 925 if (strcmp(sym->hash_elt.name, ste->ht_elt.name)) 926 continue; 927 928 switch (sym->symt.tag) 929 { 930 case SymTagFunction: 931 func = (struct symt_function*)sym; 932 if (func->address == module->format_info[DFI_MACHO]->u.macho_info->load_addr) 933 { 934 TRACE("Adjusting function %p/%s!%s from 0x%08lx to 0x%08lx\n", func, 935 debugstr_w(module->module.ModuleName), sym->hash_elt.name, 936 func->address, ste->addr); 937 func->address = ste->addr; 938 adjusted = TRUE; 939 } 940 if (func->address == ste->addr) 941 ste->used = 1; 942 break; 943 case SymTagData: 944 data = (struct symt_data*)sym; 945 switch (data->kind) 946 { 947 case DataIsGlobal: 948 case DataIsFileStatic: 949 if (data->u.var.offset == module->format_info[DFI_MACHO]->u.macho_info->load_addr) 950 { 951 TRACE("Adjusting data symbol %p/%s!%s from 0x%08lx to 0x%08lx\n", 952 data, debugstr_w(module->module.ModuleName), sym->hash_elt.name, 953 data->u.var.offset, ste->addr); 954 data->u.var.offset = ste->addr; 955 adjusted = TRUE; 956 } 957 if (data->u.var.offset == ste->addr) 958 { 959 enum DataKind new_kind; 960 961 new_kind = ste->is_global ? DataIsGlobal : DataIsFileStatic; 962 if (data->kind != new_kind) 963 { 964 WARN("Changing kind for %p/%s!%s from %d to %d\n", sym, 965 debugstr_w(module->module.ModuleName), sym->hash_elt.name, 966 (int)data->kind, (int)new_kind); 967 data->kind = new_kind; 968 adjusted = TRUE; 969 } 970 ste->used = 1; 971 } 972 break; 973 default:; 974 } 975 break; 976 default: 977 TRACE("Ignoring tag %u\n", sym->symt.tag); 978 break; 979 } 980 } 981 } 982 983 if (adjusted) 984 { 985 /* since we may have changed some addresses, mark the module to be resorted */ 986 module->sortlist_valid = FALSE; 987 } 988 989 /* Mark any of our non-debugging symbols which fall on an already-used 990 * address as "used". This allows us to skip them in the next loop, 991 * below. We do this in separate loops because symt_new_* marks the 992 * list as needing sorting and symt_find_nearest sorts if needed, 993 * causing thrashing. */ 994 if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY)) 995 { 996 hash_table_iter_init(ht_symtab, &hti_ours, NULL); 997 while ((ste = hash_table_iter_up(&hti_ours))) 998 { 999 struct symt_ht* sym; 1000 ULONG64 addr; 1001 1002 if (ste->used) continue; 1003 1004 sym = symt_find_nearest(module, ste->addr); 1005 if (sym) 1006 symt_get_address(&sym->symt, &addr); 1007 if (sym && ste->addr == addr) 1008 { 1009 ULONG64 size = 0; 1010 DWORD kind = -1; 1011 1012 ste->used = 1; 1013 1014 /* If neither symbol has a correct size (ours never does), we 1015 * consider them both to be markers. No warning is needed in 1016 * that case. 1017 * Also, we check that we don't have two symbols, one local, the other 1018 * global, which is legal. 1019 */ 1020 symt_get_info(module, &sym->symt, TI_GET_LENGTH, &size); 1021 symt_get_info(module, &sym->symt, TI_GET_DATAKIND, &kind); 1022 if (size && kind == (ste->is_global ? DataIsGlobal : DataIsFileStatic)) 1023 FIXME("Duplicate in %s: %s<%08lx> %s<%s-%s>\n", 1024 debugstr_w(module->module.ModuleName), 1025 ste->ht_elt.name, ste->addr, 1026 sym->hash_elt.name, 1027 wine_dbgstr_longlong(addr), wine_dbgstr_longlong(size)); 1028 } 1029 } 1030 } 1031 1032 /* For any of our remaining non-debugging symbols which have no match 1033 * among the module's known symbols, add them as new symbols. */ 1034 hash_table_iter_init(ht_symtab, &hti_ours, NULL); 1035 while ((ste = hash_table_iter_up(&hti_ours))) 1036 { 1037 if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY) && !ste->used) 1038 { 1039 if (ste->is_code) 1040 { 1041 symt_new_function(module, ste->compiland, ste->ht_elt.name, 1042 ste->addr, 0, NULL); 1043 } 1044 else 1045 { 1046 struct location loc; 1047 1048 loc.kind = loc_absolute; 1049 loc.reg = 0; 1050 loc.offset = ste->addr; 1051 symt_new_global_variable(module, ste->compiland, ste->ht_elt.name, 1052 !ste->is_global, loc, 0, NULL); 1053 } 1054 1055 ste->used = 1; 1056 } 1057 1058 if (ste->is_public && !(dbghelp_options & SYMOPT_NO_PUBLICS)) 1059 { 1060 symt_new_public(module, ste->compiland, ste->ht_elt.name, ste->addr, 0); 1061 } 1062 } 1063 } 1064 1065 /****************************************************************** 1066 * try_dsym 1067 * 1068 * Try to load a debug symbol file from the given path and check 1069 * if its UUID matches the UUID of an already-mapped file. If so, 1070 * stash the file map in the "dsym" field of the file and return 1071 * TRUE. If it can't be mapped or its UUID doesn't match, return 1072 * FALSE. 1073 */ 1074 static BOOL try_dsym(const WCHAR* path, struct macho_file_map* fmap) 1075 { 1076 struct image_file_map dsym_ifm; 1077 1078 if (macho_map_file(path, FALSE, &dsym_ifm)) 1079 { 1080 char uuid_string[UUID_STRING_LEN]; 1081 1082 if (dsym_ifm.u.macho.uuid && !memcmp(dsym_ifm.u.macho.uuid->uuid, fmap->uuid->uuid, sizeof(fmap->uuid->uuid))) 1083 { 1084 TRACE("found matching debug symbol file at %s\n", debugstr_w(path)); 1085 fmap->dsym = HeapAlloc(GetProcessHeap(), 0, sizeof(dsym_ifm)); 1086 *fmap->dsym = dsym_ifm; 1087 return TRUE; 1088 } 1089 1090 TRACE("candidate debug symbol file at %s has wrong UUID %s; ignoring\n", debugstr_w(path), 1091 format_uuid(dsym_ifm.u.macho.uuid->uuid, uuid_string)); 1092 1093 macho_unmap_file(&dsym_ifm); 1094 } 1095 else 1096 TRACE("couldn't map file at %s\n", debugstr_w(path)); 1097 1098 return FALSE; 1099 } 1100 1101 /****************************************************************** 1102 * find_and_map_dsym 1103 * 1104 * Search for a debugging symbols file associated with a module and 1105 * map it. First look for a .dSYM bundle next to the module file 1106 * (e.g. <path>.dSYM/Contents/Resources/DWARF/<basename of path>) 1107 * as produced by dsymutil. Next, look for a .dwarf file next to 1108 * the module file (e.g. <path>.dwarf) as produced by 1109 * "dsymutil --flat". Finally, use Spotlight to search for a 1110 * .dSYM bundle with the same UUID as the module file. 1111 */ 1112 static void find_and_map_dsym(struct module* module) 1113 { 1114 static const WCHAR dot_dsym[] = {'.','d','S','Y','M',0}; 1115 static const WCHAR dsym_subpath[] = {'/','C','o','n','t','e','n','t','s','/','R','e','s','o','u','r','c','e','s','/','D','W','A','R','F','/',0}; 1116 static const WCHAR dot_dwarf[] = {'.','d','w','a','r','f',0}; 1117 struct macho_file_map* fmap = &module->format_info[DFI_MACHO]->u.macho_info->file_map.u.macho; 1118 const WCHAR* p; 1119 size_t len; 1120 WCHAR* path = NULL; 1121 char uuid_string[UUID_STRING_LEN]; 1122 CFStringRef uuid_cfstring; 1123 CFStringRef query_string; 1124 MDQueryRef query = NULL; 1125 1126 /* Without a UUID, we can't verify that any debug info file we find corresponds 1127 to this file. Better to have no debug info than incorrect debug info. */ 1128 if (!fmap->uuid) 1129 return; 1130 1131 if ((p = strrchrW(module->module.LoadedImageName, '/'))) 1132 p++; 1133 else 1134 p = module->module.LoadedImageName; 1135 len = strlenW(module->module.LoadedImageName) + strlenW(dot_dsym) + strlenW(dsym_subpath) + strlenW(p) + 1; 1136 path = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 1137 if (!path) 1138 return; 1139 strcpyW(path, module->module.LoadedImageName); 1140 strcatW(path, dot_dsym); 1141 strcatW(path, dsym_subpath); 1142 strcatW(path, p); 1143 1144 if (try_dsym(path, fmap)) 1145 goto found; 1146 1147 strcpyW(path + strlenW(module->module.LoadedImageName), dot_dwarf); 1148 1149 if (try_dsym(path, fmap)) 1150 goto found; 1151 1152 format_uuid(fmap->uuid->uuid, uuid_string); 1153 uuid_cfstring = CFStringCreateWithCString(NULL, uuid_string, kCFStringEncodingASCII); 1154 query_string = CFStringCreateWithFormat(NULL, NULL, CFSTR("com_apple_xcode_dsym_uuids == \"%@\""), uuid_cfstring); 1155 CFRelease(uuid_cfstring); 1156 query = MDQueryCreate(NULL, query_string, NULL, NULL); 1157 CFRelease(query_string); 1158 MDQuerySetMaxCount(query, 1); 1159 if (MDQueryExecute(query, kMDQuerySynchronous) && MDQueryGetResultCount(query) >= 1) 1160 { 1161 MDItemRef item = (MDItemRef)MDQueryGetResultAtIndex(query, 0); 1162 CFStringRef item_path = MDItemCopyAttribute(item, kMDItemPath); 1163 if (item_path) 1164 { 1165 CFIndex item_path_len = CFStringGetLength(item_path); 1166 if (item_path_len + strlenW(dsym_subpath) + strlenW(p) >= len) 1167 { 1168 HeapFree(GetProcessHeap(), 0, path); 1169 len = item_path_len + strlenW(dsym_subpath) + strlenW(p) + 1; 1170 path = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 1171 } 1172 CFStringGetCharacters(item_path, CFRangeMake(0, item_path_len), (UniChar*)path); 1173 strcpyW(path + item_path_len, dsym_subpath); 1174 strcatW(path, p); 1175 CFRelease(item_path); 1176 1177 if (try_dsym(path, fmap)) 1178 goto found; 1179 } 1180 } 1181 1182 found: 1183 HeapFree(GetProcessHeap(), 0, path); 1184 if (query) CFRelease(query); 1185 } 1186 1187 /****************************************************************** 1188 * image_uses_split_segs 1189 * 1190 * Determine if the Mach-O image loaded at a particular address in 1191 * the given process is in the dyld shared cache and therefore has 1192 * its segments mapped non-contiguously. 1193 * 1194 * The image header has to be loaded from the process's memory 1195 * because the relevant flag is only set in memory, not in the file. 1196 */ 1197 static BOOL image_uses_split_segs(HANDLE process, unsigned long load_addr) 1198 { 1199 BOOL split_segs = FALSE; 1200 1201 if (process && load_addr) 1202 { 1203 macho_mach_header header; 1204 if (ReadProcessMemory(process, (void*)load_addr, &header, sizeof(header), NULL) && 1205 header.magic == TARGET_MH_MAGIC && header.cputype == TARGET_CPU_TYPE && 1206 header.flags & MACHO_DYLD_IN_SHARED_CACHE) 1207 { 1208 split_segs = TRUE; 1209 } 1210 } 1211 1212 return split_segs; 1213 } 1214 1215 /****************************************************************** 1216 * macho_load_debug_info 1217 * 1218 * Loads Mach-O debugging information from the module image file. 1219 */ 1220 BOOL macho_load_debug_info(struct module* module) 1221 { 1222 BOOL ret = FALSE; 1223 struct macho_debug_info mdi; 1224 int result; 1225 struct macho_file_map *fmap; 1226 1227 if (module->type != DMT_MACHO || !module->format_info[DFI_MACHO]->u.macho_info) 1228 { 1229 ERR("Bad Mach-O module '%s'\n", debugstr_w(module->module.LoadedImageName)); 1230 return FALSE; 1231 } 1232 1233 fmap = &module->format_info[DFI_MACHO]->u.macho_info->file_map.u.macho; 1234 1235 TRACE("(%p, %p/%d)\n", module, fmap, fmap->fd); 1236 1237 module->module.SymType = SymExport; 1238 1239 if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY)) 1240 { 1241 find_and_map_dsym(module); 1242 1243 if (dwarf2_parse(module, module->reloc_delta, NULL /* FIXME: some thunks to deal with ? */, 1244 &module->format_info[DFI_MACHO]->u.macho_info->file_map)) 1245 ret = TRUE; 1246 } 1247 1248 mdi.fmap = fmap; 1249 mdi.module = module; 1250 pool_init(&mdi.pool, 65536); 1251 hash_table_init(&mdi.pool, &mdi.ht_symtab, 256); 1252 result = macho_enum_load_commands(fmap, LC_SYMTAB, macho_parse_symtab, &mdi); 1253 if (result > 0) 1254 ret = TRUE; 1255 else if (result < 0) 1256 WARN("Couldn't correctly read stabs\n"); 1257 1258 if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY) && fmap->dsym) 1259 { 1260 mdi.fmap = &fmap->dsym->u.macho; 1261 result = macho_enum_load_commands(mdi.fmap, LC_SYMTAB, macho_parse_symtab, &mdi); 1262 if (result > 0) 1263 ret = TRUE; 1264 else if (result < 0) 1265 WARN("Couldn't correctly read stabs\n"); 1266 } 1267 1268 macho_finish_stabs(module, &mdi.ht_symtab); 1269 1270 pool_destroy(&mdi.pool); 1271 return ret; 1272 } 1273 1274 /****************************************************************** 1275 * macho_fetch_file_info 1276 * 1277 * Gathers some more information for a Mach-O module from a given file 1278 */ 1279 BOOL macho_fetch_file_info(HANDLE process, const WCHAR* name, unsigned long load_addr, DWORD_PTR* base, 1280 DWORD* size, DWORD* checksum) 1281 { 1282 struct image_file_map fmap; 1283 BOOL split_segs; 1284 1285 TRACE("(%s, %p, %p, %p)\n", debugstr_w(name), base, size, checksum); 1286 1287 split_segs = image_uses_split_segs(process, load_addr); 1288 if (!macho_map_file(name, split_segs, &fmap)) return FALSE; 1289 if (base) *base = fmap.u.macho.segs_start; 1290 *size = fmap.u.macho.segs_size; 1291 *checksum = calc_crc32(fmap.u.macho.fd); 1292 macho_unmap_file(&fmap); 1293 return TRUE; 1294 } 1295 1296 /****************************************************************** 1297 * macho_module_remove 1298 */ 1299 static void macho_module_remove(struct process* pcs, struct module_format* modfmt) 1300 { 1301 macho_unmap_file(&modfmt->u.macho_info->file_map); 1302 HeapFree(GetProcessHeap(), 0, modfmt); 1303 } 1304 1305 1306 /****************************************************************** 1307 * get_dyld_image_info_address 1308 */ 1309 static ULONG_PTR get_dyld_image_info_address(struct process* pcs) 1310 { 1311 NTSTATUS status; 1312 PROCESS_BASIC_INFORMATION pbi; 1313 ULONG_PTR dyld_image_info_address = 0; 1314 1315 /* Get address of PEB */ 1316 status = NtQueryInformationProcess(pcs->handle, ProcessBasicInformation, &pbi, sizeof(pbi), NULL); 1317 if (status == STATUS_SUCCESS) 1318 { 1319 /* Read dyld image info address from PEB */ 1320 if (ReadProcessMemory(pcs->handle, &pbi.PebBaseAddress->Reserved[0], 1321 &dyld_image_info_address, sizeof(dyld_image_info_address), NULL)) 1322 { 1323 TRACE("got dyld_image_info_address 0x%08lx from PEB %p MacDyldImageInfo %p\n", 1324 (unsigned long)dyld_image_info_address, pbi.PebBaseAddress, &pbi.PebBaseAddress->Reserved); 1325 } 1326 } 1327 1328 #ifndef __LP64__ /* No reading the symtab with nlist(3) in LP64 */ 1329 if (!dyld_image_info_address) 1330 { 1331 static void* dyld_all_image_infos_addr; 1332 1333 /* Our next best guess is that dyld was loaded at its base address 1334 and we can find the dyld image infos address by looking up its symbol. */ 1335 if (!dyld_all_image_infos_addr) 1336 { 1337 struct nlist nl[2]; 1338 memset(nl, 0, sizeof(nl)); 1339 nl[0].n_un.n_name = (char*)"_dyld_all_image_infos"; 1340 if (!nlist("/usr/lib/dyld", nl)) 1341 dyld_all_image_infos_addr = (void*)nl[0].n_value; 1342 } 1343 1344 if (dyld_all_image_infos_addr) 1345 { 1346 TRACE("got dyld_image_info_address %p from /usr/lib/dyld symbol table\n", 1347 dyld_all_image_infos_addr); 1348 dyld_image_info_address = (ULONG_PTR)dyld_all_image_infos_addr; 1349 } 1350 } 1351 #endif 1352 1353 return dyld_image_info_address; 1354 } 1355 1356 /****************************************************************** 1357 * macho_load_file 1358 * 1359 * Loads the information for Mach-O module stored in 'filename'. 1360 * The module has been loaded at 'load_addr' address. 1361 * returns 1362 * FALSE if the file cannot be found/opened or if the file doesn't 1363 * contain symbolic info (or this info cannot be read or parsed) 1364 * TRUE on success 1365 */ 1366 static BOOL macho_load_file(struct process* pcs, const WCHAR* filename, 1367 unsigned long load_addr, struct macho_info* macho_info) 1368 { 1369 BOOL ret = TRUE; 1370 BOOL split_segs; 1371 struct image_file_map fmap; 1372 1373 TRACE("(%p/%p, %s, 0x%08lx, %p/0x%08x)\n", pcs, pcs->handle, debugstr_w(filename), 1374 load_addr, macho_info, macho_info->flags); 1375 1376 split_segs = image_uses_split_segs(pcs->handle, load_addr); 1377 if (!macho_map_file(filename, split_segs, &fmap)) return FALSE; 1378 1379 /* Find the dynamic loader's table of images loaded into the process. 1380 */ 1381 if (macho_info->flags & MACHO_INFO_DEBUG_HEADER) 1382 { 1383 macho_info->dbg_hdr_addr = (unsigned long)get_dyld_image_info_address(pcs); 1384 ret = TRUE; 1385 } 1386 1387 if (macho_info->flags & MACHO_INFO_MODULE) 1388 { 1389 struct macho_module_info *macho_module_info; 1390 struct module_format* modfmt = 1391 HeapAlloc(GetProcessHeap(), 0, sizeof(struct module_format) + sizeof(struct macho_module_info)); 1392 if (!modfmt) goto leave; 1393 if (!load_addr) 1394 load_addr = fmap.u.macho.segs_start; 1395 macho_info->module = module_new(pcs, filename, DMT_MACHO, FALSE, load_addr, 1396 fmap.u.macho.segs_size, 0, calc_crc32(fmap.u.macho.fd)); 1397 if (!macho_info->module) 1398 { 1399 HeapFree(GetProcessHeap(), 0, modfmt); 1400 goto leave; 1401 } 1402 macho_info->module->reloc_delta = macho_info->module->module.BaseOfImage - fmap.u.macho.segs_start; 1403 macho_module_info = (void*)(modfmt + 1); 1404 macho_info->module->format_info[DFI_MACHO] = modfmt; 1405 1406 modfmt->module = macho_info->module; 1407 modfmt->remove = macho_module_remove; 1408 modfmt->loc_compute = NULL; 1409 modfmt->u.macho_info = macho_module_info; 1410 1411 macho_module_info->load_addr = load_addr; 1412 1413 macho_module_info->file_map = fmap; 1414 reset_file_map(&fmap); 1415 if (dbghelp_options & SYMOPT_DEFERRED_LOADS) 1416 macho_info->module->module.SymType = SymDeferred; 1417 else if (!macho_load_debug_info(macho_info->module)) 1418 ret = FALSE; 1419 1420 macho_info->module->format_info[DFI_MACHO]->u.macho_info->in_use = 1; 1421 macho_info->module->format_info[DFI_MACHO]->u.macho_info->is_loader = 0; 1422 TRACE("module = %p\n", macho_info->module); 1423 } 1424 1425 if (macho_info->flags & MACHO_INFO_NAME) 1426 { 1427 WCHAR* ptr; 1428 ptr = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(filename) + 1) * sizeof(WCHAR)); 1429 if (ptr) 1430 { 1431 strcpyW(ptr, filename); 1432 macho_info->module_name = ptr; 1433 } 1434 else ret = FALSE; 1435 TRACE("module_name = %p %s\n", macho_info->module_name, debugstr_w(macho_info->module_name)); 1436 } 1437 leave: 1438 macho_unmap_file(&fmap); 1439 1440 TRACE(" => %d\n", ret); 1441 return ret; 1442 } 1443 1444 /****************************************************************** 1445 * macho_load_file_from_path 1446 * Tries to load a Mach-O file from a set of paths (separated by ':') 1447 */ 1448 static BOOL macho_load_file_from_path(struct process* pcs, 1449 const WCHAR* filename, 1450 unsigned long load_addr, 1451 const char* path, 1452 struct macho_info* macho_info) 1453 { 1454 BOOL ret = FALSE; 1455 WCHAR *s, *t, *fn; 1456 WCHAR* pathW = NULL; 1457 unsigned len; 1458 1459 TRACE("(%p/%p, %s, 0x%08lx, %s, %p)\n", pcs, pcs->handle, debugstr_w(filename), load_addr, 1460 debugstr_a(path), macho_info); 1461 1462 if (!path) return FALSE; 1463 1464 len = MultiByteToWideChar(CP_UNIXCP, 0, path, -1, NULL, 0); 1465 pathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 1466 if (!pathW) return FALSE; 1467 MultiByteToWideChar(CP_UNIXCP, 0, path, -1, pathW, len); 1468 1469 for (s = pathW; s && *s; s = (t) ? (t+1) : NULL) 1470 { 1471 t = strchrW(s, ':'); 1472 if (t) *t = '\0'; 1473 fn = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(filename) + 1 + lstrlenW(s) + 1) * sizeof(WCHAR)); 1474 if (!fn) break; 1475 strcpyW(fn, s); 1476 strcatW(fn, S_SlashW); 1477 strcatW(fn, filename); 1478 ret = macho_load_file(pcs, fn, load_addr, macho_info); 1479 HeapFree(GetProcessHeap(), 0, fn); 1480 if (ret) break; 1481 s = (t) ? (t+1) : NULL; 1482 } 1483 1484 TRACE(" => %d\n", ret); 1485 HeapFree(GetProcessHeap(), 0, pathW); 1486 return ret; 1487 } 1488 1489 /****************************************************************** 1490 * macho_load_file_from_dll_path 1491 * 1492 * Tries to load a Mach-O file from the dll path 1493 */ 1494 static BOOL macho_load_file_from_dll_path(struct process* pcs, 1495 const WCHAR* filename, 1496 unsigned long load_addr, 1497 struct macho_info* macho_info) 1498 { 1499 BOOL ret = FALSE; 1500 unsigned int index = 0; 1501 const char *path; 1502 1503 TRACE("(%p/%p, %s, 0x%08lx, %p)\n", pcs, pcs->handle, debugstr_w(filename), load_addr, 1504 macho_info); 1505 1506 while (!ret && (path = wine_dll_enum_load_path( index++ ))) 1507 { 1508 WCHAR *name; 1509 unsigned len; 1510 1511 len = MultiByteToWideChar(CP_UNIXCP, 0, path, -1, NULL, 0); 1512 1513 name = HeapAlloc( GetProcessHeap(), 0, 1514 (len + lstrlenW(filename) + 2) * sizeof(WCHAR) ); 1515 1516 if (!name) break; 1517 MultiByteToWideChar(CP_UNIXCP, 0, path, -1, name, len); 1518 strcatW( name, S_SlashW ); 1519 strcatW( name, filename ); 1520 ret = macho_load_file(pcs, name, load_addr, macho_info); 1521 HeapFree( GetProcessHeap(), 0, name ); 1522 } 1523 TRACE(" => %d\n", ret); 1524 return ret; 1525 } 1526 1527 /****************************************************************** 1528 * macho_search_and_load_file 1529 * 1530 * Lookup a file in standard Mach-O locations, and if found, load it 1531 */ 1532 static BOOL macho_search_and_load_file(struct process* pcs, const WCHAR* filename, 1533 unsigned long load_addr, 1534 struct macho_info* macho_info) 1535 { 1536 BOOL ret = FALSE; 1537 struct module* module; 1538 static const WCHAR S_libstdcPPW[] = {'l','i','b','s','t','d','c','+','+','\0'}; 1539 const WCHAR* p; 1540 1541 TRACE("(%p/%p, %s, 0x%08lx, %p)\n", pcs, pcs->handle, debugstr_w(filename), load_addr, 1542 macho_info); 1543 1544 if (filename == NULL || *filename == '\0') return FALSE; 1545 if ((module = module_is_already_loaded(pcs, filename))) 1546 { 1547 macho_info->module = module; 1548 module->format_info[DFI_MACHO]->u.macho_info->in_use = 1; 1549 return module->module.SymType; 1550 } 1551 1552 if (strstrW(filename, S_libstdcPPW)) return FALSE; /* We know we can't do it */ 1553 1554 /* If has no directories, try PATH first. */ 1555 if (!strchrW(filename, '/')) 1556 { 1557 ret = macho_load_file_from_path(pcs, filename, load_addr, 1558 getenv("PATH"), macho_info); 1559 } 1560 /* Try DYLD_LIBRARY_PATH, with just the filename (no directories). */ 1561 if (!ret) 1562 { 1563 if ((p = strrchrW(filename, '/'))) p++; 1564 else p = filename; 1565 ret = macho_load_file_from_path(pcs, p, load_addr, 1566 getenv("DYLD_LIBRARY_PATH"), macho_info); 1567 } 1568 /* Try the path as given. */ 1569 if (!ret) 1570 ret = macho_load_file(pcs, filename, load_addr, macho_info); 1571 /* Try DYLD_FALLBACK_LIBRARY_PATH, with just the filename (no directories). */ 1572 if (!ret) 1573 { 1574 const char* fallback = getenv("DYLD_FALLBACK_LIBRARY_PATH"); 1575 if (!fallback) 1576 fallback = "/usr/local/lib:/lib:/usr/lib"; 1577 ret = macho_load_file_from_path(pcs, p, load_addr, fallback, macho_info); 1578 } 1579 if (!ret && !strchrW(filename, '/')) 1580 ret = macho_load_file_from_dll_path(pcs, filename, load_addr, macho_info); 1581 1582 return ret; 1583 } 1584 1585 /****************************************************************** 1586 * macho_enum_modules_internal 1587 * 1588 * Enumerate Mach-O modules from a running process 1589 */ 1590 static BOOL macho_enum_modules_internal(const struct process* pcs, 1591 const WCHAR* main_name, 1592 enum_modules_cb cb, void* user) 1593 { 1594 struct dyld_all_image_infos image_infos; 1595 struct dyld_image_info* info_array = NULL; 1596 unsigned long len; 1597 int i; 1598 char bufstr[256]; 1599 WCHAR bufstrW[MAX_PATH]; 1600 BOOL ret = FALSE; 1601 1602 TRACE("(%p/%p, %s, %p, %p)\n", pcs, pcs->handle, debugstr_w(main_name), cb, 1603 user); 1604 1605 if (!pcs->dbg_hdr_addr || 1606 !ReadProcessMemory(pcs->handle, (void*)pcs->dbg_hdr_addr, 1607 &image_infos, sizeof(image_infos), NULL) || 1608 !image_infos.infoArray) 1609 goto done; 1610 TRACE("Process has %u image infos at %p\n", image_infos.infoArrayCount, image_infos.infoArray); 1611 1612 len = image_infos.infoArrayCount * sizeof(info_array[0]); 1613 info_array = HeapAlloc(GetProcessHeap(), 0, len); 1614 if (!info_array || 1615 !ReadProcessMemory(pcs->handle, image_infos.infoArray, 1616 info_array, len, NULL)) 1617 goto done; 1618 TRACE("... read image infos\n"); 1619 1620 for (i = 0; i < image_infos.infoArrayCount; i++) 1621 { 1622 if (info_array[i].imageFilePath != NULL && 1623 ReadProcessMemory(pcs->handle, info_array[i].imageFilePath, bufstr, sizeof(bufstr), NULL)) 1624 { 1625 bufstr[sizeof(bufstr) - 1] = '\0'; 1626 TRACE("[%d] image file %s\n", i, debugstr_a(bufstr)); 1627 MultiByteToWideChar(CP_UNIXCP, 0, bufstr, -1, bufstrW, sizeof(bufstrW) / sizeof(WCHAR)); 1628 if (main_name && !bufstrW[0]) strcpyW(bufstrW, main_name); 1629 if (!cb(bufstrW, (unsigned long)info_array[i].imageLoadAddress, user)) break; 1630 } 1631 } 1632 1633 ret = TRUE; 1634 done: 1635 HeapFree(GetProcessHeap(), 0, info_array); 1636 return ret; 1637 } 1638 1639 struct macho_sync 1640 { 1641 struct process* pcs; 1642 struct macho_info macho_info; 1643 }; 1644 1645 static BOOL macho_enum_sync_cb(const WCHAR* name, unsigned long addr, void* user) 1646 { 1647 struct macho_sync* ms = user; 1648 1649 TRACE("(%s, 0x%08lx, %p)\n", debugstr_w(name), addr, user); 1650 macho_search_and_load_file(ms->pcs, name, addr, &ms->macho_info); 1651 return TRUE; 1652 } 1653 1654 /****************************************************************** 1655 * macho_synchronize_module_list 1656 * 1657 * Rescans the debuggee's modules list and synchronizes it with 1658 * the one from 'pcs', ie: 1659 * - if a module is in debuggee and not in pcs, it's loaded into pcs 1660 * - if a module is in pcs and not in debuggee, it's unloaded from pcs 1661 */ 1662 BOOL macho_synchronize_module_list(struct process* pcs) 1663 { 1664 struct module* module; 1665 struct macho_sync ms; 1666 1667 TRACE("(%p/%p)\n", pcs, pcs->handle); 1668 1669 for (module = pcs->lmodules; module; module = module->next) 1670 { 1671 if (module->type == DMT_MACHO && !module->is_virtual) 1672 module->format_info[DFI_MACHO]->u.macho_info->in_use = 0; 1673 } 1674 1675 ms.pcs = pcs; 1676 ms.macho_info.flags = MACHO_INFO_MODULE; 1677 if (!macho_enum_modules_internal(pcs, NULL, macho_enum_sync_cb, &ms)) 1678 return FALSE; 1679 1680 module = pcs->lmodules; 1681 while (module) 1682 { 1683 if (module->type == DMT_MACHO && !module->is_virtual && 1684 !module->format_info[DFI_MACHO]->u.macho_info->in_use && 1685 !module->format_info[DFI_MACHO]->u.macho_info->is_loader) 1686 { 1687 module_remove(pcs, module); 1688 /* restart all over */ 1689 module = pcs->lmodules; 1690 } 1691 else module = module->next; 1692 } 1693 return TRUE; 1694 } 1695 1696 /****************************************************************** 1697 * macho_search_loader 1698 * 1699 * Lookup in a running Mach-O process the loader, and sets its Mach-O link 1700 * address (for accessing the list of loaded images) in pcs. 1701 * If flags is MACHO_INFO_MODULE, the module for the loader is also 1702 * added as a module into pcs. 1703 */ 1704 static BOOL macho_search_loader(struct process* pcs, struct macho_info* macho_info) 1705 { 1706 BOOL ret = FALSE; 1707 ULONG_PTR dyld_image_info_address; 1708 struct dyld_all_image_infos image_infos; 1709 struct dyld_image_info image_info; 1710 uint32_t len; 1711 char path[PATH_MAX]; 1712 BOOL got_path = FALSE; 1713 1714 dyld_image_info_address = get_dyld_image_info_address(pcs); 1715 if (dyld_image_info_address && 1716 ReadProcessMemory(pcs->handle, (void*)dyld_image_info_address, &image_infos, sizeof(image_infos), NULL) && 1717 image_infos.infoArray && image_infos.infoArrayCount && 1718 ReadProcessMemory(pcs->handle, image_infos.infoArray, &image_info, sizeof(image_info), NULL) && 1719 image_info.imageFilePath) 1720 { 1721 for (len = sizeof(path); len > 0; len /= 2) 1722 { 1723 if (ReadProcessMemory(pcs->handle, image_info.imageFilePath, path, len, NULL)) 1724 { 1725 path[len - 1] = 0; 1726 got_path = TRUE; 1727 TRACE("got executable path from target's dyld image info: %s\n", debugstr_a(path)); 1728 break; 1729 } 1730 } 1731 } 1732 1733 /* If we couldn't get the executable path from the target process, try our 1734 own. It will almost always be the same. */ 1735 if (!got_path) 1736 { 1737 len = sizeof(path); 1738 if (!_NSGetExecutablePath(path, &len)) 1739 { 1740 got_path = TRUE; 1741 TRACE("using own executable path: %s\n", debugstr_a(path)); 1742 } 1743 } 1744 1745 if (got_path) 1746 { 1747 WCHAR* pathW; 1748 1749 len = MultiByteToWideChar(CP_UNIXCP, 0, path, -1, NULL, 0); 1750 pathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 1751 if (pathW) 1752 { 1753 MultiByteToWideChar(CP_UNIXCP, 0, path, -1, pathW, len); 1754 ret = macho_load_file(pcs, pathW, 0, macho_info); 1755 HeapFree(GetProcessHeap(), 0, pathW); 1756 } 1757 } 1758 1759 if (!ret) 1760 ret = macho_search_and_load_file(pcs, get_wine_loader_name(), 0, macho_info); 1761 return ret; 1762 } 1763 1764 /****************************************************************** 1765 * macho_read_wine_loader_dbg_info 1766 * 1767 * Try to find a decent wine executable which could have loaded the debuggee 1768 */ 1769 BOOL macho_read_wine_loader_dbg_info(struct process* pcs) 1770 { 1771 struct macho_info macho_info; 1772 1773 TRACE("(%p/%p)\n", pcs, pcs->handle); 1774 macho_info.flags = MACHO_INFO_DEBUG_HEADER | MACHO_INFO_MODULE; 1775 if (!macho_search_loader(pcs, &macho_info)) return FALSE; 1776 macho_info.module->format_info[DFI_MACHO]->u.macho_info->is_loader = 1; 1777 module_set_module(macho_info.module, S_WineLoaderW); 1778 return (pcs->dbg_hdr_addr = macho_info.dbg_hdr_addr) != 0; 1779 } 1780 1781 /****************************************************************** 1782 * macho_enum_modules 1783 * 1784 * Enumerates the Mach-O loaded modules from a running target (hProc) 1785 * This function doesn't require that someone has called SymInitialize 1786 * on this very process. 1787 */ 1788 BOOL macho_enum_modules(HANDLE hProc, enum_modules_cb cb, void* user) 1789 { 1790 struct process pcs; 1791 struct macho_info macho_info; 1792 BOOL ret; 1793 1794 TRACE("(%p, %p, %p)\n", hProc, cb, user); 1795 memset(&pcs, 0, sizeof(pcs)); 1796 pcs.handle = hProc; 1797 macho_info.flags = MACHO_INFO_DEBUG_HEADER | MACHO_INFO_NAME; 1798 if (!macho_search_loader(&pcs, &macho_info)) return FALSE; 1799 pcs.dbg_hdr_addr = macho_info.dbg_hdr_addr; 1800 ret = macho_enum_modules_internal(&pcs, macho_info.module_name, cb, user); 1801 HeapFree(GetProcessHeap(), 0, (char*)macho_info.module_name); 1802 return ret; 1803 } 1804 1805 struct macho_load 1806 { 1807 struct process* pcs; 1808 struct macho_info macho_info; 1809 const WCHAR* name; 1810 BOOL ret; 1811 }; 1812 1813 /****************************************************************** 1814 * macho_load_cb 1815 * 1816 * Callback for macho_load_module, used to walk the list of loaded 1817 * modules. 1818 */ 1819 static BOOL macho_load_cb(const WCHAR* name, unsigned long addr, void* user) 1820 { 1821 struct macho_load* ml = user; 1822 const WCHAR* p; 1823 1824 TRACE("(%s, 0x%08lx, %p)\n", debugstr_w(name), addr, user); 1825 1826 /* memcmp is needed for matches when bufstr contains also version information 1827 * ml->name: libc.so, name: libc.so.6.0 1828 */ 1829 p = strrchrW(name, '/'); 1830 if (!p++) p = name; 1831 if (!memcmp(p, ml->name, lstrlenW(ml->name) * sizeof(WCHAR))) 1832 { 1833 ml->ret = macho_search_and_load_file(ml->pcs, name, addr, &ml->macho_info); 1834 return FALSE; 1835 } 1836 return TRUE; 1837 } 1838 1839 /****************************************************************** 1840 * macho_load_module 1841 * 1842 * Loads a Mach-O module and stores it in process' module list. 1843 * Also, find module real name and load address from 1844 * the real loaded modules list in pcs address space. 1845 */ 1846 struct module* macho_load_module(struct process* pcs, const WCHAR* name, unsigned long addr) 1847 { 1848 struct macho_load ml; 1849 1850 TRACE("(%p/%p, %s, 0x%08lx)\n", pcs, pcs->handle, debugstr_w(name), addr); 1851 1852 ml.macho_info.flags = MACHO_INFO_MODULE; 1853 ml.ret = FALSE; 1854 1855 if (pcs->dbg_hdr_addr) /* we're debugging a live target */ 1856 { 1857 ml.pcs = pcs; 1858 /* do only the lookup from the filename, not the path (as we lookup module 1859 * name in the process' loaded module list) 1860 */ 1861 ml.name = strrchrW(name, '/'); 1862 if (!ml.name++) ml.name = name; 1863 ml.ret = FALSE; 1864 1865 if (!macho_enum_modules_internal(pcs, NULL, macho_load_cb, &ml)) 1866 return NULL; 1867 } 1868 else if (addr) 1869 { 1870 ml.name = name; 1871 ml.ret = macho_search_and_load_file(pcs, ml.name, addr, &ml.macho_info); 1872 } 1873 if (!ml.ret) return NULL; 1874 assert(ml.macho_info.module); 1875 return ml.macho_info.module; 1876 } 1877 1878 #else /* HAVE_MACH_O_LOADER_H */ 1879 1880 BOOL macho_find_section(struct image_file_map* ifm, const char* segname, const char* sectname, struct image_section_map* ism) 1881 { 1882 return FALSE; 1883 } 1884 1885 const char* macho_map_section(struct image_section_map* ism) 1886 { 1887 return NULL; 1888 } 1889 1890 void macho_unmap_section(struct image_section_map* ism) 1891 { 1892 } 1893 1894 DWORD_PTR macho_get_map_rva(const struct image_section_map* ism) 1895 { 1896 return 0; 1897 } 1898 1899 unsigned macho_get_map_size(const struct image_section_map* ism) 1900 { 1901 return 0; 1902 } 1903 1904 BOOL macho_synchronize_module_list(struct process* pcs) 1905 { 1906 return FALSE; 1907 } 1908 1909 BOOL macho_fetch_file_info(HANDLE process, const WCHAR* name, unsigned long load_addr, DWORD_PTR* base, 1910 DWORD* size, DWORD* checksum) 1911 { 1912 return FALSE; 1913 } 1914 1915 BOOL macho_read_wine_loader_dbg_info(struct process* pcs) 1916 { 1917 return FALSE; 1918 } 1919 1920 BOOL macho_enum_modules(HANDLE hProc, enum_modules_cb cb, void* user) 1921 { 1922 return FALSE; 1923 } 1924 1925 struct module* macho_load_module(struct process* pcs, const WCHAR* name, unsigned long addr) 1926 { 1927 return NULL; 1928 } 1929 1930 BOOL macho_load_debug_info(struct module* module) 1931 { 1932 return FALSE; 1933 } 1934 #endif /* HAVE_MACH_O_LOADER_H */ 1935