Changeset 26269 in vbox for trunk/src/VBox/Disassembler
- Timestamp:
- Feb 5, 2010 3:41:34 AM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Disassembler/DisasmCore.cpp
r26266 r26269 52 52 static int disCoreOne(PDISCPUSTATE pCpu, RTUINTPTR InstructionAddr, unsigned *pcbInstruction); 53 53 #if !defined(DIS_CORE_ONLY) && defined(LOG_ENABLED) 54 static void disasmAddString(char *psz, size_t cbString,const char *pszString);55 static void disasmAddStringF(char *psz, size_t cbString,const char *pszFormat, ...);54 static void disasmAddString(char *psz, const char *pszString); 55 static void disasmAddStringF(char *psz, const char *pszFormat, ...); 56 56 static void disasmAddChar(char *psz, char ch); 57 # define disasmAddStringF1(psz, cb, pszFmt, a1) disasmAddStringF(psz, cb, pszFmt, a1)58 # define disasmAddStringF2(psz, cb, pszFmt, a1, a2) disasmAddStringF(psz, cb, pszFmt, a1, a2)59 # define disasmAddStringF3(psz, cb, pszFmt, a1, a2, a3) disasmAddStringF(psz, cb, pszFmt, a1, a2, a3)57 # define disasmAddStringF1(psz, pszFmt, a1) disasmAddStringF(psz, pszFmt, a1) 58 # define disasmAddStringF2(psz, pszFmt, a1, a2) disasmAddStringF(psz, pszFmt, a1, a2) 59 # define disasmAddStringF3(psz, pszFmt, a1, a2, a3) disasmAddStringF(psz, pszFmt, a1, a2, a3) 60 60 #else 61 # define disasmAddString(psz, cb,pszString) do {} while (0)62 # define disasmAddStringF1(psz, cb,pszFmt, a1) do {} while (0)63 # define disasmAddStringF2(psz, cb,pszFmt, a1, a2) do {} while (0)64 # define disasmAddStringF3(psz, cb,pszFmt, a1, a2, a3) do {} while (0)65 # define disasmAddChar(psz, ch) 61 # define disasmAddString(psz, pszString) do {} while (0) 62 # define disasmAddStringF1(psz, pszFmt, a1) do {} while (0) 63 # define disasmAddStringF2(psz, pszFmt, a1, a2) do {} while (0) 64 # define disasmAddStringF3(psz, pszFmt, a1, a2, a3) do {} while (0) 65 # define disasmAddChar(psz, ch) do {} while (0) 66 66 #endif 67 67 … … 571 571 const char **ppszSIBIndexReg; 572 572 const char **ppszSIBBaseReg; 573 char szTemp[32];574 szTemp[0] = '\0';575 573 576 574 scale = pCpu->SIB.Bits.Scale; … … 603 601 604 602 if (base == 5 && pCpu->ModRM.Bits.Mod == 0) 605 disasmAddStringF2( szTemp, sizeof(szTemp), "%s%s", ppszSIBIndexReg[index], szSIBScale[scale]);603 disasmAddStringF2(pParam->szParam, "%s%s", ppszSIBIndexReg[index], szSIBScale[scale]); 606 604 else 607 disasmAddStringF3( szTemp, sizeof(szTemp), "%s+%s%s", ppszSIBBaseReg[base], ppszSIBIndexReg[index], szSIBScale[scale]);605 disasmAddStringF3(pParam->szParam, "%s+%s%s", ppszSIBBaseReg[base], ppszSIBIndexReg[index], szSIBScale[scale]); 608 606 } 609 607 else 610 608 { 611 609 if (base != 5 || pCpu->ModRM.Bits.Mod != 0) 612 disasmAddStringF1( szTemp, sizeof(szTemp), "%s", ppszSIBBaseReg[base]);610 disasmAddStringF1(pParam->szParam, "%s", ppszSIBBaseReg[base]); 613 611 } 614 612 … … 616 614 { 617 615 // [scaled index] + disp32 618 disasmAddString(pParam->szParam, sizeof(pParam->szParam), &szTemp[0]);619 616 if (pCpu->addrmode == CPUMODE_32BIT) 620 617 { … … 634 631 else 635 632 { 636 disasmAddString(pParam->szParam, sizeof(pParam->szParam), szTemp);637 638 633 pParam->flags |= USE_BASE | regtype; 639 634 pParam->base.reg_gen = base; … … 739 734 pParam->base.reg_ctrl = reg; 740 735 741 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"CR%d", pParam->base.reg_ctrl);736 disasmAddStringF1(pParam->szParam, "CR%d", pParam->base.reg_ctrl); 742 737 return 0; 743 738 744 739 case OP_PARM_D: //debug register 745 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"DR%d", reg);740 disasmAddStringF1(pParam->szParam, "DR%d", reg); 746 741 pParam->flags |= USE_REG_DBG; 747 742 pParam->base.reg_dbg = reg; … … 750 745 case OP_PARM_P: //MMX register 751 746 reg &= 7; /* REX.R has no effect here */ 752 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"MM%d", reg);747 disasmAddStringF1(pParam->szParam, "MM%d", reg); 753 748 pParam->flags |= USE_REG_MMX; 754 749 pParam->base.reg_mmx = reg; … … 763 758 case OP_PARM_T: //test register 764 759 reg &= 7; /* REX.R has no effect here */ 765 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"TR%d", reg);760 disasmAddStringF1(pParam->szParam, "TR%d", reg); 766 761 pParam->flags |= USE_REG_TEST; 767 762 pParam->base.reg_test = reg; … … 775 770 776 771 case OP_PARM_V: //XMM register 777 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"XMM%d", reg);772 disasmAddStringF1(pParam->szParam, "XMM%d", reg); 778 773 pParam->flags |= USE_REG_XMM; 779 774 pParam->base.reg_xmm = reg; … … 815 810 pParam->flags |= USE_RIPDISPLACEMENT32; 816 811 pParam->disp32 = pCpu->disp; 817 disasmAddString(pParam->szParam, sizeof(pParam->szParam),"RIP+");812 disasmAddString(pParam->szParam, "RIP+"); 818 813 disasmPrintDisp32(pParam); 819 814 } … … 1210 1205 pParam->size = sizeof(uint8_t); 1211 1206 1212 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"0%02Xh", (uint32_t)pParam->parval);1207 disasmAddStringF1(pParam->szParam, "0%02Xh", (uint32_t)pParam->parval); 1213 1208 return sizeof(uint8_t); 1214 1209 } … … 1228 1223 pParam->flags |= USE_IMMEDIATE32_SX8; 1229 1224 pParam->size = sizeof(uint32_t); 1230 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"0%08Xh", (uint32_t)pParam->parval);1225 disasmAddStringF1(pParam->szParam, "0%08Xh", (uint32_t)pParam->parval); 1231 1226 } 1232 1227 else … … 1236 1231 pParam->flags |= USE_IMMEDIATE64_SX8; 1237 1232 pParam->size = sizeof(uint64_t); 1238 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"0%016RX64h", pParam->parval);1233 disasmAddStringF1(pParam->szParam, "0%016RX64h", pParam->parval); 1239 1234 } 1240 1235 else … … 1243 1238 pParam->flags |= USE_IMMEDIATE16_SX8; 1244 1239 pParam->size = sizeof(uint16_t); 1245 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"0%04Xh", (uint16_t)pParam->parval);1240 disasmAddStringF1(pParam->szParam, "0%04Xh", (uint16_t)pParam->parval); 1246 1241 } 1247 1242 return sizeof(uint8_t); … … 1261 1256 pParam->size = sizeof(uint16_t); 1262 1257 1263 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"0%04Xh", (uint16_t)pParam->parval);1258 disasmAddStringF1(pParam->szParam, "0%04Xh", (uint16_t)pParam->parval); 1264 1259 return sizeof(uint16_t); 1265 1260 } … … 1278 1273 pParam->size = sizeof(uint32_t); 1279 1274 1280 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"0%08Xh", (uint32_t)pParam->parval);1275 disasmAddStringF1(pParam->szParam, "0%08Xh", (uint32_t)pParam->parval); 1281 1276 return sizeof(uint32_t); 1282 1277 } … … 1295 1290 pParam->size = sizeof(uint64_t); 1296 1291 1297 disasmAddStringF2(pParam->szParam, sizeof(pParam->szParam),"0%08X%08Xh",1292 disasmAddStringF2(pParam->szParam, "0%08X%08Xh", 1298 1293 (uint32_t)pParam->parval, (uint32_t)(pParam->parval >> 32)); 1299 1294 return sizeof(uint64_t); … … 1315 1310 pParam->size = sizeof(uint32_t); 1316 1311 1317 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"0%08Xh", (uint32_t)pParam->parval);1312 disasmAddStringF1(pParam->szParam, "0%08Xh", (uint32_t)pParam->parval); 1318 1313 return sizeof(uint32_t); 1319 1314 } … … 1325 1320 pParam->size = sizeof(uint64_t); 1326 1321 1327 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"0%RX64h", pParam->parval);1322 disasmAddStringF1(pParam->szParam, "0%RX64h", pParam->parval); 1328 1323 return sizeof(uint64_t); 1329 1324 } … … 1334 1329 pParam->size = sizeof(uint16_t); 1335 1330 1336 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"0%04Xh", (uint32_t)pParam->parval);1331 disasmAddStringF1(pParam->szParam, "0%04Xh", (uint32_t)pParam->parval); 1337 1332 return sizeof(uint16_t); 1338 1333 } … … 1361 1356 pParam->size = sizeof(uint16_t); 1362 1357 1363 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"0%04Xh", (uint32_t)pParam->parval);1358 disasmAddStringF1(pParam->szParam, "0%04Xh", (uint32_t)pParam->parval); 1364 1359 return sizeof(uint16_t); 1365 1360 } … … 1372 1367 pParam->flags |= USE_IMMEDIATE64; 1373 1368 pParam->size = sizeof(uint64_t); 1374 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"0%RX64h", pParam->parval);1369 disasmAddStringF1(pParam->szParam, "0%RX64h", pParam->parval); 1375 1370 } 1376 1371 else … … 1379 1374 pParam->flags |= USE_IMMEDIATE32; 1380 1375 pParam->size = sizeof(uint32_t); 1381 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"0%08Xh", (uint32_t)pParam->parval);1376 disasmAddStringF1(pParam->szParam, "0%08Xh", (uint32_t)pParam->parval); 1382 1377 } 1383 1378 return sizeof(uint32_t); … … 1403 1398 pParam->size = sizeof(uint8_t); 1404 1399 1405 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam)," (0%02Xh)", (uint32_t)pParam->parval);1400 disasmAddStringF1(pParam->szParam, " (0%02Xh)", (uint32_t)pParam->parval); 1406 1401 return sizeof(char); 1407 1402 } … … 1424 1419 pParam->size = sizeof(int32_t); 1425 1420 1426 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam)," (0%08Xh)", (uint32_t)pParam->parval);1421 disasmAddStringF1(pParam->szParam, " (0%08Xh)", (uint32_t)pParam->parval); 1427 1422 return sizeof(int32_t); 1428 1423 } … … 1435 1430 pParam->size = sizeof(int64_t); 1436 1431 1437 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam)," (0%RX64h)", pParam->parval);1432 disasmAddStringF1(pParam->szParam, " (0%RX64h)", pParam->parval); 1438 1433 return sizeof(int32_t); 1439 1434 } … … 1444 1439 pParam->size = sizeof(int16_t); 1445 1440 1446 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam)," (0%04Xh)", (uint32_t)pParam->parval);1441 disasmAddStringF1(pParam->szParam, " (0%04Xh)", (uint32_t)pParam->parval); 1447 1442 return sizeof(int16_t); 1448 1443 } … … 1472 1467 pParam->size = sizeof(uint16_t) + sizeof(uint32_t); 1473 1468 1474 disasmAddStringF2(pParam->szParam, sizeof(pParam->szParam),"0%04X:0%08Xh", (uint32_t)(pParam->parval>>32), (uint32_t)pParam->parval);1469 disasmAddStringF2(pParam->szParam, "0%04X:0%08Xh", (uint32_t)(pParam->parval>>32), (uint32_t)pParam->parval); 1475 1470 return sizeof(uint32_t) + sizeof(uint16_t); 1476 1471 } … … 1485 1480 pParam->size = sizeof(uint32_t); 1486 1481 1487 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"[0%08Xh]", pParam->disp32);1482 disasmAddStringF1(pParam->szParam, "[0%08Xh]", pParam->disp32); 1488 1483 return sizeof(uint32_t); 1489 1484 } … … 1502 1497 pParam->size = sizeof(uint64_t); 1503 1498 1504 disasmAddStringF2(pParam->szParam, sizeof(pParam->szParam),"[0%08X%08Xh]", (uint32_t)(pParam->disp64 >> 32), (uint32_t)pParam->disp64);1499 disasmAddStringF2(pParam->szParam, "[0%08X%08Xh]", (uint32_t)(pParam->disp64 >> 32), (uint32_t)pParam->disp64); 1505 1500 return sizeof(uint64_t); 1506 1501 } … … 1513 1508 pParam->size = 2*sizeof(uint16_t); 1514 1509 1515 disasmAddStringF2(pParam->szParam, sizeof(pParam->szParam),"0%04X:0%04Xh", (uint32_t)(pParam->parval>>16), (uint16_t)pParam->parval );1510 disasmAddStringF2(pParam->szParam, "0%04X:0%04Xh", (uint32_t)(pParam->parval>>16), (uint16_t)pParam->parval ); 1516 1511 return sizeof(uint32_t); 1517 1512 } … … 1526 1521 pParam->size = sizeof(uint16_t); 1527 1522 1528 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"[0%04Xh]", (uint32_t)pParam->disp16);1523 disasmAddStringF1(pParam->szParam, "[0%04Xh]", (uint32_t)pParam->disp16); 1529 1524 return sizeof(uint16_t); 1530 1525 } … … 1667 1662 { 1668 1663 disasmGetPtrString(pCpu, pOp, pParam); 1669 disasmAddString(pParam->szParam, sizeof(pParam->szParam),(pCpu->addrmode == CPUMODE_32BIT) ? "DS:ESI" : "DS:SI");1664 disasmAddString(pParam->szParam, (pCpu->addrmode == CPUMODE_32BIT) ? "DS:ESI" : "DS:SI"); 1670 1665 1671 1666 pParam->flags |= USE_POINTER_DS_BASED; … … 1692 1687 unsigned ParseXb(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu) 1693 1688 { 1694 disasmAddString(pParam->szParam, sizeof(pParam->szParam),(pCpu->addrmode == CPUMODE_32BIT) ? "DS:ESI" : "DS:SI");1689 disasmAddString(pParam->szParam, (pCpu->addrmode == CPUMODE_32BIT) ? "DS:ESI" : "DS:SI"); 1695 1690 1696 1691 pParam->flags |= USE_POINTER_DS_BASED; … … 1718 1713 { 1719 1714 disasmGetPtrString(pCpu, pOp, pParam); 1720 disasmAddString(pParam->szParam, sizeof(pParam->szParam),(pCpu->addrmode == CPUMODE_32BIT) ? "ES:EDI" : "ES:DI");1715 disasmAddString(pParam->szParam, (pCpu->addrmode == CPUMODE_32BIT) ? "ES:EDI" : "ES:DI"); 1721 1716 1722 1717 pParam->flags |= USE_POINTER_ES_BASED; … … 1743 1738 unsigned ParseYb(RTUINTPTR pu8CodeBlock, PCOPCODE pOp, POP_PARAMETER pParam, PDISCPUSTATE pCpu) 1744 1739 { 1745 disasmAddString(pParam->szParam, sizeof(pParam->szParam),(pCpu->addrmode == CPUMODE_32BIT) ? "ES:EDI" : "ES:DI");1740 disasmAddString(pParam->szParam, (pCpu->addrmode == CPUMODE_32BIT) ? "ES:EDI" : "ES:DI"); 1746 1741 1747 1742 pParam->flags |= USE_POINTER_ES_BASED; … … 2351 2346 idx += (USE_REG_SPL - USE_REG_AH); 2352 2347 } 2353 disasmAddString(pParam->szParam, s izeof(pParam->szParam), szModRMReg8[idx]);2348 disasmAddString(pParam->szParam, szModRMReg8[idx]); 2354 2349 2355 2350 pParam->flags |= USE_REG_GEN8; … … 2358 2353 2359 2354 case OP_PARM_w: 2360 disasmAddString(pParam->szParam, s izeof(pParam->szParam), szModRMReg16[idx]);2355 disasmAddString(pParam->szParam, szModRMReg16[idx]); 2361 2356 Assert(idx < (pCpu->prefix & PREFIX_REX) ? 16 : 8); 2362 2357 … … 2366 2361 2367 2362 case OP_PARM_d: 2368 disasmAddString(pParam->szParam, s izeof(pParam->szParam), szModRMReg32[idx]);2363 disasmAddString(pParam->szParam, szModRMReg32[idx]); 2369 2364 Assert(idx < (pCpu->prefix & PREFIX_REX) ? 16 : 8); 2370 2365 … … 2374 2369 2375 2370 case OP_PARM_q: 2376 disasmAddString(pParam->szParam, s izeof(pParam->szParam), szModRMReg64[idx]);2371 disasmAddString(pParam->szParam, szModRMReg64[idx]); 2377 2372 pParam->flags |= USE_REG_GEN64; 2378 2373 pParam->base.reg_gen = idx; … … 2393 2388 void disasmModRMReg16(PDISCPUSTATE pCpu, PCOPCODE pOp, unsigned idx, POP_PARAMETER pParam) 2394 2389 { 2395 disasmAddString(pParam->szParam, s izeof(pParam->szParam), szModRMReg1616[idx]);2390 disasmAddString(pParam->szParam, szModRMReg1616[idx]); 2396 2391 pParam->flags |= USE_REG_GEN16; 2397 2392 pParam->base.reg_gen = BaseModRMReg16[idx]; … … 2418 2413 2419 2414 idx = RT_MIN(idx, RT_ELEMENTS(szModRMSegReg)-1); 2420 disasmAddString(pParam->szParam, s izeof(pParam->szParam), szModRMSegReg[idx]);2415 disasmAddString(pParam->szParam, szModRMSegReg[idx]); 2421 2416 pParam->flags |= USE_REG_SEG; 2422 2417 pParam->base.reg_seg = (DIS_SELREG)idx; … … 2426 2421 void disasmPrintAbs32(POP_PARAMETER pParam) 2427 2422 { 2428 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"%08Xh", pParam->disp32);2423 disasmAddStringF1(pParam->szParam, "%08Xh", pParam->disp32); 2429 2424 } 2430 2425 //***************************************************************************** … … 2432 2427 void disasmPrintDisp32(POP_PARAMETER pParam) 2433 2428 { 2434 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"%08Xh", pParam->disp32);2429 disasmAddStringF1(pParam->szParam, "%08Xh", pParam->disp32); 2435 2430 } 2436 2431 //***************************************************************************** … … 2438 2433 void disasmPrintDisp64(POP_PARAMETER pParam) 2439 2434 { 2440 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"%16RX64h", pParam->disp64);2435 disasmAddStringF1(pParam->szParam, "%16RX64h", pParam->disp64); 2441 2436 } 2442 2437 //***************************************************************************** … … 2444 2439 void disasmPrintDisp8(POP_PARAMETER pParam) 2445 2440 { 2446 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"%d", pParam->disp8);2441 disasmAddStringF1(pParam->szParam, "%d", pParam->disp8); 2447 2442 } 2448 2443 //***************************************************************************** … … 2450 2445 void disasmPrintDisp16(POP_PARAMETER pParam) 2451 2446 { 2452 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"%04Xh", pParam->disp16);2447 disasmAddStringF1(pParam->szParam, "%04Xh", pParam->disp16); 2453 2448 } 2454 2449 //***************************************************************************** … … 2483 2478 2484 2479 case OP_PARM_b: 2485 disasmAddString(pParam->szParam, sizeof(pParam->szParam),"byte ptr ");2480 disasmAddString(pParam->szParam, "byte ptr "); 2486 2481 break; 2487 2482 2488 2483 case OP_PARM_w: 2489 disasmAddString(pParam->szParam, sizeof(pParam->szParam),"word ptr ");2484 disasmAddString(pParam->szParam, "word ptr "); 2490 2485 break; 2491 2486 2492 2487 case OP_PARM_d: 2493 disasmAddString(pParam->szParam, sizeof(pParam->szParam),"dword ptr ");2488 disasmAddString(pParam->szParam, "dword ptr "); 2494 2489 break; 2495 2490 2496 2491 case OP_PARM_q: 2497 2492 case OP_PARM_dq: 2498 disasmAddString(pParam->szParam, sizeof(pParam->szParam),"qword ptr ");2493 disasmAddString(pParam->szParam, "qword ptr "); 2499 2494 break; 2500 2495 2501 2496 case OP_PARM_p: 2502 disasmAddString(pParam->szParam, sizeof(pParam->szParam),"far ptr ");2497 disasmAddString(pParam->szParam, "far ptr "); 2503 2498 break; 2504 2499 … … 2512 2507 } 2513 2508 if (pCpu->prefix & PREFIX_SEG) 2514 disasmAddStringF1(pParam->szParam, sizeof(pParam->szParam),"%s:", szModRMSegReg[pCpu->enmPrefixSeg]);2509 disasmAddStringF1(pParam->szParam, "%s:", szModRMSegReg[pCpu->enmPrefixSeg]); 2515 2510 } 2516 2511 //***************************************************************************** … … 2616 2611 //***************************************************************************** 2617 2612 //***************************************************************************** 2618 void disasmAddString(char *psz, size_t size, const char *pszAdd) 2619 { 2620 NOREF(size); 2613 void disasmAddString(char *psz, const char *pszAdd) 2614 { 2621 2615 strcat(psz, pszAdd); 2622 2616 } 2623 2617 //***************************************************************************** 2624 2618 //***************************************************************************** 2625 void disasmAddStringF(char *psz, size_t size,const char *pszFormat, ...)2619 void disasmAddStringF(char *psz, const char *pszFormat, ...) 2626 2620 { 2627 2621 va_list args; 2628 2622 va_start(args, pszFormat); 2629 size_t cchCur = strlen(psz); 2630 RTStrPrintfV(psz + cchCur, size - cchCur, pszFormat, args); 2623 size_t cchCur = strlen(psz); 2624 Assert(cchCur < RT_SIZEOFMEMB(OP_PARAMETER, szParam)); 2625 RTStrPrintfV(psz + cchCur, RT_SIZEOFMEMB(OP_PARAMETER, szParam) - cchCur, 2626 pszFormat, args); 2631 2627 va_end(args); 2632 2628 }
Note:
See TracChangeset
for help on using the changeset viewer.