ReactOS  0.4.13-dev-698-g77671f0
macho_module.c
Go to the documentation of this file.
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 {
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  */
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 = &section[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 
635  if (!(filename = HeapAlloc(GetProcessHeap(), 0, len)))
636  {
637  WARN("failed to allocate filename buffer\n");
638  return FALSE;
639  }
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);
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)
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,
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",
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,
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 */
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. */
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  */
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",
1025  ste->ht_elt.name, ste->addr,
1026  sym->hash_elt.name,
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
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;
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  */
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 
1238 
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  */
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;
1313  ULONG_PTR dyld_image_info_address = 0;
1314 
1315  /* Get address of PEB */
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;
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);
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,
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;
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;
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  */
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  */
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  */
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 
1891 {
1892 }
1893 
1895 {
1896  return 0;
1897 }
1898 
1899 unsigned macho_get_map_size(const struct image_section_map* ism)
1900 {
1901  return 0;
1902 }
1903 
1905 {
1906  return FALSE;
1907 }
1908 
1910  DWORD* size, DWORD* checksum)
1911 {
1912  return FALSE;
1913 }
1914 
1916 {
1917  return FALSE;
1918 }
1919 
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 
1931 {
1932  return FALSE;
1933 }
1934 #endif /* HAVE_MACH_O_LOADER_H */
union image_file_map::@363 u
void(* remove)(struct process *pcs, struct module_format *modfmt)
BOOL symt_get_address(const struct symt *type, ULONG64 *addr) DECLSPEC_HIDDEN
Definition: type.c:120
GLenum func
Definition: glext.h:6028
unsigned addr_size
Definition: image_private.h:90
void module_set_module(struct module *module, const WCHAR *name) DECLSPEC_HIDDEN
Definition: module.c:103
enum module_type modtype
Definition: image_private.h:89
struct module * module_new(struct process *pcs, const WCHAR *name, enum module_type type, BOOL virtual, DWORD64 addr, DWORD64 size, unsigned long stamp, unsigned long checksum) DECLSPEC_HIDDEN
Definition: module.c:163
struct hash_table_elt hash_elt
#define TRUE
Definition: types.h:120
HMODULE module
Definition: main.cpp:47
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
#define WideCharToMultiByte
Definition: compat.h:101
WCHAR ModuleName[32]
Definition: compat.h:725
static LPCWSTR LPCWSTR module_name
Definition: db.cpp:168
#define open
Definition: acwin.h:95
Definition: ftp_var.h:139
static GLenum _GLUfuncptr fn
Definition: wgl_font.c:159
GLsizei const GLchar ** path
Definition: glext.h:7234
WINE_UNICODE_INLINE WCHAR * strchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:248
GLuint GLuint GLsizei count
Definition: gl.h:1545
int ignore(int trapCode, ppc_trap_frame_t *trap)
Definition: mmuobject.c:296
struct hash_table ht_symbols
#define WARN(fmt,...)
Definition: debug.h:111
static const char * format_uuid(const UUID *uuid)
Definition: register.c:43
void macho_unmap_section(struct image_section_map *ism)
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS NTAPI NtQueryInformationProcess(IN HANDLE ProcessHandle, IN PROCESSINFOCLASS ProcessInformationClass, OUT PVOID ProcessInformation, IN ULONG ProcessInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: query.c:59
GLintptr offset
Definition: glext.h:5920
struct image_file_map * fmap
GLdouble GLdouble t
Definition: gl.h:2047
#define assert(x)
Definition: debug.h:53
const WCHAR S_SlashW[]
Definition: module.c:43
#define ReadProcessMemory(a, b, c, d, e)
Definition: compat.h:415
_Check_return_opt_ _CRTIMP long __cdecl lseek(_In_ int _FileHandle, _In_ long _Offset, _In_ int _Origin)
DWORD calc_crc32(int fd)
Definition: crc32.c:89
int errno
Definition: parser.c:55
DataKind
Definition: compat.h:1287
const char * filename
Definition: ioapi.h:135
union module_format::@356 u
#define lstrlenW
Definition: compat.h:407
int load_addr
Definition: mkisofs.c:104
BOOL(* enum_modules_cb)(const WCHAR *, unsigned long addr, void *user)
BOOL macho_find_section(struct image_file_map *ifm, const char *segname, const char *sectname, struct image_section_map *ism)
const char * strerror(int err)
Definition: compat_str.c:23
static IMAGE_SECTION_HEADER section
Definition: loader.c:152
#define SYMOPT_DEFERRED_LOADS
Definition: compat.h:638
enum module_type type
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define IMAGE_NO_MAP
Definition: image_private.h:59
static const WCHAR filenameW[]
Definition: amstream.c:41
#define sprintf(buf, format,...)
Definition: sprintf.c:55
void * pool_alloc(struct pool *a, size_t len) DECLSPEC_HIDDEN
Definition: storage.c:90
WCHAR LoadedImageName[256]
Definition: compat.h:727
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
struct module * lmodules
unsigned int BOOL
Definition: ntddk_ex.h:94
int sortlist_valid
#define debugstr_w
Definition: kernel32.h:32
struct symt_public * symt_new_public(struct module *module, struct symt_compiland *parent, const char *typename, BOOL is_function, unsigned long address, unsigned size) DECLSPEC_HIDDEN
Definition: symbol.c:226
#define FIXME(fmt,...)
Definition: debug.h:110
unsigned int uintptr_t
Definition: crtdefs.h:300
static PVOID ptr
Definition: dispmode.c:27
BOOL stabs_parse(struct module *module, unsigned long load_offset, const void *stabs, int stablen, const char *strs, int strtablen, stabs_def_cb callback, void *user) DECLSPEC_HIDDEN
Definition: stabs.c:1275
void hash_table_iter_init(const struct hash_table *ht, struct hash_table_iter *hti, const char *name) DECLSPEC_HIDDEN
Definition: storage.c:406
#define strstrW(d, s)
Definition: unicode.h:32
smooth NULL
Definition: ftsmooth.c:416
static const WCHAR version[]
Definition: asmname.c:64
_Inout_ PERBANDINFO * pbi
Definition: winddi.h:3917
struct macho_module_info * macho_info
BOOL macho_read_wine_loader_dbg_info(struct process *pcs)
GLuint index
Definition: glext.h:6031
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
struct module * module_is_already_loaded(const struct process *pcs, const WCHAR *imgname) DECLSPEC_HIDDEN
Definition: module.c:268
struct symt_data * symt_new_global_variable(struct module *module, struct symt_compiland *parent, const char *name, unsigned is_static, struct location loc, unsigned long size, struct symt *type) DECLSPEC_HIDDEN
Definition: symbol.c:258
c used
Definition: write.c:2885
BOOL macho_load_debug_info(struct module *module)
#define SEEK_SET
Definition: jmemansi.c:26
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
DWORD64 reloc_delta
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
#define CP_UNIXCP
Definition: compat.h:69
void(* loc_compute)(struct process *pcs, const struct module_format *modfmt, const struct symt_function *func, struct location *loc)
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define debugstr_a
Definition: kernel32.h:31
#define S_ISDIR(mode)
Definition: various.h:18
#define MAX_PATH
Definition: compat.h:26
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
static FILE * out
Definition: regtests2xml.c:44
unsigned dbghelp_options
Definition: dbghelp.c:72
unsigned long DWORD
Definition: ntddk_ex.h:95
#define PATH_MAX
Definition: types.h:280
void hash_table_add(struct hash_table *ht, struct hash_table_elt *elt) DECLSPEC_HIDDEN
Definition: storage.c:379
struct symt symt
static DWORD cb
Definition: integrity.c:41
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define MAP_FAILED
GLbitfield flags
Definition: glext.h:7161
unsigned __int64 ULONG64
Definition: imports.h:198
int ret
void pool_init(struct pool *a, size_t arena_size) DECLSPEC_HIDDEN
Definition: storage.c:44
SYM_TYPE SymType
Definition: compat.h:724
GLenum const GLvoid * addr
Definition: glext.h:9621
static const WCHAR L[]
Definition: oid.c:1250
unsigned long dbg_hdr_addr
const WCHAR * get_wine_loader_name(void) DECLSPEC_HIDDEN
Definition: module.c:110
static __inline const char * debugstr_an(const char *s, int n)
Definition: compat.h:47
Definition: stat.h:55
GLenum GLsizei len
Definition: glext.h:6722
GLdouble s
Definition: gl.h:2039
void * hash_table_iter_up(struct hash_table_iter *hti) DECLSPEC_HIDDEN
Definition: storage.c:423
static cab_ULONG checksum(const cab_UBYTE *data, cab_UWORD bytes, cab_ULONG csum)
Definition: fdi.c:353
#define close
Definition: acwin.h:98
uint32_t DWORD_PTR
Definition: typedefs.h:63
BYTE uint8_t
Definition: msvideo1.c:66
char * pool_strdup(struct pool *a, const char *str) DECLSPEC_HIDDEN
Definition: storage.c:127
static UINT_PTR page_mask
Definition: virtual.c:49
WINE_UNICODE_INLINE WCHAR * strrchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:254
#define ERR(fmt,...)
Definition: debug.h:109
unsigned kind
_CRTIMP int __cdecl stat(const char *_Filename, struct stat *_Stat)
Definition: stat.h:345
static const char * uuid_string(const UUID *uuid)
Definition: header.c:146
WINE_UNICODE_INLINE WCHAR * strcpyW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:219
static unsigned __int64 next
Definition: rand_nt.c:6
_Check_return_ char *__cdecl getenv(_In_z_ const char *_VarName)
BOOL symt_get_info(struct module *module, const struct symt *type, IMAGEHLP_SYMBOL_TYPE_INFO req, void *pInfo) DECLSPEC_HIDDEN
Definition: type.c:537
static ATOM item
Definition: dde.c:856
void pool_destroy(struct pool *a) DECLSPEC_HIDDEN
Definition: storage.c:51
const char cursor[]
Definition: icontest.c:13
struct symt_function * symt_new_function(struct module *module, struct symt_compiland *parent, const char *name, unsigned long addr, unsigned long size, struct symt *type) DECLSPEC_HIDDEN
Definition: symbol.c:295
unsigned macho_get_map_size(const struct image_section_map *ism)
const WCHAR S_WineLoaderW[]
Definition: module.c:38
unsigned short is_virtual
#define long
Definition: qsort.c:33
DWORD_PTR macho_get_map_rva(const struct image_section_map *ism)
Definition: services.c:325
WINE_UNICODE_INLINE WCHAR * strcatW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:242
BOOL macho_enum_modules(HANDLE hProc, enum_modules_cb cb, void *user)
BOOL module_remove(struct process *pcs, struct module *module) DECLSPEC_HIDDEN
Definition: module.c:684
struct hash_table_elt hash_elt
BOOL dwarf2_parse(struct module *module, unsigned long load_offset, const struct elf_thunk_area *thunks, struct image_file_map *fmap) DECLSPEC_HIDDEN
Definition: dwarf.c:3522
#define lstrcpynA
Definition: compat.h:408
UINT32 uint32_t
Definition: types.h:75
struct module * module
#define MultiByteToWideChar
Definition: compat.h:100
void hash_table_init(struct pool *pool, struct hash_table *ht, unsigned num_buckets) DECLSPEC_HIDDEN
Definition: storage.c:335
Definition: name.c:36
#define SYMOPT_PUBLICS_ONLY
Definition: compat.h:641
Definition: msctf.idl:510
HANDLE handle
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:41
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define ULONG_PTR
Definition: config.h:101
struct image_file_map::@363::macho_file_map macho
#define SYMOPT_NO_PUBLICS
Definition: compat.h:642
BOOL macho_fetch_file_info(HANDLE process, const WCHAR *name, unsigned long load_addr, DWORD_PTR *base, DWORD *size, DWORD *checksum)
GLfloat GLfloat p
Definition: glext.h:8902
return STATUS_SUCCESS
Definition: btrfs.c:2777
BOOL macho_synchronize_module_list(struct process *pcs)
GLuint64EXT * result
Definition: glext.h:11304
#define memset(x, y, z)
Definition: compat.h:39
static SERVICE_STATUS status
Definition: service.c:31
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
IMAGEHLP_MODULEW64 module
struct module_format * format_info[DFI_LAST]
void user(int argc, const char *argv[])
Definition: cmds.c:1350
struct module * next
#define HeapFree(x, y, z)
Definition: compat.h:394
const char * macho_map_section(struct image_section_map *ism)
struct CFHEADER header
Definition: fdi.c:109
struct image_file_map * dsym
struct module * macho_load_module(struct process *pcs, const WCHAR *name, unsigned long addr)
_CRTIMP int __cdecl read(_In_ int _FileHandle, _Out_writes_bytes_(_MaxCharCount) void *_DstBuf, _In_ unsigned int _MaxCharCount)
struct symt_ht * symt_find_nearest(struct module *module, DWORD_PTR addr) DECLSPEC_HIDDEN
Definition: symbol.c:905
#define O_RDONLY
Definition: acwin.h:108
Definition: ps.c:97
GLuint const GLchar * name
Definition: glext.h:6031