/****************************************************************** * fetch_macho_module_info_cb * * Callback for accumulating in dump_context a Mach-O modules set */ static BOOL fetch_macho_module_info_cb(const WCHAR* name, unsigned long base, void* user) { struct dump_context* dc = (struct dump_context*)user; DWORD_PTR rbase; DWORD size, checksum; /* FIXME: there's no relevant timestamp on Mach-O modules */ /* 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)) size = checksum = 0; add_module(dc, name, base ? base : rbase, size, 0 /* FIXME */, checksum, TRUE); return TRUE; }
/* checks that buffer (as found by matching the name) matches the info * (information is based on file type) * returns TRUE when file is found, FALSE to continue searching * (NB this is the opposite convention of SymFindFileInPathProc) */ static BOOL CALLBACK module_find_cb(PCWSTR buffer, PVOID user) { struct module_find* mf = user; DWORD size, checksum, timestamp; unsigned matched = 0; /* the matching weights: * +1 if a file with same name is found and is a decent file of expected type * +1 if first parameter and second parameter match */ /* FIXME: should check that id/two match the file pointed * by buffer */ switch (mf->kind) { case DMT_PE: { HANDLE hFile, hMap; void* mapping; timestamp = ~mf->dw1; size = ~mf->dw2; hFile = CreateFileW(buffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) return FALSE; if ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != NULL) { 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; UnmapViewOfFile(mapping); } CloseHandle(hMap); } CloseHandle(hFile); if (timestamp != mf->dw1) WARN("Found %s, but wrong timestamp\n", debugstr_w(buffer)); if (size != mf->dw2) WARN("Found %s, but wrong size\n", debugstr_w(buffer)); if (timestamp == mf->dw1 && size == mf->dw2) matched++; } break; case DMT_ELF: if (elf_fetch_file_info(buffer, 0, &size, &checksum)) { matched++; if (checksum == mf->dw1) matched++; else WARN("Found %s, but wrong checksums: %08x %08x\n", debugstr_w(buffer), checksum, mf->dw1); } else { WARN("Couldn't read %s\n", debugstr_w(buffer)); return FALSE; } break; case DMT_MACHO: if (macho_fetch_file_info(NULL, buffer, 0, 0, &size, &checksum)) { matched++; if (checksum == mf->dw1) matched++; else WARN("Found %s, but wrong checksums: %08x %08x\n", debugstr_w(buffer), checksum, mf->dw1); } else { WARN("Couldn't read %s\n", debugstr_w(buffer)); return FALSE; } break; case DMT_PDB: { struct pdb_lookup pdb_lookup; char fn[MAX_PATH]; WideCharToMultiByte(CP_ACP, 0, buffer, -1, fn, MAX_PATH, NULL, NULL); pdb_lookup.filename = fn; if (mf->guid) { pdb_lookup.kind = PDB_DS; pdb_lookup.timestamp = 0; pdb_lookup.guid = *mf->guid; } else { pdb_lookup.kind = PDB_JG; pdb_lookup.timestamp = mf->dw1; /* pdb_loopkup.guid = */ } pdb_lookup.age = mf->dw2; if (!pdb_fetch_file_info(&pdb_lookup, &matched)) return FALSE; } break; case DMT_DBG: { HANDLE hFile, hMap; void* mapping; timestamp = ~mf->dw1; hFile = CreateFileW(buffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) return FALSE; if ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != NULL) { if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL) { const IMAGE_SEPARATE_DEBUG_HEADER* hdr; hdr = mapping; if (hdr->Signature == IMAGE_SEPARATE_DEBUG_SIGNATURE) { matched++; timestamp = hdr->TimeDateStamp; } UnmapViewOfFile(mapping); } CloseHandle(hMap); } CloseHandle(hFile); if (timestamp == mf->dw1) matched++; else WARN("Found %s, but wrong timestamp\n", debugstr_w(buffer)); } break; default: FIXME("What the heck??\n"); return FALSE; } if (matched > mf->matched) { strcpyW(mf->filename, buffer); mf->matched = matched; } /* yes, EnumDirTree/do_search and SymFindFileInPath callbacks use the opposite * convention to stop/continue enumeration. sigh. */ return mf->matched == 2; }