ReactOS 0.4.15-dev-7924-g5949c20
macho_module.c File Reference
#include <stdio.h>
#include <assert.h>
#include <stdarg.h>
#include <errno.h>
#include "ntstatus.h"
#include "dbghelp_private.h"
#include "image_private.h"
#include "winternl.h"
#include "winioctl.h"
#include "ddk/mountmgr.h"
#include "wine/debug.h"
#include "wine/heap.h"
Include dependency graph for macho_module.c:

Go to the source code of this file.

Classes

struct  dyld_image_info32
 
struct  dyld_all_image_infos32
 
struct  dyld_image_info64
 
struct  dyld_all_image_infos64
 
union  wine_image_info
 
union  wine_all_image_infos
 
struct  macho_header
 
struct  macho_segment_command
 
struct  macho_segment_command32
 
struct  macho_symtab_command
 
struct  macho_module_info
 
struct  section_info
 
struct  macho_info
 
struct  symtab_elt
 
struct  macho_debug_info
 
struct  macho_load_params
 
struct  macho_sync
 
struct  macho_load
 

Macros

#define WIN32_NO_STATUS
 
#define WINE_MOUNTMGR_EXTENSIONS
 
#define swap_ulong_be_to_host(n)   (RtlUlongByteSwap(n))
 
#define MACHO_DYLD_IN_SHARED_CACHE   0x80000000
 
#define MACHO_FAT_MAGIC   0xcafebabe
 
#define MACHO_MH_MAGIC_32   0xfeedface
 
#define MACHO_MH_MAGIC_64   0xfeedfacf
 
#define MACHO_CPU_TYPE_X86   0x00000007
 
#define MACHO_CPU_TYPE_X86_64   0x01000007
 
#define MACHO_MH_EXECUTE   0x2
 
#define MACHO_MH_DYLIB   0x6
 
#define MACHO_MH_DYLINKER   0x7
 
#define MACHO_MH_BUNDLE   0x8
 
#define MACHO_MH_DSYM   0xa
 
#define MACHO_LC_SEGMENT   0x01
 
#define MACHO_LC_SYMTAB   0x02
 
#define MACHO_LC_SEGMENT_64   0x19
 
#define MACHO_LC_UUID   0x1b
 
#define MACHO_SECTION_TYPE   0x000000ff
 
#define MACHO_S_ATTR_PURE_INSTRUCTIONS   0x80000000
 
#define MACHO_S_ATTR_SOME_INSTRUCTIONS   0x00000400
 
#define UUID_STRING_LEN   37 /* 16 bytes at 2 hex digits apiece, 4 dashes, and the null terminator */
 
#define MACHO_INFO_MODULE   0x0001
 
#define MACHO_INFO_NAME   0x0002
 

Functions

 WINE_DEFAULT_DEBUG_CHANNEL (dbghelp_macho)
 
static void macho_unmap_file (struct image_file_map *fmap)
 
static charformat_uuid (const UINT8 uuid[16], char out[UUID_STRING_LEN])
 
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)
 
static const charmacho_map_range (const struct macho_file_map *fmap, ULONG_PTR offset, ULONG_PTR len, const char **base)
 
static void macho_unmap_range (const char **base, const void **mapped, const struct macho_file_map *fmap, ULONG_PTR offset, ULONG_PTR len)
 
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)
 
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)
 
static BOOL macho_find_segment_section (struct image_file_map *ifm, const char *segname, const char *sectname, struct image_section_map *ism)
 
static BOOL macho_find_section (struct image_file_map *ifm, const char *sectname, struct image_section_map *ism)
 
const charmacho_map_section (struct image_section_map *ism)
 
void macho_unmap_section (struct image_section_map *ism)
 
DWORD_PTR macho_get_map_rva (const struct image_section_map *ism)
 
unsigned macho_get_map_size (const struct image_section_map *ism)
 
static const struct macho_load_commandmacho_map_load_commands (struct macho_file_map *fmap)
 
static void macho_unmap_load_commands (struct macho_file_map *fmap)
 
static const struct macho_load_commandmacho_next_load_command (const struct macho_load_command *lc)
 
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)
 
static int macho_count_sections (struct image_file_map *ifm, const struct macho_load_command *lc, void *user)
 
static int macho_load_section_info (struct image_file_map *ifm, const struct macho_load_command *lc, void *user)
 
static int find_uuid (struct image_file_map *ifm, const struct macho_load_command *lc, void *user)
 
static void reset_file_map (struct image_file_map *ifm)
 
static BOOL macho_map_file (struct process *pcs, const WCHAR *filenameW, BOOL split_segs, struct image_file_map *ifm)
 
static BOOL macho_sect_is_code (struct macho_file_map *fmap, unsigned char sectidx)
 
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)
 
static int macho_parse_symtab (struct image_file_map *ifm, const struct macho_load_command *lc, void *user)
 
static void macho_finish_stabs (struct module *module, struct hash_table *ht_symtab)
 
static BOOL try_dsym (struct process *pcs, const WCHAR *path, struct macho_file_map *fmap)
 
static WCHARquery_dsym (const GUID *uuid, const WCHAR *filename)
 
static void find_and_map_dsym (struct process *pcs, struct module *module)
 
static BOOL image_uses_split_segs (struct process *process, ULONG_PTR load_addr)
 
static BOOL macho_load_debug_info (struct process *pcs, struct module *module)
 
static BOOL macho_fetch_file_info (struct process *process, const WCHAR *name, ULONG_PTR load_addr, DWORD_PTR *base, DWORD *size, DWORD *checksum)
 
static void macho_module_remove (struct process *pcs, struct module_format *modfmt)
 
static BOOL macho_load_file (struct process *pcs, const WCHAR *filename, ULONG_PTR load_addr, struct macho_info *macho_info)
 
static BOOL macho_load_file_cb (void *param, HANDLE handle, const WCHAR *filename)
 
static BOOL macho_search_and_load_file (struct process *pcs, const WCHAR *filename, ULONG_PTR load_addr, struct macho_info *macho_info)
 
static BOOL macho_enum_modules_internal (const struct process *pcs, const WCHAR *main_name, enum_modules_cb cb, void *user)
 
static BOOL macho_enum_sync_cb (const WCHAR *name, ULONG_PTR addr, void *user)
 
static BOOL macho_synchronize_module_list (struct process *pcs)
 
static BOOL macho_enum_modules (struct process *process, enum_modules_cb cb, void *user)
 
static BOOL macho_load_cb (const WCHAR *name, ULONG_PTR addr, void *user)
 
static struct modulemacho_load_module (struct process *pcs, const WCHAR *name, ULONG_PTR addr)
 
static BOOL macho_search_loader (struct process *pcs, struct macho_info *macho_info)
 
BOOL macho_read_wine_loader_dbg_info (struct process *pcs, ULONG_PTR addr)
 

Variables

static const struct image_file_map_ops macho_file_map_ops
 
static const WCHAR dsym_subpath []
 
static const struct loader_ops macho_loader_ops
 

Macro Definition Documentation

◆ MACHO_CPU_TYPE_X86

#define MACHO_CPU_TYPE_X86   0x00000007

Definition at line 154 of file macho_module.c.

◆ MACHO_CPU_TYPE_X86_64

#define MACHO_CPU_TYPE_X86_64   0x01000007

Definition at line 155 of file macho_module.c.

◆ MACHO_DYLD_IN_SHARED_CACHE

#define MACHO_DYLD_IN_SHARED_CACHE   0x80000000

Definition at line 148 of file macho_module.c.

◆ MACHO_FAT_MAGIC

#define MACHO_FAT_MAGIC   0xcafebabe

Definition at line 150 of file macho_module.c.

◆ MACHO_INFO_MODULE

#define MACHO_INFO_MODULE   0x0001

Definition at line 189 of file macho_module.c.

◆ MACHO_INFO_NAME

#define MACHO_INFO_NAME   0x0002

Definition at line 190 of file macho_module.c.

◆ MACHO_LC_SEGMENT

#define MACHO_LC_SEGMENT   0x01

Definition at line 163 of file macho_module.c.

◆ MACHO_LC_SEGMENT_64

#define MACHO_LC_SEGMENT_64   0x19

Definition at line 165 of file macho_module.c.

◆ MACHO_LC_SYMTAB

#define MACHO_LC_SYMTAB   0x02

Definition at line 164 of file macho_module.c.

◆ MACHO_LC_UUID

#define MACHO_LC_UUID   0x1b

Definition at line 166 of file macho_module.c.

◆ MACHO_MH_BUNDLE

#define MACHO_MH_BUNDLE   0x8

Definition at line 160 of file macho_module.c.

◆ MACHO_MH_DSYM

#define MACHO_MH_DSYM   0xa

Definition at line 161 of file macho_module.c.

◆ MACHO_MH_DYLIB

#define MACHO_MH_DYLIB   0x6

Definition at line 158 of file macho_module.c.

◆ MACHO_MH_DYLINKER

#define MACHO_MH_DYLINKER   0x7

Definition at line 159 of file macho_module.c.

◆ MACHO_MH_EXECUTE

#define MACHO_MH_EXECUTE   0x2

Definition at line 157 of file macho_module.c.

◆ MACHO_MH_MAGIC_32

#define MACHO_MH_MAGIC_32   0xfeedface

Definition at line 151 of file macho_module.c.

◆ MACHO_MH_MAGIC_64

#define MACHO_MH_MAGIC_64   0xfeedfacf

Definition at line 152 of file macho_module.c.

◆ MACHO_S_ATTR_PURE_INSTRUCTIONS

#define MACHO_S_ATTR_PURE_INSTRUCTIONS   0x80000000

Definition at line 169 of file macho_module.c.

◆ MACHO_S_ATTR_SOME_INSTRUCTIONS

#define MACHO_S_ATTR_SOME_INSTRUCTIONS   0x00000400

Definition at line 170 of file macho_module.c.

◆ MACHO_SECTION_TYPE

#define MACHO_SECTION_TYPE   0x000000ff

Definition at line 168 of file macho_module.c.

◆ swap_ulong_be_to_host

#define swap_ulong_be_to_host (   n)    (RtlUlongByteSwap(n))

Definition at line 135 of file macho_module.c.

◆ UUID_STRING_LEN

#define UUID_STRING_LEN   37 /* 16 bytes at 2 hex digits apiece, 4 dashes, and the null terminator */

Definition at line 172 of file macho_module.c.

◆ WIN32_NO_STATUS

#define WIN32_NO_STATUS

Definition at line 30 of file macho_module.c.

◆ WINE_MOUNTMGR_EXTENSIONS

#define WINE_MOUNTMGR_EXTENSIONS

Definition at line 36 of file macho_module.c.

Function Documentation

◆ find_and_map_dsym()

static void find_and_map_dsym ( struct process pcs,
struct module module 
)
static

Definition at line 1288 of file macho_module.c.

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
1321 if ((path = query_dsym((const GUID *)fmap->uuid->uuid, p))) try_dsym(pcs, path, fmap);
1322
1323found:
1325}
@ DFI_MACHO
#define NULL
Definition: types.h:112
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
#define lstrcpyW
Definition: compat.h:749
#define lstrlenW
Definition: compat.h:750
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
static WCHAR * query_dsym(const GUID *uuid, const WCHAR *filename)
static const WCHAR dsym_subpath[]
static BOOL try_dsym(struct process *pcs, const WCHAR *path, struct macho_file_map *fmap)
static LPCWSTR file_name
Definition: protocol.c:147
WCHAR LoadedImageName[256]
Definition: compat.h:1078
IMAGEHLP_MODULEW64 module
struct module_format * format_info[DFI_LAST]
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by macho_load_debug_info().

◆ find_uuid()

static int find_uuid ( struct image_file_map ifm,
const struct macho_load_command lc,
void user 
)
static

Definition at line 712 of file macho_module.c.

713{
714 ifm->u.macho.uuid = (const struct macho_uuid_command*)lc;
715 return 1;
716}
struct image_file_map::@385::macho_file_map macho
union image_file_map::@385 u

Referenced by macho_map_file().

◆ format_uuid()

static char * format_uuid ( const UINT8  uuid[16],
char  out[UUID_STRING_LEN] 
)
static

Definition at line 201 of file macho_module.c.

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}
Definition: msctf.idl:550
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static FILE * out
Definition: regtests2xml.c:44

Referenced by macho_map_file(), and try_dsym().

◆ image_uses_split_segs()

static BOOL image_uses_split_segs ( struct process process,
ULONG_PTR  load_addr 
)
static

Definition at line 1337 of file macho_module.c.

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}
unsigned int UINT32
static BOOL read_process_memory(const struct process *process, UINT64 addr, void *buf, size_t size)
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
r reserved
Definition: btrfs.c:3006
unsigned int BOOL
Definition: ntddk_ex.h:94
#define MACHO_DYLD_IN_SHARED_CACHE
Definition: macho_module.c:148
#define MACHO_MH_MAGIC_64
Definition: macho_module.c:152
#define MACHO_MH_MAGIC_32
Definition: macho_module.c:151
#define MACHO_CPU_TYPE_X86_64
Definition: macho_module.c:155
#define MACHO_CPU_TYPE_X86
Definition: macho_module.c:154
int load_addr
Definition: mkisofs.c:104
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
target_cpu
Definition: widl.h:79

Referenced by macho_fetch_file_info(), and macho_load_file().

◆ macho_calc_range()

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 
)
static

Definition at line 217 of file macho_module.c.

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}
SYSTEM_INFO sysinfo
Definition: dbghelp.c:76
GLintptr offset
Definition: glext.h:5920
DWORD dwAllocationGranularity
Definition: winbase.h:1179
uint32_t ULONG_PTR
Definition: typedefs.h:65

Referenced by macho_map_range(), macho_map_ranges(), macho_unmap_range(), and macho_unmap_ranges().

◆ macho_count_sections()

static int macho_count_sections ( struct image_file_map ifm,
const struct macho_load_command lc,
void user 
)
static

Definition at line 588 of file macho_module.c.

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}
void user(int argc, const char *argv[])
Definition: cmds.c:1350
static __inline const char * debugstr_an(const char *s, int n)
Definition: compat.h:55
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define TRACE(s)
Definition: solgame.cpp:4
unsigned addr_size

Referenced by macho_map_file().

◆ macho_enum_load_commands()

static int macho_enum_load_commands ( struct image_file_map ifm,
unsigned  cmd,
int(*)(struct image_file_map *, const struct macho_load_command *, void *)  cb,
void user 
)
static

Definition at line 551 of file macho_module.c.

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}
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint64EXT * result
Definition: glext.h:11304
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 IMAGE_NO_MAP
Definition: image_private.h:24
static const struct macho_load_command * macho_map_load_commands(struct macho_file_map *fmap)
Definition: macho_module.c:503
static const struct macho_load_command * macho_next_load_command(const struct macho_load_command *lc)
Definition: macho_module.c:535
static HMODULE MODULEINFO DWORD cb
Definition: module.c:33
Definition: ftp_var.h:139

Referenced by macho_load_debug_info(), and macho_map_file().

◆ macho_enum_modules()

static BOOL macho_enum_modules ( struct process process,
enum_modules_cb  cb,
void user 
)
static

Definition at line 1736 of file macho_module.c.

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}
#define MACHO_INFO_NAME
Definition: macho_module.c:190
static BOOL macho_enum_modules_internal(const struct process *pcs, const WCHAR *main_name, enum_modules_cb cb, void *user)
const WCHAR * module_name
Definition: macho_module.c:196
unsigned flags
Definition: macho_module.c:194
HANDLE handle
int ret

◆ macho_enum_modules_internal()

static BOOL macho_enum_modules_internal ( const struct process pcs,
const WCHAR main_name,
enum_modules_cb  cb,
void user 
)
static

Definition at line 1601 of file macho_module.c.

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;
1667done:
1668 HeapFree(GetProcessHeap(), 0, info_array);
1669 return ret;
1670}
#define ARRAY_SIZE(A)
Definition: main.h:33
#define CP_UNIXCP
Definition: compat.h:79
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:49
#define MAX_PATH
Definition: compat.h:34
#define MultiByteToWideChar
Definition: compat.h:110
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_w
Definition: kernel32.h:32
static calc_node_t temp
Definition: rpn_ieee.c:38
UINT32 imageLoadAddress
Definition: macho_module.c:44
ULONG_PTR dbg_hdr_addr
struct dyld_image_info64 info64
Definition: macho_module.c:72
struct dyld_image_info32 info32
Definition: macho_module.c:71

Referenced by macho_enum_modules(), macho_load_module(), and macho_synchronize_module_list().

◆ macho_enum_sync_cb()

static BOOL macho_enum_sync_cb ( const WCHAR name,
ULONG_PTR  addr,
void user 
)
static

Definition at line 1678 of file macho_module.c.

1679{
1680 struct macho_sync* ms = user;
1681
1682 TRACE("(%s, 0x%08lx, %p)\n", debugstr_w(name), addr, user);
1684 return TRUE;
1685}
GLenum const GLvoid * addr
Definition: glext.h:9621
static BOOL macho_search_and_load_file(struct process *pcs, const WCHAR *filename, ULONG_PTR load_addr, struct macho_info *macho_info)
struct macho_info macho_info
struct process * pcs
Definition: name.c:39

Referenced by macho_synchronize_module_list().

◆ macho_fetch_file_info()

static BOOL macho_fetch_file_info ( struct process process,
const WCHAR name,
ULONG_PTR  load_addr,
DWORD_PTR base,
DWORD size,
DWORD checksum 
)
static

Definition at line 1424 of file macho_module.c.

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
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}
static cab_ULONG checksum(const cab_UBYTE *data, cab_UWORD bytes, cab_ULONG csum)
Definition: fdi.c:353
DWORD calc_crc32(HANDLE handle)
Definition: dbghelp.c:874
GLsizeiptr size
Definition: glext.h:5919
static BOOL image_uses_split_segs(struct process *process, ULONG_PTR load_addr)
static BOOL macho_map_file(struct process *pcs, const WCHAR *filenameW, BOOL split_segs, struct image_file_map *ifm)
Definition: macho_module.c:738
static void macho_unmap_file(struct image_file_map *fmap)
Definition: macho_module.c:888

◆ macho_find_section()

static BOOL macho_find_section ( struct image_file_map ifm,
const char sectname,
struct image_section_map ism 
)
static

Definition at line 432 of file macho_module.c.

433{
434 return macho_find_segment_section(ifm, NULL, sectname, ism);
435}
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

◆ macho_find_segment_section()

static BOOL macho_find_segment_section ( struct image_file_map ifm,
const char segname,
const char sectname,
struct image_section_map ism 
)
static

Definition at line 395 of file macho_module.c.

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}
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define lstrcpynA
Definition: compat.h:751
struct image_file_map * dsym
struct image_file_map * fmap

Referenced by macho_find_section().

◆ macho_finish_stabs()

static void macho_finish_stabs ( struct module module,
struct hash_table ht_symtab 
)
static

Definition at line 1035 of file macho_module.c.

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
1193 {
1194 symt_new_public(module, ste->compiland, ste->ht_elt.name, ste->is_code, ste->addr, 0);
1195 }
1196 }
1197}
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
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
BOOL symt_get_info(struct module *module, const struct symt *type, IMAGEHLP_SYMBOL_TYPE_INFO req, void *pInfo) DECLSPEC_HIDDEN
Definition: type.c:536
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
void hash_table_iter_init(const struct hash_table *ht, struct hash_table_iter *hti, const char *name) DECLSPEC_HIDDEN
Definition: storage.c:405
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
void * hash_table_iter_up(struct hash_table_iter *hti) DECLSPEC_HIDDEN
Definition: storage.c:422
BOOL symt_get_address(const struct symt *type, ULONG64 *addr) DECLSPEC_HIDDEN
Definition: type.c:119
@ loc_absolute
struct symt_ht * symt_find_nearest(struct module *module, DWORD_PTR addr) DECLSPEC_HIDDEN
Definition: symbol.c:903
#define SYMOPT_NO_PUBLICS
Definition: compat.h:993
#define SYMOPT_PUBLICS_ONLY
Definition: compat.h:992
@ TI_GET_LENGTH
Definition: compat.h:1417
@ TI_GET_DATAKIND
Definition: compat.h:1423
@ SymTagFunction
Definition: compat.h:1586
@ SymTagData
Definition: compat.h:1588
DataKind
Definition: compat.h:1647
@ DataIsGlobal
Definition: compat.h:1654
@ DataIsFileStatic
Definition: compat.h:1653
unsigned dbghelp_options
Definition: dbghelp.c:73
unsigned long DWORD
Definition: ntddk_ex.h:95
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLenum func
Definition: glext.h:6028
unsigned __int64 ULONG64
Definition: imports.h:198
static PVOID ptr
Definition: dispmode.c:27
WCHAR ModuleName[32]
Definition: compat.h:1076
unsigned kind
int sortlist_valid
struct hash_table ht_symbols
struct hash_table_elt hash_elt
struct hash_table_elt hash_elt
struct symt symt
unsigned char is_public
Definition: macho_module.c:950
struct hash_table_elt ht_elt
Definition: elf_module.c:69
unsigned used
Definition: elf_module.c:72
unsigned char is_code
Definition: macho_module.c:949
struct symt_compiland * compiland
Definition: elf_module.c:71
ULONG_PTR addr
Definition: macho_module.c:948
unsigned char is_global
Definition: macho_module.c:951
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260

Referenced by macho_load_debug_info().

◆ macho_get_map_rva()

DWORD_PTR macho_get_map_rva ( const struct image_section_map ism)

Definition at line 469 of file macho_module.c.

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}

◆ macho_get_map_size()

unsigned macho_get_map_size ( const struct image_section_map ism)

Definition at line 480 of file macho_module.c.

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}

◆ macho_load_cb()

static BOOL macho_load_cb ( const WCHAR name,
ULONG_PTR  addr,
void user 
)
static

Definition at line 1763 of file macho_module.c.

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}
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
struct macho_info macho_info
struct process * pcs
const WCHAR * name

Referenced by macho_load_module().

◆ macho_load_debug_info()

static BOOL macho_load_debug_info ( struct process pcs,
struct module module 
)
static

Definition at line 1363 of file macho_module.c.

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 {
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
1413 macho_finish_stabs(module, &mdi.ht_symtab);
1414
1415 pool_destroy(&mdi.pool);
1416 return ret;
1417}
#define ERR(fmt,...)
Definition: debug.h:110
void hash_table_init(struct pool *pool, struct hash_table *ht, unsigned num_buckets) DECLSPEC_HIDDEN
Definition: storage.c:334
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
void pool_init(struct pool *a, size_t arena_size) DECLSPEC_HIDDEN
Definition: storage.c:43
void pool_destroy(struct pool *a) DECLSPEC_HIDDEN
Definition: storage.c:50
@ DMT_MACHO
@ SymExport
Definition: compat.h:1060
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
static void find_and_map_dsym(struct process *pcs, struct module *module)
static void macho_finish_stabs(struct module *module, struct hash_table *ht_symtab)
static int macho_parse_symtab(struct image_file_map *ifm, const struct macho_load_command *lc, void *user)
Definition: macho_module.c:999
#define MACHO_LC_SYMTAB
Definition: macho_module.c:164
SYM_TYPE SymType
Definition: compat.h:1075
DWORD64 reloc_delta
enum module_type type

Referenced by macho_load_file().

◆ macho_load_file()

static BOOL macho_load_file ( struct process pcs,
const WCHAR filename,
ULONG_PTR  load_addr,
struct macho_info macho_info 
)
static

Definition at line 1460 of file macho_module.c.

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
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 {
1519 }
1520 else ret = FALSE;
1521 TRACE("module_name = %p %s\n", macho_info->module_name, debugstr_w(macho_info->module_name));
1522 }
1523leave:
1524 macho_unmap_file(&fmap);
1525
1526 TRACE(" => %d\n", ret);
1527 return ret;
1528}
#define leave
Definition: btrfs_drv.h:138
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
@ SymDeferred
Definition: compat.h:1061
#define SYMOPT_DEFERRED_LOADS
Definition: compat.h:989
const char * filename
Definition: ioapi.h:137
#define MACHO_INFO_MODULE
Definition: macho_module.c:189
static void macho_module_remove(struct process *pcs, struct module_format *modfmt)
static void reset_file_map(struct image_file_map *ifm)
Definition: macho_module.c:721
static BOOL macho_load_debug_info(struct process *pcs, struct module *module)
struct module * module
Definition: macho_module.c:195
ULONG_PTR load_addr
Definition: macho_module.c:178
struct image_file_map file_map
Definition: macho_module.c:177
struct module * module
struct macho_module_info * macho_info
void(* loc_compute)(struct process *pcs, const struct module_format *modfmt, const struct symt_function *func, struct location *loc)
void(* remove)(struct process *pcs, struct module_format *modfmt)
union module_format::@374 u

Referenced by macho_load_file_cb(), macho_search_and_load_file(), and macho_search_loader().

◆ macho_load_file_cb()

static BOOL macho_load_file_cb ( void param,
HANDLE  handle,
const WCHAR filename 
)
static

Definition at line 1537 of file macho_module.c.

1538{
1540 return macho_load_file(macho_load->process, filename, macho_load->load_addr, macho_load->macho_info);
1541}
GLfloat param
Definition: glext.h:5796
static BOOL macho_load_file(struct process *pcs, const WCHAR *filename, ULONG_PTR load_addr, struct macho_info *macho_info)

Referenced by macho_search_and_load_file().

◆ macho_load_module()

static struct module * macho_load_module ( struct process pcs,
const WCHAR name,
ULONG_PTR  addr 
)
static

Definition at line 1789 of file macho_module.c.

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;
1813 ml.ret = macho_search_and_load_file(pcs, ml.name, addr, &ml.macho_info);
1814 }
1815 if (!ml.ret) return NULL;
1816 assert(ml.macho_info.module);
1817 return ml.macho_info.module;
1818}
#define assert(x)
Definition: debug.h:53
static BOOL macho_load_cb(const WCHAR *name, ULONG_PTR addr, void *user)
char * name
Definition: compiler.c:66

◆ macho_load_section_info()

static int macho_load_section_info ( struct image_file_map ifm,
const struct macho_load_command lc,
void user 
)
static

Definition at line 620 of file macho_module.c.

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}
unsigned long long UINT64
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
static UINT_PTR page_mask
Definition: virtual.c:49
struct section sections[2]
Definition: diskspace.c:792
DWORD dwPageSize
Definition: winbase.h:1173
Definition: parser.c:56

Referenced by macho_map_file().

◆ macho_map_file()

static BOOL macho_map_file ( struct process pcs,
const WCHAR filenameW,
BOOL  split_segs,
struct image_file_map ifm 
)
static

Definition at line 738 of file macho_module.c.

740{
741 struct macho_file_map* fmap = &ifm->u.macho;
742 struct macho_header mach_header;
743 int i;
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:
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;
876done:
877 if (!ret)
878 macho_unmap_file(ifm);
880 return ret;
881}
WCHAR * get_dos_file_name(const WCHAR *filename) DECLSPEC_HIDDEN
Definition: path.c:671
#define FILE_BEGIN
Definition: compat.h:761
#define OPEN_EXISTING
Definition: compat.h:775
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define SetFilePointer
Definition: compat.h:743
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define GENERIC_READ
Definition: compat.h:135
#define CreateFileW
Definition: compat.h:741
#define FILE_SHARE_READ
Definition: compat.h:136
int align(int length, int align)
Definition: dsound8.c:36
static char * format_uuid(const UINT8 uuid[16], char out[UUID_STRING_LEN])
Definition: macho_module.c:201
#define MACHO_MH_BUNDLE
Definition: macho_module.c:160
#define MACHO_MH_DYLINKER
Definition: macho_module.c:159
#define UUID_STRING_LEN
Definition: macho_module.c:172
static int find_uuid(struct image_file_map *ifm, const struct macho_load_command *lc, void *user)
Definition: macho_module.c:712
#define MACHO_MH_DSYM
Definition: macho_module.c:161
#define MACHO_LC_SEGMENT_64
Definition: macho_module.c:165
#define MACHO_LC_SEGMENT
Definition: macho_module.c:163
#define swap_ulong_be_to_host(n)
Definition: macho_module.c:135
static int macho_load_section_info(struct image_file_map *ifm, const struct macho_load_command *lc, void *user)
Definition: macho_module.c:620
#define MACHO_MH_DYLIB
Definition: macho_module.c:158
#define MACHO_MH_EXECUTE
Definition: macho_module.c:157
#define MACHO_LC_UUID
Definition: macho_module.c:166
static const struct image_file_map_ops macho_file_map_ops
Definition: macho_module.c:488
#define MACHO_FAT_MAGIC
Definition: macho_module.c:150
static int macho_count_sections(struct image_file_map *ifm, const struct macho_load_command *lc, void *user)
Definition: macho_module.c:588
static const WCHAR filenameW[]
Definition: amstream.c:41
u32_t magic(void)
#define L(x)
Definition: ntvdm.h:50
#define errno
Definition: errno.h:18
static const char * uuid_string(const UUID *uuid)
Definition: header.c:146
enum module_type modtype
struct image_file_map * alternate
const struct image_file_map_ops * ops
DWORD WINAPI GetLastError(void)
Definition: except.c:1042

Referenced by macho_fetch_file_info(), macho_load_file(), and try_dsym().

◆ macho_map_load_commands()

static const struct macho_load_command * macho_map_load_commands ( struct macho_file_map *  fmap)
static

Definition at line 503 of file macho_module.c.

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}
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

Referenced by macho_enum_load_commands().

◆ macho_map_range()

static const char * macho_map_range ( const struct macho_file_map *  fmap,
ULONG_PTR  offset,
ULONG_PTR  len,
const char **  base 
)
static

Definition at line 238 of file macho_module.c.

240{
241 ULONG_PTR misalign, aligned_offset, aligned_map_end;
242 const void* aligned_ptr;
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}
#define CloseHandle
Definition: compat.h:739
#define PAGE_READONLY
Definition: compat.h:138
#define CreateFileMappingW(a, b, c, d, e, f)
Definition: compat.h:744
#define FILE_MAP_READ
Definition: compat.h:776
#define MapViewOfFile
Definition: compat.h:745
GLenum GLenum GLenum GLenum mapping
Definition: glext.h:9031
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

Referenced by macho_map_load_commands(), macho_map_ranges(), and macho_map_section().

◆ macho_map_ranges()

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 
)
static

Definition at line 306 of file macho_module.c.

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}
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

Referenced by macho_parse_symtab().

◆ macho_map_section()

const char * macho_map_section ( struct image_section_map ism)

Definition at line 440 of file macho_module.c.

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}

◆ macho_module_remove()

static void macho_module_remove ( struct process pcs,
struct module_format modfmt 
)
static

Definition at line 1444 of file macho_module.c.

1445{
1446 macho_unmap_file(&modfmt->u.macho_info->file_map);
1447 HeapFree(GetProcessHeap(), 0, modfmt);
1448}

Referenced by macho_load_file().

◆ macho_next_load_command()

static const struct macho_load_command * macho_next_load_command ( const struct macho_load_command lc)
static

Definition at line 535 of file macho_module.c.

536{
537 return (const struct macho_load_command*)((const char*)lc + lc->cmdsize);
538}

Referenced by macho_enum_load_commands().

◆ macho_parse_symtab()

static int macho_parse_symtab ( struct image_file_map ifm,
const struct macho_load_command lc,
void user 
)
static

Definition at line 999 of file macho_module.c.

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}
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
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
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
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
struct module * module
Definition: macho_module.c:958

Referenced by macho_load_debug_info().

◆ macho_read_wine_loader_dbg_info()

BOOL macho_read_wine_loader_dbg_info ( struct process pcs,
ULONG_PTR  addr 
)

Definition at line 1911 of file macho_module.c.

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 module_set_module(struct module *module, const WCHAR *name) DECLSPEC_HIDDEN
Definition: module.c:142
const WCHAR S_WineLoaderW[]
Definition: module.c:42
static BOOL macho_search_loader(struct process *pcs, struct macho_info *macho_info)
static const struct loader_ops macho_loader_ops
const struct loader_ops * loader

Referenced by check_live_target().

◆ macho_search_and_load_file()

static BOOL macho_search_and_load_file ( struct process pcs,
const WCHAR filename,
ULONG_PTR  load_addr,
struct macho_info macho_info 
)
static

Definition at line 1548 of file macho_module.c.

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}
BOOL search_dll_path(const struct process *process, const WCHAR *name, BOOL(*match)(void *, HANDLE, const WCHAR *), void *param) DECLSPEC_HIDDEN
Definition: path.c:697
struct module * module_is_already_loaded(const struct process *pcs, const WCHAR *imgname) DECLSPEC_HIDDEN
Definition: module.c:303
BOOL search_unix_path(const WCHAR *name, const WCHAR *path, BOOL(*match)(void *, HANDLE, const WCHAR *), void *param) DECLSPEC_HIDDEN
Definition: path.c:782
const WCHAR * process_getenv(const struct process *process, const WCHAR *name)
Definition: dbghelp.c:335
_CONST_RETURN wchar_t *__cdecl wcsstr(_In_z_ const wchar_t *_Str, _In_z_ const wchar_t *_SubStr)
static BOOL macho_load_file_cb(void *param, HANDLE handle, const WCHAR *filename)
struct macho_info * macho_info

Referenced by macho_enum_sync_cb(), macho_load_cb(), macho_load_module(), and macho_search_loader().

◆ macho_search_loader()

static BOOL macho_search_loader ( struct process pcs,
struct macho_info macho_info 
)
static

Definition at line 1828 of file macho_module.c.

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}
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
WCHAR * get_wine_loader_name(struct process *pcs) DECLSPEC_HIDDEN
Definition: module.c:150

Referenced by macho_read_wine_loader_dbg_info().

◆ macho_sect_is_code()

static BOOL macho_sect_is_code ( struct macho_file_map *  fmap,
unsigned char  sectidx 
)
static

Definition at line 927 of file macho_module.c.

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}
#define MACHO_SECTION_TYPE
Definition: macho_module.c:168
#define MACHO_S_ATTR_PURE_INSTRUCTIONS
Definition: macho_module.c:169
#define MACHO_S_ATTR_SOME_INSTRUCTIONS
Definition: macho_module.c:170

Referenced by macho_stabs_def_cb().

◆ macho_stabs_def_cb()

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 
)
static

Definition at line 968 of file macho_module.c.

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}
void * pool_alloc(struct pool *a, size_t len) DECLSPEC_HIDDEN
Definition: storage.c:89
char * pool_strdup(struct pool *a, const char *str) DECLSPEC_HIDDEN
Definition: storage.c:126
void hash_table_add(struct hash_table *ht, struct hash_table_elt *elt) DECLSPEC_HIDDEN
Definition: storage.c:378
static BOOL macho_sect_is_code(struct macho_file_map *fmap, unsigned char sectidx)
Definition: macho_module.c:927
struct hash_table ht_symtab
Definition: macho_module.c:960
struct macho_file_map * fmap
Definition: macho_module.c:957
struct pool pool
Definition: macho_module.c:959

Referenced by macho_parse_symtab().

◆ macho_synchronize_module_list()

static BOOL macho_synchronize_module_list ( struct process pcs)
static

Definition at line 1695 of file macho_module.c.

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}
BOOL module_remove(struct process *pcs, struct module *module) DECLSPEC_HIDDEN
Definition: module.c:889
static BOOL macho_enum_sync_cb(const WCHAR *name, ULONG_PTR addr, void *user)
unsigned short is_virtual
struct module * next

◆ macho_unmap_file()

static void macho_unmap_file ( struct image_file_map fmap)
static

Definition at line 888 of file macho_module.c.

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++)
906
907 HeapFree(GetProcessHeap(), 0, ifm->u.macho.sect);
908 macho_unmap_load_commands(&ifm->u.macho);
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}
const char cursor[]
Definition: icontest.c:13
void macho_unmap_section(struct image_section_map *ism)
Definition: macho_module.c:455
static void macho_unmap_load_commands(struct macho_file_map *fmap)
Definition: macho_module.c:520
static unsigned __int64 next
Definition: rand_nt.c:6

Referenced by macho_fetch_file_info(), macho_load_file(), macho_map_file(), macho_module_remove(), and try_dsym().

◆ macho_unmap_load_commands()

static void macho_unmap_load_commands ( struct macho_file_map *  fmap)
static

Definition at line 520 of file macho_module.c.

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}

Referenced by macho_unmap_file().

◆ macho_unmap_range()

static void macho_unmap_range ( const char **  base,
const void **  mapped,
const struct macho_file_map *  fmap,
ULONG_PTR  offset,
ULONG_PTR  len 
)
static

Definition at line 274 of file macho_module.c.

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)
296 }
297}
#define UnmapViewOfFile
Definition: compat.h:746

Referenced by macho_map_ranges(), macho_unmap_load_commands(), macho_unmap_ranges(), and macho_unmap_section().

◆ macho_unmap_ranges()

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 
)
static

Definition at line 358 of file macho_module.c.

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}

Referenced by macho_parse_symtab().

◆ macho_unmap_section()

void macho_unmap_section ( struct image_section_map ism)

Definition at line 455 of file macho_module.c.

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}

Referenced by macho_unmap_file().

◆ query_dsym()

static WCHAR * query_dsym ( const GUID uuid,
const WCHAR filename 
)
static

Definition at line 1239 of file macho_module.c.

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;
1271 }
1272
1273 if (query != (void *)buf) HeapFree(GetProcessHeap(), 0, query);
1274 return ret;
1275}
#define ERROR_MORE_DATA
Definition: dderror.h:13
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
GLuint res
Definition: glext.h:9613
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define MOUNTMGR_DOS_DEVICE_NAME
Definition: mountmgr.h:11
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define GENERIC_WRITE
Definition: nt_native.h:90
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3275

Referenced by find_and_map_dsym().

◆ reset_file_map()

static void reset_file_map ( struct image_file_map ifm)
inlinestatic

Definition at line 721 of file macho_module.c.

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}

Referenced by macho_load_file(), and macho_map_file().

◆ try_dsym()

static BOOL try_dsym ( struct process pcs,
const WCHAR path,
struct macho_file_map *  fmap 
)
static

Definition at line 1208 of file macho_module.c.

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}

Referenced by find_and_map_dsym().

◆ WINE_DEFAULT_DEBUG_CHANNEL()

WINE_DEFAULT_DEBUG_CHANNEL ( dbghelp_macho  )

Variable Documentation

◆ dsym_subpath

const WCHAR dsym_subpath[]
static
Initial value:
= {'\\','C','o','n','t','e','n','t','s',
'\\','R','e','s','o','u','r','c','e','s',
'\\','D','W','A','R','F','\\',0}

Definition at line 1235 of file macho_module.c.

Referenced by find_and_map_dsym(), and query_dsym().

◆ macho_file_map_ops

const struct image_file_map_ops macho_file_map_ops
static
Initial value:
=
{
}
DWORD_PTR macho_get_map_rva(const struct image_section_map *ism)
Definition: macho_module.c:469
const char * macho_map_section(struct image_section_map *ism)
Definition: macho_module.c:440
static BOOL macho_find_section(struct image_file_map *ifm, const char *sectname, struct image_section_map *ism)
Definition: macho_module.c:432
unsigned macho_get_map_size(const struct image_section_map *ism)
Definition: macho_module.c:480

Definition at line 488 of file macho_module.c.

Referenced by macho_map_file().

◆ macho_loader_ops

const struct loader_ops macho_loader_ops
static
Initial value:
=
{
}
static BOOL macho_fetch_file_info(struct process *process, const WCHAR *name, ULONG_PTR load_addr, DWORD_PTR *base, DWORD *size, DWORD *checksum)
static BOOL macho_synchronize_module_list(struct process *pcs)
static struct module * macho_load_module(struct process *pcs, const WCHAR *name, ULONG_PTR addr)
static BOOL macho_enum_modules(struct process *process, enum_modules_cb cb, void *user)

Definition at line 1897 of file macho_module.c.

Referenced by macho_read_wine_loader_dbg_info().