Changeset 32214 in vbox
- Timestamp:
- Sep 2, 2010 3:19:06 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/DBGFCoreWrite.cpp
r32050 r32214 26 26 #include "DBGFInternal.h" 27 27 #include <VBox/vm.h> 28 #include <VBox/pgm.h> 28 29 #include <VBox/err.h> 29 30 #include <VBox/log.h> 31 #include <VBox/mm.h> 30 32 31 33 #include "../Runtime/include/internal/ldrELF64.h" 34 35 /******************************************************************************* 36 * Defined Constants And Macros * 37 *******************************************************************************/ 38 #ifdef DEBUG_ramshankar 39 # undef Log 40 # define Log LogRel 41 #endif 42 #define DBGFLOG_NAME "DGBFCoreWrite" 43 44 /** 45 * DBGFCOREDATA: Core data. 46 */ 47 typedef struct 48 { 49 const char *pszDumpPath; /* File path to dump the core into. */ 50 } DBGFCOREDATA, *PDBGFCOREDATA; 51 32 52 33 53 /* … … 66 86 * @return IPRT status code. 67 87 */ 68 static int Elf64WriteElfHdr(RTFILE hFile, uint16_t cProgHdrs, uint16_t cSecHdrs, size_t *pcbElfHdr) 69 { 88 static int Elf64WriteElfHdr(RTFILE hFile, uint16_t cProgHdrs, uint16_t cSecHdrs, uint64_t *pcbElfHdr) 89 { 90 AssertCompile(sizeof(uint32_t) == 4); 91 70 92 Elf64_Ehdr ElfHdr; 71 93 RT_ZERO(ElfHdr); … … 103 125 * @param hFile The file to write to. 104 126 * @param Type Type of program header (PT_*). 105 * @param fFlags Flags (access permissions ).127 * @param fFlags Flags (access permissions, PF_*). 106 128 * @param offFileData File offset of contents. 107 129 * @param cbFileData Size of contents in the file. 108 130 * @param cbMemData Size of contents in memory. 131 * @param Phys Physical address, pass zero if not applicable. 109 132 * @param pcbProgHdr Where to store the size of written header to file, 110 133 * can be NULL. … … 112 135 * @return IPRT status code. 113 136 */ 114 static int Elf64WriteProgHdr(RTFILE hFile, uint32_t Type, uint32_t fFlags, RTFOFF offFileData, size_t cbFileData, size_t cbMemData,115 size_t *pcbProgHdr)137 static int Elf64WriteProgHdr(RTFILE hFile, uint32_t Type, uint32_t fFlags, uint64_t offFileData, uint64_t cbFileData, uint64_t cbMemData, 138 RTGCPHYS Phys, uint64_t *pcbProgHdr) 116 139 { 117 140 Elf64_Phdr ProgHdr; … … 122 145 ProgHdr.p_filesz = cbFileData; 123 146 ProgHdr.p_memsz = cbMemData; 147 ProgHdr.p_paddr = Phys; 124 148 125 149 int rc = RTFileWrite(hFile, &ProgHdr, sizeof(ProgHdr), NULL /* full write */); … … 131 155 132 156 /** 133 * Count the number of memory blobs that go into the core file. 134 * 135 * We cannot do a page-by-page dump of the entire guest memory as there will be 136 * way too many entries. Also we don't want to dump MMIO regions which means we 137 * cannot have a 1:1 mapping between core file offset and memory offset. Instead 138 * we dump the memory in blobs. A memory blob is a contiguous memory area 139 * suitable for dumping to a core file. 140 * 141 * @param pVM The VM handle. 142 * @oaram idCpu The target CPU ID. 143 * 144 * @return Number of memory blobs. 145 */ 146 static int dbgfR3CountMemoryBlobs(PVM pVM, VMCPUID idCpu) 147 { 148 /* @todo */ 149 return 0; 150 } 151 152 153 /** 154 * EMT worker function for DBGFR3CoreWrite. 155 * 156 * @param pVM The VM handle. 157 * @param idCpu The target CPU ID. 158 * @param pszDumpPath The full path of the file to dump into. 159 * 160 * @return VBox status code. 161 */ 162 static DECLCALLBACK(int) dbgfR3CoreWrite(PVM pVM, VMCPUID idCpu, const char *pszDumpPath) 163 { 164 /* 165 * Validate input. 166 */ 167 Assert(idCpu == VMMGetCpuId(pVM)); 168 AssertReturn(pszDumpPath, VERR_INVALID_POINTER); 169 170 /* 171 * Halt the VM if it is not already halted. 172 */ 173 int rc = VINF_SUCCESS; 174 if (!DBGFR3IsHalted(pVM)) 157 * Elf function to write 64-bit note header. 158 * 159 * @param hFile The file to write to. 160 * @param Type Type of this section. 161 * @param pszName Name of this section, will be limited to 8 bytes. 162 * @param pcv Opaque pointer to the data, if NULL only computes size. 163 * @param cb Size of the data. 164 * @param pcbNoteHdr Where to store the size of written header to file, 165 * can be NULL. 166 * 167 * @return IPRT status code. 168 */ 169 static int Elf64WriteNoteHeader(RTFILE hFile, uint_t Type, const char *pszName, const void *pcv, uint64_t cb, uint64_t *pcbNoteHdr) 170 { 171 AssertReturn(pcv, VERR_INVALID_POINTER); 172 AssertReturn(cb > 0, VERR_NO_DATA); 173 174 typedef struct 175 175 { 176 rc = DBGFR3Halt(pVM); 177 if (RT_FAILURE(rc)) 178 return rc; 179 } 180 181 /* 182 * Collect core information. 183 */ 184 uint16_t cMemBlobs = dbgfR3CountMemoryBlobs(pVM, idCpu); 185 uint16_t cProgHdrs = cMemBlobs + 1; /* One PT_NOTE Program header */ 186 187 /* 188 * Write the core file. 189 */ 190 RTFILE hFile = NIL_RTFILE; 191 rc = RTFileOpen(&hFile, pszDumpPath, RTFILE_O_CREATE | RTFILE_O_READWRITE); 176 Elf64_Nhdr Hdr; /* 64-bit NOTE Header */ 177 char achName[8]; /* Name of NOTE section */ 178 } ELFNOTEHDR; 179 180 ELFNOTEHDR ElfNoteHdr; 181 RT_ZERO(ElfNoteHdr); 182 RTStrCopy(ElfNoteHdr.achName, sizeof(ElfNoteHdr.achName) - 1, pszName); 183 ElfNoteHdr.Hdr.n_namesz = strlen(ElfNoteHdr.achName) + 1; 184 ElfNoteHdr.Hdr.n_type = Type; 185 186 static const char s_achPad[3] = { 0, 0, 0 }; 187 uint64_t cbAlign = RT_ALIGN_64(cb, 4); 188 ElfNoteHdr.Hdr.n_descsz = cbAlign; 189 190 /* 191 * Write note header and description. 192 */ 193 int rc = RTFileWrite(hFile, &ElfNoteHdr, sizeof(ElfNoteHdr), NULL /* full write */); 192 194 if (RT_SUCCESS(rc)) 193 195 { 194 size_t cbElfHdr = 0; 195 rc = Elf64WriteElfHdr(hFile, 0, 0 /* cSecHdrs */, &cbElfHdr); 196 rc = RTFileWrite(hFile, pcv, cb, NULL /* full write */); 196 197 if (RT_SUCCESS(rc)) 197 198 { 199 if (cbAlign > cb) 200 rc = RTFileWrite(hFile, s_achPad, cbAlign - cb, NULL /* full write*/); 201 } 202 } 203 204 if (RT_FAILURE(rc)) 205 LogRel((DBGFLOG_NAME ":RTFileWrite failed. rc=%Rrc pszName=%s cb=%u cbAlign=%u\n", rc, pszName, cb, cbAlign)); 206 207 return rc; 208 } 209 210 211 /** 212 * Count the number of memory ranges that go into the core file. 213 * 214 * We cannot do a page-by-page dump of the entire guest memory as there will be 215 * way too many program header entries. Also we don't want to dump MMIO regions 216 * which means we cannot have a 1:1 mapping between core file offset and memory 217 * offset. Instead we dump the memory in ranges. A memory range is a contiguous 218 * memory area suitable for dumping to a core file. 219 * 220 * @param pVM The VM handle. 221 * 222 * @return Number of memory ranges 223 */ 224 static uint32_t dbgfR3GetRamRangeCount(PVM pVM) 225 { 226 return PGMR3PhysGetRamRangeCount(pVM); 227 } 228 229 230 /** 231 * EMT Rendezvous worker function for DBGFR3CoreWrite. 232 * 233 * @param pVM The VM handle. 234 * @param pVCpu The handle of the calling VCPU. 235 * @param pvData Opaque data. 236 * 237 * @return VBox status code. 238 * @remarks The VM must be suspended before calling this function. 239 */ 240 static DECLCALLBACK(int) dbgfR3CoreWrite(PVM pVM, PVMCPU pVCpu, void *pvData) 241 { 242 /* 243 * Validate input. 244 */ 245 AssertReturn(pVM, VERR_INVALID_VM_HANDLE); 246 AssertReturn(pVCpu, VERR_INVALID_VMCPU_HANDLE); 247 AssertReturn(pvData, VERR_INVALID_POINTER); 248 249 PDBGFCOREDATA pDbgfData = (PDBGFCOREDATA)pvData; 250 251 /* 252 * Collect core information. 253 */ 254 uint32_t u32MemRanges = dbgfR3GetRamRangeCount(pVM); 255 uint16_t cMemRanges = u32MemRanges < UINT16_MAX - 1 ? u32MemRanges : UINT16_MAX - 1; /* One PT_NOTE Program header */ 256 uint16_t cProgHdrs = cMemRanges + 1; 257 258 /* 259 * Compute size of the note section. 260 */ 261 uint64_t cbNoteSection = pVM->cCpus * sizeof(CPUMCTX); 262 uint64_t off = 0; 263 264 /* 265 * Create the core file. 266 */ 267 RTFILE hFile = NIL_RTFILE; 268 int rc = RTFileOpen(&hFile, pDbgfData->pszDumpPath, RTFILE_O_CREATE_REPLACE | RTFILE_O_READWRITE); 269 if (RT_SUCCESS(rc)) 270 { 271 /* 272 * Write ELF header. 273 */ 274 uint64_t cbElfHdr = 0; 275 rc = Elf64WriteElfHdr(hFile, cProgHdrs, 0 /* cSecHdrs */, &cbElfHdr); 276 off += cbElfHdr; 277 if (RT_SUCCESS(rc)) 278 { 279 /* 280 * Write PT_NOTE program header. 281 */ 282 uint64_t cbProgHdr = 0; 283 rc = Elf64WriteProgHdr(hFile, PT_NOTE, PF_R, 284 cbElfHdr + cProgHdrs * sizeof(Elf64_Phdr), /* file offset to contents */ 285 cbNoteSection, /* size in core file */ 286 cbNoteSection, /* size in memory */ 287 0, /* physical address */ 288 &cbProgHdr); 289 Assert(cbProgHdr == sizeof(Elf64_Phdr)); 290 off += cbProgHdr; 291 if (RT_SUCCESS(rc)) 292 { 293 /* 294 * Write PT_LOAD program header for each memory range. 295 */ 296 uint64_t offMemRange = off + cbNoteSection; 297 for (uint16_t iRange = 0; iRange < cMemRanges; iRange++) 298 { 299 RTGCPHYS GCPhysStart; 300 RTGCPHYS GCPhysEnd; 301 302 bool fIsMmio; 303 rc = PGMR3PhysGetRange(pVM, iRange, &GCPhysStart, &GCPhysEnd, NULL /* pszDesc */, &fIsMmio); 304 if (RT_FAILURE(rc)) 305 { 306 LogRel((DBGFLOG_NAME ": PGMR3PhysGetRange failed for iRange(%u) rc=%Rrc\n", iRange, rc)); 307 break; 308 } 309 310 uint64_t cbMemRange = GCPhysEnd - GCPhysStart + 1; 311 uint64_t cbFileRange = fIsMmio ? 0 : cbMemRange; 312 313 LogRel((DBGFLOG_NAME ": PGMR3PhysGetRange iRange=%u GCPhysStart=%#x GCPhysEnd=%#x cbMemRange=%u\n", 314 iRange, GCPhysStart, GCPhysEnd, cbMemRange)); 315 316 rc = Elf64WriteProgHdr(hFile, PT_LOAD, PF_R, 317 offMemRange, /* file offset to contents */ 318 cbFileRange, /* size in core file */ 319 cbMemRange, /* size in memory */ 320 GCPhysStart, /* physical address */ 321 &cbProgHdr); 322 Assert(cbProgHdr == sizeof(Elf64_Phdr)); 323 if (RT_FAILURE(rc)) 324 { 325 LogRel((DBGFLOG_NAME ":Elf64WriteProgHdr failed for memory range(%u) cbFileRange=%u cbMemRange=%u rc=%Rrc\n", iRange, 326 cbFileRange, cbMemRange, rc)); 327 break; 328 } 329 330 offMemRange += cbFileRange; 331 } 332 333 /* 334 * Write the CPU context note headers and data. 335 */ 336 if (RT_SUCCESS(rc)) 337 { 338 for (uint32_t iCpu = 0; iCpu < pVM->cCpus; iCpu++) 339 { 340 /** @todo -XXX- cpus */ 341 } 342 } 343 } 198 344 199 345 } … … 201 347 RTFileClose(hFile); 202 348 } 203 204 /*205 * Resume the VM.206 */207 DBGFR3Resume(pVM);208 349 209 350 return rc; … … 219 360 * @param pszDumpPath The path of the file to dump into, cannot be 220 361 * NULL. 362 * 363 * @remarks The VM must be suspended before calling this function. 221 364 */ 222 365 VMMR3DECL(int) DBGFR3CoreWrite(PVM pVM, VMCPUID idCpu, const char *pszDumpPath) … … 227 370 228 371 /* 229 * Pass the core write request down to EMT. 230 */ 231 return VMR3ReqCallWaitU(pVM->pUVM, idCpu, (PFNRT)dbgfR3CoreWrite, 3, pVM, idCpu, pszDumpPath); 232 } 233 372 * Pass the core write request down to EMT rendezvous which makes sure 373 * other EMTs, if any, are not running. 374 */ 375 DBGFCOREDATA CoreData; 376 RT_ZERO(CoreData); 377 CoreData.pszDumpPath = pszDumpPath; 378 379 return VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, dbgfR3CoreWrite, &CoreData); 380 } 381
Note:
See TracChangeset
for help on using the changeset viewer.