VirtualBox

source: vbox/trunk/src/VBox/Debugger/DBGCDumpImage.cpp@ 78058

Last change on this file since 78058 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.5 KB
Line 
1/* $Id: DBGCDumpImage.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * DBGC - Debugger Console, Native Commands.
4 */
5
6/*
7 * Copyright (C) 2006-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_DBGC
23#include <VBox/dbg.h>
24#include <VBox/vmm/dbgf.h>
25#include <VBox/param.h>
26#include <iprt/errcore.h>
27#include <VBox/log.h>
28
29#include <iprt/assert.h>
30#include <iprt/ctype.h>
31#include <iprt/dir.h>
32#include <iprt/env.h>
33#include <iprt/ldr.h>
34#include <iprt/mem.h>
35#include <iprt/path.h>
36#include <iprt/string.h>
37#include <iprt/formats/mz.h>
38#include <iprt/formats/pecoff.h>
39#include <iprt/formats/elf32.h>
40#include <iprt/formats/elf64.h>
41#include <iprt/formats/codeview.h>
42
43#include "DBGCInternal.h"
44
45
46/*********************************************************************************************************************************
47* Structures and Typedefs *
48*********************************************************************************************************************************/
49/**
50 * PE dumper instance.
51 */
52typedef struct DUMPIMAGEPE
53{
54 /** Pointer to the image base address variable. */
55 PCDBGCVAR pImageBase;
56 /** Pointer to the file header. */
57 PCIMAGE_FILE_HEADER pFileHdr;
58 /** Pointer to the NT headers. */
59 union
60 {
61 PCIMAGE_NT_HEADERS32 pNt32;
62 PCIMAGE_NT_HEADERS64 pNt64;
63 void *pv;
64 } u;
65 /** Pointer to the section headers. */
66 PCIMAGE_SECTION_HEADER paShdrs;
67 /** Number of section headers. */
68 unsigned cShdrs;
69 /** Number of RVA and sizes (data directory entries). */
70 unsigned cDataDir;
71 /** Pointer to the data directory. */
72 PCIMAGE_DATA_DIRECTORY paDataDir;
73
74 /** The command descriptor (for failing the command). */
75 PCDBGCCMD pCmd;
76} DUMPIMAGEPE;
77/** Pointer to a PE dumper instance. */
78typedef DUMPIMAGEPE *PDUMPIMAGEPE;
79
80
81/*********************************************************************************************************************************
82* Internal Functions *
83*********************************************************************************************************************************/
84extern FNDBGCCMD dbgcCmdDumpImage; /* See DBGCCommands.cpp. */
85
86
87static const char *dbgcPeMachineName(uint16_t uMachine)
88{
89 switch (uMachine)
90 {
91 case IMAGE_FILE_MACHINE_I386 : return "I386";
92 case IMAGE_FILE_MACHINE_AMD64 : return "AMD64";
93 case IMAGE_FILE_MACHINE_UNKNOWN : return "UNKNOWN";
94 case IMAGE_FILE_MACHINE_BASIC_16 : return "BASIC_16";
95 case IMAGE_FILE_MACHINE_BASIC_16_TV : return "BASIC_16_TV";
96 case IMAGE_FILE_MACHINE_IAPX16 : return "IAPX16";
97 case IMAGE_FILE_MACHINE_IAPX16_TV : return "IAPX16_TV";
98 //case IMAGE_FILE_MACHINE_IAPX20 : return "IAPX20";
99 //case IMAGE_FILE_MACHINE_IAPX20_TV : return "IAPX20_TV";
100 case IMAGE_FILE_MACHINE_I8086 : return "I8086";
101 case IMAGE_FILE_MACHINE_I8086_TV : return "I8086_TV";
102 case IMAGE_FILE_MACHINE_I286_SMALL : return "I286_SMALL";
103 case IMAGE_FILE_MACHINE_MC68 : return "MC68";
104 //case IMAGE_FILE_MACHINE_MC68_WR : return "MC68_WR";
105 case IMAGE_FILE_MACHINE_MC68_TV : return "MC68_TV";
106 case IMAGE_FILE_MACHINE_MC68_PG : return "MC68_PG";
107 //case IMAGE_FILE_MACHINE_I286_LARGE : return "I286_LARGE";
108 case IMAGE_FILE_MACHINE_U370_WR : return "U370_WR";
109 case IMAGE_FILE_MACHINE_AMDAHL_470_WR: return "AMDAHL_470_WR";
110 case IMAGE_FILE_MACHINE_AMDAHL_470_RO: return "AMDAHL_470_RO";
111 case IMAGE_FILE_MACHINE_U370_RO : return "U370_RO";
112 case IMAGE_FILE_MACHINE_R4000 : return "R4000";
113 case IMAGE_FILE_MACHINE_WCEMIPSV2 : return "WCEMIPSV2";
114 case IMAGE_FILE_MACHINE_VAX_WR : return "VAX_WR";
115 case IMAGE_FILE_MACHINE_VAX_RO : return "VAX_RO";
116 case IMAGE_FILE_MACHINE_SH3 : return "SH3";
117 case IMAGE_FILE_MACHINE_SH3DSP : return "SH3DSP";
118 case IMAGE_FILE_MACHINE_SH4 : return "SH4";
119 case IMAGE_FILE_MACHINE_SH5 : return "SH5";
120 case IMAGE_FILE_MACHINE_ARM : return "ARM";
121 case IMAGE_FILE_MACHINE_THUMB : return "THUMB";
122 case IMAGE_FILE_MACHINE_ARMNT : return "ARMNT";
123 case IMAGE_FILE_MACHINE_AM33 : return "AM33";
124 case IMAGE_FILE_MACHINE_POWERPC : return "POWERPC";
125 case IMAGE_FILE_MACHINE_POWERPCFP : return "POWERPCFP";
126 case IMAGE_FILE_MACHINE_IA64 : return "IA64";
127 case IMAGE_FILE_MACHINE_MIPS16 : return "MIPS16";
128 case IMAGE_FILE_MACHINE_MIPSFPU : return "MIPSFPU";
129 case IMAGE_FILE_MACHINE_MIPSFPU16 : return "MIPSFPU16";
130 case IMAGE_FILE_MACHINE_EBC : return "EBC";
131 case IMAGE_FILE_MACHINE_M32R : return "M32R";
132 case IMAGE_FILE_MACHINE_ARM64 : return "ARM64";
133 }
134 return "??";
135}
136
137
138static const char *dbgcPeDataDirName(unsigned iDir)
139{
140 switch (iDir)
141 {
142 case IMAGE_DIRECTORY_ENTRY_EXPORT: return "EXPORT";
143 case IMAGE_DIRECTORY_ENTRY_IMPORT: return "IMPORT";
144 case IMAGE_DIRECTORY_ENTRY_RESOURCE: return "RESOURCE";
145 case IMAGE_DIRECTORY_ENTRY_EXCEPTION: return "EXCEPTION";
146 case IMAGE_DIRECTORY_ENTRY_SECURITY: return "SECURITY";
147 case IMAGE_DIRECTORY_ENTRY_BASERELOC: return "BASERELOC";
148 case IMAGE_DIRECTORY_ENTRY_DEBUG: return "DEBUG";
149 case IMAGE_DIRECTORY_ENTRY_ARCHITECTURE: return "ARCHITECTURE";
150 case IMAGE_DIRECTORY_ENTRY_GLOBALPTR: return "GLOBALPTR";
151 case IMAGE_DIRECTORY_ENTRY_TLS: return "TLS";
152 case IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG: return "LOAD_CONFIG";
153 case IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT: return "BOUND_IMPORT";
154 case IMAGE_DIRECTORY_ENTRY_IAT: return "IAT";
155 case IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT: return "DELAY_IMPORT";
156 case IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR: return "COM_DESCRIPTOR";
157 }
158 return "??";
159}
160
161
162static const char *dbgPeDebugTypeName(uint32_t uType)
163{
164 switch (uType)
165 {
166 case IMAGE_DEBUG_TYPE_UNKNOWN: return "UNKNOWN";
167 case IMAGE_DEBUG_TYPE_COFF: return "COFF";
168 case IMAGE_DEBUG_TYPE_CODEVIEW: return "CODEVIEW";
169 case IMAGE_DEBUG_TYPE_FPO: return "FPO";
170 case IMAGE_DEBUG_TYPE_MISC: return "MISC";
171 case IMAGE_DEBUG_TYPE_EXCEPTION: return "EXCEPTION";
172 case IMAGE_DEBUG_TYPE_FIXUP: return "FIXUP";
173 case IMAGE_DEBUG_TYPE_OMAP_TO_SRC: return "OMAP_TO_SRC";
174 case IMAGE_DEBUG_TYPE_OMAP_FROM_SRC: return "OMAP_FROM_SRC";
175 case IMAGE_DEBUG_TYPE_BORLAND: return "BORLAND";
176 case IMAGE_DEBUG_TYPE_RESERVED10: return "RESERVED10";
177 case IMAGE_DEBUG_TYPE_CLSID: return "CLSID";
178 case IMAGE_DEBUG_TYPE_VC_FEATURE: return "VC_FEATURE";
179 case IMAGE_DEBUG_TYPE_POGO: return "POGO";
180 case IMAGE_DEBUG_TYPE_ILTCG: return "ILTCG";
181 case IMAGE_DEBUG_TYPE_MPX: return "MPX";
182 case IMAGE_DEBUG_TYPE_REPRO: return "REPRO";
183 }
184 return "??";
185}
186
187
188static int dbgcDumpImagePeDebugDir(PDUMPIMAGEPE pThis, PDBGCCMDHLP pCmdHlp, PCDBGCVAR pDataAddr, uint32_t cbData)
189{
190 uint32_t cEntries = cbData / sizeof(IMAGE_DEBUG_DIRECTORY);
191 for (uint32_t i = 0; i < cEntries; i++)
192 {
193 /*
194 * Read the entry into memory.
195 */
196 DBGCVAR DbgDirAddr;
197 int rc = DBGCCmdHlpEval(pCmdHlp, &DbgDirAddr, "%DV + %#RX32", pDataAddr, i * sizeof(IMAGE_DEBUG_DIRECTORY));
198 if (RT_FAILURE(rc))
199 return DBGCCmdHlpFailRc(pCmdHlp, pThis->pCmd, rc, "DBGCCmdHlpEval failed on debug entry %u", i);
200
201 IMAGE_DEBUG_DIRECTORY DbgDir;
202 rc = DBGCCmdHlpMemRead(pCmdHlp, &DbgDir, sizeof(DbgDir), &DbgDirAddr, NULL);
203 if (RT_FAILURE(rc))
204 return DBGCCmdHlpFailRc(pCmdHlp, pThis->pCmd, rc, "Failed to read %zu at %Dv", sizeof(DbgDir), &DbgDirAddr);
205
206 /*
207 * Dump it.
208 */
209 DBGCVAR DebugDataAddr = *pThis->pImageBase;
210 rc = DBGCCmdHlpEval(pCmdHlp, &DebugDataAddr, "%DV + %#RX32", pThis->pImageBase, DbgDir.AddressOfRawData);
211 DBGCCmdHlpPrintf(pCmdHlp, " Debug[%u]: %Dv/%08RX32 LB %06RX32 %u (%s) v%u.%u file=%RX32 ts=%08RX32 fl=%RX32\n",
212 i, &DebugDataAddr, DbgDir.AddressOfRawData, DbgDir.SizeOfData, DbgDir.Type,
213 dbgPeDebugTypeName(DbgDir.Type), DbgDir.MajorVersion, DbgDir.MinorVersion, DbgDir.PointerToRawData,
214 DbgDir.TimeDateStamp, DbgDir.Characteristics);
215 union
216 {
217 uint8_t abPage[0x1000];
218 CVPDB20INFO Pdb20;
219 CVPDB70INFO Pdb70;
220 IMAGE_DEBUG_MISC Misc;
221 } uBuf;
222 RT_ZERO(uBuf);
223
224 if (DbgDir.Type == IMAGE_DEBUG_TYPE_CODEVIEW)
225 {
226 if ( DbgDir.SizeOfData < sizeof(uBuf)
227 && DbgDir.SizeOfData > 16
228 && DbgDir.AddressOfRawData > 0
229 && RT_SUCCESS(rc))
230 {
231 rc = DBGCCmdHlpMemRead(pCmdHlp, &uBuf, DbgDir.SizeOfData, &DebugDataAddr, NULL);
232 if (RT_FAILURE(rc))
233 return DBGCCmdHlpFailRc(pCmdHlp, pThis->pCmd, rc, "Failed to read %zu at %Dv",
234 DbgDir.SizeOfData, &DebugDataAddr);
235
236 if ( uBuf.Pdb20.u32Magic == CVPDB20INFO_MAGIC
237 && uBuf.Pdb20.offDbgInfo == 0
238 && DbgDir.SizeOfData > RT_UOFFSETOF(CVPDB20INFO, szPdbFilename) )
239 DBGCCmdHlpPrintf(pCmdHlp, " PDB2.0: ts=%08RX32 age=%RX32 %s\n",
240 uBuf.Pdb20.uTimestamp, uBuf.Pdb20.uAge, uBuf.Pdb20.szPdbFilename);
241 else if ( uBuf.Pdb20.u32Magic == CVPDB70INFO_MAGIC
242 && DbgDir.SizeOfData > RT_UOFFSETOF(CVPDB70INFO, szPdbFilename) )
243 DBGCCmdHlpPrintf(pCmdHlp, " PDB7.0: %RTuuid age=%u %s\n",
244 &uBuf.Pdb70.PdbUuid, uBuf.Pdb70.uAge, uBuf.Pdb70.szPdbFilename);
245 else
246 DBGCCmdHlpPrintf(pCmdHlp, " Unknown PDB/codeview magic: %.8Rhxs\n", uBuf.abPage);
247 }
248 }
249 else if (DbgDir.Type == IMAGE_DEBUG_TYPE_MISC)
250 {
251 if ( DbgDir.SizeOfData < sizeof(uBuf)
252 && DbgDir.SizeOfData > RT_UOFFSETOF(IMAGE_DEBUG_MISC, Data)
253 && DbgDir.AddressOfRawData > 0
254 && RT_SUCCESS(rc) )
255 {
256 rc = DBGCCmdHlpMemRead(pCmdHlp, &uBuf, DbgDir.SizeOfData, &DebugDataAddr, NULL);
257 if (RT_FAILURE(rc))
258 return DBGCCmdHlpFailRc(pCmdHlp, pThis->pCmd, rc, "Failed to read %zu at %Dv",
259 DbgDir.SizeOfData, &DebugDataAddr);
260
261 if ( uBuf.Misc.DataType == IMAGE_DEBUG_MISC_EXENAME
262 && uBuf.Misc.Length == DbgDir.SizeOfData)
263 {
264 if (!uBuf.Misc.Unicode)
265 DBGCCmdHlpPrintf(pCmdHlp, " Misc DBG: ts=%RX32 %s\n",
266 DbgDir.TimeDateStamp, (const char *)&uBuf.Misc.Data[0]);
267 else
268 DBGCCmdHlpPrintf(pCmdHlp, " Misc DBG: ts=%RX32 %ls\n",
269 DbgDir.TimeDateStamp, (PCRTUTF16)&uBuf.Misc.Data[0]);
270 }
271 }
272 }
273 }
274 return VINF_SUCCESS;
275}
276
277
278static int dbgcDumpImagePeDataDirs(PDUMPIMAGEPE pThis, PDBGCCMDHLP pCmdHlp, unsigned cDataDirs, PCIMAGE_DATA_DIRECTORY paDataDirs)
279{
280 int rcRet = VINF_SUCCESS;
281 for (unsigned i = 0; i < cDataDirs; i++)
282 {
283 if (paDataDirs[i].Size || paDataDirs[i].VirtualAddress)
284 {
285 DBGCVAR DataAddr = *pThis->pImageBase;
286 DBGCCmdHlpEval(pCmdHlp, &DataAddr, "%DV + %#RX32", pThis->pImageBase, paDataDirs[i].VirtualAddress);
287 DBGCCmdHlpPrintf(pCmdHlp, "DataDir[%02u]: %Dv/%08RX32 LB %08RX32 %s\n",
288 i, &DataAddr, paDataDirs[i].VirtualAddress, paDataDirs[i].Size, dbgcPeDataDirName(i));
289 int rc = VINF_SUCCESS;
290 if ( i == IMAGE_DIRECTORY_ENTRY_DEBUG
291 && paDataDirs[i].Size >= sizeof(IMAGE_DEBUG_DIRECTORY))
292 rc = dbgcDumpImagePeDebugDir(pThis, pCmdHlp, &DataAddr, paDataDirs[i].Size);
293 if (RT_FAILURE(rc) && RT_SUCCESS(rcRet))
294 rcRet = rc;
295 }
296 }
297 return rcRet;
298}
299
300
301static int dbgcDumpImagePeSectionHdrs(PDUMPIMAGEPE pThis, PDBGCCMDHLP pCmdHlp, unsigned cShdrs, PCIMAGE_SECTION_HEADER paShdrs)
302{
303 for (unsigned i = 0; i < cShdrs; i++)
304 {
305 DBGCVAR SectAddr = *pThis->pImageBase;
306 DBGCCmdHlpEval(pCmdHlp, &SectAddr, "%DV + %#RX32", pThis->pImageBase, paShdrs[i].VirtualAddress);
307 DBGCCmdHlpPrintf(pCmdHlp, "Section[%02u]: %Dv/%08RX32 LB %08RX32 %.8s\n",
308 i, &SectAddr, paShdrs[i].VirtualAddress, paShdrs[i].Misc.VirtualSize, paShdrs[i].Name);
309 }
310 return VINF_SUCCESS;
311}
312
313
314static int dbgcDumpImagePeOptHdr32(PDUMPIMAGEPE pThis, PDBGCCMDHLP pCmdHlp, PCIMAGE_NT_HEADERS32 pNtHdrs)
315{
316 RT_NOREF(pThis, pCmdHlp, pNtHdrs);
317 return VINF_SUCCESS;
318}
319
320static int dbgcDumpImagePeOptHdr64(PDUMPIMAGEPE pThis, PDBGCCMDHLP pCmdHlp, PCIMAGE_NT_HEADERS64 pNtHdrs)
321{
322 RT_NOREF(pThis, pCmdHlp, pNtHdrs);
323 return VINF_SUCCESS;
324}
325
326
327static int dbgcDumpImagePe(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PCDBGCVAR pImageBase,
328 PCDBGCVAR pPeHdrAddr, PCIMAGE_FILE_HEADER pFileHdr)
329{
330 /*
331 * Dump file header fields.
332 */
333 DBGCCmdHlpPrintf(pCmdHlp, "%Dv: PE image - %#x (%s), %u sections\n", pImageBase, pFileHdr->Machine,
334 dbgcPeMachineName(pFileHdr->Machine), pFileHdr->NumberOfSections);
335 DBGCCmdHlpPrintf(pCmdHlp, "Characteristics: %#06x", pFileHdr->Characteristics);
336 if (pFileHdr->Characteristics & IMAGE_FILE_RELOCS_STRIPPED) DBGCCmdHlpPrintf(pCmdHlp, " RELOCS_STRIPPED");
337 if (pFileHdr->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) DBGCCmdHlpPrintf(pCmdHlp, " EXECUTABLE_IMAGE");
338 if (pFileHdr->Characteristics & IMAGE_FILE_LINE_NUMS_STRIPPED) DBGCCmdHlpPrintf(pCmdHlp, " LINE_NUMS_STRIPPED");
339 if (pFileHdr->Characteristics & IMAGE_FILE_LOCAL_SYMS_STRIPPED) DBGCCmdHlpPrintf(pCmdHlp, " LOCAL_SYMS_STRIPPED");
340 if (pFileHdr->Characteristics & IMAGE_FILE_AGGRESIVE_WS_TRIM) DBGCCmdHlpPrintf(pCmdHlp, " AGGRESIVE_WS_TRIM");
341 if (pFileHdr->Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE) DBGCCmdHlpPrintf(pCmdHlp, " LARGE_ADDRESS_AWARE");
342 if (pFileHdr->Characteristics & IMAGE_FILE_16BIT_MACHINE) DBGCCmdHlpPrintf(pCmdHlp, " 16BIT_MACHINE");
343 if (pFileHdr->Characteristics & IMAGE_FILE_BYTES_REVERSED_LO) DBGCCmdHlpPrintf(pCmdHlp, " BYTES_REVERSED_LO");
344 if (pFileHdr->Characteristics & IMAGE_FILE_32BIT_MACHINE) DBGCCmdHlpPrintf(pCmdHlp, " 32BIT_MACHINE");
345 if (pFileHdr->Characteristics & IMAGE_FILE_DEBUG_STRIPPED) DBGCCmdHlpPrintf(pCmdHlp, " DEBUG_STRIPPED");
346 if (pFileHdr->Characteristics & IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP) DBGCCmdHlpPrintf(pCmdHlp, " REMOVABLE_RUN_FROM_SWAP");
347 if (pFileHdr->Characteristics & IMAGE_FILE_NET_RUN_FROM_SWAP) DBGCCmdHlpPrintf(pCmdHlp, " NET_RUN_FROM_SWAP");
348 if (pFileHdr->Characteristics & IMAGE_FILE_SYSTEM) DBGCCmdHlpPrintf(pCmdHlp, " SYSTEM");
349 if (pFileHdr->Characteristics & IMAGE_FILE_DLL) DBGCCmdHlpPrintf(pCmdHlp, " DLL");
350 if (pFileHdr->Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY) DBGCCmdHlpPrintf(pCmdHlp, " UP_SYSTEM_ONLY");
351 if (pFileHdr->Characteristics & IMAGE_FILE_BYTES_REVERSED_HI) DBGCCmdHlpPrintf(pCmdHlp, " BYTES_REVERSED_HI");
352 DBGCCmdHlpPrintf(pCmdHlp, "\n");
353
354 /*
355 * Allocate memory for all the headers, including section headers, and read them into memory.
356 */
357 size_t offSHdrs = pFileHdr->SizeOfOptionalHeader + sizeof(*pFileHdr) + sizeof(uint32_t);
358 size_t cbHdrs = offSHdrs + pFileHdr->NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
359 if (cbHdrs > _2M)
360 return DBGCCmdHlpFail(pCmdHlp, pCmd, "%Dv: headers too big: %zu.\n", pImageBase, cbHdrs);
361
362 void *pvBuf = RTMemTmpAllocZ(cbHdrs);
363 if (!pvBuf)
364 return DBGCCmdHlpFail(pCmdHlp, pCmd, "%Dv: failed to allocate %zu bytes.\n", pImageBase, cbHdrs);
365 int rc = DBGCCmdHlpMemRead(pCmdHlp, pvBuf, cbHdrs, pPeHdrAddr, NULL);
366 if (RT_SUCCESS(rc))
367 {
368 DUMPIMAGEPE This;
369 RT_ZERO(This);
370 This.pImageBase = pImageBase;
371 This.pFileHdr = pFileHdr;
372 This.u.pv = pvBuf;
373 This.cShdrs = pFileHdr->NumberOfSections;
374 This.paShdrs = (PCIMAGE_SECTION_HEADER)((uintptr_t)pvBuf + offSHdrs);
375 This.pCmd = pCmd;
376
377 if (pFileHdr->SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32))
378 {
379 This.paDataDir = This.u.pNt32->OptionalHeader.DataDirectory;
380 This.cDataDir = This.u.pNt32->OptionalHeader.NumberOfRvaAndSizes;
381 rc = dbgcDumpImagePeOptHdr32(&This, pCmdHlp, This.u.pNt32);
382 }
383 else if (pFileHdr->SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER64))
384 {
385 This.paDataDir = This.u.pNt64->OptionalHeader.DataDirectory;
386 This.cDataDir = This.u.pNt64->OptionalHeader.NumberOfRvaAndSizes;
387 rc = dbgcDumpImagePeOptHdr64(&This, pCmdHlp, This.u.pNt64);
388 }
389 else
390 rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "%Dv: Unsupported optional header size: %#x\n",
391 pImageBase, pFileHdr->SizeOfOptionalHeader);
392
393 int rc2 = dbgcDumpImagePeSectionHdrs(&This, pCmdHlp, This.cShdrs, This.paShdrs);
394 if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
395 rc = rc2;
396
397 rc2 = dbgcDumpImagePeDataDirs(&This, pCmdHlp, This.cDataDir, This.paDataDir);
398 if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
399 rc = rc2;
400 }
401 else
402 rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "%Dv: Failed to read %zu at %Dv", pImageBase, cbHdrs, pPeHdrAddr);
403 RTMemTmpFree(pvBuf);
404 return rc;
405}
406
407
408static int dbgcDumpImageElf(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PCDBGCVAR pImageBase)
409{
410 RT_NOREF_PV(pCmd);
411 DBGCCmdHlpPrintf(pCmdHlp, "%Dv: ELF image dumping not implemented yet.\n", pImageBase);
412 return VINF_SUCCESS;
413}
414
415
416/**
417 * @callback_method_impl{FNDBGCCMD, The 'dumpimage' command.}
418 */
419DECLCALLBACK(int) dbgcCmdDumpImage(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
420{
421 int rcRet = VINF_SUCCESS;
422 for (unsigned iArg = 0; iArg < cArgs; iArg++)
423 {
424 union
425 {
426 uint8_t ab[0x10];
427 IMAGE_DOS_HEADER DosHdr;
428 struct
429 {
430 uint32_t u32Magic;
431 IMAGE_FILE_HEADER FileHdr;
432 } Nt;
433 } uBuf;
434 DBGCVAR const ImageBase = paArgs[iArg];
435 int rc = DBGCCmdHlpMemRead(pCmdHlp, &uBuf.DosHdr, sizeof(uBuf.DosHdr), &ImageBase, NULL);
436 if (RT_SUCCESS(rc))
437 {
438 /*
439 * MZ.
440 */
441 if (uBuf.DosHdr.e_magic == IMAGE_DOS_SIGNATURE)
442 {
443 uint32_t offNewHdr = uBuf.DosHdr.e_lfanew;
444 if (offNewHdr < _256K && offNewHdr >= 16)
445 {
446 /* Look for new header. */
447 DBGCVAR NewHdrAddr;
448 rc = DBGCCmdHlpEval(pCmdHlp, &NewHdrAddr, "%DV + %#RX32", &ImageBase, offNewHdr);
449 if (RT_SUCCESS(rc))
450 {
451 rc = DBGCCmdHlpMemRead(pCmdHlp, &uBuf.Nt, sizeof(uBuf.Nt), &NewHdrAddr, NULL);
452 if (RT_SUCCESS(rc))
453 {
454 /* PE: */
455 if (uBuf.Nt.u32Magic == IMAGE_NT_SIGNATURE)
456 rc = dbgcDumpImagePe(pCmd, pCmdHlp, &ImageBase, &NewHdrAddr, &uBuf.Nt.FileHdr);
457 else
458 rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "%Dv: Unknown new header magic: %.8Rhxs\n",
459 &ImageBase, uBuf.ab);
460 }
461 else
462 rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "%Dv: Failed to read %zu at %Dv",
463 &ImageBase, sizeof(uBuf.Nt), &NewHdrAddr);
464 }
465 else
466 rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "%Dv: Failed to calc address of new header", &ImageBase);
467 }
468 else
469 rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "%Dv: MZ header but e_lfanew=%#RX32 is out of bounds (16..256K).\n",
470 &ImageBase, offNewHdr);
471 }
472 /*
473 * ELF.
474 */
475 else if (uBuf.ab[0] == ELFMAG0 && uBuf.ab[1] == ELFMAG1 && uBuf.ab[2] == ELFMAG2 && uBuf.ab[3] == ELFMAG3)
476 rc = dbgcDumpImageElf(pCmd, pCmdHlp, &ImageBase);
477 /*
478 * Dunno.
479 */
480 else
481 rc = DBGCCmdHlpFail(pCmdHlp, pCmd, "%Dv: Unknown magic: %.8Rhxs\n", &ImageBase, uBuf.ab);
482 }
483 else
484 rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "%Dv: Failed to read %zu", &ImageBase, sizeof(uBuf.DosHdr));
485 if (RT_FAILURE(rc) && RT_SUCCESS(rcRet))
486 rcRet = rc;
487 }
488 RT_NOREF(pUVM);
489 return rcRet;
490}
491
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette