Changeset 61369 in vbox
- Timestamp:
- Jun 1, 2016 12:50:48 PM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 107677
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Debugger/DBGPlugInLinux.cpp
r61040 r61369 24 24 #include "DBGPlugInCommonELF.h" 25 25 #include <VBox/vmm/dbgf.h> 26 #include <VBox/dis.h> 26 27 #include <iprt/string.h> 27 28 #include <iprt/mem.h> … … 163 164 164 165 /** 166 * Disassembles a simple getter returning the value for it. 167 * 168 * @returns VBox status code. 169 * @param pThis The Linux digger data. 170 * @param pUVM The VM handle. 171 * @param hMod The module to use. 172 * @param pszSymbol The symbol of the getter. 173 * @param pvVal Where to store the value on success. 174 * @param cbVal Size of the value in bytes. 175 */ 176 static int dbgDiggerLinuxDisassembleSimpleGetter(PDBGDIGGERLINUX pThis, PUVM pUVM, RTDBGMOD hMod, 177 const char *pszSymbol, void *pvVal, uint32_t cbVal) 178 { 179 int rc = VINF_SUCCESS; 180 181 RTDBGSYMBOL SymInfo; 182 rc = RTDbgModSymbolByName(hMod, pszSymbol, &SymInfo); 183 if (RT_SUCCESS(rc)) 184 { 185 /* 186 * Do the diassembling. Disassemble until a ret instruction is encountered 187 * or a limit is reached (don't want to disassemble for too long as the getter 188 * should be short). 189 * push and pop instructions are skipped as well as any mov instructions not 190 * touching the rax or eax register (depending on the size of the value). 191 */ 192 unsigned cInstrDisassembled = 0; 193 uint32_t offInstr = 0; 194 bool fRet = false; 195 DISSTATE DisState; 196 RT_ZERO(DisState); 197 198 do 199 { 200 DBGFADDRESS Addr; 201 RTGCPTR GCPtrCur = (RTGCPTR)SymInfo.Value + pThis->AddrKernelBase.FlatPtr + offInstr; 202 DBGFR3AddrFromFlat(pUVM, &Addr, GCPtrCur); 203 204 /* Prefetch the instruction. */ 205 uint8_t abInstr[32]; 206 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &Addr, &abInstr[0], sizeof(abInstr)); 207 if (RT_SUCCESS(rc)) 208 { 209 uint32_t cbInstr = 0; 210 211 rc = DISInstr(&abInstr[0], pThis->f64Bit ? DISCPUMODE_64BIT : DISCPUMODE_32BIT, &DisState, &cbInstr); 212 if (RT_SUCCESS(rc)) 213 { 214 switch (DisState.pCurInstr->uOpcode) 215 { 216 case OP_PUSH: 217 case OP_POP: 218 case OP_NOP: 219 case OP_LEA: 220 break; 221 case OP_RETN: 222 /* Getter returned, abort disassembling. */ 223 fRet = true; 224 break; 225 case OP_MOV: 226 /* 227 * Check that the destination is either rax or eax depending on the 228 * value size. 229 * 230 * Param1 is the destination and Param2 the source. 231 */ 232 if ( ( ( (DisState.Param1.fUse & (DISUSE_BASE | DISUSE_REG_GEN32)) 233 && cbVal == sizeof(uint32_t)) 234 || ( (DisState.Param1.fUse & (DISUSE_BASE | DISUSE_REG_GEN64)) 235 && cbVal == sizeof(uint64_t))) 236 && DisState.Param1.Base.idxGenReg == DISGREG_RAX) 237 { 238 /* Parse the source. */ 239 if (DisState.Param2.fUse & (DISUSE_IMMEDIATE32 | DISUSE_IMMEDIATE64)) 240 memcpy(pvVal, &DisState.Param2.uValue, cbVal); 241 else if (DisState.Param2.fUse & (DISUSE_RIPDISPLACEMENT32|DISUSE_DISPLACEMENT32|DISUSE_DISPLACEMENT64)) 242 { 243 RTGCPTR GCPtrVal = 0; 244 245 if (DisState.Param2.fUse & DISUSE_RIPDISPLACEMENT32) 246 GCPtrVal = GCPtrCur + DisState.Param2.uDisp.i32 + cbInstr; 247 else if (DisState.Param2.fUse & DISUSE_DISPLACEMENT32) 248 GCPtrVal = (RTGCPTR)DisState.Param2.uDisp.u32; 249 else if (DisState.Param2.fUse & DISUSE_DISPLACEMENT64) 250 GCPtrVal = (RTGCPTR)DisState.Param2.uDisp.u64; 251 else 252 AssertMsgFailedBreakStmt(("Invalid displacement\n"), rc = VERR_INVALID_STATE); 253 254 DBGFADDRESS AddrVal; 255 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, 256 DBGFR3AddrFromFlat(pUVM, &AddrVal, GCPtrVal), 257 pvVal, cbVal); 258 } 259 } 260 break; 261 default: 262 /* All other instructions will cause an error for now (playing safe here). */ 263 rc = VERR_INVALID_PARAMETER; 264 break; 265 } 266 cInstrDisassembled++; 267 offInstr += cbInstr; 268 } 269 } 270 } while ( RT_SUCCESS(rc) 271 && cInstrDisassembled < 20 272 && !fRet); 273 } 274 275 return rc; 276 } 277 278 /** 279 * Try to get at the log buffer starting address and size by disassembling some exposed helpers. 280 * 281 * @returns VBox status code. 282 * @param pThis The Linux digger data. 283 * @param pUVM The VM handle. 284 * @param hMod The module to use. 285 * @param pGCPtrLogBuf Where to store the log buffer pointer on success. 286 * @param pcbLogBuf Where to store the size of the log buffer on success. 287 */ 288 static int dbgDiggerLinuxQueryLogBufferPtrs(PDBGDIGGERLINUX pThis, PUVM pUVM, RTDBGMOD hMod, 289 RTGCPTR *pGCPtrLogBuf, uint32_t *pcbLogBuf) 290 { 291 int rc = VINF_SUCCESS; 292 293 struct { void *pvVar; size_t cbHost, cbGuest; const char *pszSymbol; } aSymbols[] = 294 { 295 { pGCPtrLogBuf, sizeof(RTGCPTR), pThis->f64Bit ? sizeof(uint64_t) : sizeof(uint32_t), "log_buf_addr_get" }, 296 { pcbLogBuf, sizeof(uint32_t), sizeof(uint32_t), "log_buf_len_get" } 297 }; 298 for (uint32_t i = 0; i < RT_ELEMENTS(aSymbols) && RT_SUCCESS(rc); i++) 299 { 300 RT_BZERO(aSymbols[i].pvVar, aSymbols[i].cbHost); 301 Assert(aSymbols[i].cbHost >= aSymbols[i].cbGuest); 302 rc = dbgDiggerLinuxDisassembleSimpleGetter(pThis, pUVM, hMod, aSymbols[i].pszSymbol, 303 aSymbols[i].pvVar, aSymbols[i].cbGuest); 304 } 305 306 return rc; 307 } 308 309 /** 165 310 * @interface_method_impl{DBGFOSIDMESG,pfnQueryKernelLog} 166 311 */ … … 213 358 else 214 359 Log(("dbgDiggerLinuxIDmsg_QueryKernelLog: Error looking up '%s': %Rrc\n", aSymbols[i].pszSymbol, rc)); 360 rc = VERR_NOT_FOUND; 361 break; 362 } 363 364 /* 365 * Some kernels don't expose the variables in kallsyms so we have to try disassemble 366 * some public helpers to get at the addresses. 367 * 368 * @todo: Maybe cache those values so we don't have to do the heavy work every time? 369 */ 370 if (rc == VERR_NOT_FOUND) 371 { 372 idxFirst = 0; 373 idxNext = 0; 374 rc = dbgDiggerLinuxQueryLogBufferPtrs(pData, pUVM, hMod, &GCPtrLogBuf, &cbLogBuf); 375 376 /* Release the module in any case. */ 215 377 RTDbgModRelease(hMod); 216 return VERR_NOT_FOUND; 378 379 if (RT_FAILURE(rc)) 380 return rc; 217 381 } 218 382
Note:
See TracChangeset
for help on using the changeset viewer.