ReactOS  0.4.15-dev-1171-gab82533
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 <stdio.h>
25 #include <assert.h>
26 #include <stdarg.h>
27 #include <errno.h>
28 
29 #include "ntstatus.h"
30 #define WIN32_NO_STATUS
31 #include "dbghelp_private.h"
32 #include "image_private.h"
33 
34 #include "winternl.h"
35 #include "winioctl.h"
36 #define WINE_MOUNTMGR_EXTENSIONS
37 #include "ddk/mountmgr.h"
38 
39 #include "wine/debug.h"
40 #include "wine/heap.h"
41 
43 {
44  UINT32 imageLoadAddress; /* const struct mach_header* */
45  UINT32 imageFilePath; /* const char* */
46  UINT32 imageFileModDate; /* uintptr_t */
47 };
48 
50 {
53  UINT32 infoArray; /* const struct dyld_image_info* */
54 };
55 
57 {
58  UINT64 imageLoadAddress; /* const struct mach_header* */
59  UINT64 imageFilePath; /* const char* */
60  UINT64 imageFileModDate; /* uintptr_t */
61 };
62 
64 {
67  UINT64 infoArray; /* const struct dyld_image_info* */
68 };
69 
73 };
74 
78 };
79 
81 {
82  UINT32 magic; /* mach magic number identifier */
83  UINT32 cputype; /* cpu specifier */
84  UINT32 cpusubtype; /* machine specifier */
85  UINT32 filetype; /* type of file */
86  UINT32 ncmds; /* number of load commands */
87  UINT32 sizeofcmds; /* the size of all the load commands */
88  UINT32 flags; /* flags */
89  UINT32 reserved; /* reserved */
90 };
91 
93 {
94  UINT32 cmd; /* LC_SEGMENT_64 */
95  UINT32 cmdsize; /* includes sizeof section_64 structs */
96  char segname[16]; /* segment name */
97  UINT64 vmaddr; /* memory address of this segment */
98  UINT64 vmsize; /* memory size of this segment */
99  UINT64 fileoff; /* file offset of this segment */
100  UINT64 filesize; /* amount to map from the file */
101  UINT32 maxprot; /* maximum VM protection */
102  UINT32 initprot; /* initial VM protection */
103  UINT32 nsects; /* number of sections in segment */
104  UINT32 flags; /* flags */
105 };
106 
108 {
109  UINT32 cmd; /* LC_SEGMENT */
110  UINT32 cmdsize; /* includes sizeof section structs */
111  char segname[16]; /* segment name */
112  UINT32 vmaddr; /* memory address of this segment */
113  UINT32 vmsize; /* memory size of this segment */
114  UINT32 fileoff; /* file offset of this segment */
115  UINT32 filesize; /* amount to map from the file */
116  UINT32 maxprot; /* maximum VM protection */
117  UINT32 initprot; /* initial VM protection */
118  UINT32 nsects; /* number of sections in segment */
119  UINT32 flags; /* flags */
120 };
121 
123 {
124  UINT32 cmd; /* LC_SYMTAB */
125  UINT32 cmdsize; /* sizeof(struct symtab_command) */
126  UINT32 symoff; /* symbol table offset */
127  UINT32 nsyms; /* number of symbol table entries */
128  UINT32 stroff; /* string table offset */
129  UINT32 strsize; /* string table size in bytes */
130 };
131 
132 #ifdef WORDS_BIGENDIAN
133 #define swap_ulong_be_to_host(n) (n)
134 #else
135 #define swap_ulong_be_to_host(n) (RtlUlongByteSwap(n))
136 #endif
137 
138 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_macho);
139 
140 
141 /* Bitmask for Mach-O image header flags indicating that the image is in dyld's
142  shared cached. That implies that its segments are mapped non-contiguously.
143  This value isn't defined anywhere in headers. It's used in dyld and in
144  debuggers which support OS X as a magic number.
145 
146  The flag also isn't set in the on-disk image file. It's only set in
147  memory by dyld. */
148 #define MACHO_DYLD_IN_SHARED_CACHE 0x80000000
149 
150 #define MACHO_FAT_MAGIC 0xcafebabe
151 #define MACHO_MH_MAGIC_32 0xfeedface
152 #define MACHO_MH_MAGIC_64 0xfeedfacf
153 
154 #define MACHO_CPU_TYPE_X86 0x00000007
155 #define MACHO_CPU_TYPE_X86_64 0x01000007
156 
157 #define MACHO_MH_EXECUTE 0x2
158 #define MACHO_MH_DYLIB 0x6
159 #define MACHO_MH_DYLINKER 0x7
160 #define MACHO_MH_BUNDLE 0x8
161 #define MACHO_MH_DSYM 0xa
162 
163 #define MACHO_LC_SEGMENT 0x01
164 #define MACHO_LC_SYMTAB 0x02
165 #define MACHO_LC_SEGMENT_64 0x19
166 #define MACHO_LC_UUID 0x1b
167 
168 #define MACHO_SECTION_TYPE 0x000000ff
169 #define MACHO_S_ATTR_PURE_INSTRUCTIONS 0x80000000
170 #define MACHO_S_ATTR_SOME_INSTRUCTIONS 0x00000400
171 
172 #define UUID_STRING_LEN 37 /* 16 bytes at 2 hex digits apiece, 4 dashes, and the null terminator */
173 
174 
176 {
179  unsigned short in_use : 1,
180  is_loader : 1;
181 };
182 
184 {
186  unsigned int section_index;
187 };
188 
189 #define MACHO_INFO_MODULE 0x0001
190 #define MACHO_INFO_NAME 0x0002
191 
193 {
194  unsigned flags; /* IN one (or several) of the MACHO_INFO constants */
195  struct module* module; /* OUT loaded module (if MACHO_INFO_MODULE is set) */
196  const WCHAR* module_name; /* OUT found module name (if MACHO_INFO_NAME is set) */
197 };
198 
199 static void macho_unmap_file(struct image_file_map* fmap);
200 
201 static char* format_uuid(const UINT8 uuid[16], char out[UUID_STRING_LEN])
202 {
203  sprintf(out, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
204  uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
205  uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
206  return out;
207 }
208 
209 /******************************************************************
210  * macho_calc_range
211  *
212  * For a range (offset & length) of a single architecture within
213  * a Mach-O file, calculate the page-aligned range of the whole file
214  * that encompasses it. For a fat binary, the architecture will
215  * itself be offset within the file, so take that into account.
216  */
217 static void macho_calc_range(const struct macho_file_map* fmap, ULONG_PTR offset,
218  ULONG_PTR len, ULONG_PTR* out_aligned_offset,
219  ULONG_PTR* out_aligned_end, ULONG_PTR* out_misalign)
220 {
221  ULONG_PTR pagemask;
222  ULONG_PTR file_offset, misalign;
223 
224  pagemask = sysinfo.dwAllocationGranularity - 1;
225  file_offset = fmap->arch_offset + offset;
226  misalign = file_offset & pagemask;
227  *out_aligned_offset = file_offset - misalign;
228  *out_aligned_end = file_offset + len;
229  if (out_misalign)
230  *out_misalign = misalign;
231 }
232 
233 /******************************************************************
234  * macho_map_range
235  *
236  * Maps a range (offset, length in bytes) from a Mach-O file into memory
237  */
238 static const char* macho_map_range(const struct macho_file_map* fmap, ULONG_PTR offset, ULONG_PTR len,
239  const char** base)
240 {
241  ULONG_PTR misalign, aligned_offset, aligned_map_end;
242  const void* aligned_ptr;
243  HANDLE mapping;
244 
245  TRACE("(%p/%p, 0x%08lx, 0x%08lx)\n", fmap, fmap->handle, offset, len);
246 
247  macho_calc_range(fmap, offset, len, &aligned_offset, &aligned_map_end, &misalign);
248 
249  if (!(mapping = CreateFileMappingW(fmap->handle, NULL, PAGE_READONLY, 0, 0, NULL)))
250  {
251  ERR("map creation %p failed %u size %lu\n", fmap->handle, GetLastError(), aligned_map_end);
252  return IMAGE_NO_MAP;
253  }
254  aligned_ptr = MapViewOfFile(mapping, FILE_MAP_READ, 0, aligned_offset, aligned_map_end - aligned_offset);
256  if (!aligned_ptr)
257  {
258  ERR("map failed %u\n", GetLastError());
259  return IMAGE_NO_MAP;
260  }
261 
262  TRACE("Mapped (0x%08lx - 0x%08lx) to %p\n", aligned_offset, aligned_map_end, aligned_ptr);
263 
264  if (base)
265  *base = aligned_ptr;
266  return (const char*)aligned_ptr + misalign;
267 }
268 
269 /******************************************************************
270  * macho_unmap_range
271  *
272  * Unmaps a range (offset, length in bytes) of a Mach-O file from memory
273  */
274 static void macho_unmap_range(const char** base, const void** mapped, const struct macho_file_map* fmap,
276 {
277  TRACE("(%p, %p, %p/%p, 0x%08lx, 0x%08lx)\n", base, mapped, fmap, fmap->handle, offset, len);
278 
279  if ((mapped && *mapped != IMAGE_NO_MAP) || (base && *base != IMAGE_NO_MAP))
280  {
281  ULONG_PTR misalign, aligned_offset, aligned_map_end;
282  void* aligned_ptr;
283 
284  macho_calc_range(fmap, offset, len, &aligned_offset, &aligned_map_end, &misalign);
285 
286  if (mapped)
287  aligned_ptr = (char*)*mapped - misalign;
288  else
289  aligned_ptr = (void*)*base;
290  if (!UnmapViewOfFile(aligned_ptr))
291  WARN("Couldn't unmap the range\n");
292  if (mapped)
293  *mapped = IMAGE_NO_MAP;
294  if (base)
295  *base = IMAGE_NO_MAP;
296  }
297 }
298 
299 /******************************************************************
300  * macho_map_ranges
301  *
302  * Maps two ranges (offset, length in bytes) from a Mach-O file
303  * into memory. If the two ranges overlap, use one mmap so that
304  * the munmap doesn't fragment the mapping.
305  */
306 static BOOL macho_map_ranges(const struct macho_file_map* fmap,
307  ULONG_PTR offset1, ULONG_PTR len1,
308  ULONG_PTR offset2, ULONG_PTR len2,
309  const void** mapped1, const void** mapped2)
310 {
311  ULONG_PTR aligned_offset1, aligned_map_end1;
312  ULONG_PTR aligned_offset2, aligned_map_end2;
313 
314  TRACE("(%p/%p, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, %p, %p)\n", fmap, fmap->handle,
315  offset1, len1, offset2, len2, mapped1, mapped2);
316 
317  macho_calc_range(fmap, offset1, len1, &aligned_offset1, &aligned_map_end1, NULL);
318  macho_calc_range(fmap, offset2, len2, &aligned_offset2, &aligned_map_end2, NULL);
319 
320  if (aligned_map_end1 < aligned_offset2 || aligned_map_end2 < aligned_offset1)
321  {
322  *mapped1 = macho_map_range(fmap, offset1, len1, NULL);
323  if (*mapped1 != IMAGE_NO_MAP)
324  {
325  *mapped2 = macho_map_range(fmap, offset2, len2, NULL);
326  if (*mapped2 == IMAGE_NO_MAP)
327  macho_unmap_range(NULL, mapped1, fmap, offset1, len1);
328  }
329  }
330  else
331  {
332  if (offset1 < offset2)
333  {
334  *mapped1 = macho_map_range(fmap, offset1, offset2 + len2 - offset1, NULL);
335  if (*mapped1 != IMAGE_NO_MAP)
336  *mapped2 = (const char*)*mapped1 + offset2 - offset1;
337  }
338  else
339  {
340  *mapped2 = macho_map_range(fmap, offset2, offset1 + len1 - offset2, NULL);
341  if (*mapped2 != IMAGE_NO_MAP)
342  *mapped1 = (const char*)*mapped2 + offset1 - offset2;
343  }
344  }
345 
346  TRACE(" => %p, %p\n", *mapped1, *mapped2);
347 
348  return (*mapped1 != IMAGE_NO_MAP) && (*mapped2 != IMAGE_NO_MAP);
349 }
350 
351 /******************************************************************
352  * macho_unmap_ranges
353  *
354  * Unmaps two ranges (offset, length in bytes) of a Mach-O file
355  * from memory. Use for ranges which were mapped by
356  * macho_map_ranges.
357  */
358 static void macho_unmap_ranges(const struct macho_file_map* fmap,
359  ULONG_PTR offset1, ULONG_PTR len1,
360  ULONG_PTR offset2, ULONG_PTR len2,
361  const void** mapped1, const void** mapped2)
362 {
363  ULONG_PTR aligned_offset1, aligned_map_end1;
364  ULONG_PTR aligned_offset2, aligned_map_end2;
365 
366  TRACE("(%p/%p, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, %p/%p, %p/%p)\n", fmap, fmap->handle,
367  offset1, len1, offset2, len2, mapped1, *mapped1, mapped2, *mapped2);
368 
369  macho_calc_range(fmap, offset1, len1, &aligned_offset1, &aligned_map_end1, NULL);
370  macho_calc_range(fmap, offset2, len2, &aligned_offset2, &aligned_map_end2, NULL);
371 
372  if (aligned_map_end1 < aligned_offset2 || aligned_map_end2 < aligned_offset1)
373  {
374  macho_unmap_range(NULL, mapped1, fmap, offset1, len1);
375  macho_unmap_range(NULL, mapped2, fmap, offset2, len2);
376  }
377  else
378  {
379  if (offset1 < offset2)
380  {
381  macho_unmap_range(NULL, mapped1, fmap, offset1, offset2 + len2 - offset1);
382  *mapped2 = IMAGE_NO_MAP;
383  }
384  else
385  {
386  macho_unmap_range(NULL, mapped2, fmap, offset2, offset1 + len1 - offset2);
387  *mapped1 = IMAGE_NO_MAP;
388  }
389  }
390 }
391 
392 /******************************************************************
393  * macho_find_section
394  */
395 static BOOL macho_find_segment_section(struct image_file_map* ifm, const char* segname, const char* sectname, struct image_section_map* ism)
396 {
397  struct macho_file_map* fmap;
398  unsigned i;
399  char tmp[sizeof(fmap->sect[0].section.sectname)];
400 
401  /* Other parts of dbghelp use section names like ".eh_frame". Mach-O uses
402  names like "__eh_frame". Convert those. */
403  if (sectname[0] == '.')
404  {
405  lstrcpynA(tmp, "__", sizeof(tmp));
406  lstrcpynA(tmp + 2, sectname + 1, sizeof(tmp) - 2);
407  sectname = tmp;
408  }
409 
410  while (ifm)
411  {
412  fmap = &ifm->u.macho;
413  for (i = 0; i < fmap->num_sections; i++)
414  {
415  if (!fmap->sect[i].ignored &&
416  strcmp(fmap->sect[i].section.sectname, sectname) == 0 &&
417  (!segname || strcmp(fmap->sect[i].section.segname, segname) == 0))
418  {
419  ism->fmap = ifm;
420  ism->sidx = i;
421  return TRUE;
422  }
423  }
424  ifm = fmap->dsym;
425  }
426 
427  ism->fmap = NULL;
428  ism->sidx = -1;
429  return FALSE;
430 }
431 
432 static BOOL macho_find_section(struct image_file_map* ifm, const char* sectname, struct image_section_map* ism)
433 {
434  return macho_find_segment_section(ifm, NULL, sectname, ism);
435 }
436 
437 /******************************************************************
438  * macho_map_section
439  */
440 const char* macho_map_section(struct image_section_map* ism)
441 {
442  struct macho_file_map* fmap = &ism->fmap->u.macho;
443 
444  assert(ism->fmap->modtype == DMT_MACHO);
445  if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.macho.num_sections || fmap->sect[ism->sidx].ignored)
446  return IMAGE_NO_MAP;
447 
448  return macho_map_range(fmap, fmap->sect[ism->sidx].section.offset, fmap->sect[ism->sidx].section.size,
449  &fmap->sect[ism->sidx].mapped);
450 }
451 
452 /******************************************************************
453  * macho_unmap_section
454  */
456 {
457  struct macho_file_map* fmap = &ism->fmap->u.macho;
458 
459  if (ism->sidx >= 0 && ism->sidx < fmap->num_sections && fmap->sect[ism->sidx].mapped != IMAGE_NO_MAP)
460  {
461  macho_unmap_range(&fmap->sect[ism->sidx].mapped, NULL, fmap, fmap->sect[ism->sidx].section.offset,
462  fmap->sect[ism->sidx].section.size);
463  }
464 }
465 
466 /******************************************************************
467  * macho_get_map_rva
468  */
470 {
471  if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.macho.num_sections ||
472  ism->fmap->u.macho.sect[ism->sidx].ignored)
473  return 0;
474  return ism->fmap->u.macho.sect[ism->sidx].section.addr - ism->fmap->u.macho.segs_start;
475 }
476 
477 /******************************************************************
478  * macho_get_map_size
479  */
480 unsigned macho_get_map_size(const struct image_section_map* ism)
481 {
482  if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.macho.num_sections ||
483  ism->fmap->u.macho.sect[ism->sidx].ignored)
484  return 0;
485  return ism->fmap->u.macho.sect[ism->sidx].section.size;
486 }
487 
489 {
496 };
497 
498 /******************************************************************
499  * macho_map_load_commands
500  *
501  * Maps the load commands from a Mach-O file into memory
502  */
503 static const struct macho_load_command* macho_map_load_commands(struct macho_file_map* fmap)
504 {
505  if (fmap->load_commands == IMAGE_NO_MAP)
506  {
507  fmap->load_commands = (const struct macho_load_command*) macho_map_range(
508  fmap, fmap->header_size, fmap->commands_size, NULL);
509  TRACE("Mapped load commands: %p\n", fmap->load_commands);
510  }
511 
512  return fmap->load_commands;
513 }
514 
515 /******************************************************************
516  * macho_unmap_load_commands
517  *
518  * Unmaps the load commands of a Mach-O file from memory
519  */
520 static void macho_unmap_load_commands(struct macho_file_map* fmap)
521 {
522  if (fmap->load_commands != IMAGE_NO_MAP)
523  {
524  TRACE("Unmapping load commands: %p\n", fmap->load_commands);
525  macho_unmap_range(NULL, (const void**)&fmap->load_commands, fmap,
526  fmap->header_size, fmap->commands_size);
527  }
528 }
529 
530 /******************************************************************
531  * macho_next_load_command
532  *
533  * Advance to the next load command
534  */
535 static const struct macho_load_command* macho_next_load_command(const struct macho_load_command* lc)
536 {
537  return (const struct macho_load_command*)((const char*)lc + lc->cmdsize);
538 }
539 
540 /******************************************************************
541  * macho_enum_load_commands
542  *
543  * Enumerates the load commands for a Mach-O file, selecting by
544  * the command type, calling a callback for each. If the callback
545  * returns <0, that indicates an error. If it returns >0, that means
546  * it's not interested in getting any more load commands.
547  * If this function returns <0, that's an error produced by the
548  * callback. If >=0, that's the count of load commands successfully
549  * processed.
550  */
551 static int macho_enum_load_commands(struct image_file_map *ifm, unsigned cmd,
552  int (*cb)(struct image_file_map*, const struct macho_load_command*, void*),
553  void* user)
554 {
555  struct macho_file_map* fmap = &ifm->u.macho;
556  const struct macho_load_command* lc;
557  int i;
558  int count = 0;
559 
560  TRACE("(%p/%p, %u, %p, %p)\n", fmap, fmap->handle, cmd, cb, user);
561 
562  if ((lc = macho_map_load_commands(fmap)) == IMAGE_NO_MAP) return -1;
563 
564  TRACE("%u total commands\n", fmap->commands_count);
565 
566  for (i = 0; i < fmap->commands_count; i++, lc = macho_next_load_command(lc))
567  {
568  int result;
569 
570  if (cmd && cmd != lc->cmd) continue;
571  count++;
572 
573  result = cb(ifm, lc, user);
574  TRACE("load_command[%d] (%p), cmd %u; callback => %d\n", i, lc, lc->cmd, result);
575  if (result) return (result < 0) ? result : count;
576  }
577 
578  return count;
579 }
580 
581 /******************************************************************
582  * macho_count_sections
583  *
584  * Callback for macho_enum_load_commands. Counts the number of
585  * significant sections in a Mach-O file. All commands are
586  * expected to be of LC_SEGMENT[_64] type.
587  */
588 static int macho_count_sections(struct image_file_map* ifm, const struct macho_load_command* lc, void* user)
589 {
590  char segname[16];
591  size_t nsects;
592 
593  if (ifm->addr_size == 32)
594  {
595  const struct macho_segment_command32 *sc = (const struct macho_segment_command32 *)lc;
596  memcpy(segname, sc->segname, sizeof(segname));
597  nsects = sc->nsects;
598  }
599  else
600  {
601  const struct macho_segment_command *sc = (const struct macho_segment_command *)lc;
602  memcpy(segname, sc->segname, sizeof(segname));
603  nsects = sc->nsects;
604  }
605 
606  TRACE("(%p/%p, %p, %p) segment %s\n", ifm, ifm->u.macho.handle, lc, user,
607  debugstr_an(segname, sizeof(segname)));
608 
609  ifm->u.macho.num_sections += nsects;
610  return 0;
611 }
612 
613 /******************************************************************
614  * macho_load_section_info
615  *
616  * Callback for macho_enum_load_commands. Accumulates the address
617  * range covered by the segments of a Mach-O file and builds the
618  * section map. All commands are expected to be of LC_SEGMENT[_64] type.
619  */
620 static int macho_load_section_info(struct image_file_map* ifm, const struct macho_load_command* lc, void* user)
621 {
622  struct macho_file_map* fmap = &ifm->u.macho;
623  struct section_info* info = user;
624  BOOL ignore;
625  int i;
627  UINT64 vmaddr, vmsize;
628  char segname[16];
629  size_t nsects;
630  const void *sections;
631 
632  if (ifm->addr_size == 32)
633  {
634  const struct macho_segment_command32 *sc = (const struct macho_segment_command32 *)lc;
635  vmaddr = sc->vmaddr;
636  vmsize = sc->vmsize;
637  memcpy(segname, sc->segname, sizeof(segname));
638  nsects = sc->nsects;
639  sections = (const void *)(sc + 1);
640  }
641  else
642  {
643  const struct macho_segment_command *sc = (const struct macho_segment_command *)lc;
644  vmaddr = sc->vmaddr;
645  vmsize = sc->vmsize;
646  memcpy(segname, sc->segname, sizeof(segname));
647  nsects = sc->nsects;
648  sections = (const void *)(sc + 1);
649  }
650 
651  TRACE("(%p/%p, %p, %p) before: 0x%08lx - 0x%08lx\n", fmap, fmap->handle, lc, user,
652  (ULONG_PTR)fmap->segs_start, (ULONG_PTR)fmap->segs_size);
653  TRACE("Segment command vm: 0x%08lx - 0x%08lx\n", (ULONG_PTR)vmaddr,
654  (ULONG_PTR)(vmaddr + vmsize));
655 
656  /* Images in the dyld shared cache have their segments mapped non-contiguously.
657  We don't know how to properly locate any of the segments other than __TEXT,
658  so ignore them. */
659  ignore = (info->split_segs && strcmp(segname, "__TEXT"));
660 
661  if (!strncmp(segname, "WINE_", 5))
662  TRACE("Ignoring special Wine segment %s\n", debugstr_an(segname, sizeof(segname)));
663  else if (!strncmp(segname, "__PAGEZERO", 10))
664  TRACE("Ignoring __PAGEZERO segment\n");
665  else if (ignore)
666  TRACE("Ignoring %s segment because image has split segments\n", segname);
667  else
668  {
669  /* If this segment starts before previously-known earliest, record new earliest. */
670  if (vmaddr < fmap->segs_start)
671  fmap->segs_start = vmaddr;
672 
673  /* If this segment extends beyond previously-known furthest, record new furthest. */
674  tmp = (vmaddr + vmsize + page_mask) & ~page_mask;
675  if (fmap->segs_size < tmp) fmap->segs_size = tmp;
676 
677  TRACE("after: 0x%08lx - 0x%08lx\n", (ULONG_PTR)fmap->segs_start, (ULONG_PTR)fmap->segs_size);
678  }
679 
680  for (i = 0; i < nsects; i++)
681  {
682  if (ifm->addr_size == 32)
683  {
684  const struct macho_section32 *section = &((const struct macho_section32 *)sections)[i];
685  memcpy(fmap->sect[info->section_index].section.sectname, section->sectname, sizeof(section->sectname));
686  memcpy(fmap->sect[info->section_index].section.segname, section->segname, sizeof(section->segname));
687  fmap->sect[info->section_index].section.addr = section->addr;
688  fmap->sect[info->section_index].section.size = section->size;
689  fmap->sect[info->section_index].section.offset = section->offset;
690  fmap->sect[info->section_index].section.align = section->align;
691  fmap->sect[info->section_index].section.reloff = section->reloff;
692  fmap->sect[info->section_index].section.nreloc = section->nreloc;
693  fmap->sect[info->section_index].section.flags = section->flags;
694  }
695  else
696  fmap->sect[info->section_index].section = ((const struct macho_section *)sections)[i];
697 
698  fmap->sect[info->section_index].mapped = IMAGE_NO_MAP;
699  fmap->sect[info->section_index].ignored = ignore;
700  info->section_index++;
701  }
702 
703  return 0;
704 }
705 
706 /******************************************************************
707  * find_uuid
708  *
709  * Callback for macho_enum_load_commands. Records the UUID load
710  * command of a Mach-O file.
711  */
712 static int find_uuid(struct image_file_map* ifm, const struct macho_load_command* lc, void* user)
713 {
714  ifm->u.macho.uuid = (const struct macho_uuid_command*)lc;
715  return 1;
716 }
717 
718 /******************************************************************
719  * reset_file_map
720  */
721 static inline void reset_file_map(struct image_file_map* ifm)
722 {
723  struct macho_file_map* fmap = &ifm->u.macho;
724 
725  fmap->handle = INVALID_HANDLE_VALUE;
726  fmap->dsym = NULL;
727  fmap->load_commands = IMAGE_NO_MAP;
728  fmap->uuid = NULL;
729  fmap->num_sections = 0;
730  fmap->sect = NULL;
731 }
732 
733 /******************************************************************
734  * macho_map_file
735  *
736  * Maps a Mach-O file into memory (and checks it's a real Mach-O file)
737  */
738 static BOOL macho_map_file(struct process *pcs, const WCHAR *filenameW,
739  BOOL split_segs, struct image_file_map* ifm)
740 {
741  struct macho_file_map* fmap = &ifm->u.macho;
742  struct macho_header mach_header;
743  int i;
744  WCHAR* filename;
745  struct section_info info;
746  BOOL ret = FALSE;
748  UINT32 target_magic = (pcs->is_64bit) ? MACHO_MH_MAGIC_64 : MACHO_MH_MAGIC_32;
749  UINT32 target_cmd = (pcs->is_64bit) ? MACHO_LC_SEGMENT_64 : MACHO_LC_SEGMENT;
750  DWORD bytes_read;
751 
752  struct
753  {
754  UINT32 magic; /* FAT_MAGIC or FAT_MAGIC_64 */
755  UINT32 nfat_arch; /* number of structs that follow */
756  } fat_header;
757 
758  TRACE("(%s, %p)\n", debugstr_w(filenameW), fmap);
759 
760  reset_file_map(ifm);
761 
762  ifm->modtype = DMT_MACHO;
763  ifm->ops = &macho_file_map_ops;
764  ifm->alternate = NULL;
765  ifm->addr_size = (pcs->is_64bit) ? 64 : 32;
766  fmap->header_size = (pcs->is_64bit) ? sizeof(struct macho_header) : FIELD_OFFSET(struct macho_header, reserved);
767 
768  if (!(filename = get_dos_file_name(filenameW))) return FALSE;
769 
770  /* Now open the file, so that we can map it. */
772  if (fmap->handle == INVALID_HANDLE_VALUE)
773  {
774  TRACE("failed to open file %s: %d\n", debugstr_w(filename), errno);
775  goto done;
776  }
777 
778  if (!ReadFile(fmap->handle, &fat_header, sizeof(fat_header), &bytes_read, NULL) || bytes_read != sizeof(fat_header))
779  {
780  TRACE("failed to read fat header: %u\n", GetLastError());
781  goto done;
782  }
783  TRACE("... got possible fat header\n");
784 
785  /* Fat header is always in big-endian order. */
786  if (swap_ulong_be_to_host(fat_header.magic) == MACHO_FAT_MAGIC)
787  {
788  int narch = swap_ulong_be_to_host(fat_header.nfat_arch);
789  for (i = 0; i < narch; i++)
790  {
791  struct
792  {
793  UINT32 cputype; /* cpu specifier (int) */
794  UINT32 cpusubtype; /* machine specifier (int) */
795  UINT32 offset; /* file offset to this object file */
796  UINT32 size; /* size of this object file */
797  UINT32 align; /* alignment as a power of 2 */
798  } fat_arch;
799 
800  if (!ReadFile(fmap->handle, &fat_arch, sizeof(fat_arch), &bytes_read, NULL) || bytes_read != sizeof(fat_arch))
801  goto done;
802  if (swap_ulong_be_to_host(fat_arch.cputype) == target_cpu)
803  {
804  fmap->arch_offset = swap_ulong_be_to_host(fat_arch.offset);
805  break;
806  }
807  }
808  if (i >= narch) goto done;
809  TRACE("... found target arch (%d)\n", target_cpu);
810  }
811  else
812  {
813  fmap->arch_offset = 0;
814  TRACE("... not a fat header\n");
815  }
816 
817  /* Individual architecture (standalone or within a fat file) is in its native byte order. */
818  SetFilePointer(fmap->handle, fmap->arch_offset, 0, FILE_BEGIN);
819  if (!ReadFile(fmap->handle, &mach_header, fmap->header_size, &bytes_read, NULL)
820  || bytes_read != fmap->header_size)
821  goto done;
822  TRACE("... got possible Mach header\n");
823  /* and check for a Mach-O header */
824  if (mach_header.magic != target_magic || mach_header.cputype != target_cpu) goto done;
825  fmap->commands_size = mach_header.sizeofcmds;
826  fmap->commands_count = mach_header.ncmds;
827  /* Make sure the file type is one of the ones we expect. */
828  switch (mach_header.filetype)
829  {
830  case MACHO_MH_EXECUTE:
831  case MACHO_MH_DYLIB:
832  case MACHO_MH_DYLINKER:
833  case MACHO_MH_BUNDLE:
834  case MACHO_MH_DSYM:
835  break;
836  default:
837  goto done;
838  }
839  TRACE("... verified Mach header\n");
840 
841  fmap->num_sections = 0;
842  if (macho_enum_load_commands(ifm, target_cmd, macho_count_sections, NULL) < 0)
843  goto done;
844  TRACE("%d sections\n", fmap->num_sections);
845 
846  fmap->sect = HeapAlloc(GetProcessHeap(), 0, fmap->num_sections * sizeof(fmap->sect[0]));
847  if (!fmap->sect)
848  goto done;
849 
850  fmap->segs_size = 0;
851  fmap->segs_start = ~0L;
852 
853  info.split_segs = split_segs;
854  info.section_index = 0;
855  if (macho_enum_load_commands(ifm, target_cmd, macho_load_section_info, &info) < 0)
856  {
857  fmap->num_sections = 0;
858  goto done;
859  }
860 
861  fmap->segs_size -= fmap->segs_start;
862  TRACE("segs_start: 0x%08lx, segs_size: 0x%08lx\n", (ULONG_PTR)fmap->segs_start,
863  (ULONG_PTR)fmap->segs_size);
864 
866  goto done;
867  if (fmap->uuid)
868  {
870  TRACE("UUID %s\n", format_uuid(fmap->uuid->uuid, uuid_string));
871  }
872  else
873  TRACE("no UUID found\n");
874 
875  ret = TRUE;
876 done:
877  if (!ret)
878  macho_unmap_file(ifm);
880  return ret;
881 }
882 
883 /******************************************************************
884  * macho_unmap_file
885  *
886  * Unmaps a Mach-O file from memory (previously mapped with macho_map_file)
887  */
888 static void macho_unmap_file(struct image_file_map* ifm)
889 {
890  struct image_file_map* cursor;
891 
892  TRACE("(%p/%p)\n", ifm, ifm->u.macho.handle);
893 
894  cursor = ifm;
895  while (cursor)
896  {
897  struct image_file_map* next;
898 
899  if (ifm->u.macho.handle != INVALID_HANDLE_VALUE)
900  {
901  struct image_section_map ism;
902 
903  ism.fmap = ifm;
904  for (ism.sidx = 0; ism.sidx < ifm->u.macho.num_sections; ism.sidx++)
905  macho_unmap_section(&ism);
906 
907  HeapFree(GetProcessHeap(), 0, ifm->u.macho.sect);
909  CloseHandle(ifm->u.macho.handle);
910  ifm->u.macho.handle = INVALID_HANDLE_VALUE;
911  }
912 
913  next = cursor->u.macho.dsym;
914  if (cursor != ifm)
916  cursor = next;
917  }
918 }
919 
920 /******************************************************************
921  * macho_sect_is_code
922  *
923  * Checks if a section, identified by sectidx which is a 1-based
924  * index into the sections of all segments, in order of load
925  * commands, contains code.
926  */
927 static BOOL macho_sect_is_code(struct macho_file_map* fmap, unsigned char sectidx)
928 {
929  BOOL ret;
930 
931  TRACE("(%p/%p, %u)\n", fmap, fmap->handle, sectidx);
932 
933  if (!sectidx) return FALSE;
934 
935  sectidx--; /* convert from 1-based to 0-based */
936  if (sectidx >= fmap->num_sections || fmap->sect[sectidx].ignored) return FALSE;
937 
938  ret = (!(fmap->sect[sectidx].section.flags & MACHO_SECTION_TYPE) &&
939  (fmap->sect[sectidx].section.flags & (MACHO_S_ATTR_PURE_INSTRUCTIONS | MACHO_S_ATTR_SOME_INSTRUCTIONS)));
940  TRACE("-> %d\n", ret);
941  return ret;
942 }
943 
944 struct symtab_elt
945 {
946  struct hash_table_elt ht_elt;
947  struct symt_compiland* compiland;
949  unsigned char is_code:1,
950  is_public:1,
951  is_global:1,
952  used:1;
953 };
954 
956 {
957  struct macho_file_map* fmap;
958  struct module* module;
959  struct pool pool;
961 };
962 
963 /******************************************************************
964  * macho_stabs_def_cb
965  *
966  * Callback for stabs_parse. Collect symbol definitions.
967  */
968 static void macho_stabs_def_cb(struct module* module, ULONG_PTR load_offset,
969  const char* name, ULONG_PTR offset,
970  BOOL is_public, BOOL is_global, unsigned char sectidx,
971  struct symt_compiland* compiland, void* user)
972 {
973  struct macho_debug_info* mdi = user;
974  struct symtab_elt* ste;
975 
976  TRACE("(%p, 0x%08lx, %s, 0x%08lx, %d, %d, %u, %p, %p/%p/%p)\n", module, load_offset,
978  compiland, mdi, mdi->fmap, mdi->fmap->handle);
979 
980  /* Defer the creation of new non-debugging symbols until after we've
981  * finished parsing the stabs. */
982  ste = pool_alloc(&mdi->pool, sizeof(*ste));
983  ste->ht_elt.name = pool_strdup(&mdi->pool, name);
984  ste->compiland = compiland;
985  ste->addr = load_offset + offset;
986  ste->is_code = !!macho_sect_is_code(mdi->fmap, sectidx);
987  ste->is_public = !!is_public;
988  ste->is_global = !!is_global;
989  ste->used = 0;
990  hash_table_add(&mdi->ht_symtab, &ste->ht_elt);
991 }
992 
993 /******************************************************************
994  * macho_parse_symtab
995  *
996  * Callback for macho_enum_load_commands. Processes the LC_SYMTAB
997  * load commands from the Mach-O file.
998  */
999 static int macho_parse_symtab(struct image_file_map* ifm,
1000  const struct macho_load_command* lc, void* user)
1001 {
1002  struct macho_file_map* fmap = &ifm->u.macho;
1003  const struct macho_symtab_command* sc = (const struct macho_symtab_command*)lc;
1004  struct macho_debug_info* mdi = user;
1005  const char* stabstr;
1006  int ret = 0;
1007  size_t stabsize = (ifm->addr_size == 32) ? sizeof(struct stab_nlist) : sizeof(struct macho64_nlist);
1008  const char *stab;
1009 
1010  TRACE("(%p/%p, %p, %p) %u syms at 0x%08x, strings 0x%08x - 0x%08x\n", fmap, fmap->handle, lc,
1011  user, sc->nsyms, sc->symoff, sc->stroff, sc->stroff + sc->strsize);
1012 
1013  if (!macho_map_ranges(fmap, sc->symoff, sc->nsyms * stabsize,
1014  sc->stroff, sc->strsize, (const void**)&stab, (const void**)&stabstr))
1015  return 0;
1016 
1017  if (!stabs_parse(mdi->module,
1018  mdi->module->format_info[DFI_MACHO]->u.macho_info->load_addr - fmap->segs_start,
1019  stab, sc->nsyms, stabsize,
1020  stabstr, sc->strsize, macho_stabs_def_cb, mdi))
1021  ret = -1;
1022 
1023  macho_unmap_ranges(fmap, sc->symoff, sc->nsyms * stabsize,
1024  sc->stroff, sc->strsize, (const void**)&stab, (const void**)&stabstr);
1025 
1026  return ret;
1027 }
1028 
1029 /******************************************************************
1030  * macho_finish_stabs
1031  *
1032  * Integrate the non-debugging symbols we've gathered into the
1033  * symbols that were generated during stabs parsing.
1034  */
1035 static void macho_finish_stabs(struct module* module, struct hash_table* ht_symtab)
1036 {
1037  struct hash_table_iter hti_ours;
1038  struct symtab_elt* ste;
1039  BOOL adjusted = FALSE;
1040 
1041  TRACE("(%p, %p)\n", module, ht_symtab);
1042 
1043  /* For each of our non-debugging symbols, see if it can provide some
1044  * missing details to one of the module's known symbols. */
1045  hash_table_iter_init(ht_symtab, &hti_ours, NULL);
1046  while ((ste = hash_table_iter_up(&hti_ours)))
1047  {
1048  struct hash_table_iter hti_modules;
1049  void* ptr;
1050  struct symt_ht* sym;
1051  struct symt_function* func;
1052  struct symt_data* data;
1053 
1054  hash_table_iter_init(&module->ht_symbols, &hti_modules, ste->ht_elt.name);
1055  while ((ptr = hash_table_iter_up(&hti_modules)))
1056  {
1057  sym = CONTAINING_RECORD(ptr, struct symt_ht, hash_elt);
1058 
1059  if (strcmp(sym->hash_elt.name, ste->ht_elt.name))
1060  continue;
1061 
1062  switch (sym->symt.tag)
1063  {
1064  case SymTagFunction:
1065  func = (struct symt_function*)sym;
1066  if (func->address == module->format_info[DFI_MACHO]->u.macho_info->load_addr)
1067  {
1068  TRACE("Adjusting function %p/%s!%s from 0x%08lx to 0x%08lx\n", func,
1070  func->address, ste->addr);
1071  func->address = ste->addr;
1072  adjusted = TRUE;
1073  }
1074  if (func->address == ste->addr)
1075  ste->used = 1;
1076  break;
1077  case SymTagData:
1078  data = (struct symt_data*)sym;
1079  switch (data->kind)
1080  {
1081  case DataIsGlobal:
1082  case DataIsFileStatic:
1083  if (data->u.var.offset == module->format_info[DFI_MACHO]->u.macho_info->load_addr)
1084  {
1085  TRACE("Adjusting data symbol %p/%s!%s from 0x%08lx to 0x%08lx\n",
1087  data->u.var.offset, ste->addr);
1088  data->u.var.offset = ste->addr;
1089  adjusted = TRUE;
1090  }
1091  if (data->u.var.offset == ste->addr)
1092  {
1093  enum DataKind new_kind;
1094 
1095  new_kind = ste->is_global ? DataIsGlobal : DataIsFileStatic;
1096  if (data->kind != new_kind)
1097  {
1098  WARN("Changing kind for %p/%s!%s from %d to %d\n", sym,
1100  (int)data->kind, (int)new_kind);
1101  data->kind = new_kind;
1102  adjusted = TRUE;
1103  }
1104  ste->used = 1;
1105  }
1106  break;
1107  default:;
1108  }
1109  break;
1110  default:
1111  TRACE("Ignoring tag %u\n", sym->symt.tag);
1112  break;
1113  }
1114  }
1115  }
1116 
1117  if (adjusted)
1118  {
1119  /* since we may have changed some addresses, mark the module to be resorted */
1121  }
1122 
1123  /* Mark any of our non-debugging symbols which fall on an already-used
1124  * address as "used". This allows us to skip them in the next loop,
1125  * below. We do this in separate loops because symt_new_* marks the
1126  * list as needing sorting and symt_find_nearest sorts if needed,
1127  * causing thrashing. */
1129  {
1130  hash_table_iter_init(ht_symtab, &hti_ours, NULL);
1131  while ((ste = hash_table_iter_up(&hti_ours)))
1132  {
1133  struct symt_ht* sym;
1134  ULONG64 addr;
1135 
1136  if (ste->used) continue;
1137 
1138  sym = symt_find_nearest(module, ste->addr);
1139  if (sym)
1140  symt_get_address(&sym->symt, &addr);
1141  if (sym && ste->addr == addr)
1142  {
1143  ULONG64 size = 0;
1144  DWORD kind = -1;
1145 
1146  ste->used = 1;
1147 
1148  /* If neither symbol has a correct size (ours never does), we
1149  * consider them both to be markers. No warning is needed in
1150  * that case.
1151  * Also, we check that we don't have two symbols, one local, the other
1152  * global, which is legal.
1153  */
1155  symt_get_info(module, &sym->symt, TI_GET_DATAKIND, &kind);
1156  if (size && kind == (ste->is_global ? DataIsGlobal : DataIsFileStatic))
1157  FIXME("Duplicate in %s: %s<%08lx> %s<%s-%s>\n",
1159  ste->ht_elt.name, ste->addr,
1160  sym->hash_elt.name,
1162  }
1163  }
1164  }
1165 
1166  /* For any of our remaining non-debugging symbols which have no match
1167  * among the module's known symbols, add them as new symbols. */
1168  hash_table_iter_init(ht_symtab, &hti_ours, NULL);
1169  while ((ste = hash_table_iter_up(&hti_ours)))
1170  {
1171  if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY) && !ste->used)
1172  {
1173  if (ste->is_code)
1174  {
1175  symt_new_function(module, ste->compiland, ste->ht_elt.name,
1176  ste->addr, 0, NULL);
1177  }
1178  else
1179  {
1180  struct location loc;
1181 
1182  loc.kind = loc_absolute;
1183  loc.reg = 0;
1184  loc.offset = ste->addr;
1186  !ste->is_global, loc, 0, NULL);
1187  }
1188 
1189  ste->used = 1;
1190  }
1191 
1192  if (ste->is_public && !(dbghelp_options & SYMOPT_NO_PUBLICS))
1193  {
1194  symt_new_public(module, ste->compiland, ste->ht_elt.name, ste->is_code, ste->addr, 0);
1195  }
1196  }
1197 }
1198 
1199 /******************************************************************
1200  * try_dsym
1201  *
1202  * Try to load a debug symbol file from the given path and check
1203  * if its UUID matches the UUID of an already-mapped file. If so,
1204  * stash the file map in the "dsym" field of the file and return
1205  * TRUE. If it can't be mapped or its UUID doesn't match, return
1206  * FALSE.
1207  */
1208 static BOOL try_dsym(struct process *pcs, const WCHAR* path, struct macho_file_map* fmap)
1209 {
1210  struct image_file_map dsym_ifm;
1211 
1212  if (macho_map_file(pcs, path, FALSE, &dsym_ifm))
1213  {
1215 
1216  if (dsym_ifm.u.macho.uuid && !memcmp(dsym_ifm.u.macho.uuid->uuid, fmap->uuid->uuid, sizeof(fmap->uuid->uuid)))
1217  {
1218  TRACE("found matching debug symbol file at %s\n", debugstr_w(path));
1219  fmap->dsym = HeapAlloc(GetProcessHeap(), 0, sizeof(dsym_ifm));
1220  *fmap->dsym = dsym_ifm;
1221  return TRUE;
1222  }
1223 
1224  TRACE("candidate debug symbol file at %s has wrong UUID %s; ignoring\n", debugstr_w(path),
1225  format_uuid(dsym_ifm.u.macho.uuid->uuid, uuid_string));
1226 
1227  macho_unmap_file(&dsym_ifm);
1228  }
1229  else
1230  TRACE("couldn't map file at %s\n", debugstr_w(path));
1231 
1232  return FALSE;
1233 }
1234 
1235 static const WCHAR dsym_subpath[] = {'\\','C','o','n','t','e','n','t','s',
1236  '\\','R','e','s','o','u','r','c','e','s',
1237  '\\','D','W','A','R','F','\\',0};
1238 
1239 static WCHAR *query_dsym(const GUID *uuid, const WCHAR *filename)
1240 {
1242  WCHAR *ret = NULL;
1243  char buf[1024];
1244  HANDLE mgr;
1245  BOOL res;
1246 
1248  OPEN_EXISTING, 0, 0);
1249  if (mgr == INVALID_HANDLE_VALUE) return NULL;
1250 
1251  query = (void *)buf;
1252  res = DeviceIoControl( mgr, IOCTL_MOUNTMGR_QUERY_SYMBOL_FILE, (void*)uuid, sizeof(*uuid), query, sizeof(buf), NULL, NULL );
1253  if (!res && GetLastError() == ERROR_MORE_DATA)
1254  {
1255  size_t size = FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName[query->DeviceNameLength]);
1257  if (query)
1258  res = DeviceIoControl( mgr, IOCTL_MOUNTMGR_QUERY_SYMBOL_FILE, (void*)uuid, sizeof(*uuid), query, size, NULL, NULL );
1259  }
1260  CloseHandle(mgr);
1261 
1262  if (res && (ret = HeapAlloc(GetProcessHeap(), 0,
1263  query->DeviceNameLength + sizeof(dsym_subpath) + lstrlenW(filename) * sizeof(WCHAR))))
1264  {
1265  WCHAR *p = ret;
1266  memcpy(p, query->DeviceName, query->DeviceNameLength);
1267  p += query->DeviceNameLength / sizeof(WCHAR);
1268  memcpy(p, dsym_subpath, sizeof(dsym_subpath));
1269  p += ARRAY_SIZE(dsym_subpath) - 1;
1270  lstrcpyW(p, filename);
1271  }
1272 
1273  if (query != (void *)buf) HeapFree(GetProcessHeap(), 0, query);
1274  return ret;
1275 }
1276 
1277 /******************************************************************
1278  * find_and_map_dsym
1279  *
1280  * Search for a debugging symbols file associated with a module and
1281  * map it. First look for a .dSYM bundle next to the module file
1282  * (e.g. <path>.dSYM/Contents/Resources/DWARF/<basename of path>)
1283  * as produced by dsymutil. Next, look for a .dwarf file next to
1284  * the module file (e.g. <path>.dwarf) as produced by
1285  * "dsymutil --flat". Finally, use Spotlight to search for a
1286  * .dSYM bundle with the same UUID as the module file.
1287  */
1288 static void find_and_map_dsym(struct process *pcs, struct module* module)
1289 {
1290  static const WCHAR dot_dsym[] = {'.','d','S','Y','M',0};
1291  static const WCHAR dot_dwarf[] = {'.','d','w','a','r','f',0};
1292  struct macho_file_map* fmap = &module->format_info[DFI_MACHO]->u.macho_info->file_map.u.macho;
1293  const WCHAR* p;
1294  size_t len;
1295  WCHAR* path = NULL;
1296 
1297  /* Without a UUID, we can't verify that any debug info file we find corresponds
1298  to this file. Better to have no debug info than incorrect debug info. */
1299  if (!fmap->uuid)
1300  return;
1301 
1304  path = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1305  if (!path)
1306  return;
1308  lstrcatW(path, dot_dsym);
1310  lstrcatW(path, p);
1311 
1312  if (try_dsym(pcs, path, fmap))
1313  goto found;
1314 
1316 
1317  if (try_dsym(pcs, path, fmap))
1318  goto found;
1319 
1320  HeapFree(GetProcessHeap(), 0, path);
1321  if ((path = query_dsym((const GUID *)fmap->uuid->uuid, p))) try_dsym(pcs, path, fmap);
1322 
1323 found:
1324  HeapFree(GetProcessHeap(), 0, path);
1325 }
1326 
1327 /******************************************************************
1328  * image_uses_split_segs
1329  *
1330  * Determine if the Mach-O image loaded at a particular address in
1331  * the given process is in the dyld shared cache and therefore has
1332  * its segments mapped non-contiguously.
1333  *
1334  * The image header has to be loaded from the process's memory
1335  * because the relevant flag is only set in memory, not in the file.
1336  */
1338 {
1339  BOOL split_segs = FALSE;
1340 
1341  if (load_addr)
1342  {
1345  struct macho_header header;
1346 
1348  header.magic == target_magic && header.cputype == target_cpu &&
1350  {
1351  split_segs = TRUE;
1352  }
1353  }
1354 
1355  return split_segs;
1356 }
1357 
1358 /******************************************************************
1359  * macho_load_debug_info
1360  *
1361  * Loads Mach-O debugging information from the module image file.
1362  */
1363 static BOOL macho_load_debug_info(struct process *pcs, struct module* module)
1364 {
1365  BOOL ret = FALSE;
1366  struct macho_debug_info mdi;
1367  int result;
1368  struct image_file_map *ifm;
1369  struct macho_file_map *fmap;
1370 
1371  if (module->type != DMT_MACHO || !module->format_info[DFI_MACHO]->u.macho_info)
1372  {
1373  ERR("Bad Mach-O module '%s'\n", debugstr_w(module->module.LoadedImageName));
1374  return FALSE;
1375  }
1376 
1377  ifm = &module->format_info[DFI_MACHO]->u.macho_info->file_map;
1378  fmap = &ifm->u.macho;
1379 
1380  TRACE("(%p, %p/%p)\n", module, fmap, fmap->handle);
1381 
1383 
1385  {
1386  find_and_map_dsym(pcs, module);
1387 
1388  if (dwarf2_parse(module, module->reloc_delta, NULL /* FIXME: some thunks to deal with ? */,
1389  &module->format_info[DFI_MACHO]->u.macho_info->file_map))
1390  ret = TRUE;
1391  }
1392 
1393  mdi.fmap = fmap;
1394  mdi.module = module;
1395  pool_init(&mdi.pool, 65536);
1396  hash_table_init(&mdi.pool, &mdi.ht_symtab, 256);
1398  if (result > 0)
1399  ret = TRUE;
1400  else if (result < 0)
1401  WARN("Couldn't correctly read stabs\n");
1402 
1403  if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY) && fmap->dsym)
1404  {
1405  mdi.fmap = &fmap->dsym->u.macho;
1407  if (result > 0)
1408  ret = TRUE;
1409  else if (result < 0)
1410  WARN("Couldn't correctly read stabs\n");
1411  }
1412 
1414 
1415  pool_destroy(&mdi.pool);
1416  return ret;
1417 }
1418 
1419 /******************************************************************
1420  * macho_fetch_file_info
1421  *
1422  * Gathers some more information for a Mach-O module from a given file
1423  */
1425  DWORD* size, DWORD* checksum)
1426 {
1427  struct image_file_map fmap;
1428  BOOL split_segs;
1429 
1430  TRACE("(%s, %p, %p, %p)\n", debugstr_w(name), base, size, checksum);
1431 
1432  split_segs = image_uses_split_segs(process, load_addr);
1433  if (!macho_map_file(process, name, split_segs, &fmap)) return FALSE;
1434  if (base) *base = fmap.u.macho.segs_start;
1435  *size = fmap.u.macho.segs_size;
1436  *checksum = calc_crc32(fmap.u.macho.handle);
1437  macho_unmap_file(&fmap);
1438  return TRUE;
1439 }
1440 
1441 /******************************************************************
1442  * macho_module_remove
1443  */
1444 static void macho_module_remove(struct process* pcs, struct module_format* modfmt)
1445 {
1446  macho_unmap_file(&modfmt->u.macho_info->file_map);
1447  HeapFree(GetProcessHeap(), 0, modfmt);
1448 }
1449 
1450 /******************************************************************
1451  * macho_load_file
1452  *
1453  * Loads the information for Mach-O module stored in 'filename'.
1454  * The module has been loaded at 'load_addr' address.
1455  * returns
1456  * FALSE if the file cannot be found/opened or if the file doesn't
1457  * contain symbolic info (or this info cannot be read or parsed)
1458  * TRUE on success
1459  */
1460 static BOOL macho_load_file(struct process* pcs, const WCHAR* filename,
1462 {
1463  BOOL ret = TRUE;
1464  BOOL split_segs;
1465  struct image_file_map fmap;
1466 
1467  TRACE("(%p/%p, %s, 0x%08lx, %p/0x%08x)\n", pcs, pcs->handle, debugstr_w(filename),
1469 
1470  split_segs = image_uses_split_segs(pcs, load_addr);
1471  if (!macho_map_file(pcs, filename, split_segs, &fmap)) return FALSE;
1472 
1474  {
1476  struct module_format* modfmt =
1477  HeapAlloc(GetProcessHeap(), 0, sizeof(struct module_format) + sizeof(struct macho_module_info));
1478  if (!modfmt) goto leave;
1479  if (!load_addr)
1480  load_addr = fmap.u.macho.segs_start;
1482  fmap.u.macho.segs_size, 0, calc_crc32(fmap.u.macho.handle));
1483  if (!macho_info->module)
1484  {
1485  HeapFree(GetProcessHeap(), 0, modfmt);
1486  goto leave;
1487  }
1488  macho_info->module->reloc_delta = macho_info->module->module.BaseOfImage - fmap.u.macho.segs_start;
1489  macho_module_info = (void*)(modfmt + 1);
1490  macho_info->module->format_info[DFI_MACHO] = modfmt;
1491 
1492  modfmt->module = macho_info->module;
1493  modfmt->remove = macho_module_remove;
1494  modfmt->loc_compute = NULL;
1495  modfmt->u.macho_info = macho_module_info;
1496 
1498 
1499  macho_module_info->file_map = fmap;
1500  reset_file_map(&fmap);
1502  macho_info->module->module.SymType = SymDeferred;
1503  else if (!macho_load_debug_info(pcs, macho_info->module))
1504  ret = FALSE;
1505 
1506  macho_info->module->format_info[DFI_MACHO]->u.macho_info->in_use = 1;
1507  macho_info->module->format_info[DFI_MACHO]->u.macho_info->is_loader = 0;
1508  TRACE("module = %p\n", macho_info->module);
1509  }
1510 
1512  {
1513  WCHAR* ptr;
1514  ptr = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(filename) + 1) * sizeof(WCHAR));
1515  if (ptr)
1516  {
1517  lstrcpyW(ptr, filename);
1519  }
1520  else ret = FALSE;
1521  TRACE("module_name = %p %s\n", macho_info->module_name, debugstr_w(macho_info->module_name));
1522  }
1523 leave:
1524  macho_unmap_file(&fmap);
1525 
1526  TRACE(" => %d\n", ret);
1527  return ret;
1528 }
1529 
1531 {
1532  struct process *process;
1535 };
1536 
1538 {
1540  return macho_load_file(macho_load->process, filename, macho_load->load_addr, macho_load->macho_info);
1541 }
1542 
1543 /******************************************************************
1544  * macho_search_and_load_file
1545  *
1546  * Lookup a file in standard Mach-O locations, and if found, load it
1547  */
1550  struct macho_info* macho_info)
1551 {
1552  BOOL ret = FALSE;
1553  struct module* module;
1554  static const WCHAR S_libstdcPPW[] = {'l','i','b','s','t','d','c','+','+','\0'};
1555  const WCHAR* p;
1556  struct macho_load_params load_params;
1557 
1558  TRACE("(%p/%p, %s, 0x%08lx, %p)\n", pcs, pcs->handle, debugstr_w(filename), load_addr,
1559  macho_info);
1560 
1561  if (filename == NULL || *filename == '\0') return FALSE;
1563  {
1565  module->format_info[DFI_MACHO]->u.macho_info->in_use = 1;
1566  return module->module.SymType;
1567  }
1568 
1569  if (wcsstr(filename, S_libstdcPPW)) return FALSE; /* We know we can't do it */
1570 
1571  load_params.process = pcs;
1572  load_params.load_addr = load_addr;
1573  load_params.macho_info = macho_info;
1574 
1575  /* Try DYLD_LIBRARY_PATH first. */
1576  p = file_name(filename);
1577  ret = search_unix_path(p, process_getenv(pcs, L"DYLD_LIBRARY_PATH"), macho_load_file_cb, &load_params);
1578 
1579  /* Try the path as given. */
1580  if (!ret)
1582  /* Try DYLD_FALLBACK_LIBRARY_PATH, with just the filename (no directories). */
1583  if (!ret)
1584  {
1585  const WCHAR* fallback = process_getenv(pcs, L"DYLD_FALLBACK_LIBRARY_PATH");
1586  if (!fallback)
1587  fallback = L"/usr/local/lib:/lib:/usr/lib";
1588  ret = search_unix_path(p, fallback, macho_load_file_cb, &load_params);
1589  }
1590  if (!ret && p == filename)
1591  ret = search_dll_path(pcs, filename, macho_load_file_cb, &load_params);
1592 
1593  return ret;
1594 }
1595 
1596 /******************************************************************
1597  * macho_enum_modules_internal
1598  *
1599  * Enumerate Mach-O modules from a running process
1600  */
1601 static BOOL macho_enum_modules_internal(const struct process* pcs,
1602  const WCHAR* main_name,
1603  enum_modules_cb cb, void* user)
1604 {
1605  union wine_all_image_infos image_infos;
1606  union wine_image_info* info_array = NULL;
1607  ULONG_PTR len;
1608  int i;
1609  char bufstr[256];
1610  WCHAR bufstrW[MAX_PATH];
1611  BOOL ret = FALSE;
1612 
1613  TRACE("(%p/%p, %s, %p, %p)\n", pcs, pcs->handle, debugstr_w(main_name), cb,
1614  user);
1615 
1616  if (pcs->is_64bit)
1617  len = sizeof(image_infos.infos64);
1618  else
1619  len = sizeof(image_infos.infos32);
1620  if (!pcs->dbg_hdr_addr ||
1621  !read_process_memory(pcs, pcs->dbg_hdr_addr, &image_infos, len))
1622  goto done;
1623  if (!pcs->is_64bit)
1624  {
1625  struct dyld_all_image_infos32 temp = image_infos.infos32;
1626  image_infos.infos64.infoArrayCount = temp.infoArrayCount;
1627  image_infos.infos64.infoArray = temp.infoArray;
1628  }
1629  if (!image_infos.infos64.infoArray)
1630  goto done;
1631  TRACE("Process has %u image infos at %s\n", image_infos.infos64.infoArrayCount, wine_dbgstr_longlong(image_infos.infos64.infoArray));
1632 
1633  if (pcs->is_64bit)
1634  len = sizeof(info_array->info64);
1635  else
1636  len = sizeof(info_array->info32);
1637  len *= image_infos.infos64.infoArrayCount;
1638  info_array = HeapAlloc(GetProcessHeap(), 0, len);
1639  if (!info_array ||
1640  !read_process_memory(pcs, image_infos.infos64.infoArray, info_array, len))
1641  goto done;
1642  TRACE("... read image infos\n");
1643 
1644  for (i = 0; i < image_infos.infos64.infoArrayCount; i++)
1645  {
1646  struct dyld_image_info64 info;
1647  if (pcs->is_64bit)
1648  info = info_array[i].info64;
1649  else
1650  {
1651  struct dyld_image_info32 *info32 = &info_array->info32 + i;
1652  info.imageLoadAddress = info32->imageLoadAddress;
1653  info.imageFilePath = info32->imageFilePath;
1654  }
1655  if (info.imageFilePath &&
1656  read_process_memory(pcs, info.imageFilePath, bufstr, sizeof(bufstr)))
1657  {
1658  bufstr[sizeof(bufstr) - 1] = '\0';
1659  TRACE("[%d] image file %s\n", i, debugstr_a(bufstr));
1660  MultiByteToWideChar(CP_UNIXCP, 0, bufstr, -1, bufstrW, ARRAY_SIZE(bufstrW));
1661  if (main_name && !bufstrW[0]) lstrcpyW(bufstrW, main_name);
1662  if (!cb(bufstrW, info.imageLoadAddress, user)) break;
1663  }
1664  }
1665 
1666  ret = TRUE;
1667 done:
1668  HeapFree(GetProcessHeap(), 0, info_array);
1669  return ret;
1670 }
1671 
1673 {
1674  struct process* pcs;
1676 };
1677 
1679 {
1680  struct macho_sync* ms = user;
1681 
1682  TRACE("(%s, 0x%08lx, %p)\n", debugstr_w(name), addr, user);
1684  return TRUE;
1685 }
1686 
1687 /******************************************************************
1688  * macho_synchronize_module_list
1689  *
1690  * Rescans the debuggee's modules list and synchronizes it with
1691  * the one from 'pcs', ie:
1692  * - if a module is in debuggee and not in pcs, it's loaded into pcs
1693  * - if a module is in pcs and not in debuggee, it's unloaded from pcs
1694  */
1696 {
1697  struct module* module;
1698  struct macho_sync ms;
1699 
1700  TRACE("(%p/%p)\n", pcs, pcs->handle);
1701 
1702  for (module = pcs->lmodules; module; module = module->next)
1703  {
1704  if (module->type == DMT_MACHO && !module->is_virtual)
1705  module->format_info[DFI_MACHO]->u.macho_info->in_use = 0;
1706  }
1707 
1708  ms.pcs = pcs;
1709  ms.macho_info.flags = MACHO_INFO_MODULE;
1711  return FALSE;
1712 
1713  module = pcs->lmodules;
1714  while (module)
1715  {
1716  if (module->type == DMT_MACHO && !module->is_virtual &&
1717  !module->format_info[DFI_MACHO]->u.macho_info->in_use &&
1718  !module->format_info[DFI_MACHO]->u.macho_info->is_loader)
1719  {
1721  /* restart all over */
1722  module = pcs->lmodules;
1723  }
1724  else module = module->next;
1725  }
1726  return TRUE;
1727 }
1728 
1729 /******************************************************************
1730  * macho_enum_modules
1731  *
1732  * Enumerates the Mach-O loaded modules from a running target (hProc)
1733  * This function doesn't require that someone has called SymInitialize
1734  * on this very process.
1735  */
1737 {
1738  struct macho_info macho_info;
1739  BOOL ret;
1740 
1741  TRACE("(%p, %p, %p)\n", process->handle, cb, user);
1746  return ret;
1747 }
1748 
1750 {
1751  struct process* pcs;
1753  const WCHAR* name;
1755 };
1756 
1757 /******************************************************************
1758  * macho_load_cb
1759  *
1760  * Callback for macho_load_module, used to walk the list of loaded
1761  * modules.
1762  */
1764 {
1765  struct macho_load* ml = user;
1766  const WCHAR* p;
1767 
1768  TRACE("(%s, 0x%08lx, %p)\n", debugstr_w(name), addr, user);
1769 
1770  /* memcmp is needed for matches when bufstr contains also version information
1771  * ml->name: libc.so, name: libc.so.6.0
1772  */
1773  p = file_name(name);
1774  if (!memcmp(p, ml->name, lstrlenW(ml->name) * sizeof(WCHAR)))
1775  {
1777  return FALSE;
1778  }
1779  return TRUE;
1780 }
1781 
1782 /******************************************************************
1783  * macho_load_module
1784  *
1785  * Loads a Mach-O module and stores it in process' module list.
1786  * Also, find module real name and load address from
1787  * the real loaded modules list in pcs address space.
1788  */
1789 static struct module* macho_load_module(struct process* pcs, const WCHAR* name, ULONG_PTR addr)
1790 {
1791  struct macho_load ml;
1792 
1793  TRACE("(%p/%p, %s, 0x%08lx)\n", pcs, pcs->handle, debugstr_w(name), addr);
1794 
1795  ml.macho_info.flags = MACHO_INFO_MODULE;
1796  ml.ret = FALSE;
1797 
1798  if (pcs->dbg_hdr_addr) /* we're debugging a live target */
1799  {
1800  ml.pcs = pcs;
1801  /* do only the lookup from the filename, not the path (as we lookup module
1802  * name in the process' loaded module list)
1803  */
1804  ml.name = file_name(name);
1805  ml.ret = FALSE;
1806 
1808  return NULL;
1809  }
1810  else if (addr)
1811  {
1812  ml.name = name;
1814  }
1815  if (!ml.ret) return NULL;
1816  assert(ml.macho_info.module);
1817  return ml.macho_info.module;
1818 }
1819 
1820 /******************************************************************
1821  * macho_search_loader
1822  *
1823  * Lookup in a running Mach-O process the loader, and sets its Mach-O link
1824  * address (for accessing the list of loaded images) in pcs.
1825  * If flags is MACHO_INFO_MODULE, the module for the loader is also
1826  * added as a module into pcs.
1827  */
1829 {
1830  BOOL ret = FALSE;
1831  union wine_all_image_infos image_infos;
1832  union wine_image_info image_info;
1833  unsigned int len;
1834  char path[1024];
1835  BOOL got_path = FALSE;
1836 
1837  if (pcs->is_64bit)
1838  len = sizeof(image_infos.infos64);
1839  else
1840  len = sizeof(image_infos.infos32);
1841  if (read_process_memory(pcs, pcs->dbg_hdr_addr, &image_infos, len))
1842  {
1843  if (pcs->is_64bit)
1844  len = sizeof(image_info.info64);
1845  else
1846  {
1847  struct dyld_all_image_infos32 temp = image_infos.infos32;
1848  image_infos.infos64.infoArrayCount = temp.infoArrayCount;
1849  image_infos.infos64.infoArray = temp.infoArray;
1850  len = sizeof(image_info.info32);
1851  }
1852  if (image_infos.infos64.infoArray && image_infos.infos64.infoArrayCount &&
1853  read_process_memory(pcs, image_infos.infos64.infoArray, &image_info, len))
1854  {
1855  if (!pcs->is_64bit)
1856  {
1857  struct dyld_image_info32 temp = image_info.info32;
1858  image_info.info64.imageLoadAddress = temp.imageLoadAddress;
1859  image_info.info64.imageFilePath = temp.imageFilePath;
1860  }
1861  for (len = sizeof(path); image_info.info64.imageFilePath && len > 0; len /= 2)
1862  {
1863  if (read_process_memory(pcs, image_info.info64.imageFilePath, path, len))
1864  {
1865  path[len - 1] = 0;
1866  got_path = TRUE;
1867  TRACE("got executable path from target's dyld image info: %s\n", debugstr_a(path));
1868  break;
1869  }
1870  }
1871  }
1872  }
1873 
1874  if (got_path)
1875  {
1876  WCHAR* pathW;
1877 
1878  len = MultiByteToWideChar(CP_UNIXCP, 0, path, -1, NULL, 0);
1879  pathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1880  if (pathW)
1881  {
1882  MultiByteToWideChar(CP_UNIXCP, 0, path, -1, pathW, len);
1883  ret = macho_load_file(pcs, pathW, 0, macho_info);
1884  HeapFree(GetProcessHeap(), 0, pathW);
1885  }
1886  }
1887 
1888  if (!ret)
1889  {
1890  WCHAR *loader = get_wine_loader_name(pcs);
1891  ret = loader && macho_search_and_load_file(pcs, loader, 0, macho_info);
1892  heap_free(loader);
1893  }
1894  return ret;
1895 }
1896 
1897 static const struct loader_ops macho_loader_ops =
1898 {
1904 };
1905 
1906 /******************************************************************
1907  * macho_read_wine_loader_dbg_info
1908  *
1909  * Try to find a decent wine executable which could have loaded the debuggee
1910  */
1912 {
1913  struct macho_info macho_info;
1914 
1915  TRACE("(%p/%p)\n", pcs, pcs->handle);
1916  pcs->dbg_hdr_addr = addr;
1918  if (!macho_search_loader(pcs, &macho_info)) return FALSE;
1919  macho_info.module->format_info[DFI_MACHO]->u.macho_info->is_loader = 1;
1921  pcs->loader = &macho_loader_ops;
1922  TRACE("Found macho debug header %#lx\n", pcs->dbg_hdr_addr);
1923  return TRUE;
1924 }
void(* remove)(struct process *pcs, struct module_format *modfmt)
BOOL symt_get_address(const struct symt *type, ULONG64 *addr) DECLSPEC_HIDDEN
Definition: type.c:119
GLenum func
Definition: glext.h:6028
unsigned addr_size
UINT32 cputype
Definition: macho_module.c:83
UINT32 filetype
Definition: macho_module.c:85
struct symt_function * symt_new_function(struct module *module, struct symt_compiland *parent, const char *name, ULONG_PTR addr, ULONG_PTR size, struct symt *type) DECLSPEC_HIDDEN
Definition: symbol.c:293
unsigned short is_loader
Definition: macho_module.c:179
void module_set_module(struct module *module, const WCHAR *name) DECLSPEC_HIDDEN
Definition: module.c:142
ULONG_PTR load_addr
Definition: macho_module.c:178
enum module_type modtype
struct hash_table_elt hash_elt
union image_file_map::@376 u
unsigned flags
Definition: macho_module.c:194
#define MACHO_S_ATTR_PURE_INSTRUCTIONS
Definition: macho_module.c:169
static BOOL macho_load_file_cb(void *param, HANDLE handle, const WCHAR *filename)
#define CloseHandle
Definition: compat.h:487
HMODULE module
Definition: main.cpp:47
static char * format_uuid(const UINT8 uuid[16], char out[UUID_STRING_LEN])
Definition: macho_module.c:201
#define MACHO_S_ATTR_SOME_INSTRUCTIONS
Definition: macho_module.c:170
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define MACHO_MH_DYLIB
Definition: macho_module.c:158
#define MapViewOfFile
Definition: compat.h:493
UINT32 cpusubtype
Definition: macho_module.c:84
WCHAR ModuleName[32]
Definition: compat.h:824
DWORD dwAllocationGranularity
Definition: winbase.h:1145
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
Definition: ftp_var.h:139
static struct module * macho_load_module(struct process *pcs, const WCHAR *name, ULONG_PTR addr)
#define TRUE
Definition: types.h:120
static BOOL macho_load_debug_info(struct process *pcs, struct module *module)
_CONST_RETURN wchar_t *__cdecl wcsstr(_In_z_ const wchar_t *_Str, _In_z_ const wchar_t *_SubStr)
GLuint GLuint GLsizei count
Definition: gl.h:1545
int ignore(int trapCode, ppc_trap_frame_t *trap)
Definition: mmuobject.c:296
static const struct macho_load_command * macho_map_load_commands(struct macho_file_map *fmap)
Definition: macho_module.c:503
struct hash_table ht_symbols
#define WARN(fmt,...)
Definition: debug.h:112
static void macho_unmap_range(const char **base, const void **mapped, const struct macho_file_map *fmap, ULONG_PTR offset, ULONG_PTR len)
Definition: macho_module.c:274
void macho_unmap_section(struct image_section_map *ism)
Definition: macho_module.c:455
static const WCHAR dsym_subpath[]
struct hash_table_elt ht_elt
Definition: elf_module.c:69
GLintptr offset
Definition: glext.h:5920
struct image_file_map * fmap
BOOL search_dll_path(const struct process *process, const WCHAR *name, BOOL(*match)(void *, HANDLE, const WCHAR *), void *param) DECLSPEC_HIDDEN
Definition: path.c:695
unsigned char is_global
Definition: macho_module.c:949
u32_t magic(void)
#define INVALID_HANDLE_VALUE
Definition: compat.h:479
#define assert(x)
Definition: debug.h:53
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1044
static const struct image_file_map_ops macho_file_map_ops
Definition: macho_module.c:488
int align(int length, int align)
Definition: dsound8.c:36
int errno
#define FILE_BEGIN
Definition: compat.h:509
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
Definition: parser.c:55
WCHAR DeviceName[]
Definition: adapter.cpp:21
#define MACHO_MH_MAGIC_64
Definition: macho_module.c:152
DataKind
Definition: compat.h:1394
const char * filename
Definition: ioapi.h:135
UINT32 flags
Definition: macho_module.c:88
#define lstrlenW
Definition: compat.h:498
int load_addr
Definition: mkisofs.c:104
#define MACHO_LC_SEGMENT
Definition: macho_module.c:163
#define FILE_SHARE_READ
Definition: compat.h:136
#define SYMOPT_DEFERRED_LOADS
Definition: compat.h:737
#define MACHO_LC_SYMTAB
Definition: macho_module.c:164
enum module_type type
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IMAGE_NO_MAP
Definition: image_private.h:24
#define MACHO_MH_DSYM
Definition: macho_module.c:161
struct dyld_image_info32 info32
Definition: macho_module.c:71
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:89
WCHAR LoadedImageName[256]
Definition: compat.h:826
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
#define MACHO_MH_BUNDLE
Definition: macho_module.c:160
#define MACHO_DYLD_IN_SHARED_CACHE
Definition: macho_module.c:148
#define FALSE
Definition: types.h:117
unsigned int UINT32
ULONG_PTR dbg_hdr_addr
unsigned int BOOL
Definition: ntddk_ex.h:94
UINT32 magic
Definition: macho_module.c:82
ULONG_PTR addr
Definition: macho_module.c:948
int sortlist_valid
struct section sections[2]
Definition: diskspace.c:792
#define GENERIC_WRITE
Definition: nt_native.h:90
#define debugstr_w
Definition: kernel32.h:32
static BOOL macho_load_file(struct process *pcs, const WCHAR *filename, ULONG_PTR load_addr, struct macho_info *macho_info)
#define FIXME(fmt,...)
Definition: debug.h:111
static PVOID ptr
Definition: dispmode.c:27
r reserved
Definition: btrfs.c:2940
unsigned short in_use
Definition: macho_module.c:179
static BOOL macho_synchronize_module_list(struct process *pcs)
void hash_table_iter_init(const struct hash_table *ht, struct hash_table_iter *hti, const char *name) DECLSPEC_HIDDEN
Definition: storage.c:405
smooth NULL
Definition: ftsmooth.c:416
struct dyld_all_image_infos32 infos32
Definition: macho_module.c:76
#define MOUNTMGR_DOS_DEVICE_NAME
Definition: mountmgr.h:11
static BOOL macho_sect_is_code(struct macho_file_map *fmap, unsigned char sectidx)
Definition: macho_module.c:927
static BOOL macho_enum_modules(struct process *process, enum_modules_cb cb, void *user)
ULONG_PTR offset
static int macho_parse_symtab(struct image_file_map *ifm, const struct macho_load_command *lc, void *user)
Definition: macho_module.c:999
unsigned int section_index
Definition: macho_module.c:186
target_cpu
Definition: widl.h:78
static int macho_enum_load_commands(struct image_file_map *ifm, unsigned cmd, int(*cb)(struct image_file_map *, const struct macho_load_command *, void *), void *user)
Definition: macho_module.c:551
struct macho_module_info * macho_info
static const struct loader_ops macho_loader_ops
static WCHAR * query_dsym(const GUID *uuid, const WCHAR *filename)
#define FILE_MAP_READ
Definition: compat.h:524
#define OPEN_EXISTING
Definition: compat.h:523
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
#define MACHO_LC_UUID
Definition: macho_module.c:166
struct module * module_is_already_loaded(const struct process *pcs, const WCHAR *imgname) DECLSPEC_HIDDEN
Definition: module.c:303
static BOOL macho_enum_modules_internal(const struct process *pcs, const WCHAR *main_name, enum_modules_cb cb, void *user)
#define TRACE(s)
Definition: solgame.cpp:4
const WCHAR * process_getenv(const struct process *process, const WCHAR *name)
Definition: dbghelp.c:285
struct image_file_map * alternate
GLsizeiptr size
Definition: glext.h:5919
DWORD64 reloc_delta
#define GetProcessHeap()
Definition: compat.h:484
UINT32 reserved
Definition: macho_module.c:89
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
#define CP_UNIXCP
Definition: compat.h:79
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
BOOL dwarf2_parse(struct module *module, ULONG_PTR load_offset, const struct elf_thunk_area *thunks, struct image_file_map *fmap) DECLSPEC_HIDDEN
Definition: dwarf.c:3509
const struct loader_ops * loader
#define MACHO_INFO_MODULE
Definition: macho_module.c:189
#define debugstr_a
Definition: kernel32.h:31
static BOOL macho_search_and_load_file(struct process *pcs, const WCHAR *filename, ULONG_PTR load_addr, struct macho_info *macho_info)
#define CreateFileMappingW(a, b, c, d, e, f)
Definition: compat.h:492
static void macho_calc_range(const struct macho_file_map *fmap, ULONG_PTR offset, ULONG_PTR len, ULONG_PTR *out_aligned_offset, ULONG_PTR *out_aligned_end, ULONG_PTR *out_misalign)
Definition: macho_module.c:217
SYSTEM_INFO sysinfo
Definition: dbghelp.c:76
BOOL macho_read_wine_loader_dbg_info(struct process *pcs, ULONG_PTR addr)
unsigned char used
Definition: macho_module.c:949
static BOOL macho_find_section(struct image_file_map *ifm, const char *sectname, struct image_section_map *ism)
Definition: macho_module.c:432
GLfloat param
Definition: glext.h:5796
#define MACHO_MH_MAGIC_32
Definition: macho_module.c:151
#define MAX_PATH
Definition: compat.h:34
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
static FILE * out
Definition: regtests2xml.c:44
unsigned long DWORD
Definition: ntddk_ex.h:95
GLenum GLenum GLenum GLenum mapping
Definition: glext.h:9031
BOOL search_unix_path(const WCHAR *name, const WCHAR *path, BOOL(*match)(void *, HANDLE, const WCHAR *), void *param) DECLSPEC_HIDDEN
Definition: path.c:780
struct macho_info macho_info
static BOOL macho_fetch_file_info(struct process *process, const WCHAR *name, ULONG_PTR load_addr, DWORD_PTR *base, DWORD *size, DWORD *checksum)
void hash_table_add(struct hash_table *ht, struct hash_table_elt *elt) DECLSPEC_HIDDEN
Definition: storage.c:378
struct hash_table ht_symtab
Definition: macho_module.c:960
struct symt symt
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define MACHO_CPU_TYPE_X86
Definition: macho_module.c:154
UINT64 imageLoadAddress
Definition: macho_module.c:58
static void macho_stabs_def_cb(struct module *module, ULONG_PTR load_offset, const char *name, ULONG_PTR offset, BOOL is_public, BOOL is_global, unsigned char sectidx, struct symt_compiland *compiland, void *user)
Definition: macho_module.c:968
#define MACHO_FAT_MAGIC
Definition: macho_module.c:150
unsigned __int64 ULONG64
Definition: imports.h:198
unsigned reg
int ret
void pool_init(struct pool *a, size_t arena_size) DECLSPEC_HIDDEN
Definition: storage.c:43
UINT32 imageLoadAddress
Definition: macho_module.c:44
UINT32 sizeofcmds
Definition: macho_module.c:87
SYM_TYPE SymType
Definition: compat.h:823
GLenum const GLvoid * addr
Definition: glext.h:9621
static const WCHAR L[]
Definition: oid.c:1250
static __inline const char * debugstr_an(const char *s, int n)
Definition: compat.h:55
struct symt_public * symt_new_public(struct module *module, struct symt_compiland *parent, const char *typename, BOOL is_function, ULONG_PTR address, unsigned size) DECLSPEC_HIDDEN
Definition: symbol.c:224
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
void * hash_table_iter_up(struct hash_table_iter *hti) DECLSPEC_HIDDEN
Definition: storage.c:422
#define GENERIC_READ
Definition: compat.h:135
static cab_ULONG checksum(const cab_UBYTE *data, cab_UWORD bytes, cab_ULONG csum)
Definition: fdi.c:353
static void macho_unmap_load_commands(struct macho_file_map *fmap)
Definition: macho_module.c:520
uint32_t DWORD_PTR
Definition: typedefs.h:65
#define ERROR_MORE_DATA
Definition: dderror.h:13
#define MACHO_INFO_NAME
Definition: macho_module.c:190
UINT32 imageFileModDate
Definition: macho_module.c:46
char * pool_strdup(struct pool *a, const char *str) DECLSPEC_HIDDEN
Definition: storage.c:126
struct process * pcs
static BOOL macho_enum_sync_cb(const WCHAR *name, ULONG_PTR addr, void *user)
static UINT_PTR page_mask
Definition: virtual.c:49
WCHAR * get_wine_loader_name(struct process *pcs) DECLSPEC_HIDDEN
Definition: module.c:150
unsigned char is_public
Definition: macho_module.c:949
const struct image_file_map_ops * ops
#define MACHO_MH_DYLINKER
Definition: macho_module.c:159
#define ERR(fmt,...)
Definition: debug.h:110
unsigned kind
static const struct macho_load_command * macho_next_load_command(const struct macho_load_command *lc)
Definition: macho_module.c:535
#define MACHO_CPU_TYPE_X86_64
Definition: macho_module.c:155
static int macho_count_sections(struct image_file_map *ifm, const struct macho_load_command *lc, void *user)
Definition: macho_module.c:588
unsigned char is_code
Definition: macho_module.c:949
static void find_and_map_dsym(struct process *pcs, struct module *module)
static const char * uuid_string(const UUID *uuid)
Definition: header.c:146
DWORD dwPageSize
Definition: winbase.h:1139
#define MACHO_MH_EXECUTE
Definition: macho_module.c:157
static unsigned __int64 next
Definition: rand_nt.c:6
BOOL symt_get_info(struct module *module, const struct symt *type, IMAGEHLP_SYMBOL_TYPE_INFO req, void *pInfo) DECLSPEC_HIDDEN
Definition: type.c:536
BOOL WINAPI DeviceIoControl(IN HANDLE hDevice, IN DWORD dwIoControlCode, IN LPVOID lpInBuffer OPTIONAL, IN DWORD nInBufferSize OPTIONAL, OUT LPVOID lpOutBuffer OPTIONAL, IN DWORD nOutBufferSize OPTIONAL, OUT LPDWORD lpBytesReturned OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: deviceio.c:136
void pool_destroy(struct pool *a) DECLSPEC_HIDDEN
Definition: storage.c:50
const char cursor[]
Definition: icontest.c:13
#define lstrcpyW
Definition: compat.h:497
static void macho_module_remove(struct process *pcs, struct module_format *modfmt)
static int macho_load_section_info(struct image_file_map *ifm, const struct macho_load_command *lc, void *user)
Definition: macho_module.c:620
static calc_node_t temp
Definition: rpn_ieee.c:38
unsigned macho_get_map_size(const struct image_section_map *ism)
Definition: macho_module.c:480
#define ARRAY_SIZE(a)
Definition: main.h:24
static const char * macho_map_range(const struct macho_file_map *fmap, ULONG_PTR offset, ULONG_PTR len, const char **base)
Definition: macho_module.c:238
const WCHAR S_WineLoaderW[]
Definition: module.c:42
struct process * process
unsigned short is_virtual
DWORD_PTR macho_get_map_rva(const struct image_section_map *ism)
Definition: macho_module.c:469
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
static int find_uuid(struct image_file_map *ifm, const struct macho_load_command *lc, void *user)
Definition: macho_module.c:712
struct macho_file_map * fmap
Definition: macho_module.c:957
#define ReadFile(a, b, c, d, e)
Definition: compat.h:490
DWORD calc_crc32(HANDLE handle)
Definition: dbghelp.c:848
static BOOL macho_map_ranges(const struct macho_file_map *fmap, ULONG_PTR offset1, ULONG_PTR len1, ULONG_PTR offset2, ULONG_PTR len2, const void **mapped1, const void **mapped2)
Definition: macho_module.c:306
unsigned dbghelp_options
Definition: dbghelp.c:73
#define PAGE_READONLY
Definition: compat.h:138
BOOL module_remove(struct process *pcs, struct module *module) DECLSPEC_HIDDEN
Definition: module.c:885
struct hash_table_elt hash_elt
struct macho_info macho_info
#define lstrcpynA
Definition: compat.h:499
struct module * module
#define MultiByteToWideChar
Definition: compat.h:110
void hash_table_init(struct pool *pool, struct hash_table *ht, unsigned num_buckets) DECLSPEC_HIDDEN
Definition: storage.c:334
static LPCWSTR file_name
Definition: protocol.c:147
#define CreateFileW
Definition: compat.h:489
struct process * pcs
static HMODULE MODULEINFO DWORD cb
Definition: module.c:32
Definition: name.c:38
static void reset_file_map(struct image_file_map *ifm)
Definition: macho_module.c:721
GLuint res
Definition: glext.h:9613
const WCHAR * module_name
Definition: macho_module.c:196
BOOL stabs_parse(struct module *module, ULONG_PTR load_offset, const char *stabs, size_t nstab, size_t stabsize, const char *strs, int strtablen, stabs_def_cb callback, void *user) DECLSPEC_HIDDEN
Definition: stabs.c:1241
struct symt_data * symt_new_global_variable(struct module *module, struct symt_compiland *parent, const char *name, unsigned is_static, struct location loc, ULONG_PTR size, struct symt *type) DECLSPEC_HIDDEN
Definition: symbol.c:256
#define SYMOPT_PUBLICS_ONLY
Definition: compat.h:740
#define swap_ulong_be_to_host(n)
Definition: macho_module.c:135
Definition: msctf.idl:510
unsigned used
Definition: elf_module.c:72
HANDLE handle
UINT32 ncmds
Definition: macho_module.c:86
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:49
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_macho)
struct module * module_new(struct process *pcs, const WCHAR *name, enum module_type type, BOOL virtual, DWORD64 addr, DWORD64 size, ULONG_PTR stamp, ULONG_PTR checksum) DECLSPEC_HIDDEN
Definition: module.c:198
WCHAR * get_dos_file_name(const WCHAR *filename) DECLSPEC_HIDDEN
Definition: path.c:671
struct module * module
Definition: macho_module.c:958
union module_format::@365 u
struct dyld_image_info64 info64
Definition: macho_module.c:72
static void macho_unmap_file(struct image_file_map *fmap)
Definition: macho_module.c:888
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
#define MACHO_SECTION_TYPE
Definition: macho_module.c:168
static void macho_finish_stabs(struct module *module, struct hash_table *ht_symtab)
struct pool pool
Definition: macho_module.c:959
#define SYMOPT_NO_PUBLICS
Definition: compat.h:741
unsigned long long UINT64
GLfloat GLfloat p
Definition: glext.h:8902
struct module * module
Definition: macho_module.c:195
struct image_file_map::@376::macho_file_map macho
#define UnmapViewOfFile
Definition: compat.h:494
static BOOL try_dsym(struct process *pcs, const WCHAR *path, struct macho_file_map *fmap)
struct dyld_all_image_infos64 infos64
Definition: macho_module.c:77
unsigned char UINT8
GLuint64EXT * result
Definition: glext.h:11304
IMAGEHLP_MODULEW64 module
struct module_format * format_info[DFI_LAST]
struct macho_info * macho_info
static BOOL read_process_memory(const struct process *process, UINT64 addr, void *buf, size_t size)
void user(int argc, const char *argv[])
Definition: cmds.c:1350
GLenum query
Definition: glext.h:7781
struct module * next
static void macho_unmap_ranges(const struct macho_file_map *fmap, ULONG_PTR offset1, ULONG_PTR len1, ULONG_PTR offset2, ULONG_PTR len2, const void **mapped1, const void **mapped2)
Definition: macho_module.c:358
#define HeapFree(x, y, z)
Definition: compat.h:483
const char * macho_map_section(struct image_section_map *ism)
Definition: macho_module.c:440
static BOOL image_uses_split_segs(struct process *process, ULONG_PTR load_addr)
#define UUID_STRING_LEN
Definition: macho_module.c:172
#define SetFilePointer
Definition: compat.h:491
static BOOL macho_load_cb(const WCHAR *name, ULONG_PTR addr, void *user)
struct image_file_map * dsym
struct symt_compiland * compiland
Definition: elf_module.c:71
struct image_file_map file_map
Definition: macho_module.c:177
static BOOL macho_find_segment_section(struct image_file_map *ifm, const char *segname, const char *sectname, struct image_section_map *ism)
Definition: macho_module.c:395
static BOOL macho_search_loader(struct process *pcs, struct macho_info *macho_info)
const WCHAR * name
UINT64 imageFileModDate
Definition: macho_module.c:60
static BOOL macho_map_file(struct process *pcs, const WCHAR *filenameW, BOOL split_segs, struct image_file_map *ifm)
Definition: macho_module.c:738
struct symt_ht * symt_find_nearest(struct module *module, DWORD_PTR addr) DECLSPEC_HIDDEN
Definition: symbol.c:903
static BOOL heap_free(void *mem)
Definition: appwiz.h:75
BOOL(* enum_modules_cb)(const WCHAR *, ULONG_PTR addr, void *user)
#define MACHO_LC_SEGMENT_64
Definition: macho_module.c:165
GLuint const GLchar * name
Definition: glext.h:6031