mirror of
https://github.com/reactos/reactos.git
synced 2024-12-31 19:42:51 +00:00
[DBGHELP] Sync with Wine Staging 1.7.55. CORE-10536
svn path=/trunk/; revision=69971
This commit is contained in:
parent
2a4a7e23eb
commit
1e9f469b55
14 changed files with 304 additions and 127 deletions
|
@ -263,7 +263,7 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CO
|
|||
}
|
||||
}
|
||||
else
|
||||
/* FIXME: this will allow to work when we're not attached to a live target,
|
||||
/* FIXME: this will allow it to work when we're not attached to a live target,
|
||||
* but the 16 <=> 32 switch facility won't be available.
|
||||
*/
|
||||
curr_switch = 0;
|
||||
|
|
|
@ -276,7 +276,7 @@ static BOOL check_live_target(struct process* pcs)
|
|||
* The initialisation of a dbghelp's context.
|
||||
* Note that hProcess doesn't need to be a valid process handle (except
|
||||
* when fInvadeProcess is TRUE).
|
||||
* Since, we're also allow to load ELF (pure) libraries and Wine ELF libraries
|
||||
* Since we also allow loading ELF (pure) libraries and Wine ELF libraries
|
||||
* containing PE (and NE) module(s), here's how we handle it:
|
||||
* - we load every module (ELF, NE, PE) passed in SymLoadModule
|
||||
* - in fInvadeProcess (in SymInitialize) is TRUE, we set up what is called ELF
|
||||
|
|
|
@ -187,7 +187,7 @@
|
|||
@ stdcall SymUnloadModule(long long)
|
||||
@ stdcall SymUnloadModule64(long double)
|
||||
@ stdcall UnDecorateSymbolName(str str long long)
|
||||
@ stdcall UnDecorateSymbolNameW(str str long long)
|
||||
@ stdcall UnDecorateSymbolNameW(wstr ptr long long)
|
||||
@ stdcall UnmapDebugInformation(ptr)
|
||||
@ stdcall WinDbgExtensionDllInit(ptr long long)
|
||||
#@ stdcall block
|
||||
|
|
|
@ -621,7 +621,7 @@ extern int elf_is_in_thunk_area(unsigned long addr, const struct elf_th
|
|||
|
||||
/* macho_module.c */
|
||||
extern BOOL macho_enum_modules(HANDLE hProc, enum_modules_cb, void*) DECLSPEC_HIDDEN;
|
||||
extern BOOL macho_fetch_file_info(const WCHAR* name, DWORD_PTR* base, DWORD* size, DWORD* checksum) DECLSPEC_HIDDEN;
|
||||
extern BOOL macho_fetch_file_info(HANDLE process, const WCHAR* name, unsigned long load_addr, DWORD_PTR* base, DWORD* size, DWORD* checksum) DECLSPEC_HIDDEN;
|
||||
extern BOOL macho_load_debug_info(struct module* module) DECLSPEC_HIDDEN;
|
||||
extern struct module*
|
||||
macho_load_module(struct process* pcs, const WCHAR* name, unsigned long) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -1811,6 +1811,9 @@ static void dwarf2_parse_subprogram_block(dwarf2_subprogram_t* subpgm,
|
|||
case DW_TAG_subroutine_type:
|
||||
dwarf2_parse_subroutine_type(subpgm->ctx, di);
|
||||
break;
|
||||
case DW_TAG_const_type:
|
||||
dwarf2_parse_const_type(subpgm->ctx, di);
|
||||
break;
|
||||
case DW_TAG_lexical_block:
|
||||
dwarf2_parse_subprogram_block(subpgm, block, child);
|
||||
break;
|
||||
|
@ -1945,6 +1948,9 @@ static struct symt* dwarf2_parse_subprogram(dwarf2_parse_context_t* ctx,
|
|||
case DW_TAG_pointer_type:
|
||||
dwarf2_parse_pointer_type(subpgm.ctx, di);
|
||||
break;
|
||||
case DW_TAG_const_type:
|
||||
dwarf2_parse_const_type(subpgm.ctx, di);
|
||||
break;
|
||||
case DW_TAG_subprogram:
|
||||
/* FIXME: likely a declaration (to be checked)
|
||||
* skip it for now
|
||||
|
|
|
@ -128,6 +128,7 @@ struct image_file_map
|
|||
{
|
||||
const macho_section* section;
|
||||
const char* mapped;
|
||||
unsigned int ignored : 1;
|
||||
}* sect;
|
||||
#endif
|
||||
} macho;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <mach-o/fat.h>
|
||||
#include <mach-o/loader.h>
|
||||
#include <mach-o/nlist.h>
|
||||
#include <mach-o/dyld.h>
|
||||
|
||||
#ifdef HAVE_MACH_O_DYLD_IMAGES_H
|
||||
#include <mach-o/dyld_images.h>
|
||||
|
@ -77,6 +78,16 @@ typedef struct nlist macho_nlist;
|
|||
#endif
|
||||
|
||||
|
||||
/* Bitmask for Mach-O image header flags indicating that the image is in dyld's
|
||||
shared cached. That implies that its segments are mapped non-contiguously.
|
||||
This value isn't defined anywhere in headers. It's used in dyld and in
|
||||
debuggers which support OS X as a magic number.
|
||||
|
||||
The flag also isn't set in the on-disk image file. It's only set in
|
||||
memory by dyld. */
|
||||
#define MACHO_DYLD_IN_SHARED_CACHE 0x80000000
|
||||
|
||||
|
||||
#define UUID_STRING_LEN 37 /* 16 bytes at 2 hex digits apiece, 4 dashes, and the null terminator */
|
||||
|
||||
|
||||
|
@ -88,6 +99,12 @@ struct macho_module_info
|
|||
is_loader : 1;
|
||||
};
|
||||
|
||||
struct section_info
|
||||
{
|
||||
BOOL split_segs;
|
||||
unsigned int section_index;
|
||||
};
|
||||
|
||||
#define MACHO_INFO_DEBUG_HEADER 0x0001
|
||||
#define MACHO_INFO_MODULE 0x0002
|
||||
#define MACHO_INFO_NAME 0x0004
|
||||
|
@ -310,8 +327,9 @@ BOOL macho_find_section(struct image_file_map* ifm, const char* segname, const c
|
|||
fmap = &ifm->u.macho;
|
||||
for (i = 0; i < fmap->num_sections; i++)
|
||||
{
|
||||
if (strcmp(fmap->sect[i].section->sectname, sectname) == 0 &&
|
||||
(!segname || strcmp(fmap->sect[i].section->sectname, segname) == 0))
|
||||
if (!fmap->sect[i].ignored &&
|
||||
strcmp(fmap->sect[i].section->sectname, sectname) == 0 &&
|
||||
(!segname || strcmp(fmap->sect[i].section->segname, segname) == 0))
|
||||
{
|
||||
ism->fmap = ifm;
|
||||
ism->sidx = i;
|
||||
|
@ -334,7 +352,7 @@ const char* macho_map_section(struct image_section_map* ism)
|
|||
struct macho_file_map* fmap = &ism->fmap->u.macho;
|
||||
|
||||
assert(ism->fmap->modtype == DMT_MACHO);
|
||||
if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.macho.num_sections)
|
||||
if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.macho.num_sections || fmap->sect[ism->sidx].ignored)
|
||||
return IMAGE_NO_MAP;
|
||||
|
||||
return macho_map_range(fmap, fmap->sect[ism->sidx].section->offset, fmap->sect[ism->sidx].section->size,
|
||||
|
@ -360,7 +378,8 @@ void macho_unmap_section(struct image_section_map* ism)
|
|||
*/
|
||||
DWORD_PTR macho_get_map_rva(const struct image_section_map* ism)
|
||||
{
|
||||
if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.macho.num_sections)
|
||||
if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.macho.num_sections ||
|
||||
ism->fmap->u.macho.sect[ism->sidx].ignored)
|
||||
return 0;
|
||||
return ism->fmap->u.macho.sect[ism->sidx].section->addr - ism->fmap->u.macho.segs_start;
|
||||
}
|
||||
|
@ -370,7 +389,8 @@ DWORD_PTR macho_get_map_rva(const struct image_section_map* ism)
|
|||
*/
|
||||
unsigned macho_get_map_size(const struct image_section_map* ism)
|
||||
{
|
||||
if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.macho.num_sections)
|
||||
if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.macho.num_sections ||
|
||||
ism->fmap->u.macho.sect[ism->sidx].ignored)
|
||||
return 0;
|
||||
return ism->fmap->u.macho.sect[ism->sidx].section->size;
|
||||
}
|
||||
|
@ -484,7 +504,8 @@ static int macho_count_sections(struct macho_file_map* fmap, const struct load_c
|
|||
static int macho_load_section_info(struct macho_file_map* fmap, const struct load_command* lc, void* user)
|
||||
{
|
||||
const macho_segment_command* sc = (const macho_segment_command*)lc;
|
||||
int* section_index = (int*)user;
|
||||
struct section_info* info = user;
|
||||
BOOL ignore;
|
||||
const macho_section* section;
|
||||
int i;
|
||||
unsigned long tmp, page_mask = sysconf( _SC_PAGESIZE ) - 1;
|
||||
|
@ -494,10 +515,17 @@ static int macho_load_section_info(struct macho_file_map* fmap, const struct loa
|
|||
TRACE("Segment command vm: 0x%08lx - 0x%08lx\n", (unsigned long)sc->vmaddr,
|
||||
(unsigned long)(sc->vmaddr + sc->vmsize));
|
||||
|
||||
/* Images in the dyld shared cache have their segments mapped non-contiguously.
|
||||
We don't know how to properly locate any of the segments other than __TEXT,
|
||||
so ignore them. */
|
||||
ignore = (info->split_segs && strcmp(sc->segname, SEG_TEXT));
|
||||
|
||||
if (!strncmp(sc->segname, "WINE_", 5))
|
||||
TRACE("Ignoring special Wine segment %s\n", debugstr_an(sc->segname, sizeof(sc->segname)));
|
||||
else if (!strncmp(sc->segname, "__PAGEZERO", 10))
|
||||
TRACE("Ignoring __PAGEZERO segment\n");
|
||||
else if (ignore)
|
||||
TRACE("Ignoring %s segment because image has split segments\n", sc->segname);
|
||||
else
|
||||
{
|
||||
/* If this segment starts before previously-known earliest, record new earliest. */
|
||||
|
@ -514,9 +542,10 @@ static int macho_load_section_info(struct macho_file_map* fmap, const struct loa
|
|||
section = (const macho_section*)(sc + 1);
|
||||
for (i = 0; i < sc->nsects; i++)
|
||||
{
|
||||
fmap->sect[*section_index].section = §ion[i];
|
||||
fmap->sect[*section_index].mapped = IMAGE_NO_MAP;
|
||||
(*section_index)++;
|
||||
fmap->sect[info->section_index].section = §ion[i];
|
||||
fmap->sect[info->section_index].mapped = IMAGE_NO_MAP;
|
||||
fmap->sect[info->section_index].ignored = ignore;
|
||||
info->section_index++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -554,7 +583,7 @@ static inline void reset_file_map(struct image_file_map* ifm)
|
|||
*
|
||||
* Maps a Mach-O file into memory (and checks it's a real Mach-O file)
|
||||
*/
|
||||
static BOOL macho_map_file(const WCHAR* filenameW, struct image_file_map* ifm)
|
||||
static BOOL macho_map_file(const WCHAR* filenameW, BOOL split_segs, struct image_file_map* ifm)
|
||||
{
|
||||
struct macho_file_map* fmap = &ifm->u.macho;
|
||||
struct fat_header fat_header;
|
||||
|
@ -562,6 +591,7 @@ static BOOL macho_map_file(const WCHAR* filenameW, struct image_file_map* ifm)
|
|||
int i;
|
||||
char* filename;
|
||||
unsigned len;
|
||||
struct section_info info;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
TRACE("(%s, %p)\n", debugstr_w(filenameW), fmap);
|
||||
|
@ -662,8 +692,9 @@ static BOOL macho_map_file(const WCHAR* filenameW, struct image_file_map* ifm)
|
|||
fmap->segs_size = 0;
|
||||
fmap->segs_start = ~0L;
|
||||
|
||||
i = 0;
|
||||
if (macho_enum_load_commands(fmap, TARGET_SEGMENT_COMMAND, macho_load_section_info, &i) < 0)
|
||||
info.split_segs = split_segs;
|
||||
info.section_index = 0;
|
||||
if (macho_enum_load_commands(fmap, TARGET_SEGMENT_COMMAND, macho_load_section_info, &info) < 0)
|
||||
{
|
||||
fmap->num_sections = 0;
|
||||
goto done;
|
||||
|
@ -744,7 +775,7 @@ static BOOL macho_sect_is_code(struct macho_file_map* fmap, unsigned char sectid
|
|||
if (!sectidx) return FALSE;
|
||||
|
||||
sectidx--; /* convert from 1-based to 0-based */
|
||||
if (sectidx >= fmap->num_sections) return FALSE;
|
||||
if (sectidx >= fmap->num_sections || fmap->sect[sectidx].ignored) return FALSE;
|
||||
|
||||
ret = (!(fmap->sect[sectidx].section->flags & SECTION_TYPE) &&
|
||||
(fmap->sect[sectidx].section->flags & (S_ATTR_PURE_INSTRUCTIONS|S_ATTR_SOME_INSTRUCTIONS)));
|
||||
|
@ -1018,7 +1049,7 @@ static BOOL try_dsym(const WCHAR* path, struct macho_file_map* fmap)
|
|||
{
|
||||
struct image_file_map dsym_ifm;
|
||||
|
||||
if (macho_map_file(path, &dsym_ifm))
|
||||
if (macho_map_file(path, FALSE, &dsym_ifm))
|
||||
{
|
||||
char uuid_string[UUID_STRING_LEN];
|
||||
|
||||
|
@ -1127,6 +1158,34 @@ found:
|
|||
if (query) CFRelease(query);
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* image_uses_split_segs
|
||||
*
|
||||
* Determine if the Mach-O image loaded at a particular address in
|
||||
* the given process is in the dyld shared cache and therefore has
|
||||
* its segments mapped non-contiguously.
|
||||
*
|
||||
* The image header has to be loaded from the process's memory
|
||||
* because the relevant flag is only set in memory, not in the file.
|
||||
*/
|
||||
static BOOL image_uses_split_segs(HANDLE process, unsigned long load_addr)
|
||||
{
|
||||
BOOL split_segs = FALSE;
|
||||
|
||||
if (process && load_addr)
|
||||
{
|
||||
macho_mach_header header;
|
||||
if (ReadProcessMemory(process, (void*)load_addr, &header, sizeof(header), NULL) &&
|
||||
header.magic == TARGET_MH_MAGIC && header.cputype == TARGET_CPU_TYPE &&
|
||||
header.flags & MACHO_DYLD_IN_SHARED_CACHE)
|
||||
{
|
||||
split_segs = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return split_segs;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* macho_load_debug_info
|
||||
*
|
||||
|
@ -1191,14 +1250,16 @@ BOOL macho_load_debug_info(struct module* module)
|
|||
*
|
||||
* Gathers some more information for a Mach-O module from a given file
|
||||
*/
|
||||
BOOL macho_fetch_file_info(const WCHAR* name, DWORD_PTR* base,
|
||||
BOOL macho_fetch_file_info(HANDLE process, const WCHAR* name, unsigned long load_addr, DWORD_PTR* base,
|
||||
DWORD* size, DWORD* checksum)
|
||||
{
|
||||
struct image_file_map fmap;
|
||||
BOOL split_segs;
|
||||
|
||||
TRACE("(%s, %p, %p, %p)\n", debugstr_w(name), base, size, checksum);
|
||||
|
||||
if (!macho_map_file(name, &fmap)) return FALSE;
|
||||
split_segs = image_uses_split_segs(process, load_addr);
|
||||
if (!macho_map_file(name, split_segs, &fmap)) return FALSE;
|
||||
if (base) *base = fmap.u.macho.segs_start;
|
||||
*size = fmap.u.macho.segs_size;
|
||||
*checksum = calc_crc32(fmap.u.macho.fd);
|
||||
|
@ -1215,6 +1276,57 @@ static void macho_module_remove(struct process* pcs, struct module_format* modfm
|
|||
HeapFree(GetProcessHeap(), 0, modfmt);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* get_dyld_image_info_address
|
||||
*/
|
||||
static ULONG_PTR get_dyld_image_info_address(struct process* pcs)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PROCESS_BASIC_INFORMATION pbi;
|
||||
ULONG_PTR dyld_image_info_address = 0;
|
||||
|
||||
/* Get address of PEB */
|
||||
status = NtQueryInformationProcess(pcs->handle, ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
|
||||
if (status == STATUS_SUCCESS)
|
||||
{
|
||||
/* Read dyld image info address from PEB */
|
||||
if (ReadProcessMemory(pcs->handle, &pbi.PebBaseAddress->Reserved[0],
|
||||
&dyld_image_info_address, sizeof(dyld_image_info_address), NULL))
|
||||
{
|
||||
TRACE("got dyld_image_info_address 0x%08lx from PEB %p MacDyldImageInfo %p\n",
|
||||
(unsigned long)dyld_image_info_address, pbi.PebBaseAddress, &pbi.PebBaseAddress->Reserved);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef __LP64__ /* No reading the symtab with nlist(3) in LP64 */
|
||||
if (!dyld_image_info_address)
|
||||
{
|
||||
static void* dyld_all_image_infos_addr;
|
||||
|
||||
/* Our next best guess is that dyld was loaded at its base address
|
||||
and we can find the dyld image infos address by looking up its symbol. */
|
||||
if (!dyld_all_image_infos_addr)
|
||||
{
|
||||
struct nlist nl[2];
|
||||
memset(nl, 0, sizeof(nl));
|
||||
nl[0].n_un.n_name = (char*)"_dyld_all_image_infos";
|
||||
if (!nlist("/usr/lib/dyld", nl))
|
||||
dyld_all_image_infos_addr = (void*)nl[0].n_value;
|
||||
}
|
||||
|
||||
if (dyld_all_image_infos_addr)
|
||||
{
|
||||
TRACE("got dyld_image_info_address %p from /usr/lib/dyld symbol table\n",
|
||||
dyld_all_image_infos_addr);
|
||||
dyld_image_info_address = (ULONG_PTR)dyld_all_image_infos_addr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return dyld_image_info_address;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* macho_load_file
|
||||
*
|
||||
|
@ -1229,65 +1341,21 @@ static BOOL macho_load_file(struct process* pcs, const WCHAR* filename,
|
|||
unsigned long load_addr, struct macho_info* macho_info)
|
||||
{
|
||||
BOOL ret = TRUE;
|
||||
BOOL split_segs;
|
||||
struct image_file_map fmap;
|
||||
|
||||
TRACE("(%p/%p, %s, 0x%08lx, %p/0x%08x)\n", pcs, pcs->handle, debugstr_w(filename),
|
||||
load_addr, macho_info, macho_info->flags);
|
||||
|
||||
if (!macho_map_file(filename, &fmap)) return FALSE;
|
||||
split_segs = image_uses_split_segs(pcs->handle, load_addr);
|
||||
if (!macho_map_file(filename, split_segs, &fmap)) return FALSE;
|
||||
|
||||
/* Find the dynamic loader's table of images loaded into the process.
|
||||
*/
|
||||
if (macho_info->flags & MACHO_INFO_DEBUG_HEADER)
|
||||
{
|
||||
PROCESS_BASIC_INFORMATION pbi;
|
||||
NTSTATUS status;
|
||||
|
||||
ret = FALSE;
|
||||
|
||||
/* Get address of PEB */
|
||||
status = NtQueryInformationProcess(pcs->handle, ProcessBasicInformation,
|
||||
&pbi, sizeof(pbi), NULL);
|
||||
if (status == STATUS_SUCCESS)
|
||||
{
|
||||
ULONG_PTR dyld_image_info;
|
||||
|
||||
/* Read dyld image info address from PEB */
|
||||
if (ReadProcessMemory(pcs->handle, &pbi.PebBaseAddress->Reserved[0],
|
||||
&dyld_image_info, sizeof(dyld_image_info), NULL))
|
||||
{
|
||||
TRACE("got dyld_image_info 0x%08lx from PEB %p MacDyldImageInfo %p\n",
|
||||
(unsigned long)dyld_image_info, pbi.PebBaseAddress, &pbi.PebBaseAddress->Reserved);
|
||||
macho_info->dbg_hdr_addr = dyld_image_info;
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef __LP64__ /* No reading the symtab with nlist(3) in LP64 */
|
||||
if (!ret)
|
||||
{
|
||||
static void* dyld_all_image_infos_addr;
|
||||
|
||||
/* Our next best guess is that dyld was loaded at its base address
|
||||
and we can find the dyld image infos address by looking up its symbol. */
|
||||
if (!dyld_all_image_infos_addr)
|
||||
{
|
||||
struct nlist nl[2];
|
||||
memset(nl, 0, sizeof(nl));
|
||||
nl[0].n_un.n_name = (char*)"_dyld_all_image_infos";
|
||||
if (!nlist("/usr/lib/dyld", nl))
|
||||
dyld_all_image_infos_addr = (void*)nl[0].n_value;
|
||||
}
|
||||
|
||||
if (dyld_all_image_infos_addr)
|
||||
{
|
||||
TRACE("got dyld_image_info %p from /usr/lib/dyld symbol table\n",
|
||||
dyld_all_image_infos_addr);
|
||||
macho_info->dbg_hdr_addr = (unsigned long)dyld_all_image_infos_addr;
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
macho_info->dbg_hdr_addr = (unsigned long)get_dyld_image_info_address(pcs);
|
||||
ret = TRUE;
|
||||
}
|
||||
|
||||
if (macho_info->flags & MACHO_INFO_MODULE)
|
||||
|
@ -1457,7 +1525,7 @@ static BOOL macho_search_and_load_file(struct process* pcs, const WCHAR* filenam
|
|||
|
||||
if (strstrW(filename, S_libstdcPPW)) return FALSE; /* We know we can't do it */
|
||||
|
||||
/* If has no directories, try LD_LIBRARY_PATH first. */
|
||||
/* If has no directories, try PATH first. */
|
||||
if (!strchrW(filename, '/'))
|
||||
{
|
||||
ret = macho_load_file_from_path(pcs, filename, load_addr,
|
||||
|
@ -1477,8 +1545,10 @@ static BOOL macho_search_and_load_file(struct process* pcs, const WCHAR* filenam
|
|||
/* Try DYLD_FALLBACK_LIBRARY_PATH, with just the filename (no directories). */
|
||||
if (!ret)
|
||||
{
|
||||
ret = macho_load_file_from_path(pcs, p, load_addr,
|
||||
getenv("DYLD_FALLBACK_LIBRARY_PATH"), macho_info);
|
||||
const char* fallback = getenv("DYLD_FALLBACK_LIBRARY_PATH");
|
||||
if (!fallback)
|
||||
fallback = "/usr/local/lib:/lib:/usr/lib";
|
||||
ret = macho_load_file_from_path(pcs, p, load_addr, fallback, macho_info);
|
||||
}
|
||||
if (!ret && !strchrW(filename, '/'))
|
||||
ret = macho_load_file_from_dll_path(pcs, filename, load_addr, macho_info);
|
||||
|
@ -1607,7 +1677,62 @@ BOOL macho_synchronize_module_list(struct process* pcs)
|
|||
*/
|
||||
static BOOL macho_search_loader(struct process* pcs, struct macho_info* macho_info)
|
||||
{
|
||||
return macho_search_and_load_file(pcs, get_wine_loader_name(), 0, macho_info);
|
||||
BOOL ret = FALSE;
|
||||
ULONG_PTR dyld_image_info_address;
|
||||
struct dyld_all_image_infos image_infos;
|
||||
struct dyld_image_info image_info;
|
||||
uint32_t len;
|
||||
char path[PATH_MAX];
|
||||
BOOL got_path = FALSE;
|
||||
|
||||
dyld_image_info_address = get_dyld_image_info_address(pcs);
|
||||
if (dyld_image_info_address &&
|
||||
ReadProcessMemory(pcs->handle, (void*)dyld_image_info_address, &image_infos, sizeof(image_infos), NULL) &&
|
||||
image_infos.infoArray && image_infos.infoArrayCount &&
|
||||
ReadProcessMemory(pcs->handle, image_infos.infoArray, &image_info, sizeof(image_info), NULL) &&
|
||||
image_info.imageFilePath)
|
||||
{
|
||||
for (len = sizeof(path); len > 0; len /= 2)
|
||||
{
|
||||
if (ReadProcessMemory(pcs->handle, image_info.imageFilePath, path, len, NULL))
|
||||
{
|
||||
path[len - 1] = 0;
|
||||
got_path = TRUE;
|
||||
TRACE("got executable path from target's dyld image info: %s\n", debugstr_a(path));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we couldn't get the executable path from the target process, try our
|
||||
own. It will almost always be the same. */
|
||||
if (!got_path)
|
||||
{
|
||||
len = sizeof(path);
|
||||
if (!_NSGetExecutablePath(path, &len))
|
||||
{
|
||||
got_path = TRUE;
|
||||
TRACE("using own executable path: %s\n", debugstr_a(path));
|
||||
}
|
||||
}
|
||||
|
||||
if (got_path)
|
||||
{
|
||||
WCHAR* pathW;
|
||||
|
||||
len = MultiByteToWideChar(CP_UNIXCP, 0, path, -1, NULL, 0);
|
||||
pathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
||||
if (pathW)
|
||||
{
|
||||
MultiByteToWideChar(CP_UNIXCP, 0, path, -1, pathW, len);
|
||||
ret = macho_load_file(pcs, pathW, 0, macho_info);
|
||||
HeapFree(GetProcessHeap(), 0, pathW);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
ret = macho_search_and_load_file(pcs, get_wine_loader_name(), 0, macho_info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
|
@ -1755,7 +1880,7 @@ BOOL macho_synchronize_module_list(struct process* pcs)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL macho_fetch_file_info(const WCHAR* name, DWORD_PTR* base,
|
||||
BOOL macho_fetch_file_info(HANDLE process, const WCHAR* name, unsigned long load_addr, DWORD_PTR* base,
|
||||
DWORD* size, DWORD* checksum)
|
||||
{
|
||||
return FALSE;
|
||||
|
|
|
@ -279,7 +279,7 @@ static BOOL fetch_macho_module_info_cb(const WCHAR* name, unsigned long base,
|
|||
/* NB: if we have a non-null base from the live-target use it. If we have
|
||||
* a null base, then grab its base address from Mach-O file.
|
||||
*/
|
||||
if (!macho_fetch_file_info(name, &rbase, &size, &checksum))
|
||||
if (!macho_fetch_file_info(dc->hProcess, name, base, &rbase, &size, &checksum))
|
||||
size = checksum = 0;
|
||||
add_module(dc, name, base ? base : rbase, size, 0 /* FIXME */, checksum, TRUE);
|
||||
return TRUE;
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
|
||||
|
||||
#define DLLPREFIX ""
|
||||
|
||||
const WCHAR S_ElfW[] = {'<','e','l','f','>','\0'};
|
||||
const WCHAR S_WineLoaderW[] = {'<','w','i','n','e','-','l','o','a','d','e','r','>','\0'};
|
||||
static const WCHAR S_DotSoW[] = {'.','s','o','\0'};
|
||||
|
@ -422,16 +420,6 @@ static BOOL module_is_container_loaded(const struct process* pcs,
|
|||
size_t len;
|
||||
struct module* module;
|
||||
PCWSTR filename, modname;
|
||||
static WCHAR* dll_prefix;
|
||||
static int dll_prefix_len;
|
||||
|
||||
if (!dll_prefix)
|
||||
{
|
||||
dll_prefix_len = MultiByteToWideChar( CP_UNIXCP, 0, DLLPREFIX, -1, NULL, 0 );
|
||||
dll_prefix = HeapAlloc( GetProcessHeap(), 0, dll_prefix_len * sizeof(WCHAR) );
|
||||
MultiByteToWideChar( CP_UNIXCP, 0, DLLPREFIX, -1, dll_prefix, dll_prefix_len );
|
||||
dll_prefix_len--;
|
||||
}
|
||||
|
||||
if (!base) return FALSE;
|
||||
filename = get_filename(ImageName, NULL);
|
||||
|
@ -444,7 +432,6 @@ static BOOL module_is_container_loaded(const struct process* pcs,
|
|||
base < module->module.BaseOfImage + module->module.ImageSize)
|
||||
{
|
||||
modname = get_filename(module->module.LoadedImageName, NULL);
|
||||
if (dll_prefix_len && !strncmpW( modname, dll_prefix, dll_prefix_len )) modname += dll_prefix_len;
|
||||
if (!strncmpiW(modname, filename, len) &&
|
||||
!memcmp(modname + len, S_DotSoW, 3 * sizeof(WCHAR)))
|
||||
{
|
||||
|
|
|
@ -208,6 +208,31 @@ static void codeview_init_basic_types(struct module* module)
|
|||
cv_basic_types[T_64PINT8] = &symt_new_pointer(module, cv_basic_types[T_INT8], 8)->symt;
|
||||
cv_basic_types[T_64PUINT8] = &symt_new_pointer(module, cv_basic_types[T_UINT8], 8)->symt;
|
||||
cv_basic_types[T_64PHRESULT]= &symt_new_pointer(module, cv_basic_types[T_HRESULT], 8)->symt;
|
||||
|
||||
cv_basic_types[T_PVOID] = &symt_new_pointer(module, cv_basic_types[T_VOID], sizeof(void*))->symt;
|
||||
cv_basic_types[T_PCHAR] = &symt_new_pointer(module, cv_basic_types[T_CHAR], sizeof(void*))->symt;
|
||||
cv_basic_types[T_PSHORT] = &symt_new_pointer(module, cv_basic_types[T_SHORT], sizeof(void*))->symt;
|
||||
cv_basic_types[T_PLONG] = &symt_new_pointer(module, cv_basic_types[T_LONG], sizeof(void*))->symt;
|
||||
cv_basic_types[T_PQUAD] = &symt_new_pointer(module, cv_basic_types[T_QUAD], sizeof(void*))->symt;
|
||||
cv_basic_types[T_PUCHAR] = &symt_new_pointer(module, cv_basic_types[T_UCHAR], sizeof(void*))->symt;
|
||||
cv_basic_types[T_PUSHORT] = &symt_new_pointer(module, cv_basic_types[T_USHORT], sizeof(void*))->symt;
|
||||
cv_basic_types[T_PULONG] = &symt_new_pointer(module, cv_basic_types[T_ULONG], sizeof(void*))->symt;
|
||||
cv_basic_types[T_PUQUAD] = &symt_new_pointer(module, cv_basic_types[T_UQUAD], sizeof(void*))->symt;
|
||||
cv_basic_types[T_PBOOL08] = &symt_new_pointer(module, cv_basic_types[T_BOOL08], sizeof(void*))->symt;
|
||||
cv_basic_types[T_PBOOL16] = &symt_new_pointer(module, cv_basic_types[T_BOOL16], sizeof(void*))->symt;
|
||||
cv_basic_types[T_PBOOL32] = &symt_new_pointer(module, cv_basic_types[T_BOOL32], sizeof(void*))->symt;
|
||||
cv_basic_types[T_PBOOL64] = &symt_new_pointer(module, cv_basic_types[T_BOOL64], sizeof(void*))->symt;
|
||||
cv_basic_types[T_PREAL32] = &symt_new_pointer(module, cv_basic_types[T_REAL32], sizeof(void*))->symt;
|
||||
cv_basic_types[T_PREAL64] = &symt_new_pointer(module, cv_basic_types[T_REAL64], sizeof(void*))->symt;
|
||||
cv_basic_types[T_PREAL80] = &symt_new_pointer(module, cv_basic_types[T_REAL80], sizeof(void*))->symt;
|
||||
cv_basic_types[T_PRCHAR] = &symt_new_pointer(module, cv_basic_types[T_RCHAR], sizeof(void*))->symt;
|
||||
cv_basic_types[T_PWCHAR] = &symt_new_pointer(module, cv_basic_types[T_WCHAR], sizeof(void*))->symt;
|
||||
cv_basic_types[T_PINT2] = &symt_new_pointer(module, cv_basic_types[T_INT2], sizeof(void*))->symt;
|
||||
cv_basic_types[T_PUINT2] = &symt_new_pointer(module, cv_basic_types[T_UINT2], sizeof(void*))->symt;
|
||||
cv_basic_types[T_PINT4] = &symt_new_pointer(module, cv_basic_types[T_INT4], sizeof(void*))->symt;
|
||||
cv_basic_types[T_PUINT4] = &symt_new_pointer(module, cv_basic_types[T_UINT4], sizeof(void*))->symt;
|
||||
cv_basic_types[T_PINT8] = &symt_new_pointer(module, cv_basic_types[T_INT8], sizeof(void*))->symt;
|
||||
cv_basic_types[T_PUINT8] = &symt_new_pointer(module, cv_basic_types[T_UINT8], sizeof(void*))->symt;
|
||||
}
|
||||
|
||||
static int leaf_as_variant(VARIANT* v, const unsigned short int* leaf)
|
||||
|
@ -1960,24 +1985,24 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* roo
|
|||
break;
|
||||
|
||||
/* the symbols we can safely ignore for now */
|
||||
case 0x112c:
|
||||
case S_TRAMPOLINE:
|
||||
case S_FRAMEINFO_V2:
|
||||
case S_SECUCOOKIE_V3:
|
||||
case S_SECTINFO_V3:
|
||||
case S_SUBSECTINFO_V3:
|
||||
case S_ENTRYPOINT_V3:
|
||||
case 0x113e:
|
||||
case 0x1139:
|
||||
case 0x1141:
|
||||
case 0x1142:
|
||||
case 0x1143:
|
||||
case 0x1144:
|
||||
case 0x114c:
|
||||
case 0x114d:
|
||||
case 0x114e:
|
||||
case 0x1145:
|
||||
case 0x115a:
|
||||
case 0x1153:
|
||||
case S_LOCAL_VS2013:
|
||||
case S_CALLSITEINFO:
|
||||
case S_DEFRANGE_REGISTER:
|
||||
case S_DEFRANGE_FRAMEPOINTER_REL:
|
||||
case S_DEFRANGE_SUBFIELD_REGISTER:
|
||||
case S_FPOFF_VS2013:
|
||||
case S_DEFRANGE_REGISTER_REL:
|
||||
case S_BUILDINFO:
|
||||
case S_INLINESITE:
|
||||
case S_INLINESITE_END:
|
||||
case S_FILESTATIC:
|
||||
case S_CALLEES:
|
||||
TRACE("Unsupported symbol id %x\n", sym->generic.id);
|
||||
break;
|
||||
|
||||
|
|
|
@ -482,7 +482,13 @@ static BOOL CALLBACK module_find_cb(PCWSTR buffer, PVOID user)
|
|||
if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL)
|
||||
{
|
||||
IMAGE_NT_HEADERS* nth = RtlImageNtHeader(mapping);
|
||||
|
||||
if (!nth)
|
||||
{
|
||||
UnmapViewOfFile(mapping);
|
||||
CloseHandle(hMap);
|
||||
CloseHandle(hFile);
|
||||
return FALSE;
|
||||
}
|
||||
matched++;
|
||||
timestamp = nth->FileHeader.TimeDateStamp;
|
||||
size = nth->OptionalHeader.SizeOfImage;
|
||||
|
@ -514,7 +520,7 @@ static BOOL CALLBACK module_find_cb(PCWSTR buffer, PVOID user)
|
|||
}
|
||||
break;
|
||||
case DMT_MACHO:
|
||||
if (macho_fetch_file_info(buffer, 0, &size, &checksum))
|
||||
if (macho_fetch_file_info(NULL, buffer, 0, 0, &size, &checksum))
|
||||
{
|
||||
matched++;
|
||||
if (checksum == mf->dw1) matched++;
|
||||
|
|
|
@ -600,16 +600,6 @@ SymSrvStoreSupplementW(HANDLE hProcess,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
DWORD WINAPI
|
||||
UnDecorateSymbolNameW(PCWSTR DecoratedName,
|
||||
PWSTR pszUnDecoratedName,
|
||||
DWORD dwUndecoratedLength,
|
||||
DWORD dwFlags)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
HANDLE
|
||||
WINAPI
|
||||
FindDebugInfoFileExW(
|
||||
|
|
|
@ -1760,32 +1760,69 @@ BOOL WINAPI SymUnDName64(PIMAGEHLP_SYMBOL64 sym, PSTR UnDecName, DWORD UnDecName
|
|||
static void * CDECL und_alloc(size_t len) { return HeapAlloc(GetProcessHeap(), 0, len); }
|
||||
static void CDECL und_free (void* ptr) { HeapFree(GetProcessHeap(), 0, ptr); }
|
||||
|
||||
/***********************************************************************
|
||||
* UnDecorateSymbolName (DBGHELP.@)
|
||||
*/
|
||||
DWORD WINAPI UnDecorateSymbolName(PCSTR DecoratedName, PSTR UnDecoratedName,
|
||||
DWORD UndecoratedLength, DWORD Flags)
|
||||
static char *und_name(char *buffer, const char *mangled, int buflen, unsigned short flags)
|
||||
{
|
||||
/* undocumented from msvcrt */
|
||||
static HANDLE hMsvcrt;
|
||||
static char* (CDECL *p_undname)(char*, const char*, int, void* (CDECL*)(size_t), void (CDECL*)(void*), unsigned short);
|
||||
static const WCHAR szMsvcrt[] = {'m','s','v','c','r','t','.','d','l','l',0};
|
||||
|
||||
TRACE("(%s, %p, %d, 0x%08x)\n",
|
||||
debugstr_a(DecoratedName), UnDecoratedName, UndecoratedLength, Flags);
|
||||
|
||||
if (!p_undname)
|
||||
{
|
||||
if (!hMsvcrt) hMsvcrt = LoadLibraryW(szMsvcrt);
|
||||
if (hMsvcrt) p_undname = (void*)GetProcAddress(hMsvcrt, "__unDName");
|
||||
if (!p_undname) return 0;
|
||||
if (!p_undname) return NULL;
|
||||
}
|
||||
|
||||
if (!UnDecoratedName) return 0;
|
||||
if (!p_undname(UnDecoratedName, DecoratedName, UndecoratedLength,
|
||||
und_alloc, und_free, Flags))
|
||||
return p_undname(buffer, mangled, buflen, und_alloc, und_free, flags);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* UnDecorateSymbolName (DBGHELP.@)
|
||||
*/
|
||||
DWORD WINAPI UnDecorateSymbolName(const char *decorated_name, char *undecorated_name,
|
||||
DWORD undecorated_length, DWORD flags)
|
||||
{
|
||||
TRACE("(%s, %p, %d, 0x%08x)\n",
|
||||
debugstr_a(decorated_name), undecorated_name, undecorated_length, flags);
|
||||
|
||||
if (!undecorated_name || !undecorated_length)
|
||||
return 0;
|
||||
return strlen(UnDecoratedName);
|
||||
if (!und_name(undecorated_name, decorated_name, undecorated_length, flags))
|
||||
return 0;
|
||||
return strlen(undecorated_name);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* UnDecorateSymbolNameW (DBGHELP.@)
|
||||
*/
|
||||
DWORD WINAPI UnDecorateSymbolNameW(const WCHAR *decorated_name, WCHAR *undecorated_name,
|
||||
DWORD undecorated_length, DWORD flags)
|
||||
{
|
||||
char *buf, *ptr;
|
||||
int len, ret = 0;
|
||||
|
||||
TRACE("(%s, %p, %d, 0x%08x)\n",
|
||||
debugstr_w(decorated_name), undecorated_name, undecorated_length, flags);
|
||||
|
||||
if (!undecorated_name || !undecorated_length)
|
||||
return 0;
|
||||
|
||||
len = WideCharToMultiByte(CP_ACP, 0, decorated_name, -1, NULL, 0, NULL, NULL);
|
||||
if ((buf = HeapAlloc(GetProcessHeap(), 0, len)))
|
||||
{
|
||||
WideCharToMultiByte(CP_ACP, 0, decorated_name, -1, buf, len, NULL, NULL);
|
||||
if ((ptr = und_name(NULL, buf, 0, flags)))
|
||||
{
|
||||
MultiByteToWideChar(CP_ACP, 0, ptr, -1, undecorated_name, undecorated_length);
|
||||
undecorated_name[undecorated_length - 1] = 0;
|
||||
ret = strlenW(undecorated_name);
|
||||
und_free(ptr);
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, buf);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define WILDCHAR(x) (-(x))
|
||||
|
|
|
@ -63,7 +63,7 @@ reactos/dll/win32/cryptdlg # Synced to WineStaging-1.7.47
|
|||
reactos/dll/win32/cryptdll # Synced to WineStaging-1.7.47
|
||||
reactos/dll/win32/cryptnet # Synced to WineStaging-1.7.47
|
||||
reactos/dll/win32/cryptui # Synced to WineStaging-1.7.47
|
||||
reactos/dll/win32/dbghelp # Synced to WineStaging-1.7.47
|
||||
reactos/dll/win32/dbghelp # Synced to WineStaging-1.7.55
|
||||
reactos/dll/win32/dciman32 # Synced to WineStaging-1.7.47
|
||||
reactos/dll/win32/faultrep # Synced to WineStaging-1.7.47
|
||||
reactos/dll/win32/fltlib # Synced to WineStaging-1.7.47
|
||||
|
|
Loading…
Reference in a new issue