/******************************Module*Header*******************************\ * Module Name: math.cxx * * Copyright (c) 2000 Microsoft Corporation * \**************************************************************************/ #include "precomp.hxx" #include HRESULT GetAddressAndLength( OutputControl &OutCtl, PCSTR args, PBOOL UnknownArg, PDEBUG_VALUE Address, PDEBUG_VALUE Length ) { HRESULT hr = S_OK; BOOL ArgsOk = TRUE; DEBUG_VALUE Addr; DEBUG_VALUE Len; ULONG RemIndex; if (UnknownArg != NULL) *UnknownArg = FALSE; if (Address != NULL) Address->Type = DEBUG_VALUE_INVALID; if (Length != NULL) Length->Type = DEBUG_VALUE_INVALID; Addr.Type = DEBUG_VALUE_INVALID; Len.Type = DEBUG_VALUE_INVALID; while (isspace(*args)) args++; while (hr == S_OK && ArgsOk && *args != '\0') { if (*args == '-') { ArgsOk = FALSE; do { args++; } while (*args != '\0' && !isspace(*args)); } else if (Addr.Type == DEBUG_VALUE_INVALID) { hr = OutCtl.Evaluate(args, DEBUG_VALUE_INT64, &Addr, &RemIndex); if (hr == S_OK && Addr.I64 != 0) { args += RemIndex; } else { PCHAR pEOA; CHAR EOAChar; ArgsOk = FALSE; if (hr == S_OK) { pEOA = (PCHAR)&args[RemIndex]; EOAChar = *pEOA; *pEOA = '\0'; } OutCtl.OutErr("Invalid Address: %s\n", args); if (hr == S_OK) { *pEOA = EOAChar; } } } else if (Len.Type == DEBUG_VALUE_INVALID) { hr = OutCtl.Evaluate(args, DEBUG_VALUE_INT32, &Len, &RemIndex); if (hr == S_OK && Len.I64 != 0) { args += RemIndex; } else { PCHAR pEOA; CHAR EOAChar; ArgsOk = FALSE; if (hr == S_OK) { pEOA = (PCHAR)&args[RemIndex]; EOAChar = *pEOA; *pEOA = '\0'; } OutCtl.OutErr("Invalid Length: %s\n", args); if (hr == S_OK) { *pEOA = EOAChar; } } } else { ArgsOk = FALSE; } while (isspace(*args)) args++; } if (hr == S_OK) { if (UnknownArg != NULL) *UnknownArg = !ArgsOk; if (Address != NULL) *Address = Addr; if (Length != NULL) *Length = Len; } return hr; } /******************************Public*Routine******************************\ * * Routine Name: * * dfloat * \**************************************************************************/ DECLARE_API( dfloat ) { dprintf("Extension 'dfloat' is not converted.\n"); #if ENABLE_OLD_EXTS // DOES NOT SUPPORT API64 ULONG Num; ULONG Adr; BOOL List=FALSE; ULONG Value; PARSE_ARGUMENTS(dfloat_help); if(ntok<1) { goto dfloat_help; } //find valid tokens - ignore the rest tok_pos = parse_iFindSwitch(tokens, ntok, 'l'); if(tok_pos>=0) { List = TRUE; if((tok_pos+1)>=ntok) { goto dfloat_help; //-l requires an argument and it can't be the last arg } tok_pos++; Num = (LONG)GetExpression(tokens[tok_pos]); } //find first non-switch token not preceeded by a -l tok_pos = -1; do { tok_pos = parse_FindNonSwitch(tokens, ntok, tok_pos+1); } while ( (tok_pos!=-1)&&(parse_iIsSwitch(tokens, tok_pos-1, 'l'))); if(tok_pos==-1) { goto dfloat_help; } Adr = (ULONG)GetExpression(tokens[tok_pos]); if(List) { for(ULONG i=0; iQueryInterface(__uuidof(IDebugSymbols), (void **)&Symbols)) != S_OK) { return hr; } BEGIN_API( efloat ); hr = GetAddressAndLength(OutCtl, args, &UnknownArg, &Addr, &Length); if (hr != S_OK || UnknownArg || Addr.Type != DEBUG_VALUE_INT64) { OutCtl.Output("Usage: efloat [Length]\n"); } else { if (Length.Type != DEBUG_VALUE_INT32) { Length.I32 = 1; } OutputReader OutputBuffer; OutputState OutState(Client, FALSE); ULONG64 Module; ULONG TypeId; ULONG Size; PSTR TypeDump; if ((hr = OutState.Setup(0, &OutputBuffer)) == S_OK && (hr = GetTypeId(Client, "EFLOAT", &TypeId, &Module)) == S_OK && (hr = Symbols->GetTypeSize(Module, TypeId, &Size)) == S_OK) { if (Size == 0) { OutCtl.OutErr("EFLOAT type has 0 size.\n"); hr = S_FALSE; } else { ULONG64 LastAddr = Addr.I64 + Size*Length.I32; ULONG BytesRead; while (Addr.I64 < LastAddr && OutCtl.GetInterrupt() != S_OK) { OutCtl.Output("0x%p ", Addr.I64); OutputBuffer.DiscardOutput(); hr = OutState.OutputTypeVirtual(Addr.I64, Module, TypeId, DEBUG_OUTTYPE_NO_INDENT | DEBUG_OUTTYPE_NO_OFFSET | DEBUG_OUTTYPE_COMPACT_OUTPUT); if (hr == S_OK && (hr = OutputBuffer.GetOutputCopy(&TypeDump)) == S_OK) { for (PSTR psz = TypeDump; *psz != '\0'; psz++) { if (*psz == '\n') *psz = ' '; } OutCtl.Output("%s", TypeDump); OutputEFLOAT_S(Client, &OutCtl, Module, TypeId, TypeDump, DEBUG_OUTTYPE_NO_INDENT | DEBUG_OUTTYPE_NO_OFFSET | DEBUG_OUTTYPE_COMPACT_OUTPUT, NULL); OutputBuffer.FreeOutputCopy(TypeDump); } else { OutCtl.Output("?"); } OutCtl.Output("\n"); Addr.I64 += Size; } } } } Symbols->Release(); return hr; #else INIT_API(); ULONG64 EFloatAddr; ULONG EFloatSize; int count; char ach[64]; PARSE_POINTER(efloat_help); tok_pos = parse_FindNonSwitch(tokens, ntok, tok_pos+1); if (tok_pos==-1) { count=1; } else { if (sscanf(tokens[tok_pos], "%d", &count) == EOF || count <= 0) { goto efloat_help; } } EFloatAddr = arg; EFloatSize = GetTypeSize(GDIType(EFLOAT)); while (count > 0 && !CheckControlC()) { for (ULONG offset = 0; offset < EFloatSize; offset+=sizeof(DWORD)) { ULONG64 Value; GetFieldValue(EFloatAddr+offset, "DWORD", NULL, Value); sprintf(ach, " %%0%dx", 2*min(sizeof(DWORD), EFloatSize-offset)); dprintf(ach, (DWORD)Value); } dprintf(" = "); sprintEFLOAT(Client, ach, EFloatAddr ); dprintf("%s\n", ach); EFloatAddr += EFloatSize; count--; } EXIT_API(S_OK); efloat_help: dprintf("Usage: efloat [-?] address [count]\n"); EXIT_API(S_OK); #endif } /******************************Public*Routine******************************\ * * Routine Name: * * sprintEFLOAT * \**************************************************************************/ #if ENABLE_OLD_EXTS // DOES NOT SUPPORT API64 // Here for reference int sprintEFLOAT_Old(char *ach, EFLOAT& ef) { EFLOATEXT efInt; EFLOATEXT efFrac; LONG lInt, lFrac; char chSign; efFrac = ef; if (efFrac.bIsNegative()) { efFrac.vNegate(); chSign = '-'; } else chSign = '+'; efFrac.bEfToLTruncate(lInt); efInt = lInt; efFrac -= efInt; efFrac *= (LONG) 1000000; efFrac.bEfToLTruncate(lFrac); return(sprintf(ach,"%c%d.%06d", chSign, lInt, lFrac)); } #endif // DOES NOT SUPPORT API64 int sprintEFLOAT_I386(PDEBUG_CLIENT Client, char *ach, ULONG64 offEF) { ULONG64 lMant; LONG lExp; ULONG lInt, lFrac; ULONG64 fx3232; ULONG error; char chSign = '+'; if (error = (ULONG)InitTypeRead(offEF, win32k!EFLOAT_S)) { dprintf(" Unable to get contents of EFLOAT\n"); dprintf(" (InitTypeRead returned %s)\n", pszWinDbgError(error)); return 0; } lMant = ReadField(lMant); lExp = (LONG)ReadField(lExp); if (lMant & 0x80000000) // EFLOAT::bIsNegative { // EFLOAT::vNegate() if ((lMant & 0x7FFFFFFF) == 0) { lMant = 0x40000000; lExp += 1; } else { lMant = - (LONG)lMant; } chSign = '-'; } // EFLOAT::bEfToLTruncate if (lExp > 32) return(sprintf(ach,"Overflow: exponent %d > 32", lExp)); if (lExp < -32) return(sprintf(ach,"%c0.000000", chSign)); if (lExp < 0) { fx3232 = lMant >> -lExp; } else { fx3232 = lMant << lExp; } lInt = (ULONG) (fx3232 >> 32); lFrac = (ULONG) ( ( (fx3232 & 0xFFFFFFFF) * 1000000 + 0x80000000) >> 32); if (lFrac > 1000000) { return(sprintf(ach,"Bug in sprintEFLOAT_I386: fraction above 1000000")); } if (lFrac == 1000000) { lInt++; lFrac = 0; } return(sprintf(ach,"%c%u.%06d", chSign, lInt, lFrac)); } int sprintEFLOAT_IA64(PDEBUG_CLIENT Client, char *ach, ULONG64 offEF) { return(sprintf(ach,"EFLOAT parser needs written for IA64")); } int sprintEFLOAT(PDEBUG_CLIENT Client, char *ach, ULONG64 offEF) { switch (TargetMachine) { case IMAGE_FILE_MACHINE_I386: return(sprintEFLOAT_I386(Client, ach, offEF)); case IMAGE_FILE_MACHINE_IA64: return(sprintEFLOAT_IA64(Client, ach, offEF)); default: return(sprintf(ach,"EFLOAT parser needs written for machine type %X", TargetMachine)); } } /**************************************************************************\ * * Routine Name: * * OutputEFLOAT_S * * Routine Description: * * Outputs an EFLOAT_S * \**************************************************************************/ HRESULT OutputEFLOAT_S( PDEBUG_CLIENT Client, OutputControl *OutCtl, ULONG64 Module, ULONG TypeId, PSTR Buffer, ULONG Flags, PULONG BufferUsed ) { HRESULT hr = S_FALSE; TypeOutputParser Parser(Client); DEBUG_VALUE Mant, Exp; if (Parser.LookFor(&Mant, "lMant", DEBUG_VALUE_INT32) == S_OK && Parser.Parse(Buffer, NULL) == S_OK && Parser.Complete() == S_OK && Parser.LookFor(&Exp, "lExp", DEBUG_VALUE_INT32) == S_OK && Parser.Parse(Buffer, NULL) == S_OK && Parser.Complete() == S_OK) { LONG lMant = Mant.I32; LONG lExp = Exp.I32; ULONG lInt, lFrac; ULONG64 fx3232; char chSign = '+'; if (lMant < 0) // EFLOAT::bIsNegative { // EFLOAT::vNegate() if (lMant == LONG_MIN) { lMant = -(LONG_MIN/2); lExp += 1; } else { lMant = -lMant; } chSign = '-'; } // EFLOAT::bEfToLTruncate if (lExp > 32) return OutCtl->Output("Overflow: exponent %d > 32", lExp); if (lExp < -32) return OutCtl->Output("%c0.000000", chSign); fx3232 = (lExp < 0) ? (((ULONG64) lMant) >> -lExp) : (((ULONG64) lMant) << lExp); lInt = (ULONG) (fx3232 >> 32); lFrac = (ULONG) ( ( (fx3232 & 0xFFFFFFFF) * 1000000 + 0x80000000) >> 32); if (lFrac > 1000000) { OutCtl->Output(DEBUG_OUTPUT_NORMAL | DEBUG_OUTPUT_ERROR, "Bug in sprintEFLOAT_I386: fraction above 1000000"); } else { if (lFrac == 1000000) { lInt++; lFrac = 0; } hr = OutCtl->Output("%c%u.%06d", chSign, lInt, lFrac); } } else { hr = OutCtl->Output("%s", Buffer); } return hr; } /**************************************************************************\ * * Routine Name: * * OutputFLOATL * * Routine Description: * * Outputs a FLOAT from a DEBUG_VALUE regardless of Type * \**************************************************************************/ HRESULT OutputFLOATL( OutputControl *OutCtl, PDEBUG_CLIENT Client, PDEBUG_VALUE Value ) { if (OutCtl == NULL || Value == NULL) { return E_INVALIDARG; } return OutCtl->Output("%#g", (double) Value->F32); } /******************************Public*Routine******************************\ * FLOATL * * dumps an array of FLOAT's * * History: * Wed 24-Apr-1996 10:00:27 by Kirk Olynyk [kirko] * Wrote it. \**************************************************************************/ DECLARE_API( floatl ) { HRESULT hr = E_POINTER; PDEBUG_SYMBOLS Symbols; OutputControl OutCtl(Client); DEBUG_VALUE Addr; DEBUG_VALUE Length; BOOL UnknownArg; if (Client == NULL || (hr = Client->QueryInterface(__uuidof(IDebugSymbols), (void **)&Symbols)) != S_OK) { return hr; } BEGIN_API( floatl ); hr = GetAddressAndLength(OutCtl, args, &UnknownArg, &Addr, &Length); if (hr != S_OK || UnknownArg || Addr.Type != DEBUG_VALUE_INT64) { OutCtl.Output("Usage: floatl [Count]\n"); } else { if (Length.Type != DEBUG_VALUE_INT32) { Length.I32 = 1; } ULONG64 Module; ULONG TypeId; ULONG Size; DEBUG_VALUE Value; if ((hr = GetTypeId(Client, "FLOATL", &TypeId, &Module)) == S_OK && (hr = Symbols->GetTypeSize(Module, TypeId, &Size)) == S_OK) { if (Size == 0 || Size > sizeof(Value.RawBytes)) { OutCtl.OutErr("FLOATL type has unexpected size.\n"); hr = S_FALSE; } else { ULONG64 LastAddr = Addr.I64 + Size*Length.I32; ULONG BytesRead; while (Addr.I64 < LastAddr && OutCtl.GetInterrupt() != S_OK) { OutCtl.Output("0x%p ", Addr.I64); if (Symbols->ReadTypedDataVirtual(Addr.I64, Type_Module.Base, TypeId, &Value, Size, &BytesRead) == S_OK && BytesRead == Size) { OutputFLOATL(&OutCtl, Client, &Value); } else { OutCtl.Output("?"); } OutCtl.Output("\n"); Addr.I64 += Size; } } } } Symbols->Release(); return hr; } /******************************Public*Routine******************************\ * * Routine Name: * * vDumpMATRIX * \**************************************************************************/ void vDumpMATRIX(PDEBUG_CLIENT Client, ULONG64 offMX) { DumpType(Client, "MATRIX", offMX); } /******************************Public*Routine******************************\ * MATRIX * \**************************************************************************/ DECLARE_API( matrix ) { return ExtDumpType(Client, "matrix", "MATRIX", args); } /******************************Public*Routine******************************\ * * Routine Name: * * mx * \**************************************************************************/ DECLARE_API( mx ) { return ExtDumpType(Client, "mx", "MATRIX", args); }