1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532 |
- /*++
- Copyright (c) 2013 Minoca Corp. All Rights Reserved
- Module Name:
- dbgsym.c
- Abstract:
- This module implements high level symbol support for the debugger.
- Author:
- Evan Green 7-May-2013
- Environment:
- Kernel
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include "dbgrtl.h"
- #include <minoca/debug/spproto.h>
- #include <minoca/lib/im.h>
- #include <minoca/debug/dbgext.h>
- #include "symbols.h"
- #include "dbgapi.h"
- #include "dbgrprof.h"
- #include "dbgrcomm.h"
- #include "dbgsym.h"
- #include <assert.h>
- #include <errno.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- //
- // ---------------------------------------------------------------- Definitions
- //
- //
- // Define a constant representing the maximum string length of an address
- // symbol offset. This is equal to the length of "+0x0000000000000000".
- //
- #define OFFSET_MAX_LENGTH 19
- #define LINE_NUMBER_STRING_LENGTH 9
- #define MAX_LINE_NUMBER 99999999
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- typedef union _NUMERIC_UNION {
- UCHAR Uint8;
- CHAR Int8;
- USHORT Uint16;
- SHORT Int16;
- ULONG Uint32;
- LONG Int32;
- ULONGLONG Uint64;
- LONGLONG Int64;
- float Float32;
- double Float64;
- } NUMERIC_UNION, *PNUMERIC_UNION;
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- //
- // -------------------------------------------------------------------- Globals
- //
- //
- // ------------------------------------------------------------------ Functions
- //
- INT
- DbgPrintAddressSymbol (
- PDEBUGGER_CONTEXT Context,
- ULONGLONG Address
- )
- /*++
- Routine Description:
- This routine prints a descriptive version of the given address, including
- the module and function name if possible.
- Arguments:
- Context - Supplies a pointer to the application context.
- Address - Supplies the virtual address of the target to print information
- about.
- Return Value:
- 0 if information was successfully printed.
- Returns an error code on failure.
- --*/
- {
- PSTR AddressSymbol;
- AddressSymbol = DbgGetAddressSymbol(Context, Address);
- if (AddressSymbol == NULL) {
- return ENOENT;
- }
- DbgOut("%s", AddressSymbol);
- free(AddressSymbol);
- return 0;
- }
- PSTR
- DbgGetAddressSymbol (
- PDEBUGGER_CONTEXT Context,
- ULONGLONG Address
- )
- /*++
- Routine Description:
- This routine gets a descriptive string version of the given address,
- including the module and function name if possible. It is the caller's
- responsibility to free the returned string.
- Arguments:
- Context - Supplies a pointer to the application context.
- Address - Supplies the virtual address of the target to get information
- about.
- Return Value:
- Returns a null-terminated string if successfull, or NULL on failure.
- --*/
- {
- PSTR FunctionName;
- PSOURCE_LINE_SYMBOL Line;
- LONG LineNumber;
- PDEBUGGER_MODULE Module;
- ULONGLONG Offset;
- PSYMBOL_SEARCH_RESULT ResultValid;
- SYMBOL_SEARCH_RESULT SearchResult;
- PSTR Symbol;
- ULONG SymbolSize;
- Line = NULL;
- //
- // Attempt to get the module this address is in. If one cannot be found,
- // then there is no useful information to print, so exit.
- //
- Module = DbgpFindModuleFromAddress(Context, Address, &Address);
- if (Module == NULL) {
- SymbolSize = OFFSET_MAX_LENGTH + sizeof(CHAR);
- Symbol = malloc(SymbolSize);
- if (Symbol == NULL) {
- return NULL;
- }
- sprintf(Symbol, "0x%08I64x", Address);
- return Symbol;
- }
- //
- // Attempt to find the current function symbol in the module.
- //
- SearchResult.Variety = SymbolResultInvalid;
- ResultValid = NULL;
- if (Module->Symbols != NULL) {
- ResultValid = DbgLookupSymbol(Module->Symbols, Address, &SearchResult);
- }
- //
- // If a symbol was found, allocate a buffer of the appropriate size and
- // print the string into that buffer.
- //
- if (ResultValid != NULL) {
- if (SearchResult.Variety == SymbolResultFunction) {
- LineNumber = 0;
- if ((Context->Flags & DEBUGGER_FLAG_PRINT_LINE_NUMBERS) != 0) {
- Line = DbgLookupSourceLine(Module->Symbols, Address);
- if (Line != NULL) {
- LineNumber = Line->LineNumber;
- if (LineNumber > MAX_LINE_NUMBER) {
- LineNumber = MAX_LINE_NUMBER;
- }
- }
- }
- //
- // Determine the size of the function string, accounting for the
- // module name, function name, the separating exclamation point
- // and the NULL terminating character.
- //
- SymbolSize = RtlStringLength(Module->ModuleName) +
- (sizeof(CHAR) * 2);
- FunctionName = SearchResult.U.FunctionResult->Name;
- if (FunctionName != NULL) {
- SymbolSize += RtlStringLength(FunctionName);
- }
- //
- // If there's a line number, also include space for a space,
- // open bracket, source file string, colon, line number, and
- // close bracket.
- //
- if (Line != NULL) {
- SymbolSize += RtlStringLength(Line->ParentSource->SourceFile) +
- LINE_NUMBER_STRING_LENGTH +
- (4 * sizeof(CHAR));
- }
- //
- // Add additional length if an offset needs to be appended.
- //
- Offset = Address - SearchResult.U.FunctionResult->StartAddress;
- if (Offset != 0) {
- SymbolSize += OFFSET_MAX_LENGTH;
- }
- Symbol = malloc(SymbolSize);
- if (Symbol == NULL) {
- return NULL;
- }
- if (Offset != 0) {
- if (Line != NULL) {
- snprintf(Symbol,
- SymbolSize,
- "%s!%s+0x%I64x [%s:%d]",
- Module->ModuleName,
- SearchResult.U.FunctionResult->Name,
- Offset,
- Line->ParentSource->SourceFile,
- LineNumber);
- } else {
- snprintf(Symbol,
- SymbolSize,
- "%s!%s+0x%I64x",
- Module->ModuleName,
- SearchResult.U.FunctionResult->Name,
- Offset);
- }
- } else {
- if (Line != NULL) {
- snprintf(Symbol,
- SymbolSize,
- "%s!%s [%s:%d]",
- Module->ModuleName,
- SearchResult.U.FunctionResult->Name,
- Line->ParentSource->SourceFile,
- LineNumber);
- } else {
- snprintf(Symbol,
- SymbolSize,
- "%s!%s",
- Module->ModuleName,
- SearchResult.U.FunctionResult->Name);
- }
- }
- return Symbol;
- } else if (SearchResult.Variety == SymbolResultData) {
- //
- // Determine the size of the data string, accounting for the
- // module name, data name, the separating exclamation pointer and
- // the NULL terminating character.
- //
- SymbolSize = RtlStringLength(Module->ModuleName) +
- RtlStringLength(SearchResult.U.DataResult->Name) +
- (sizeof(CHAR) * 2);
- Symbol = malloc(SymbolSize);
- if (Symbol == NULL) {
- return NULL;
- }
- sprintf(Symbol,
- "%s!%s",
- Module->ModuleName,
- SearchResult.U.DataResult->Name);
- return Symbol;
- } else {
- return NULL;
- }
- }
- //
- // If a symbol was not found, then create a string based on the module name
- // and the module offset. Allocate a string accounting for the module name,
- // offset length, and NULL terminating character.
- //
- SymbolSize = RtlStringLength(Module->ModuleName) +
- OFFSET_MAX_LENGTH +
- sizeof(CHAR);
- Symbol = malloc(SymbolSize);
- if (Symbol == NULL) {
- return NULL;
- }
- Address += Module->BaseDifference;
- if (Address >= Module->BaseAddress) {
- Offset = Address - Module->BaseAddress;
- sprintf(Symbol, "%s+0x%I64x", Module->ModuleName, Offset);
- } else {
- Offset = Module->BaseAddress - Address;
- sprintf(Symbol, "%s-0x%I64x", Module->ModuleName, Offset);
- }
- return Symbol;
- }
- BOOL
- DbgGetDataSymbolTypeInformation (
- PDATA_SYMBOL DataSymbol,
- PTYPE_SYMBOL *TypeSymbol,
- PULONG TypeSize
- )
- /*++
- Routine Description:
- This routine computes the type and type size of the given data symbol.
- Arguments:
- DataSymbol - Supplies a pointer to the data symbol whose type and type size
- are to be calculated.
- TypeSymbol - Supplies a pointer that receives a pointer to the type symbol
- that corresponds to the given data symbol.
- TypeSize - Supplies a pointer that receives the type size of the given
- data symbol.
- Return Value:
- Returns TRUE on success, or FALSE on failure.
- --*/
- {
- PTYPE_SYMBOL Type;
- assert(DataSymbol != NULL);
- assert(TypeSize != NULL);
- assert(TypeSymbol != NULL);
- //
- // Get the type information and size.
- //
- Type = DbgGetType(DataSymbol->TypeOwner, DataSymbol->TypeNumber);
- if (Type == NULL) {
- DbgOut("Error: Could not lookup type number for data symbol!\n"
- "Type was in file %s, symbol number %d\n",
- DataSymbol->TypeOwner->SourceFile,
- DataSymbol->TypeNumber);
- return FALSE;
- }
- *TypeSize = DbgGetTypeSize(Type, 0);
- *TypeSymbol = Type;
- return TRUE;
- }
- INT
- DbgGetDataSymbolAddress (
- PDEBUGGER_CONTEXT Context,
- PDEBUG_SYMBOLS Symbols,
- PDATA_SYMBOL DataSymbol,
- ULONGLONG DebasedPc,
- PULONGLONG Address
- )
- /*++
- Routine Description:
- This routine returns the memory address of the given data symbol.
- Arguments:
- Context - Supplies a pointer to the application context.
- Symbols - Supplies a pointer to the module symbols.
- DataSymbol - Supplies a pointer to the data symbol whose address is to be
- returned.
- DebasedPc - Supplies the program counter value, assuming the image were
- loaded at its preferred base address (that is, actual PC minus the
- loaded base difference of the module).
- Address - Supplies a pointer where the debased memory address of the symbol
- will be returned. That is, the caller needs to add any loaded base
- difference of the module to this value.
- Return Value:
- 0 on success.
- ENOENT if the data symbol is not currently valid.
- ERANGE if the data symbol is not stored in memory.
- Other error codes on other failures.
- --*/
- {
- PSYMBOLS_GET_ADDRESS_OF_DATA_SYMBOL AddressOf;
- INT Status;
- if (DebasedPc < DataSymbol->MinimumValidExecutionAddress) {
- return ENOENT;
- }
- switch (DataSymbol->LocationType) {
- case DataLocationAbsoluteAddress:
- *Address = DataSymbol->Location.Address;
- Status = 0;
- break;
- case DataLocationComplex:
- AddressOf = Symbols->Interface->GetAddressOfDataSymbol;
- if (AddressOf == NULL) {
- DbgOut("Error: Complex symbol had no AddressOf function.\n");
- Status = EINVAL;
- break;
- }
- Status = AddressOf(Symbols, DataSymbol, DebasedPc, Address);
- break;
- default:
- Status = ERANGE;
- break;
- }
- return Status;
- }
- INT
- DbgGetDataSymbolData (
- PDEBUGGER_CONTEXT Context,
- PDEBUG_SYMBOLS Symbols,
- PDATA_SYMBOL DataSymbol,
- ULONGLONG DebasedPc,
- PVOID DataStream,
- ULONG DataStreamSize,
- PSTR Location,
- ULONG LocationSize
- )
- /*++
- Routine Description:
- This routine returns the data contained by the given data symbol.
- Arguments:
- Context - Supplies a pointer to the application context.
- Symbols - Supplies a pointer to the module symbols.
- DataSymbol - Supplies a pointer to the data symbol whose data is to be
- retrieved.
- DebasedPc - Supplies the program counter value, assuming the image were
- loaded at its preferred base address (that is, actual PC minus the
- loaded base difference of the module).
- DataStream - Supplies a pointer that receives the data from the data symbol.
- DataStreamSize - Supplies the size of the data stream buffer.
- Location - Supplies an optional pointer where a string describing the
- location of the data symbol will be returned on success.
- LocationSize - Supplies the size of the location in bytes.
- Return Value:
- 0 on success.
- ENOENT if the data symbol is not currently active given the current state
- of the machine.
- Returns an error code on failure.
- --*/
- {
- ULONG BytesRead;
- LONGLONG Offset;
- INT Printed;
- ULONG Register;
- INT Result;
- ULONGLONG TargetAddress;
- ULONGLONG Value;
- //
- // Collect the data contents for the symbol based on where it is located.
- //
- switch (DataSymbol->LocationType) {
- case DataLocationRegister:
- Register = DataSymbol->Location.Register;
- if (LocationSize != 0) {
- Printed = snprintf(Location,
- LocationSize,
- "@%s",
- DbgGetRegisterName(Symbols->Machine, Register));
- if (Printed > 0) {
- Location += Printed;
- LocationSize -= Printed;
- }
- }
- Result = DbgGetRegister(Context,
- &(Context->FrameRegisters),
- Register,
- &Value);
- if (Result != 0) {
- goto GetDataSymbolDataEnd;
- }
- //
- // Get a pointer to the data.
- //
- switch (Context->MachineType) {
- case MACHINE_TYPE_X86:
- if (DataStreamSize >= 4) {
- *(PULONG)DataStream = Value;
- DataStream += 4;
- DataStreamSize -= 4;
- }
- if (DataStreamSize >= 4) {
- switch (Register) {
- case X86RegisterEax:
- Register = X86RegisterEdx;
- break;
- case X86RegisterEbx:
- Register = X86RegisterEcx;
- break;
- default:
- DbgOut("Error: Data symbol location was a register, but "
- "type size was %d!\n"
- "Error: the register was %d.\n",
- DataStreamSize,
- Register);
- break;
- }
- DbgGetRegister(Context,
- &(Context->FrameRegisters),
- Register,
- &Value);
- *(PULONG)DataStream = Value;
- }
- break;
- //
- // ARM registers. Since the registers are all in order and are named
- // r0-r15, the register number is an offset from the register base, r0.
- //
- case MACHINE_TYPE_ARM:
- if (DataStreamSize >= 4) {
- *(PULONG)DataStream = Value;
- DataStream += 4;
- DataStreamSize -= 4;
- }
- if (DataStreamSize >= 4) {
- DbgGetRegister(Context,
- &(Context->FrameRegisters),
- Register + 1,
- &Value);
- *(PULONG)DataStream = Value;
- }
- break;
- //
- // Unknown machine type.
- //
- default:
- DbgOut("Error: Unknown machine type %d.\n", Context->MachineType);
- Result = EINVAL;
- break;
- }
- break;
- case DataLocationIndirect:
- Register = DataSymbol->Location.Indirect.Register;
- Offset = DataSymbol->Location.Indirect.Offset;
- //
- // Get the target virtual address and attempt to read from the debuggee.
- //
- Result = DbgGetRegister(Context,
- &(Context->FrameRegisters),
- Register,
- &TargetAddress);
- if (Result != 0) {
- DbgOut("Error: Failed to get register %d.\n",
- DataSymbol->Location.Indirect.Register);
- goto GetDataSymbolDataEnd;
- }
- TargetAddress += Offset;
- if (LocationSize != 0) {
- if (Offset >= 0) {
- Printed = snprintf(
- Location,
- LocationSize,
- "[@%s+0x%I64x]",
- DbgGetRegisterName(Symbols->Machine, Register),
- Offset);
- } else {
- Printed = snprintf(
- Location,
- LocationSize,
- "[@%s-0x%I64x]",
- DbgGetRegisterName(Symbols->Machine, Register),
- -Offset);
- }
- if (Printed > 0) {
- Location += Printed;
- LocationSize -= Printed;
- }
- }
- Result = DbgReadMemory(Context,
- TRUE,
- TargetAddress,
- DataStreamSize,
- DataStream,
- &BytesRead);
- if ((Result != 0) || (BytesRead != DataStreamSize)) {
- if (Result == 0) {
- Result = EINVAL;
- }
- DbgOut("Error: Type is %d bytes large, but only %d bytes could be "
- "read from the target!\n",
- DataStreamSize,
- BytesRead);
- goto GetDataSymbolDataEnd;
- }
- break;
- case DataLocationAbsoluteAddress:
- TargetAddress = DataSymbol->Location.Address;
- if (LocationSize != 0) {
- Printed = snprintf(Location,
- LocationSize,
- "[%+I64x]",
- TargetAddress);
- if (Printed > 0) {
- Location += Printed;
- LocationSize -= Printed;
- }
- }
- Result = DbgReadMemory(Context,
- TRUE,
- TargetAddress,
- DataStreamSize,
- DataStream,
- &BytesRead);
- if ((Result != 0) || (BytesRead != DataStreamSize)) {
- if (Result == 0) {
- Result = EINVAL;
- }
- DbgOut("Error: Type is %d bytes large, but only %d bytes could be "
- "read from the target!\n",
- DataStreamSize,
- BytesRead);
- goto GetDataSymbolDataEnd;
- }
- break;
- case DataLocationComplex:
- if (Symbols->Interface->ReadDataSymbol == NULL) {
- DbgOut("Error: Cannot resolve complex symbol.\n");
- Result = EINVAL;
- goto GetDataSymbolDataEnd;
- }
- Result = Symbols->Interface->ReadDataSymbol(Symbols,
- DataSymbol,
- DebasedPc,
- DataStream,
- DataStreamSize,
- Location,
- LocationSize);
- if (Result != 0) {
- if (Result != ENOENT) {
- DbgOut("Error: Cannot read local %s.\n", DataSymbol->Name);
- }
- goto GetDataSymbolDataEnd;
- }
- LocationSize = 0;
- break;
- default:
- DbgOut("Error: Unknown data symbol location %d.\n",
- DataSymbol->LocationType);
- Result = EINVAL;
- goto GetDataSymbolDataEnd;
- }
- if (LocationSize != 0) {
- *Location = '\0';
- }
- Result = 0;
- GetDataSymbolDataEnd:
- return Result;
- }
- INT
- DbgPrintDataSymbol (
- PDEBUGGER_CONTEXT Context,
- PDEBUG_SYMBOLS Symbols,
- PDATA_SYMBOL DataSymbol,
- ULONGLONG DebasedPc,
- ULONG SpaceLevel,
- ULONG RecursionDepth
- )
- /*++
- Routine Description:
- This routine prints the location and value of a data symbol.
- Arguments:
- Context - Supplies a pointer to the application context.
- Symbols - Supplies a pointer to the module symbols.
- DataSymbol - Supplies a pointer to the data symbol to print.
- DebasedPc - Supplies the program counter value, assuming the image were
- loaded at its preferred base address (that is, actual PC minus the
- loaded base difference of the module).
- SpaceLevel - Supplies the number of spaces to print after every newline.
- Used for nesting types.
- RecursionDepth - Supplies how many times this should recurse on structure
- members. If 0, only the name of the type is printed.
- Return Value:
- 0 on success.
- ENOENT if the data symbol is not currently active given the current state
- of the machine.
- Returns an error code on failure.
- --*/
- {
- PVOID DataStream;
- CHAR Location[64];
- INT Result;
- PTYPE_SYMBOL Type;
- ULONG TypeSize;
- DataStream = NULL;
- assert(Context->CurrentEvent.Type == DebuggerEventBreak);
- Result = DbgGetDataSymbolTypeInformation(DataSymbol, &Type, &TypeSize);
- if (Result == FALSE) {
- Result = 0;
- goto PrintDataSymbolEnd;
- }
- //
- // Allocate and get the data stream.
- //
- DataStream = malloc(TypeSize);
- if (DataStream == NULL) {
- Result = ENOMEM;
- goto PrintDataSymbolEnd;
- }
- Result = DbgGetDataSymbolData(Context,
- Symbols,
- DataSymbol,
- DebasedPc,
- DataStream,
- TypeSize,
- Location,
- sizeof(Location));
- if (Result != 0) {
- if (Result != ENOENT) {
- DbgOut("Error: unable to get data for data symbol %s\n",
- DataSymbol->Name);
- }
- goto PrintDataSymbolEnd;
- }
- Location[sizeof(Location) - 1] = '\0';
- DbgOut("%-12s %-20s: ", Location, DataSymbol->Name);
- //
- // Print the type contents.
- //
- Result = DbgPrintType(Context,
- Type,
- DataStream,
- TypeSize,
- SpaceLevel,
- RecursionDepth);
- Result = 0;
- PrintDataSymbolEnd:
- if (DataStream != NULL) {
- free(DataStream);
- }
- return Result;
- }
- INT
- DbgGetRegister (
- PDEBUGGER_CONTEXT Context,
- PREGISTERS_UNION Registers,
- ULONG RegisterNumber,
- PULONGLONG RegisterValue
- )
- /*++
- Routine Description:
- This routine returns the contents of a register given a debug symbol
- register index.
- Arguments:
- Context - Supplies a pointer to the application context.
- Registers - Supplies a pointer to the current machine context.
- RegisterNumber - Supplies the register index to get.
- RegisterValue - Supplies a pointer where the register value will be
- returned on success.
- Return Value:
- 0 on success.
- EINVAL if the register number is invalid.
- Other error codes on other failures.
- --*/
- {
- PULONG Registers32;
- INT Status;
- ULONGLONG Value;
- Status = 0;
- Value = -1ULL;
- switch (Context->MachineType) {
- case MACHINE_TYPE_X86:
- switch (RegisterNumber) {
- case X86RegisterEax:
- Value = Registers->X86.Eax;
- break;
- case X86RegisterEcx:
- Value = Registers->X86.Ecx;
- break;
- case X86RegisterEdx:
- Value = Registers->X86.Edx;
- break;
- case X86RegisterEbx:
- Value = Registers->X86.Ebx;
- break;
- case X86RegisterEsp:
- Value = Registers->X86.Esp;
- break;
- case X86RegisterEbp:
- Value = Registers->X86.Ebp;
- break;
- case X86RegisterEsi:
- Value = Registers->X86.Esi;
- break;
- case X86RegisterEdi:
- Value = Registers->X86.Edi;
- break;
- case X86RegisterEip:
- Value = Registers->X86.Eip;
- break;
- case X86RegisterEflags:
- Value = Registers->X86.Eflags;
- break;
- case X86RegisterCs:
- Value = Registers->X86.Cs;
- break;
- case X86RegisterSs:
- Value = Registers->X86.Ss;
- break;
- case X86RegisterDs:
- Value = Registers->X86.Ds;
- break;
- case X86RegisterEs:
- Value = Registers->X86.Es;
- break;
- case X86RegisterFs:
- Value = Registers->X86.Fs;
- break;
- case X86RegisterGs:
- Value = Registers->X86.Gs;
- break;
- default:
- //
- // TODO: Fetch the floating point registers if not yet grabbed.
- //
- if ((RegisterNumber >= X86RegisterSt0) &&
- (RegisterNumber <= X86RegisterFpDo)) {
- DbgOut("TODO: FPU Register %d.\n", RegisterNumber);
- Value = 0;
- break;
- }
- assert(FALSE);
- Status = EINVAL;
- break;
- }
- break;
- case MACHINE_TYPE_ARM:
- if ((RegisterNumber >= ArmRegisterR0) &&
- (RegisterNumber <= ArmRegisterR15)) {
- Registers32 = &(Registers->Arm.R0);
- Value = Registers32[RegisterNumber];
- } else if ((RegisterNumber >= ArmRegisterD0) &&
- (RegisterNumber <= ArmRegisterD31)) {
- //
- // TODO: Fetch the floating point registers if not yet grabbed.
- //
- DbgOut("TODO: FPU Register D%d\n", RegisterNumber - ArmRegisterD0);
- Value = 0;
- } else {
- assert(FALSE);
- Status = EINVAL;
- }
- break;
- default:
- assert(FALSE);
- Status = EINVAL;
- break;
- }
- *RegisterValue = Value;
- return Status;
- }
- INT
- DbgSetRegister (
- PDEBUGGER_CONTEXT Context,
- PREGISTERS_UNION Registers,
- ULONG RegisterNumber,
- ULONGLONG Value
- )
- /*++
- Routine Description:
- This routine sets the contents of a register given its register number.
- Arguments:
- Context - Supplies a pointer to the application context.
- Registers - Supplies a pointer to the current machine context. The register
- value will be set in this context.
- RegisterNumber - Supplies the register index to set.
- Value - Supplies the new value to set.
- Return Value:
- 0 on success.
- EINVAL if the register number is invalid.
- Other error codes on other failures.
- --*/
- {
- PULONG Registers32;
- INT Status;
- Status = 0;
- switch (Context->MachineType) {
- case MACHINE_TYPE_X86:
- switch (RegisterNumber) {
- case X86RegisterEax:
- Registers->X86.Eax = Value;
- break;
- case X86RegisterEcx:
- Registers->X86.Ecx = Value;
- break;
- case X86RegisterEdx:
- Registers->X86.Edx = Value;
- break;
- case X86RegisterEbx:
- Registers->X86.Ebx = Value;
- break;
- case X86RegisterEsp:
- Registers->X86.Esp = Value;
- break;
- case X86RegisterEbp:
- Registers->X86.Ebp = Value;
- break;
- case X86RegisterEsi:
- Registers->X86.Esi = Value;
- break;
- case X86RegisterEdi:
- Registers->X86.Edi = Value;
- break;
- case X86RegisterEip:
- Registers->X86.Eip = Value;
- break;
- case X86RegisterEflags:
- Registers->X86.Eflags = Value;
- break;
- case X86RegisterCs:
- Registers->X86.Cs = Value;
- break;
- case X86RegisterSs:
- Registers->X86.Ss = Value;
- break;
- case X86RegisterDs:
- Registers->X86.Ds = Value;
- break;
- case X86RegisterEs:
- Registers->X86.Es = Value;
- break;
- case X86RegisterFs:
- Registers->X86.Fs = Value;
- break;
- case X86RegisterGs:
- Registers->X86.Gs = Value;
- break;
- default:
- //
- // TODO: Fetch the floating point registers if not yet grabbed.
- //
- if ((RegisterNumber >= X86RegisterSt0) &&
- (RegisterNumber <= X86RegisterFpDo)) {
- DbgOut("TODO: FPU Register %d.\n", RegisterNumber);
- break;
- }
- assert(FALSE);
- Status = EINVAL;
- break;
- }
- break;
- case MACHINE_TYPE_ARM:
- if ((RegisterNumber >= ArmRegisterR0) &&
- (RegisterNumber <= ArmRegisterR15)) {
- Registers32 = &(Registers->Arm.R0);
- Registers32[RegisterNumber] = Value;
- } else if ((RegisterNumber >= ArmRegisterD0) &&
- (RegisterNumber <= ArmRegisterD31)) {
- //
- // TODO: Fetch the floating point registers if not yet grabbed.
- //
- DbgOut("TODO: FPU Register D%d\n", RegisterNumber - ArmRegisterD0);
- } else {
- assert(FALSE);
- Status = EINVAL;
- }
- break;
- default:
- assert(FALSE);
- Status = EINVAL;
- break;
- }
- return Status;
- }
- INT
- DbgGetTypeByName (
- PDEBUGGER_CONTEXT Context,
- PSTR TypeName,
- PTYPE_SYMBOL *Type
- )
- /*++
- Routine Description:
- This routine finds a type symbol object by its type name.
- Arguments:
- Context - Supplies a pointer to the application context.
- TypeName - Supplies a pointer to the string containing the name of the
- type to find. This can be prefixed with an module name if needed.
- Type - Supplies a pointer where a pointer to the type will be returned.
- Return Value:
- 0 on success.
- ENOENT if no type with the given name was found.
- Returns an error number on failure.
- --*/
- {
- PTYPE_SYMBOL FoundType;
- BOOL Result;
- SYMBOL_SEARCH_RESULT SearchResult;
- INT Status;
- FoundType = NULL;
- SearchResult.Variety = SymbolResultType;
- Result = DbgpFindSymbol(Context, TypeName, &SearchResult);
- if ((Result == FALSE) || (SearchResult.Variety != SymbolResultType)) {
- Status = ENOENT;
- goto GetTypeByNameEnd;
- }
- //
- // Read the base type.
- //
- FoundType = SearchResult.U.TypeResult;
- FoundType = DbgSkipTypedefs(FoundType);
- Status = 0;
- GetTypeByNameEnd:
- if (Status != 0) {
- FoundType = NULL;
- }
- *Type = FoundType;
- return Status;
- }
- INT
- DbgReadIntegerMember (
- PDEBUGGER_CONTEXT Context,
- PTYPE_SYMBOL Type,
- PSTR MemberName,
- ULONGLONG Address,
- PVOID Data,
- ULONG DataSize,
- PULONGLONG Value
- )
- /*++
- Routine Description:
- This routine reads an integer sized member out of an already read-in
- structure.
- Arguments:
- Context - Supplies a pointer to the application context.
- Type - Supplies a pointer to the type of the data.
- MemberName - Supplies a pointer to the member name.
- Address - Supplies the address where the data was obtained.
- Data - Supplies a pointer to the data contents.
- DataSize - Supplies the size of the data buffer in bytes.
- Value - Supplies a pointer where the value will be returned on success.
- Return Value:
- 0 on success.
- Returns an error number on failure.
- --*/
- {
- PVOID ShiftedData;
- UINTN ShiftedDataSize;
- INT Status;
- Status = DbgpGetStructureMember(Context,
- Type,
- MemberName,
- Address,
- Data,
- DataSize,
- &ShiftedData,
- &ShiftedDataSize,
- &Type);
- if (Status != 0) {
- return Status;
- }
- if (ShiftedDataSize > sizeof(ULONGLONG)) {
- DbgOut("Error: Member %s.%s was larger than integer size.\n",
- Type->Name,
- MemberName);
- free(ShiftedData);
- return EINVAL;
- }
- *Value = 0;
- memcpy(Value, ShiftedData, ShiftedDataSize);
- return Status;
- }
- INT
- DbgReadTypeByName (
- PDEBUGGER_CONTEXT Context,
- ULONGLONG Address,
- PSTR TypeName,
- PTYPE_SYMBOL *FinalType,
- PVOID *Data,
- PULONG DataSize
- )
- /*++
- Routine Description:
- This routine reads in data from the target for a specified type, which is
- given as a string.
- Arguments:
- Context - Supplies a pointer to the application context.
- Address - Supplies a target address pointer where the data resides.
- TypeName - Supplies a pointer to a string containing the type name to get.
- This should start with a type name, and can use dot '.' notation to
- specify field members, and array[] notation to specify dereferences.
- FinalType - Supplies a pointer where the final type symbol will be returned
- on success.
- Data - Supplies a pointer where the data will be returned on success. The
- caller is responsible for freeing this data when finished.
- DataSize - Supplies a pointer where the size of the data in bytes will be
- returned.
- Return Value:
- 0 on success.
- Returns an error number on failure.
- --*/
- {
- PSTR Current;
- PVOID CurrentData;
- ULONG CurrentDataSize;
- PSTR End;
- PVOID NewData;
- UINTN NewDataSize;
- INT Status;
- PTYPE_SYMBOL Type;
- CurrentData = NULL;
- CurrentDataSize = 0;
- TypeName = strdup(TypeName);
- if (TypeName == NULL) {
- Status = ENOMEM;
- goto ReadTypeByNameEnd;
- }
- End = TypeName + strlen(TypeName);
- //
- // Get the base type name.
- //
- Current = TypeName;
- while ((*Current != '\0') && (*Current != '.') && (*Current != '[')) {
- Current += 1;
- }
- *Current = '\0';
- Current += 1;
- Status = DbgGetTypeByName(Context, TypeName, &Type);
- if (Status != 0) {
- goto ReadTypeByNameEnd;
- }
- if (Type == NULL) {
- DbgOut("Error: Cannot read void.\n");
- Status = EINVAL;
- goto ReadTypeByNameEnd;
- }
- //
- // Read the base type.
- //
- Status = DbgReadType(Context,
- Address,
- Type,
- &CurrentData,
- &CurrentDataSize);
- if (Status != 0) {
- goto ReadTypeByNameEnd;
- }
- //
- // Dereference through the structure members.
- //
- if (Current < End) {
- Status = DbgpGetStructureMember(Context,
- Type,
- Current,
- Address,
- CurrentData,
- CurrentDataSize,
- &NewData,
- &NewDataSize,
- &Type);
- if (Status != 0) {
- goto ReadTypeByNameEnd;
- }
- free(CurrentData);
- CurrentData = NewData;
- CurrentDataSize = NewDataSize;
- }
- ReadTypeByNameEnd:
- if (TypeName != NULL) {
- free(TypeName);
- }
- if (Status != 0) {
- if (CurrentData != NULL) {
- free(CurrentData);
- CurrentData = NULL;
- }
- CurrentDataSize = 0;
- Type = NULL;
- }
- if (FinalType != NULL) {
- *FinalType = Type;
- }
- *Data = CurrentData;
- *DataSize = CurrentDataSize;
- return Status;
- }
- INT
- DbgReadType (
- PDEBUGGER_CONTEXT Context,
- ULONGLONG Address,
- PTYPE_SYMBOL Type,
- PVOID *Data,
- PULONG DataSize
- )
- /*++
- Routine Description:
- This routine reads in data from the target for a specified type.
- Arguments:
- Context - Supplies a pointer to the application context.
- Address - Supplies a target address pointer where the data resides.
- Type - Supplies a pointer to the type symbol to get.
- Data - Supplies a pointer where the data will be returned on success. The
- caller is responsible for freeing this data when finished.
- DataSize - Supplies a pointer where the size of the data in bytes will be
- returned.
- Return Value:
- 0 on success.
- Returns an error number on failure.
- --*/
- {
- PVOID Buffer;
- ULONG BytesRead;
- ULONGLONG Size;
- INT Status;
- *Data = NULL;
- *DataSize = 0;
- Size = DbgGetTypeSize(Type, 0);
- Buffer = malloc(Size);
- if (Buffer == NULL) {
- return ENOMEM;
- }
- memset(Buffer, 0, Size);
- Status = DbgReadMemory(Context, TRUE, Address, Size, Buffer, &BytesRead);
- if (Status != 0) {
- free(Buffer);
- return Status;
- }
- *Data = Buffer;
- *DataSize = Size;
- return 0;
- }
- INT
- DbgPrintTypeByName (
- PDEBUGGER_CONTEXT Context,
- ULONGLONG Address,
- PSTR TypeName,
- ULONG SpaceLevel,
- ULONG RecursionCount
- )
- /*++
- Routine Description:
- This routine prints a structure or value at a specified address, whose type
- is specified by a string.
- Arguments:
- Context - Supplies a pointer to the application context.
- Address - Supplies a target address pointer where the data resides.
- TypeName - Supplies a pointer to a string containing the type name to get.
- This should start with a type name, and can use dot '.' notation to
- specify field members, and array[] notation to specify dereferences.
- SpaceLevel - Supplies the number of spaces worth of indentation to print
- for subsequent lines.
- RecursionCount - Supplies the number of substructures to recurse into.
- Return Value:
- 0 on success.
- Returns an error number on failure.
- --*/
- {
- PVOID Data;
- UINTN DataSize;
- INT Status;
- PTYPE_SYMBOL Type;
- Data = NULL;
- Status = DbgReadTypeByName(Context,
- Address,
- TypeName,
- &Type,
- &Data,
- &DataSize);
- if (Status != 0) {
- return Status;
- }
- Status = DbgPrintType(Context,
- Type,
- Data,
- DataSize,
- SpaceLevel,
- RecursionCount);
- free(Data);
- return Status;
- }
- INT
- DbgPrintTypeMember (
- PDEBUGGER_CONTEXT Context,
- ULONGLONG Address,
- PVOID Data,
- ULONG DataSize,
- PTYPE_SYMBOL Type,
- PSTR MemberName,
- ULONG SpaceLevel,
- ULONG RecursionCount
- )
- /*++
- Routine Description:
- This routine prints a member of a structure or union whose contents have
- already been read in.
- Arguments:
- Context - Supplies a pointer to the application context.
- Address - Supplies the address where this data came from.
- Data - Supplies a pointer to the data contents.
- DataSize - Supplies the size of the data contents buffer in bytes.
- Type - Supplies a pointer to the structure type.
- MemberName - Supplies the name of the member to print.
- SpaceLevel - Supplies the number of spaces worth of indentation to print
- for subsequent lines.
- RecursionCount - Supplies the number of substructures to recurse into.
- Return Value:
- 0 on success.
- Returns an error number on failure.
- --*/
- {
- PVOID ShiftedData;
- UINTN ShiftedDataSize;
- INT Status;
- Status = DbgpGetStructureMember(Context,
- Type,
- MemberName,
- Address,
- Data,
- DataSize,
- &ShiftedData,
- &ShiftedDataSize,
- &Type);
- if (Status != 0) {
- return Status;
- }
- Status = DbgPrintType(Context,
- Type,
- ShiftedData,
- ShiftedDataSize,
- SpaceLevel,
- RecursionCount);
- return Status;
- }
- INT
- DbgPrintType (
- PDEBUGGER_CONTEXT Context,
- PTYPE_SYMBOL Type,
- PVOID Data,
- UINTN DataSize,
- ULONG SpaceLevel,
- ULONG RecursionCount
- )
- /*++
- Routine Description:
- This routine prints the given type to the debugger console.
- Arguments:
- Context - Supplies a pointer to the application context.
- Type - Supplies a pointer to the data type to print.
- Data - Supplies a pointer to the data contents.
- DataSize - Supplies the size of the data buffer in bytes.
- SpaceLevel - Supplies the number of spaces worth of indentation to print
- for subsequent lines.
- RecursionCount - Supplies the number of substructures to recurse into.
- Return Value:
- 0 on success.
- Returns an error number on failure.
- --*/
- {
- ULONGLONG ArrayIndex;
- ULONG BitRemainder;
- ULONG Bytes;
- PDATA_TYPE_ENUMERATION Enumeration;
- PENUMERATION_MEMBER EnumerationMember;
- CHAR Field[256];
- PVOID MemberData;
- PSTR MemberName;
- PTYPE_SYMBOL MemberType;
- NUMERIC_UNION NumericValue;
- PDATA_TYPE_RELATION Relation;
- PTYPE_SYMBOL RelativeType;
- PVOID ShiftedData;
- INT Status;
- PDATA_TYPE_STRUCTURE Structure;
- PSTRUCTURE_MEMBER StructureMember;
- UINTN TypeSize;
- Status = 0;
- switch (Type->Type) {
- case DataTypeNumeric:
- Status = DbgpPrintNumeric(Type, Data, DataSize);
- break;
- case DataTypeRelation:
- Type = DbgSkipTypedefs(Type);
- if (Type == NULL) {
- DbgOut("void");
- Status = 0;
- break;
- }
- //
- // If it just ended up being a typedef to something else, print that
- // something else.
- //
- if (Type->Type != DataTypeRelation) {
- Status = DbgPrintType(Context,
- Type,
- Data,
- DataSize,
- SpaceLevel,
- RecursionCount);
- return Status;
- }
- //
- // This is either a pointer or an array.
- //
- Relation = &(Type->U.Relation);
- RelativeType = DbgGetType(Relation->OwningFile, Relation->TypeNumber);
- assert((Relation->Array.Minimum != Relation->Array.Maximum) ||
- (Relation->Pointer != 0));
- //
- // If it's a pointer, then the type is just a pointer.
- //
- if (Relation->Pointer != 0) {
- TypeSize = Relation->Pointer;
- if (DataSize < TypeSize) {
- return ERANGE;
- }
- NumericValue.Uint64 = 0;
- memcpy(&NumericValue, Data, TypeSize);
- DbgOut("0x%08I64x", NumericValue.Uint64);
- break;
- }
- //
- // This is an array.
- //
- TypeSize = 0;
- DbgPrintTypeName(Type);
- if (RecursionCount == 0) {
- break;
- }
- SpaceLevel += 2;
- TypeSize = DbgGetTypeSize(RelativeType, 0);
- //
- // If it's a a string, print it out as such.
- //
- if ((RelativeType->Type == DataTypeNumeric) &&
- (RelativeType->U.Numeric.Signed != FALSE) &&
- (RelativeType->U.Numeric.BitSize == BITS_PER_BYTE) &&
- (RelativeType->U.Numeric.Float == FALSE)) {
- TypeSize = Relation->Array.Maximum - Relation->Array.Minimum + 1;
- if (DataSize < TypeSize) {
- return ERANGE;
- }
- DbgPrintStringData(Data, TypeSize, SpaceLevel);
- } else {
- for (ArrayIndex = Relation->Array.Minimum;
- ArrayIndex <= Relation->Array.Maximum;
- ArrayIndex += 1) {
- if (DataSize < TypeSize) {
- Status = ERANGE;
- break;
- }
- DbgOut("\n%*s", SpaceLevel, "");
- DbgOut("[%I64d] --------------------------------------"
- "-------", ArrayIndex);
- DbgOut("\n%*s", SpaceLevel + 2, "");
- Status = DbgPrintType(Context,
- RelativeType,
- Data,
- DataSize,
- SpaceLevel + 2,
- RecursionCount - 1);
- if (Status != 0) {
- break;
- }
- Data += TypeSize;
- DataSize -= TypeSize;
- }
- }
- SpaceLevel -= 2;
- break;
- case DataTypeEnumeration:
- Enumeration = &(Type->U.Enumeration);
- TypeSize = Enumeration->SizeInBytes;
- if (TypeSize > sizeof(NumericValue)) {
- TypeSize = sizeof(NumericValue);
- }
- NumericValue.Uint64 = 0;
- memcpy(&NumericValue, Data, TypeSize);
- switch (TypeSize) {
- case 1:
- NumericValue.Int64 = NumericValue.Int8;
- break;
- case 2:
- NumericValue.Int64 = NumericValue.Int16;
- break;
- case 4:
- NumericValue.Int64 = NumericValue.Int32;
- break;
- case 8:
- break;
- default:
- assert(FALSE);
- return EINVAL;
- }
- DbgOut("%I64d", NumericValue.Int64);
- EnumerationMember = Enumeration->FirstMember;
- while (EnumerationMember != NULL) {
- if (EnumerationMember->Value == NumericValue.Int64) {
- DbgOut(" %s", EnumerationMember->Name);
- break;
- }
- EnumerationMember = EnumerationMember->NextMember;
- }
- break;
- case DataTypeStructure:
- Structure = &(Type->U.Structure);
- TypeSize = Structure->SizeInBytes;
- if (DataSize < TypeSize) {
- return ERANGE;
- }
- //
- // If the recursion depth is zero, don't print this structure contents
- // out, only print the name.
- //
- DbgPrintTypeName(Type);
- if (RecursionCount == 0) {
- break;
- }
- SpaceLevel += 2;
- StructureMember = Structure->FirstMember;
- while (StructureMember != NULL) {
- Bytes = StructureMember->BitOffset / BITS_PER_BYTE;
- if (Bytes >= DataSize) {
- return ERANGE;
- }
- BitRemainder = StructureMember->BitOffset % BITS_PER_BYTE;
- MemberData = Data + Bytes;
- DbgOut("\n%*s", SpaceLevel, "");
- snprintf(Field, sizeof(Field), "+0x%x", Bytes);
- DbgOut("%-6s ", Field);
- ShiftedData = NULL;
- MemberName = StructureMember->Name;
- if (MemberName == NULL) {
- MemberName = "";
- }
- if (BitRemainder != 0) {
- snprintf(Field,
- sizeof(Field),
- "%s:%d",
- MemberName,
- BitRemainder);
- } else {
- snprintf(Field, sizeof(Field), "%s", MemberName);
- }
- Field[sizeof(Field) - 1] = '\0';
- DbgOut("%-17s : ", Field);
- //
- // Manipulate the data for the structure member if it's got a
- // bitwise offset or size.
- //
- if ((BitRemainder != 0) || (StructureMember->BitSize != 0)) {
- ShiftedData = DbgpShiftBufferRight(MemberData,
- DataSize - Bytes,
- BitRemainder,
- StructureMember->BitSize);
- if (ShiftedData == NULL) {
- return ENOMEM;
- }
- MemberData = ShiftedData;
- }
- MemberType = DbgGetType(StructureMember->TypeFile,
- StructureMember->TypeNumber);
- if (MemberType == NULL) {
- DbgOut("DANGLING REFERENCE %s, %d\n",
- StructureMember->TypeFile->SourceFile,
- StructureMember->TypeNumber);
- assert(MemberType != NULL);
- } else {
- Status = DbgPrintType(Context,
- MemberType,
- MemberData,
- DataSize - Bytes,
- SpaceLevel,
- RecursionCount - 1);
- if (Status != 0) {
- break;
- }
- }
- if (ShiftedData != NULL) {
- free(ShiftedData);
- ShiftedData = NULL;
- }
- StructureMember = StructureMember->NextMember;
- }
- SpaceLevel -= 2;
- break;
- case DataTypeFunctionPointer:
- TypeSize = Type->U.FunctionPointer.SizeInBytes;
- if (TypeSize > sizeof(NumericValue)) {
- TypeSize = sizeof(NumericValue);
- }
- NumericValue.Uint64 = 0;
- memcpy(&NumericValue, Data, TypeSize);
- DbgOut("(*0x%08I64x)()", NumericValue.Uint64);
- break;
- default:
- assert(FALSE);
- break;
- }
- return Status;
- }
- VOID
- DbgPrintStringData (
- PSTR String,
- UINTN Size,
- ULONG SpaceDepth
- )
- /*++
- Routine Description:
- This routine prints string data to the debugger console.
- Arguments:
- String - Supplies a pointer to the string data.
- Size - Supplies the number of bytes to print out.
- SpaceDepth - Supplies the indentation to use when breaking up a string into
- multiple lines.
- Return Value:
- None.
- --*/
- {
- UCHAR Character;
- ULONG Column;
- Column = SpaceDepth;
- DbgOut("\"");
- Column += 1;
- while (Size != 0) {
- Character = *String;
- if ((Character >= ' ') && (Character < 0x80)) {
- DbgOut("%c", Character);
- Column += 1;
- } else if (Character == '\0') {
- DbgOut("\\0");
- Column += 2;
- } else if (Character == '\r') {
- DbgOut("\\r");
- Column += 2;
- } else if (Character == '\n') {
- DbgOut("\\n");
- Column += 2;
- } else if (Character == '\f') {
- DbgOut("\\f");
- Column += 2;
- } else if (Character == '\v') {
- DbgOut("\\v");
- Column += 2;
- } else if (Character == '\t') {
- DbgOut("\\t");
- Column += 2;
- } else if (Character == '\a') {
- DbgOut("\\a");
- Column += 2;
- } else if (Character == '\b') {
- DbgOut("\\b");
- Column += 2;
- } else {
- DbgOut("\\x%02x", Character);
- Column += 4;
- }
- String += 1;
- Size -= 1;
- if (Column >= 80) {
- Column = SpaceDepth;
- DbgOut("\n%*s", SpaceDepth, "");
- }
- }
- DbgOut("\"");
- return;
- }
- PDEBUGGER_MODULE
- DbgpFindModuleFromAddress (
- PDEBUGGER_CONTEXT Context,
- ULONGLONG Address,
- PULONGLONG DebasedAddress
- )
- /*++
- Routine Description:
- This routine attempts to locate a loaded module that corresponds to a
- virtual address in the target.
- Arguments:
- Context - Supplies a pointer to the application context.
- Address - Supplies an address somewhere in one of the loaded modules.
- DebasedAddress - Supplies an optional pointer where the address minus the
- loaded base difference from where the module would have preferred to
- have been loaded will be returned. This will be the address from the
- symbols' perspective.
- Return Value:
- Returns a pointer to the module that the address is contained in, or NULL if
- one cannot be found.
- --*/
- {
- PDEBUGGER_MODULE CurrentModule;
- PLIST_ENTRY CurrentModuleEntry;
- PDEBUGGER_MODULE FoundModule;
- FoundModule = NULL;
- CurrentModuleEntry = Context->ModuleList.ModulesHead.Next;
- while (CurrentModuleEntry != &(Context->ModuleList.ModulesHead)) {
- CurrentModule = LIST_VALUE(CurrentModuleEntry,
- DEBUGGER_MODULE,
- ListEntry);
- CurrentModuleEntry = CurrentModuleEntry->Next;
- if (!IS_MODULE_IN_CURRENT_PROCESS(Context, CurrentModule)) {
- continue;
- }
- if ((Address >= CurrentModule->LowestAddress) &&
- (Address < CurrentModule->LowestAddress + CurrentModule->Size)) {
- FoundModule = CurrentModule;
- break;
- }
- }
- if ((FoundModule != NULL) && (DebasedAddress != NULL)) {
- *DebasedAddress = Address - FoundModule->BaseDifference;
- }
- return FoundModule;
- }
- PDEBUGGER_MODULE
- DbgpGetModule (
- PDEBUGGER_CONTEXT Context,
- PSTR ModuleName,
- ULONG MaxLength
- )
- /*++
- Routine Description:
- This routine gets a module given the module name.
- Arguments:
- Context - Supplies a pointer to the application context.
- ModuleName - Supplies a null terminated string specifying the module name.
- MaxLength - Supplies the maximum length of the module name.
- Return Value:
- Returns a pointer to the module, or NULL if one could not be found.
- --*/
- {
- PDEBUGGER_MODULE CurrentModule;
- PLIST_ENTRY CurrentModuleEntry;
- CurrentModuleEntry = Context->ModuleList.ModulesHead.Next;
- while (CurrentModuleEntry != &(Context->ModuleList.ModulesHead)) {
- CurrentModule = LIST_VALUE(CurrentModuleEntry,
- DEBUGGER_MODULE,
- ListEntry);
- CurrentModuleEntry = CurrentModuleEntry->Next;
- if (!IS_MODULE_IN_CURRENT_PROCESS(Context, CurrentModule)) {
- continue;
- }
- if (strncasecmp(ModuleName, CurrentModule->ModuleName, MaxLength) ==
- 0) {
- return CurrentModule;
- }
- }
- return NULL;
- }
- ULONGLONG
- DbgpGetFunctionStartAddress (
- PDEBUGGER_CONTEXT Context,
- ULONGLONG Address
- )
- /*++
- Routine Description:
- This routine looks up the address for the beginning of the function given
- an address somewhere in the function.
- Arguments:
- Context - Supplies a pointer to the application context.
- Address - Supplies a virtual address somewhere inside the function.
- Return Value:
- Returns the address of the first instruction of the current function, or 0
- if the funtion could not be found.
- --*/
- {
- ULONGLONG DebasedAddress;
- ULONGLONG FunctionStart;
- PDEBUGGER_MODULE Module;
- PSYMBOL_SEARCH_RESULT ResultValid;
- SYMBOL_SEARCH_RESULT SearchResult;
- FunctionStart = 0;
- //
- // Attempt to get the module this address is in. If one cannot be found,
- // then there is no useful information to print, so exit.
- //
- Module = DbgpFindModuleFromAddress(Context, Address, &DebasedAddress);
- if (Module == NULL) {
- goto GetFunctionStartAddressEnd;
- }
- //
- // Attempt to find the current function symbol in the module.
- //
- SearchResult.Variety = SymbolResultInvalid;
- ResultValid = NULL;
- if (Module->Symbols != NULL) {
- ResultValid = DbgLookupSymbol(Module->Symbols,
- DebasedAddress,
- &SearchResult);
- }
- if ((ResultValid != NULL) &&
- (SearchResult.Variety == SymbolResultFunction)) {
- FunctionStart = SearchResult.U.FunctionResult->StartAddress +
- Module->BaseDifference;
- }
- GetFunctionStartAddressEnd:
- return FunctionStart;
- }
- BOOL
- DbgpFindSymbol (
- PDEBUGGER_CONTEXT Context,
- PSTR SearchString,
- PSYMBOL_SEARCH_RESULT SearchResult
- )
- /*++
- Routine Description:
- This routine searches for symbols. Wildcards are accepted. If the search
- string is preceded by "modulename!" then only that module will be searched.
- Arguments:
- Context - Supplies a pointer to the application context.
- SearchString - Supplies the string to search for.
- SearchResult - Supplies a pointer that receives symbol search result data.
- Return Value:
- Returns TRUE on success, or FALSE on failure.
- --*/
- {
- PDEBUGGER_MODULE CurrentModule;
- PLIST_ENTRY CurrentModuleEntry;
- BOOL HaveSilverMedalResult;
- PSTR ModuleEnd;
- ULONG ModuleLength;
- PTYPE_SYMBOL ResolvedType;
- BOOL Result;
- PSYMBOL_SEARCH_RESULT ResultValid;
- SYMBOL_SEARCH_RESULT SilverMedalResult;
- PDATA_TYPE_STRUCTURE Structure;
- PDEBUGGER_MODULE UserModule;
- Result = FALSE;
- ResultValid = NULL;
- HaveSilverMedalResult = FALSE;
- UserModule = NULL;
- //
- // Parameter checking.
- //
- if (SearchResult == NULL) {
- goto FindSymbolEnd;
- }
- //
- // If an exclamation point exists, then the module was specified. Find that
- // module.
- //
- ModuleEnd = strchr(SearchString, '!');
- if (ModuleEnd != NULL) {
- ModuleLength = (UINTN)ModuleEnd - (UINTN)SearchString;
- UserModule = DbgpGetModule(Context, SearchString, ModuleLength);
- if (UserModule == NULL) {
- DbgOut("Module %s not found.\n", SearchString);
- goto FindSymbolEnd;
- }
- //
- // Move the search string and initialize the list entry.
- //
- SearchString = ModuleEnd + 1;
- CurrentModuleEntry = &(UserModule->ListEntry);
- //
- // If a module was not specified, simply start with the first one.
- //
- } else {
- CurrentModuleEntry = Context->ModuleList.ModulesHead.Next;
- }
- //
- // Loop over all modules.
- //
- while (CurrentModuleEntry != &(Context->ModuleList.ModulesHead)) {
- CurrentModule = LIST_VALUE(CurrentModuleEntry,
- DEBUGGER_MODULE,
- ListEntry);
- CurrentModuleEntry = CurrentModuleEntry->Next;
- if (!IS_MODULE_IN_CURRENT_PROCESS(Context, CurrentModule)) {
- if (UserModule != NULL) {
- break;
- }
- continue;
- }
- //
- // Search for the symbol in the current module. Exit if it is found.
- //
- SearchResult->U.TypeResult = NULL;
- while (TRUE) {
- ResultValid = DbgpFindSymbolInModule(CurrentModule->Symbols,
- SearchString,
- SearchResult);
- //
- // If not found, stop looking in this module, and go to the next
- // module.
- //
- if (ResultValid == NULL) {
- break;
- }
- Result = TRUE;
- //
- // If it's a structure with a zero size, keep looking to see if
- // another there is a different definition with a non-zero size.
- //
- if (SearchResult->Variety == SymbolResultType) {
- ResolvedType = DbgSkipTypedefs(SearchResult->U.TypeResult);
- if ((ResolvedType != NULL) &&
- (ResolvedType->Type == DataTypeStructure)) {
- Structure = &(ResolvedType->U.Structure);
- //
- // If it's got a body, return it.
- //
- if (Structure->SizeInBytes != 0) {
- goto FindSymbolEnd;
- }
- RtlCopyMemory(&SilverMedalResult,
- SearchResult,
- sizeof(SYMBOL_SEARCH_RESULT));
- //
- // Remember that there is this search result with a zero
- // size in case that's all there is, but keep looking for
- // something better.
- //
- HaveSilverMedalResult = TRUE;
- //
- // It doesn't resolve or it's not a structure, so return it.
- //
- } else {
- goto FindSymbolEnd;
- }
- //
- // It's not a type result, so return it.
- //
- } else {
- goto FindSymbolEnd;
- }
- }
- //
- // If a specific user module was specified, do not loop over more
- // modules.
- //
- if (UserModule != NULL) {
- break;
- }
- }
- //
- // If there's not a valid result but there's a valid "second best"
- // result, then use that and declare success.
- //
- if (HaveSilverMedalResult != FALSE) {
- Result = TRUE;
- RtlCopyMemory(SearchResult,
- &SilverMedalResult,
- sizeof(SYMBOL_SEARCH_RESULT));
- }
- FindSymbolEnd:
- return Result;
- }
- PDEBUGGER_MODULE
- DbgpFindModuleFromEntry (
- PDEBUGGER_CONTEXT Context,
- PLOADED_MODULE_ENTRY TargetEntry
- )
- /*++
- Routine Description:
- This routine attempts to locate a loaded module that corresponds to the
- target's description of a loaded module.
- Arguments:
- Context - Supplies a pointer to the application context.
- TargetEntry - Supplies the target's module description.
- Return Value:
- Returns a pointer to the existing loaded module if one exists, or NULL if
- one cannot be found.
- --*/
- {
- PDEBUGGER_MODULE Backup;
- ULONG BinaryNameLength;
- ULONG CharacterIndex;
- PLIST_ENTRY CurrentListEntry;
- PDEBUGGER_MODULE CurrentModule;
- PSTR FriendlyName;
- ULONG FriendlyNameLength;
- Backup = NULL;
- if (TargetEntry == NULL) {
- return NULL;
- }
- CurrentListEntry = Context->ModuleList.ModulesHead.Next;
- while (CurrentListEntry != &(Context->ModuleList.ModulesHead)) {
- CurrentModule = LIST_VALUE(CurrentListEntry,
- DEBUGGER_MODULE,
- ListEntry);
- //
- // Set up now for the next entry so that conditions can fail and use
- // continue.
- //
- CurrentListEntry = CurrentListEntry->Next;
- if (CurrentModule->Process != TargetEntry->Process) {
- continue;
- }
- if (CurrentModule->LowestAddress != TargetEntry->LowestAddress) {
- continue;
- }
- BinaryNameLength = TargetEntry->StructureSize -
- sizeof(LOADED_MODULE_ENTRY) +
- (ANYSIZE_ARRAY * sizeof(CHAR));
- DbgpGetFriendlyName(TargetEntry->BinaryName,
- BinaryNameLength,
- &FriendlyName,
- &FriendlyNameLength);
- CharacterIndex = 0;
- while (CharacterIndex < FriendlyNameLength) {
- if (CurrentModule->ModuleName[CharacterIndex] !=
- FriendlyName[CharacterIndex]) {
- break;
- }
- CharacterIndex += 1;
- }
- if (CharacterIndex < FriendlyNameLength) {
- continue;
- }
- if (CurrentModule->ModuleName[CharacterIndex] != '\0') {
- continue;
- }
- //
- // If the timestamps don't match, save this as a backup but look for
- // something even better.
- //
- if ((TargetEntry->Timestamp != 0) &&
- (TargetEntry->Timestamp != CurrentModule->Timestamp)) {
- if (Backup == NULL) {
- Backup = CurrentModule;
- }
- continue;
- }
- //
- // All conditions were met, so this must be a match.
- //
- return CurrentModule;
- }
- return Backup;
- }
- INT
- DbgpFindLocal (
- PDEBUGGER_CONTEXT Context,
- PREGISTERS_UNION Registers,
- PSTR LocalName,
- PDEBUG_SYMBOLS *ModuleSymbols,
- PDATA_SYMBOL *Local,
- PULONGLONG DebasedPc
- )
- /*++
- Routine Description:
- This routine searches the local variables and parameters in the function
- containing the given address for a variable matching the given name.
- Arguments:
- Context - Supplies a pointer to the application context.
- Registers - Supplies a pointer to the registers to use for the search.
- LocalName - Supplies a case insensitive string of the local name.
- ModuleSymbols - Supplies a pointer where the symbols for the module will be
- returned on success.
- Local - Supplies a pointer where the local symbol will be returned on
- success.
- DebasedPc - Supplies a pointer where the PC will be returned, adjusted by
- the amount the image load was adjusted by.
- Return Value:
- 0 on success.
- ENOENT if no local by that name could be found.
- Returns an error number on other failures.
- --*/
- {
- PLIST_ENTRY CurrentEntry;
- PFUNCTION_SYMBOL Function;
- PDATA_SYMBOL LocalSymbol;
- PDEBUGGER_MODULE Module;
- PDATA_SYMBOL Parameter;
- ULONGLONG Pc;
- PSYMBOL_SEARCH_RESULT ResultValid;
- SYMBOL_SEARCH_RESULT SearchResult;
- //
- // Attempt to get the module this address is in. If one cannot be found,
- // then there is no useful information to print, so exit.
- //
- Pc = DbgGetPc(Context, Registers);
- Module = DbgpFindModuleFromAddress(Context, Pc, &Pc);
- if (Module == NULL) {
- return ENOENT;
- }
- //
- // Attempt to find the current function symbol in the module.
- //
- SearchResult.Variety = SymbolResultInvalid;
- ResultValid = NULL;
- if (Module->Symbols != NULL) {
- ResultValid = DbgFindFunctionSymbol(Module->Symbols,
- NULL,
- Pc,
- &SearchResult);
- } else {
- return ENOENT;
- }
- //
- // If a function could not be found, bail.
- //
- if ((ResultValid == NULL) ||
- (SearchResult.Variety != SymbolResultFunction)) {
- return ENOENT;
- }
- Function = SearchResult.U.FunctionResult;
- //
- // First check the locals.
- //
- LocalSymbol = DbgpGetLocal(Function, LocalName, Pc);
- if (LocalSymbol == NULL) {
- //
- // Check any function parameters.
- //
- CurrentEntry = Function->ParametersHead.Next;
- while (CurrentEntry != &(Function->ParametersHead)) {
- Parameter = LIST_VALUE(CurrentEntry, DATA_SYMBOL, ListEntry);
- CurrentEntry = CurrentEntry->Next;
- if (strcasecmp(LocalName, Parameter->Name) == 0) {
- LocalSymbol = Parameter;
- break;
- }
- }
- }
- if (LocalSymbol != NULL) {
- if (ModuleSymbols != NULL) {
- *ModuleSymbols = Module->Symbols;
- }
- if (Local != NULL) {
- *Local = LocalSymbol;
- }
- if (DebasedPc != NULL) {
- *DebasedPc = Pc;
- }
- return 0;
- }
- return ENOENT;
- }
- PDATA_SYMBOL
- DbgpGetLocal (
- PFUNCTION_SYMBOL Function,
- PSTR LocalName,
- ULONGLONG ExecutionAddress
- )
- /*++
- Routine Description:
- This routine gets the most up to date version of a local variable symbol.
- Arguments:
- Function - Supplies a pointer to the function with the desired local
- variables.
- LocalName - Supplies a case sensitive string of the local name.
- ExecutionAddress - Supplies the current execution address. This function
- will attempt to find the local variable matching the LocalName whose
- minimum execution address is as close to ExecutionAddress as possible.
- It is assumed that this address has already been de-based (the current
- base address has been subtracted from it).
- Return Value:
- Returns a pointer to the local variable symbol, or NULL if one could not
- be found.
- --*/
- {
- PDATA_SYMBOL CurrentLocal;
- PLIST_ENTRY CurrentLocalEntry;
- PDATA_SYMBOL Winner;
- Winner = NULL;
- CurrentLocalEntry = Function->LocalsHead.Next;
- while (CurrentLocalEntry != &(Function->LocalsHead)) {
- CurrentLocal = LIST_VALUE(CurrentLocalEntry,
- DATA_SYMBOL,
- ListEntry);
- CurrentLocalEntry = CurrentLocalEntry->Next;
- //
- // Skip this symbol if the minimum execution address is not even valid.
- // This is done first because it is a cheaper test than string compare.
- //
- if (ExecutionAddress < CurrentLocal->MinimumValidExecutionAddress) {
- continue;
- }
- //
- // Check if the name matches.
- //
- if (strcasecmp(LocalName, CurrentLocal->Name) != 0) {
- continue;
- }
- //
- // If no winner has been found yet, this one becomes the current winner
- // by default.
- //
- if (Winner == NULL) {
- Winner = CurrentLocal;
- //
- // There is already a current winner, see if this one has a lower
- // minimum execution address (closer to the current one, but still
- // greater).
- //
- } else {
- if (CurrentLocal->MinimumValidExecutionAddress <
- Winner->MinimumValidExecutionAddress) {
- Winner = CurrentLocal;
- }
- }
- }
- return Winner;
- }
- VOID
- DbgpGetFriendlyName (
- PSTR FullName,
- ULONG FullNameLength,
- PSTR *NameBegin,
- PULONG NameLength
- )
- /*++
- Routine Description:
- This routine determines the portion of the given binary name to use as the
- friendly name.
- Arguments:
- FullName - Supplies a pointer to the full path of the binary, null
- terminated.
- FullNameLength - Supplies the length of the full name buffer in bytes
- including the null terminator.
- NameBegin - Supplies a pointer where the beginning of the friendly name
- will be returned. This will point inside the full name.
- NameLength - Supplies a pointer where the number of characters in the
- friendly name will be returned, not including the null terminator.
- Return Value:
- Returns TRUE on success, or FALSE on failure.
- --*/
- {
- ULONG FriendlyNameLength;
- PSTR LastSeparator;
- PSTR LastSlash;
- PSTR Period;
- LastSeparator = RtlStringFindCharacterRight(FullName, '\\', FullNameLength);
- if (LastSeparator != NULL) {
- LastSeparator += 1;
- }
- LastSlash = RtlStringFindCharacterRight(FullName, '/', FullNameLength);
- if (LastSlash != NULL) {
- LastSlash += 1;
- }
- if ((LastSeparator == NULL) ||
- ((LastSlash != NULL) && (LastSlash > LastSeparator))) {
- LastSeparator = LastSlash;
- }
- if (LastSeparator == NULL) {
- LastSeparator = FullName;
- }
- FullNameLength -= (UINTN)LastSeparator - (UINTN)FullName;
- Period = RtlStringFindCharacterRight(LastSeparator, '.', FullNameLength);
- if (Period == NULL) {
- FriendlyNameLength = FullNameLength;
- } else {
- FriendlyNameLength = (UINTN)Period - (UINTN)LastSeparator;
- if (FriendlyNameLength == 0) {
- assert(FullNameLength > 1);
- FriendlyNameLength = FullNameLength - 1;
- LastSeparator += 1;
- }
- }
- assert(FriendlyNameLength != 0);
- *NameBegin = LastSeparator;
- *NameLength = FriendlyNameLength;
- return;
- }
- INT
- DbgpPrintNumeric (
- PTYPE_SYMBOL Type,
- PVOID Data,
- UINTN DataSize
- )
- /*++
- Routine Description:
- This routine prints a numeric type's contents.
- Arguments:
- Type - Supplies a pointer to the type symbol to print.
- Data - Supplies a pointer to the data contents.
- DataSize - Supplies the size of the data in bytes.
- Return Value:
- 0 on success.
- ENOBUFS if the provided buffer is not large enough to accomodate the given
- type.
- --*/
- {
- ULONG BitSize;
- PDATA_TYPE_NUMERIC Numeric;
- NUMERIC_UNION NumericValue;
- UINTN TypeSize;
- assert(Type->Type == DataTypeNumeric);
- Numeric = &(Type->U.Numeric);
- BitSize = Numeric->BitSize;
- TypeSize = ALIGN_RANGE_UP(BitSize, BITS_PER_BYTE) / BITS_PER_BYTE;
- if (DataSize < TypeSize) {
- return ERANGE;
- }
- NumericValue.Uint64 = 0;
- memcpy(&NumericValue, Data, TypeSize);
- if ((BitSize & (BITS_PER_BYTE - 1)) != 0) {
- NumericValue.Uint64 &= (1ULL << BitSize) - 1;
- }
- if (Numeric->Float != FALSE) {
- switch (TypeSize) {
- case 4:
- DbgOut("%f", (double)(NumericValue.Float32));
- break;
- case 8:
- DbgOut("%f", NumericValue.Float64);
- break;
- default:
- DbgOut("%I64x", NumericValue.Uint64);
- break;
- }
- } else if (Numeric->Signed != FALSE) {
- switch (TypeSize) {
- case 1:
- DbgOut("%d", NumericValue.Int8);
- break;
- case 2:
- DbgOut("%d", NumericValue.Int16);
- break;
- case 4:
- DbgOut("%d", NumericValue.Int32);
- break;
- case 8:
- default:
- DbgOut("%I64d", NumericValue.Int64);
- break;
- }
- } else {
- DbgOut("0x%I64x", NumericValue.Uint64);
- }
- return 0;
- }
- INT
- DbgpGetStructureMember (
- PDEBUGGER_CONTEXT Context,
- PTYPE_SYMBOL Type,
- PSTR MemberName,
- ULONGLONG Address,
- PVOID Data,
- UINTN DataSize,
- PVOID *ShiftedData,
- PUINTN ShiftedDataSize,
- PTYPE_SYMBOL *FinalType
- )
- /*++
- Routine Description:
- This routine returns a shifted form of the given data for accessing
- specific members of a structure.
- Arguments:
- Context - Supplies a pointer to the application context.
- Type - Supplies a pointer to the structure type.
- MemberName - Supplies a pointer to the member name string, which can
- contain dot '.' notation for accessing members, and array [] notation
- for access sub-elements and dereferencing.
- Address - Supplies the address the read data is located at.
- Data - Supplies a pointer to the read in data.
- DataSize - Supplies the size of the read data in bytes.
- ShiftedData - Supplies a pointer where the shifted data will be returned on
- success. The caller is responsible for freeing this data when finished.
- ShiftedDataSize - Supplies a pointer where the size of the shifted data
- will be returned on success.
- FinalType - Supplies an optional pointer where the final type of the
- data will be returned on success.
- Return Value:
- 0 on success.
- Returns an error number on failure.
- --*/
- {
- ULONGLONG ArrayIndex;
- PSTR Current;
- PVOID CurrentData;
- UINTN CurrentDataSize;
- BOOL Dereference;
- PSTR End;
- PSTR FieldName;
- CHAR FieldType;
- PSTRUCTURE_MEMBER Member;
- PVOID NewData;
- ULONG NewDataSize;
- CHAR OriginalCharacter;
- PTYPE_SYMBOL RelativeType;
- UINT ShiftAmount;
- INT Status;
- UINTN TypeSize;
- CurrentData = Data;
- CurrentDataSize = DataSize;
- MemberName = strdup(MemberName);
- if (MemberName == NULL) {
- Status = ENOMEM;
- goto GetStructureMemberEnd;
- }
- Type = DbgSkipTypedefs(Type);
- End = MemberName + strlen(MemberName);
- Current = MemberName;
- Status = 0;
- //
- // Now loop reading members and array indices.
- //
- while (Current < End) {
- //
- // Assume a member if a dot is missing from the beginning.
- //
- if ((*Current != '.') && (*Current != '[')) {
- FieldType = '.';
- } else {
- FieldType = *Current;
- Current += 1;
- }
- if (*Current == '\0') {
- break;
- }
- FieldName = Current;
- //
- // Handle an array access.
- //
- if (FieldType == '[') {
- //
- // Find the closing square bracket.
- //
- while ((*Current != '\0') && (*Current != ']')) {
- Current += 1;
- }
- *Current = '\0';
- Current += 1;
- Status = DbgEvaluate(Context, FieldName, &ArrayIndex);
- if (Status != 0) {
- DbgOut("Error: Failed to evaluate array index '%s'.\n",
- FieldName);
- goto GetStructureMemberEnd;
- }
- //
- // If this current type is not a relation, then a dereference will
- // have to occur to make something like mytype[3] work, where
- // mytype is a structure.
- //
- Dereference = FALSE;
- if (Type->Type != DataTypeRelation) {
- Dereference = TRUE;
- //
- // If it is a relation, use the relative type as the type size. If
- // this is a pointer type, then it will also need a dereference
- // through it.
- //
- } else if ((Type->U.Relation.Pointer != 0) ||
- (Type->U.Relation.Array.Minimum !=
- Type->U.Relation.Array.Maximum)) {
- if (Type->U.Relation.Pointer != 0) {
- Dereference = TRUE;
- Address = 0;
- memcpy(&Address, CurrentData, Type->U.Relation.Pointer);
- }
- RelativeType = DbgGetType(Type->U.Relation.OwningFile,
- Type->U.Relation.TypeNumber);
- if ((RelativeType == NULL) || (RelativeType == Type)) {
- DbgOut("Error: Cannot get void type.\n");
- Status = EINVAL;
- goto GetStructureMemberEnd;
- }
- Type = RelativeType;
- }
- TypeSize = DbgGetTypeSize(Type, 0);
- if (TypeSize == 0) {
- DbgOut("Error: Got a type size of zero.\n");
- Status = EINVAL;
- goto GetStructureMemberEnd;
- }
- //
- // If this was a pointer, dereference through the pointer to get
- // the new data.
- //
- if (Dereference != FALSE) {
- Address += TypeSize * ArrayIndex;
- Status = DbgReadType(Context,
- Address,
- Type,
- &NewData,
- &NewDataSize);
- if (Status != 0) {
- goto GetStructureMemberEnd;
- }
- //
- // If this was an array, just shift the buffer over to index into
- // it.
- //
- } else {
- ShiftAmount = TypeSize * ArrayIndex * BITS_PER_BYTE;
- NewData = DbgpShiftBufferRight(CurrentData,
- CurrentDataSize,
- ShiftAmount,
- 0);
- if (NewData == NULL) {
- Status = ENOMEM;
- goto GetStructureMemberEnd;
- }
- NewDataSize = TypeSize;
- }
- //
- // Access a structure member.
- //
- } else if (FieldType == '.') {
- //
- // Find the end of the member name.
- //
- while ((*Current != '\0') && (*Current != '.') &&
- (*Current != '[')) {
- Current += 1;
- }
- OriginalCharacter = *Current;
- *Current = '\0';
- if (Type->Type != DataTypeStructure) {
- DbgOut("Error: %s is not a structure.\n", Type->Name);
- Status = EINVAL;
- goto GetStructureMemberEnd;
- }
- //
- // Find the member. First try matching case, then try case
- // insensitive.
- //
- Member = Type->U.Structure.FirstMember;
- while (Member != NULL) {
- if ((Member->Name != NULL) &&
- (strcmp(Member->Name, FieldName) == 0)) {
- break;
- }
- Member = Member->NextMember;
- }
- if (Member == NULL) {
- Member = Type->U.Structure.FirstMember;
- while (Member != NULL) {
- if ((Member->Name != NULL) &&
- (strcasecmp(Member->Name, FieldName) == 0)) {
- break;
- }
- Member = Member->NextMember;
- }
- }
- if (Member == NULL) {
- DbgOut("Error: Structure %s has no member %s.\n",
- Type->Name,
- FieldName);
- Status = ENOENT;
- goto GetStructureMemberEnd;
- }
- //
- // Get the next type of this member.
- //
- Type = DbgGetType(Member->TypeFile, Member->TypeNumber);
- if (Type != NULL) {
- Type = DbgSkipTypedefs(Type);
- }
- if (Type == NULL) {
- DbgOut("Error: Got incomplete member %s.\n", FieldName);
- Status = EINVAL;
- goto GetStructureMemberEnd;
- }
- //
- // Manipulate the buffer to put the member at the beginning, which
- // creates a new buffer.
- //
- NewData = DbgpShiftBufferRight(CurrentData,
- CurrentDataSize,
- Member->BitOffset,
- Member->BitSize);
- if (NewData == NULL) {
- Status = ENOMEM;
- goto GetStructureMemberEnd;
- }
- NewDataSize = DbgGetTypeSize(Type, 0);
- *Current = OriginalCharacter;
- } else {
- assert(FALSE);
- Status = EINVAL;
- break;
- }
- assert(NewData != NULL);
- if (CurrentData != Data) {
- free(CurrentData);
- }
- CurrentData = NewData;
- CurrentDataSize = NewDataSize;
- }
- GetStructureMemberEnd:
- if (MemberName != NULL) {
- free(MemberName);
- }
- if (Status != 0) {
- if ((CurrentData != NULL) && (CurrentData != Data)) {
- free(CurrentData);
- CurrentData = NULL;
- }
- CurrentDataSize = 0;
- Type = NULL;
- }
- *ShiftedData = CurrentData;
- *ShiftedDataSize = CurrentDataSize;
- *FinalType = Type;
- return Status;
- }
- PVOID
- DbgpShiftBufferRight (
- PVOID Buffer,
- UINTN DataSize,
- UINTN Bits,
- UINTN BitSize
- )
- /*++
- Routine Description:
- This routine shifts a buffer right by a given number of bits. Zero bits
- will be shifted in from the left.
- Arguments:
- Buffer - Supplies a pointer to the buffer contents to shift. This buffer
- will remain untouched.
- DataSize - Supplies the size of the data in bytes.
- Bits - Supplies the number of bits to shift.
- BitSize - Supplies an optional number of bits to keep after shifting, all
- others will be masked. Supply 0 to perform no masking.
- Return Value:
- Returns a pointer to a newly allocated and shifted buffer on success.
- NULL on allocation failure.
- --*/
- {
- UINTN ByteCount;
- PUCHAR Bytes;
- UINTN Index;
- Bytes = malloc(DataSize);
- if (Bytes == NULL) {
- return NULL;
- }
- ByteCount = Bits / BITS_PER_BYTE;
- Bits %= BITS_PER_BYTE;
- if (DataSize > ByteCount) {
- memcpy(Bytes, Buffer + ByteCount, DataSize - ByteCount);
- memset(Bytes + DataSize - ByteCount, 0, ByteCount);
- } else {
- memset(Bytes, 0, DataSize);
- return Bytes;
- }
- if (Bits != 0) {
- //
- // Now the tricky part, shifting by between 1 and 7 bits.
- //
- for (Index = 0; Index < DataSize - 1; Index += 1) {
- Bytes[Index] = (Bytes[Index] >> Bits) |
- (Bytes[Index + 1] << (BITS_PER_BYTE - Bits));
- }
- Bytes[Index] = Bytes[Index] >> Bits;
- }
- //
- // Do some masking as well.
- //
- if (BitSize != 0) {
- Index = BitSize / BITS_PER_BYTE;
- BitSize %= BITS_PER_BYTE;
- if (BitSize != 0) {
- Bytes[Index] &= (1 << BitSize) - 1;
- Index += 1;
- }
- if (Index != DataSize) {
- memset(Bytes + Index, 0, DataSize - Index);
- }
- }
- return Bytes;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
|