/****************************************************************** * module_get_debug * * get the debug information from a module: * - if the module's type is deferred, then force loading of debug info (and return * the module itself) * - if the module has no debug info and has an ELF container, then return the ELF * container (and also force the ELF container's debug info loading if deferred) * - otherwise return the module itself if it has some debug info */ BOOL module_get_debug(struct module_pair* pair) { IMAGEHLP_DEFERRED_SYMBOL_LOADW64 idslW64; if (!pair->requested) return FALSE; /* for a PE builtin, always get info from container */ if (!(pair->effective = module_get_container(pair->pcs, pair->requested))) pair->effective = pair->requested; /* if deferred, force loading */ if (pair->effective->module.SymType == SymDeferred) { BOOL ret; if (pair->effective->is_virtual) ret = FALSE; else switch (pair->effective->type) { #ifndef DBGHELP_STATIC_LIB case DMT_ELF: ret = elf_load_debug_info(pair->effective); break; #endif case DMT_PE: idslW64.SizeOfStruct = sizeof(idslW64); idslW64.BaseOfImage = pair->effective->module.BaseOfImage; idslW64.CheckSum = pair->effective->module.CheckSum; idslW64.TimeDateStamp = pair->effective->module.TimeDateStamp; memcpy(idslW64.FileName, pair->effective->module.ImageName, sizeof(pair->effective->module.ImageName)); idslW64.Reparse = FALSE; idslW64.hFile = INVALID_HANDLE_VALUE; pcs_callback(pair->pcs, CBA_DEFERRED_SYMBOL_LOAD_START, &idslW64); ret = pe_load_debug_info(pair->pcs, pair->effective); pcs_callback(pair->pcs, ret ? CBA_DEFERRED_SYMBOL_LOAD_COMPLETE : CBA_DEFERRED_SYMBOL_LOAD_FAILURE, &idslW64); break; #ifndef DBGHELP_STATIC_LIB case DMT_MACHO: ret = macho_load_debug_info(pair->effective); break; #endif default: ret = FALSE; break; } if (!ret) pair->effective->module.SymType = SymNone; assert(pair->effective->module.SymType != SymDeferred); pair->effective->module.NumSyms = pair->effective->ht_symbols.num_elts; } return pair->effective->module.SymType != SymNone; }
/****************************************************************** * macho_load_file * * Loads the information for Mach-O module stored in 'filename'. * The module has been loaded at 'load_addr' address. * returns * FALSE if the file cannot be found/opened or if the file doesn't * contain symbolic info (or this info cannot be read or parsed) * TRUE on success */ static BOOL macho_load_file(struct process* pcs, const WCHAR* filename, unsigned long load_addr, struct macho_info* macho_info) { BOOL ret = TRUE; struct macho_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; /* Find the dynamic loader's table of images loaded into the process. */ if (macho_info->flags & MACHO_INFO_DEBUG_HEADER) { static void* dyld_all_image_infos_addr; /* This symbol should be in the same place in all processes. */ 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) macho_info->dbg_hdr_addr = (unsigned long)dyld_all_image_infos_addr; else ret = FALSE; TRACE("dbg_hdr_addr = 0x%08lx\n", macho_info->dbg_hdr_addr); } if (macho_info->flags & MACHO_INFO_MODULE) { struct macho_module_info *macho_module_info; struct module_format* modfmt = HeapAlloc(GetProcessHeap(), 0, sizeof(struct module_format) + sizeof(struct macho_module_info)); if (!modfmt) goto leave; macho_info->module = module_new(pcs, filename, DMT_MACHO, FALSE, load_addr, fmap.segs_size, 0, calc_crc32(fmap.fd)); if (!macho_info->module) { HeapFree(GetProcessHeap(), 0, modfmt); goto leave; } macho_module_info = (void*)(modfmt + 1); macho_info->module->format_info[DFI_MACHO] = modfmt; modfmt->module = macho_info->module; modfmt->remove = NULL; modfmt->loc_compute = NULL; modfmt->u.macho_info = macho_module_info; macho_module_info->load_addr = load_addr; if (dbghelp_options & SYMOPT_DEFERRED_LOADS) macho_info->module->module.SymType = SymDeferred; else if (!macho_load_debug_info(macho_info->module, &fmap)) ret = FALSE; macho_info->module->format_info[DFI_MACHO]->u.macho_info->in_use = 1; macho_info->module->format_info[DFI_MACHO]->u.macho_info->is_loader = 0; TRACE("module = %p\n", macho_info->module); } if (macho_info->flags & MACHO_INFO_NAME) { WCHAR* ptr; ptr = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(filename) + 1) * sizeof(WCHAR)); if (ptr) { strcpyW(ptr, filename); macho_info->module_name = ptr; } else ret = FALSE; TRACE("module_name = %p %s\n", macho_info->module_name, debugstr_w(macho_info->module_name)); } leave: macho_unmap_file(&fmap); TRACE(" => %d\n", ret); return ret; }