123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974 |
- /*++
- Copyright (c) 2012 Minoca Corp. All Rights Reserved
- Module Name:
- symbols.c
- Abstract:
- This module implements symbol translation helper routines used by the
- debugger.
- Author:
- Evan Green 2-Jul-2012
- Environment:
- Debugger client
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include <minoca/lib/types.h>
- #include <minoca/lib/status.h>
- #include <minoca/lib/im.h>
- #include <minoca/debug/dbgext.h>
- #include "symbols.h"
- #include "stabs.h"
- #include "dwarf.h"
- #include <assert.h>
- #include <errno.h>
- #include <stdio.h>
- #include <string.h>
- #include <sys/stat.h>
- //
- // ---------------------------------------------------------------- Definitions
- //
- #define MEMBER_NAME_SPACE 17
- #define MAX_RELATION_TYPE_DEPTH 50
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- BOOL
- DbgpStringMatch (
- PSTR Query,
- PSTR PossibleMatch
- );
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- //
- // -------------------------------------------------------------------- Globals
- //
- //
- // Define the set of known symbol libraries.
- //
- PSYMBOLS_LOAD DbgSymbolLoaders[] = {
- DwarfLoadSymbols,
- DbgpStabsLoadSymbols,
- DbgpElfLoadSymbols,
- DbgpCoffLoadSymbols,
- NULL
- };
- //
- // Define a default void type that has a source file of NULL (this is unique)
- // and a type number of -1.
- //
- TYPE_SYMBOL DbgVoidType = {
- {NULL, NULL},
- NULL,
- -1,
- "void",
- NULL,
- DataTypeNumeric,
- {
- {
- FALSE,
- NULL,
- -1
- }
- }
- };
- //
- // Define the machine register names.
- //
- PSTR DbgX86RegisterSymbolNames[] = {
- "eax",
- "ecx",
- "edx",
- "ebx",
- "esp",
- "ebp",
- "esi",
- "edi",
- "eip",
- "eflags",
- "cs",
- "ss",
- "ds",
- "es",
- "fs",
- "gs",
- "st0",
- "st1",
- "st2",
- "st3",
- "st4",
- "st5",
- "st6",
- "st7",
- "xmm0",
- "xmm1",
- "xmm2",
- "xmm3",
- "xmm4",
- "xmm5",
- "xmm6",
- "xmm7",
- };
- PSTR DbgX64RegisterSymbolNames[] = {
- "rax",
- "rdx",
- "rcx",
- "rbx",
- "rsi",
- "rdi",
- "rbp",
- "rsp",
- "r8",
- "r9",
- "r10",
- "r11",
- "r12",
- "r13",
- "r14",
- "r15",
- "rip",
- "xmm0",
- "xmm1",
- "xmm2",
- "xmm3",
- "xmm4",
- "xmm5",
- "xmm6",
- "xmm7",
- "xmm8",
- "xmm9",
- "xmm10",
- "xmm11",
- "xmm12",
- "xmm13",
- "xmm14",
- "xmm15",
- "st0",
- "st1",
- "st2",
- "st3",
- "st4",
- "st5",
- "st6",
- "st7",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "eflags",
- "es",
- "cs",
- "ss",
- "ds",
- "fs",
- "gs",
- };
- PSTR DbgArmRegisterSymbolNames[] = {
- "r0",
- "r1",
- "r2",
- "r3",
- "r4",
- "r5",
- "r6",
- "r7",
- "r8",
- "r9",
- "r10",
- "r11",
- "r12",
- "sp",
- "lr",
- "pc",
- "f0"
- "f1",
- "f2",
- "f3",
- "f4",
- "f5",
- "f6",
- "f7",
- "fps",
- "cpsr"
- };
- PSTR DbgArmVfpRegisterSymbolNames[] = {
- "d0",
- "d1",
- "d2",
- "d3",
- "d4",
- "d5",
- "d6",
- "d7",
- "d8",
- "d9",
- "d10",
- "d11",
- "d12",
- "d13",
- "d14",
- "d15",
- "d16",
- "d17",
- "d18",
- "d19",
- "d20",
- "d21",
- "d22",
- "d23",
- "d24",
- "d25",
- "d26",
- "d27",
- "d28",
- "d29",
- "d30",
- "d31",
- };
- //
- // ------------------------------------------------------------------ Functions
- //
- INT
- DbgLoadSymbols (
- PSTR Filename,
- IMAGE_MACHINE_TYPE MachineType,
- PVOID HostContext,
- PDEBUG_SYMBOLS *Symbols
- )
- /*++
- Routine Description:
- This routine loads debugging symbol information from the specified file.
- Arguments:
- Filename - Supplies the name of the binary to load symbols from.
- MachineType - Supplies the required machine type of the image. Set to
- unknown to allow the symbol library to load a file with any machine
- type.
- HostContext - Supplies the value to store in the host context field of the
- debug symbols.
- Symbols - Supplies an optional pointer where a pointer to the symbols will
- be returned on success.
- Return Value:
- 0 on success.
- Returns an error number on failure.
- --*/
- {
- PSYMBOLS_LOAD *LoadFunction;
- struct stat Stat;
- INT Status;
- //
- // Don't go through the whole process if the file isn't even there.
- //
- if (stat(Filename, &Stat) != 0) {
- return errno;
- }
- LoadFunction = &(DbgSymbolLoaders[0]);
- Status = ENOSYS;
- while (*LoadFunction != NULL) {
- Status = (*LoadFunction)(Filename,
- MachineType,
- 0,
- HostContext,
- Symbols);
- if (Status == 0) {
- break;
- }
- LoadFunction += 1;
- }
- return Status;
- }
- VOID
- DbgUnloadSymbols (
- PDEBUG_SYMBOLS Symbols
- )
- /*++
- Routine Description:
- This routine frees all memory associated with an instance of debugging
- symbols. Once called, the pointer passed in should not be dereferenced
- again by the caller.
- Arguments:
- Symbols - Supplies a pointer to the debugging symbols.
- Return Value:
- None.
- --*/
- {
- Symbols->Interface->Unload(Symbols);
- return;
- }
- VOID
- DbgPrintFunctionPrototype (
- PFUNCTION_SYMBOL Function,
- PSTR ModuleName,
- ULONGLONG Address
- )
- /*++
- Routine Description:
- This routine prints a C function prototype directly to the screen.
- Arguments:
- Function - Supplies a pointer to the function symbol to print.
- ModuleName - Supplies an optional string containing the module name.
- Address - Supplies the final address of the function.
- Return Value:
- None (information is printed directly to the standard output).
- --*/
- {
- PDATA_SYMBOL CurrentParameter;
- PTYPE_SYMBOL CurrentParameterType;
- BOOL FirstParameter;
- PLIST_ENTRY ParameterEntry;
- PTYPE_SYMBOL ReturnType;
- if (Function == NULL) {
- return;
- }
- ReturnType = DbgGetType(Function->ReturnTypeOwner,
- Function->ReturnTypeNumber);
- DbgPrintTypeName(ReturnType);
- if (ModuleName != NULL) {
- DbgOut(" %s!%s (", ModuleName, Function->Name);
- } else {
- DbgOut(" %s (", Function->Name);
- }
- ParameterEntry = Function->ParametersHead.Next;
- FirstParameter = TRUE;
- while (ParameterEntry != &(Function->ParametersHead)) {
- CurrentParameter = LIST_VALUE(ParameterEntry,
- DATA_SYMBOL,
- ListEntry);
- if (FirstParameter == FALSE) {
- DbgOut(", ");
- }
- CurrentParameterType = DbgGetType(CurrentParameter->TypeOwner,
- CurrentParameter->TypeNumber);
- if (CurrentParameterType == NULL) {
- DbgOut("UNKNOWN_TYPE");
- } else {
- DbgPrintTypeName(CurrentParameterType);
- }
- DbgOut(" %s", CurrentParameter->Name);
- FirstParameter = FALSE;
- ParameterEntry = ParameterEntry->Next;
- }
- DbgOut("); 0x%I64x", Address);
- return;
- }
- VOID
- DbgPrintTypeName (
- PTYPE_SYMBOL Type
- )
- /*++
- Routine Description:
- This routine prints a type name, formatted with any array an pointer
- decorations.
- Arguments:
- Type - Supplies a pointer to the type to print information about.
- Return Value:
- None (information is printed directly to the standard output).
- --*/
- {
- PDATA_TYPE_RELATION RelationData;
- PTYPE_SYMBOL Relative;
- switch (Type->Type) {
- case DataTypeStructure:
- if (Type->Name == NULL) {
- DbgOut("struct (anon)");
- } else {
- DbgOut("struct %s", Type->Name);
- }
- break;
- case DataTypeEnumeration:
- if ((Type->Name == NULL) || (strlen(Type->Name) == 0) ||
- (strcmp(Type->Name, " ") == 0)) {
- DbgOut("(unnamed enum)");
- } else {
- DbgOut(Type->Name);
- }
- break;
- case DataTypeNumeric:
- if ((Type->Name == NULL) || (strlen(Type->Name) == 0) ||
- (strcmp(Type->Name, " ") == 0)) {
- DbgOut("(unnamed numeric)");
- } else {
- DbgOut(Type->Name);
- }
- break;
- case DataTypeRelation:
- if ((Type->Name == NULL) || (strlen(Type->Name) == 0)) {
- RelationData = &(Type->U.Relation);
- Relative = DbgGetType(RelationData->OwningFile,
- RelationData->TypeNumber);
- DbgPrintTypeName(Relative);
- if (RelationData->Array.Minimum != RelationData->Array.Maximum) {
- assert(RelationData->Array.Maximum >
- RelationData->Array.Minimum);
- if (RelationData->Array.Minimum != 0) {
- DbgOut("[%I64d:%I64d]",
- RelationData->Array.Minimum,
- RelationData->Array.Maximum + 1);
- } else {
- DbgOut("[%I64d]", RelationData->Array.Maximum + 1);
- }
- }
- if (RelationData->Pointer != 0) {
- DbgOut("*");
- }
- } else {
- DbgOut(Type->Name);
- }
- break;
- case DataTypeFunctionPointer:
- DbgOut("(Function pointer)");
- break;
- default:
- assert(FALSE);
- return;
- }
- return;
- }
- ULONG
- DbgGetTypeSize (
- PTYPE_SYMBOL Type,
- ULONG RecursionDepth
- )
- /*++
- Routine Description:
- This routine determines the size in bytes of a given type.
- Arguments:
- Type - Supplies a pointer to the type to get the size of.
- RecursionDepth - Supplies the function recursion depth. Supply zero here.
- Return Value:
- Returns the size of the type in bytes. On error or on querying a void type,
- 0 is returned.
- --*/
- {
- ULONGLONG ArraySize;
- PDATA_TYPE_NUMERIC NumericData;
- PDATA_TYPE_RELATION RelationData;
- PTYPE_SYMBOL Relative;
- PDATA_TYPE_STRUCTURE StructureData;
- if (Type == NULL) {
- return 0;
- }
- switch (Type->Type) {
- case DataTypeEnumeration:
- return Type->U.Enumeration.SizeInBytes;
- case DataTypeNumeric:
- //
- // For a numeric type, return the size rounded up to the nearest byte.
- //
- NumericData = &(Type->U.Numeric);
- return (NumericData->BitSize + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
- case DataTypeStructure:
- StructureData = &(Type->U.Structure);
- return StructureData->SizeInBytes;
- case DataTypeRelation:
- RelationData = &(Type->U.Relation);
- Relative = DbgGetType(RelationData->OwningFile,
- RelationData->TypeNumber);
- ArraySize = 1;
- if (Relative == NULL) {
- assert(Relative != NULL);
- return 0;
- }
- if (RecursionDepth >= MAX_RELATION_TYPE_DEPTH) {
- DbgOut("Infinite recursion of type %s (%s, %d) to %s (%s, %d) "
- "...\n",
- Type->Name,
- Type->ParentSource->SourceFile,
- Type->TypeNumber,
- Relative->Name,
- Relative->ParentSource->SourceFile,
- Relative->TypeNumber);
- return 0;
- }
- //
- // If it is an array, all subsequent values must be multiplied by
- // the array length.
- //
- if (RelationData->Array.Minimum != RelationData->Array.Maximum) {
- assert(RelationData->Array.Maximum >
- RelationData->Array.Minimum);
- ArraySize = (RelationData->Array.Maximum + 1 -
- RelationData->Array.Minimum);
- }
- //
- // If in the end the relation is a pointer, then the data is only
- // as big as that pointer (or an array of them).
- //
- if (RelationData->Pointer != 0) {
- return ArraySize * RelationData->Pointer;
- }
- //
- // If its relation is itself, stop now.
- //
- if (Relative == Type) {
- return 0;
- }
- //
- // Recurse to get the size of the underlying type.
- //
- return ArraySize * DbgGetTypeSize(Relative, RecursionDepth + 1);
- case DataTypeFunctionPointer:
- return Type->U.FunctionPointer.SizeInBytes;
- default:
- return 0;
- }
- //
- // Execution should never get here.
- //
- assert(FALSE);
- return 0;
- }
- VOID
- DbgPrintTypeDescription (
- PTYPE_SYMBOL Type,
- ULONG SpaceLevel,
- ULONG RecursionDepth
- )
- /*++
- Routine Description:
- This routine prints a description of the structure of a given type.
- Arguments:
- Type - Supplies a pointer to the type to print information about.
- 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:
- None (information is printed directly to the standard output).
- --*/
- {
- ULONG BitRemainder;
- ULONG Bytes;
- PDATA_TYPE_ENUMERATION EnumerationData;
- PENUMERATION_MEMBER EnumerationMember;
- PSTR MemberName;
- CHAR MemberNameBuffer[256];
- PTYPE_SYMBOL MemberType;
- PDATA_TYPE_NUMERIC NumericData;
- PDATA_TYPE_RELATION RelationData;
- PTYPE_SYMBOL RelativeType;
- PDATA_TYPE_STRUCTURE StructureData;
- PSTRUCTURE_MEMBER StructureMember;
- //
- // Print only the type name if the recursion depth has reached 0.
- //
- if (RecursionDepth == 0) {
- DbgPrintTypeName(Type);
- return;
- }
- switch (Type->Type) {
- case DataTypeNumeric:
- NumericData = &(Type->U.Numeric);
- if (NumericData->Float != FALSE) {
- DbgOut("%d bit floating point number.", NumericData->BitSize);
- } else if (NumericData->Signed == FALSE) {
- DbgOut("U");
- }
- DbgOut("Int%d", NumericData->BitSize);
- break;
- case DataTypeRelation:
- //
- // Get the type this relation refers to.
- //
- RelationData = &(Type->U.Relation);
- RelativeType = DbgGetType(RelationData->OwningFile,
- RelationData->TypeNumber);
- //
- // If it cannot be found, this is an error.
- //
- if (RelativeType == NULL) {
- DbgOut("DANGLING RELATION %s, %d\n",
- RelationData->OwningFile->SourceFile,
- RelationData->TypeNumber);
- assert(RelativeType != NULL);
- return;
- }
- //
- // If it's a reference to itself, it's a void.
- //
- if (RelativeType == Type) {
- DbgOut("void type.");
- //
- // If the type is neither a pointer nor an array, print the description
- // of this type. This recurses until we actually print the description
- // of something that's *not* a relation, hit an array, or hit a pointer.
- // Note that simply following relations does not count against the
- // recursion depth since these types merely equal each other. This is
- // why the recursion depth is not decreased.
- //
- } else if ((RelationData->Array.Minimum ==
- RelationData->Array.Maximum) &&
- (RelationData->Pointer == 0)) {
- DbgPrintTypeDescription(RelativeType,
- SpaceLevel,
- RecursionDepth - 1);
- //
- // If the relation is a pointer or an array, print out that information
- // and do not recurse.
- //
- } else {
- //
- // Print the pointer symbol if this type is a pointer to another
- // type.
- //
- if (RelationData->Pointer != 0) {
- DbgOut("*");
- }
- //
- // Print the type's name. If this type has no name, this function
- // will follow the reference to a type that does have a name.
- //
- DbgPrintTypeName(RelativeType);
- //
- // If the type is an array, print that information.
- //
- if (RelationData->Array.Minimum != RelationData->Array.Maximum) {
- DbgOut("[");
- if (RelationData->Array.Minimum != 0) {
- DbgOut("%I64d:", RelationData->Array.Minimum);
- }
- DbgOut("%I64d]", RelationData->Array.Maximum + 1);
- }
- }
- break;
- case DataTypeEnumeration:
- SpaceLevel += 2;
- DbgOut("enum {\n");
- EnumerationData = &(Type->U.Enumeration);
- EnumerationMember = EnumerationData->FirstMember;
- while (EnumerationMember != NULL) {
- DbgOut("%*s", SpaceLevel, "");
- MemberName = EnumerationMember->Name;
- if (MemberName == NULL) {
- MemberName = "";
- }
- DbgOut("%-*s = %I64d\n",
- MEMBER_NAME_SPACE,
- MemberName,
- EnumerationMember->Value);
- EnumerationMember = EnumerationMember->NextMember;
- }
- SpaceLevel -= 2;
- DbgOut("%*s", SpaceLevel, "");
- DbgOut("}");
- break;
- case DataTypeStructure:
- DbgOut("struct {\n");
- SpaceLevel += 2;
- StructureData = &(Type->U.Structure);
- StructureMember = StructureData->FirstMember;
- while (StructureMember != NULL) {
- Bytes = StructureMember->BitOffset / BITS_PER_BYTE;
- BitRemainder = StructureMember->BitOffset % BITS_PER_BYTE;
- DbgOut("%*s", SpaceLevel, "");
- MemberName = StructureMember->Name;
- if (MemberName == NULL) {
- MemberName = "";
- }
- if (BitRemainder != 0) {
- snprintf(MemberNameBuffer,
- sizeof(MemberNameBuffer),
- "%s:%d",
- MemberName,
- BitRemainder);
- MemberNameBuffer[sizeof(MemberNameBuffer) - 1] = '\0';
- MemberName = MemberNameBuffer;
- }
- DbgOut("+0x%03x %-*s", Bytes, MEMBER_NAME_SPACE, MemberName);
- DbgOut(" : ");
- MemberType = DbgGetType(StructureMember->TypeFile,
- StructureMember->TypeNumber);
- if (MemberType == NULL) {
- DbgOut("DANGLING REFERENCE %s, %d\n",
- StructureMember->TypeFile->SourceFile,
- StructureMember->TypeNumber);
- assert(MemberType != NULL);
- StructureMember = StructureMember->NextMember;
- continue;
- }
- DbgPrintTypeDescription(MemberType, SpaceLevel, RecursionDepth - 1);
- DbgOut("\n");
- StructureMember = StructureMember->NextMember;
- }
- SpaceLevel -= 2;
- DbgOut("%*s}", SpaceLevel, "");
- if (SpaceLevel == 0) {
- DbgOut("\nType Size: %d Bytes.", StructureData->SizeInBytes);
- }
- break;
- case DataTypeFunctionPointer:
- DbgOut("(*)()");
- break;
- default:
- assert(FALSE);
- break;
- }
- }
- INT
- DbgGetMemberOffset (
- PTYPE_SYMBOL StructureType,
- PSTR FieldName,
- PULONG FieldOffset,
- PULONG FieldSize
- )
- /*++
- Routine Description:
- This routine returns the given field's offset (in bits) within the
- given structure.
- Arguments:
- StructureType - Supplies a pointer to a symbol structure type.
- FieldName - Supplies a string containing the name of the field whose offset
- will be returned.
- FieldOffset - Supplies a pointer that will receive the bit offset of the
- given field name within the given structure.
- FieldSize - Supplies a pointer that will receive the size of the field in
- bits.
- Return Value:
- 0 on success.
- ENOENT if no such field name exists.
- Other error codes on other errors.
- --*/
- {
- ULONG Index;
- INT Result;
- PDATA_TYPE_STRUCTURE StructureData;
- PSTRUCTURE_MEMBER StructureMember;
- //
- // Parameter checking.
- //
- if ((StructureType == NULL) ||
- (StructureType->Type != DataTypeStructure) ||
- (FieldOffset == NULL)) {
- return EINVAL;
- }
- //
- // Search for the field within the structure.
- //
- Result = ENOENT;
- StructureData = &(StructureType->U.Structure);
- StructureMember = StructureData->FirstMember;
- for (Index = 0; Index < StructureData->MemberCount; Index += 1) {
- if ((StructureMember->Name != NULL) &&
- (strcmp(FieldName, StructureMember->Name) == 0)) {
- if (FieldOffset != NULL) {
- *FieldOffset = StructureMember->BitOffset;
- }
- if (FieldSize != NULL) {
- *FieldSize = StructureMember->BitSize;
- }
- Result = 0;
- break;
- }
- StructureMember = StructureMember->NextMember;
- }
- if (Result != 0) {
- DbgOut("GetMemberOffset: %s has no member %s.\n",
- StructureType->Name,
- FieldName);
- }
- return Result;
- }
- PTYPE_SYMBOL
- DbgSkipTypedefs (
- PTYPE_SYMBOL Type
- )
- /*++
- Routine Description:
- This routine skips all relation types that aren't pointers or arrays.
- Arguments:
- Type - Supplies a pointer to the type to get to the bottom of.
- Return Value:
- NULL if the type ended up being void or not found.
- Returns a pointer to the root type on success.
- --*/
- {
- ULONG MaxCount;
- PDATA_TYPE_RELATION Relation;
- PTYPE_SYMBOL RelativeType;
- if (Type->Type != DataTypeRelation) {
- return Type;
- }
- Relation = &(Type->U.Relation);
- //
- // Loop scanning through typedefs.
- //
- MaxCount = 50;
- while ((MaxCount != 0) &&
- (Type->Type == DataTypeRelation) &&
- (Relation->Array.Minimum == Relation->Array.Maximum) &&
- (Relation->Pointer == 0)) {
- RelativeType = DbgGetType(Relation->OwningFile, Relation->TypeNumber);
- if ((RelativeType == NULL) || (RelativeType == Type)) {
- return NULL;
- }
- Type = RelativeType;
- Relation = &(Type->U.Relation);
- MaxCount -= 1;
- }
- if (MaxCount == 0) {
- return NULL;
- }
- return Type;
- }
- PTYPE_SYMBOL
- DbgGetType (
- PSOURCE_FILE_SYMBOL SourceFile,
- LONG TypeNumber
- )
- /*++
- Routine Description:
- This routine looks up a type symbol based on the type number and the source
- file the type is in.
- Arguments:
- SourceFile - Supplies a pointer to the source file containing the type.
- TypeNumber - Supplies the type number to look up.
- Return Value:
- Returns a pointer to the type on success, or NULL on error.
- --*/
- {
- PLIST_ENTRY CurrentEntry;
- PTYPE_SYMBOL CurrentType;
- if (SourceFile == NULL) {
- assert(TypeNumber == -1);
- return &DbgVoidType;
- }
- CurrentEntry = SourceFile->TypesHead.Next;
- while (CurrentEntry != &(SourceFile->TypesHead)) {
- CurrentType = LIST_VALUE(CurrentEntry, TYPE_SYMBOL, ListEntry);
- if (CurrentType->TypeNumber == TypeNumber) {
- return CurrentType;
- }
- CurrentEntry = CurrentEntry->Next;
- }
- DbgOut("Error: Failed to look up type %s:%x\n",
- SourceFile->SourceFile,
- TypeNumber);
- return NULL;
- }
- PSOURCE_LINE_SYMBOL
- DbgLookupSourceLine (
- PDEBUG_SYMBOLS Module,
- ULONGLONG Address
- )
- /*++
- Routine Description:
- This routine looks up a source line in a given module based on the address.
- Arguments:
- Module - Supplies a pointer to the module which contains the symbols to
- search through.
- Address - Supplies the query address to search the source line symbols for.
- Return Value:
- If a successful match is found, returns a pointer to the source line symbol.
- If a source line matching the address could not be found or an error
- occured, returns NULL.
- --*/
- {
- PLIST_ENTRY CurrentEntry;
- PSOURCE_LINE_SYMBOL CurrentLine;
- PSOURCE_FILE_SYMBOL CurrentSource;
- PLIST_ENTRY CurrentSourceEntry;
- //
- // Parameter checking.
- //
- if (Module == NULL) {
- return NULL;
- }
- //
- // Begin searching. Loop over all source files in the module.
- //
- CurrentSourceEntry = Module->SourcesHead.Next;
- CurrentEntry = NULL;
- while (CurrentSourceEntry != &(Module->SourcesHead)) {
- CurrentSource = LIST_VALUE(CurrentSourceEntry,
- SOURCE_FILE_SYMBOL,
- ListEntry);
- if (CurrentEntry == NULL) {
- CurrentEntry = CurrentSource->SourceLinesHead.Next;
- }
- //
- // Loop over every source line in the current source file.
- //
- while (CurrentEntry != &(CurrentSource->SourceLinesHead)) {
- CurrentLine = LIST_VALUE(CurrentEntry,
- SOURCE_LINE_SYMBOL,
- ListEntry);
- if ((Address >= CurrentLine->Start) &&
- (Address < CurrentLine->End)) {
- //
- // A match has been found!
- //
- return CurrentLine;
- }
- CurrentEntry = CurrentEntry->Next;
- }
- CurrentEntry = NULL;
- CurrentSourceEntry = CurrentSourceEntry->Next;
- }
- return NULL;
- }
- PSYMBOL_SEARCH_RESULT
- DbgLookupSymbol (
- PDEBUG_SYMBOLS Module,
- ULONGLONG Address,
- PSYMBOL_SEARCH_RESULT Input
- )
- /*++
- Routine Description:
- This routine looks up a symbol in a module based on the given address. It
- first searches through data symbols, then functions.
- Arguments:
- Module - Supplies a pointer to the module which contains the symbols to
- search through.
- Address - Supplies the address of the symbol to look up.
- Input - Supplies a pointer to the search result structure. On input, the
- parameter contains the search result to start the search from. On
- output, contains the new found search result. To signify that the search
- should start from the beginning, set the Type member to ResultInvalid.
- Return Value:
- If a successful match is found, returns Input with the search results filled
- into the structure. If no result was found or an error occurred, NULL is
- returned.
- --*/
- {
- //
- // Parameter checking.
- //
- if ((Module == NULL) || (Address == (INTN)NULL) || (Input == NULL)) {
- return NULL;
- }
- //
- // Start searching, depending on the input parameter. Note that fallthrough
- // *is* intended.
- //
- switch (Input->Variety) {
- case SymbolResultInvalid:
- case SymbolResultType:
- case SymbolResultData:
- if (DbgFindDataSymbol(Module, NULL, Address, Input) != NULL) {
- return Input;
- }
- case SymbolResultFunction:
- if (DbgFindFunctionSymbol(Module, NULL, Address, Input) != NULL) {
- return Input;
- }
- default:
- break;
- }
- return NULL;
- }
- PSYMBOL_SEARCH_RESULT
- DbgpFindSymbolInModule (
- PDEBUG_SYMBOLS Module,
- PSTR Query,
- PSYMBOL_SEARCH_RESULT Input
- )
- /*++
- Routine Description:
- This routine searches for a symbol in a module. It first searches through
- types, then data symbols, then functions.
- Arguments:
- Module - Supplies a pointer to the module which contains the symbols to
- search through.
- Query - Supplies the search string.
- Input - Supplies a pointer to the search result structure. On input, the
- parameter contains the search result to start the search from. On
- output, contains the new found search result. To signify that the search
- should start from the beginning, set the Type member to ResultInvalid.
- Return Value:
- If a successful match is found, returns Input with the search results filled
- into the structure. If no result was found or an error occurred, NULL is
- returned.
- --*/
- {
- //
- // Parameter checking.
- //
- if ((Module == NULL) || (Query == NULL) || (Input == NULL)) {
- return NULL;
- }
- //
- // Start searching, depending on the input parameter. Note that fallthrough
- // *is* intended.
- //
- switch (Input->Variety) {
- case SymbolResultInvalid:
- case SymbolResultType:
- if (DbgFindTypeSymbol(Module, Query, Input) != NULL) {
- return Input;
- }
- case SymbolResultData:
- if (DbgFindDataSymbol(Module, Query, (INTN)NULL, Input) != NULL) {
- return Input;
- }
- case SymbolResultFunction:
- if (DbgFindFunctionSymbol(Module, Query, (INTN)NULL, Input) != NULL) {
- return Input;
- }
- default:
- break;
- }
- return NULL;
- }
- PSYMBOL_SEARCH_RESULT
- DbgFindTypeSymbol (
- PDEBUG_SYMBOLS Module,
- PSTR Query,
- PSYMBOL_SEARCH_RESULT Input
- )
- /*++
- Routine Description:
- This routine searches for a type symbol in a module.
- Arguments:
- Module - Supplies a pointer to the module which contains the symbols to
- search through.
- Query - Supplies the search string.
- Input - Supplies a pointer to the search result structure. On input, the
- parameter contains the search result to start the search from. On
- output, contains the new found search result. To signify that the search
- should start from the beginning, set the Type member to ResultInvalid.
- Return Value:
- If a successful match is found, returns Input with the search results filled
- into the structure. If no result was found or an error occurred, NULL is
- returned.
- --*/
- {
- PLIST_ENTRY CurrentEntry;
- PSOURCE_FILE_SYMBOL CurrentSource;
- PLIST_ENTRY CurrentSourceEntry;
- PTYPE_SYMBOL CurrentType;
- //
- // Parameter checking.
- //
- if ((Query == NULL) || (Module == NULL) || (Input == NULL)) {
- return NULL;
- }
- //
- // Initialize the search variables based on the input parameter.
- //
- CurrentEntry = NULL;
- if ((Input->Variety == SymbolResultType) && (Input->U.TypeResult != NULL)) {
- CurrentEntry = &(Input->U.TypeResult->ListEntry);
- CurrentType = LIST_VALUE(CurrentEntry, TYPE_SYMBOL, ListEntry);
- CurrentSource = CurrentType->ParentSource;
- CurrentSourceEntry = &(CurrentSource->ListEntry);
- CurrentEntry = CurrentEntry->Next;
- } else {
- CurrentSourceEntry = Module->SourcesHead.Next;
- CurrentSource = LIST_VALUE(CurrentSourceEntry,
- SOURCE_FILE_SYMBOL,
- ListEntry);
- }
- //
- // Begin searching. Loop over all source files in the module.
- //
- while (CurrentSourceEntry != &(Module->SourcesHead)) {
- CurrentSource = LIST_VALUE(CurrentSourceEntry,
- SOURCE_FILE_SYMBOL,
- ListEntry);
- if (CurrentEntry == NULL) {
- CurrentEntry = CurrentSource->TypesHead.Next;
- }
- //
- // Loop over every type in the current source file.
- //
- while (CurrentEntry != &(CurrentSource->TypesHead)) {
- CurrentType = LIST_VALUE(CurrentEntry,
- TYPE_SYMBOL,
- ListEntry);
- if (DbgpStringMatch(Query, CurrentType->Name) != FALSE) {
- //
- // A match has been found. Fill out the structure and return.
- //
- Input->Variety = SymbolResultType;
- Input->U.TypeResult = CurrentType;
- return Input;
- }
- CurrentEntry = CurrentEntry->Next;
- }
- CurrentEntry = NULL;
- CurrentSourceEntry = CurrentSourceEntry->Next;
- }
- return NULL;
- }
- PSYMBOL_SEARCH_RESULT
- DbgFindDataSymbol (
- PDEBUG_SYMBOLS Module,
- PSTR Query,
- ULONGLONG Address,
- PSYMBOL_SEARCH_RESULT Input
- )
- /*++
- Routine Description:
- This routine searches for a data symbol in a module based on a query string
- or address.
- Arguments:
- Module - Supplies a pointer to the module which contains the symbols to
- search through.
- Query - Supplies the search string. This parameter can be NULL if searching
- by address.
- Address - Supplies the address of the symbol. Can be NULL if search by
- query string is desired.
- Input - Supplies a pointer to the search result structure. On input, the
- parameter contains the search result to start the search from. On
- output, contains the new found search result. To signify that the search
- should start from the beginning, set the Type member to ResultInvalid.
- Return Value:
- If a successful match is found, returns Input with the search results filled
- into the structure. If no result was found or an error occurred, NULL is
- returned.
- --*/
- {
- PDATA_SYMBOL CurrentData;
- PLIST_ENTRY CurrentEntry;
- PSOURCE_FILE_SYMBOL CurrentSource;
- PLIST_ENTRY CurrentSourceEntry;
- //
- // Parameter checking.
- //
- if ((Module == NULL) || (Input == NULL)) {
- return NULL;
- }
- if ((Query == NULL) && (Address == (INTN)NULL)) {
- return NULL;
- }
- //
- // Initialize the search variables based on the input parameter.
- //
- CurrentEntry = NULL;
- if ((Input->Variety == SymbolResultData) && (Input->U.DataResult != NULL)) {
- CurrentEntry = &(Input->U.DataResult->ListEntry);
- CurrentData = LIST_VALUE(CurrentEntry, DATA_SYMBOL, ListEntry);
- CurrentSource = CurrentData->ParentSource;
- CurrentSourceEntry = &(CurrentSource->ListEntry);
- CurrentEntry = CurrentEntry->Next;
- } else {
- CurrentSourceEntry = Module->SourcesHead.Next;
- CurrentSource = LIST_VALUE(CurrentSourceEntry,
- SOURCE_FILE_SYMBOL,
- ListEntry);
- }
- //
- // Begin searching. Loop over all source files in the module.
- //
- while (CurrentSourceEntry != &(Module->SourcesHead)) {
- CurrentSource = LIST_VALUE(CurrentSourceEntry,
- SOURCE_FILE_SYMBOL,
- ListEntry);
- //
- // Set up the current symbol entry.
- //
- if (CurrentEntry == NULL) {
- CurrentEntry = CurrentSource->DataSymbolsHead.Next;
- }
- //
- // Loop over every data symbol in the current source file.
- //
- while (CurrentEntry != &(CurrentSource->DataSymbolsHead)) {
- CurrentData = LIST_VALUE(CurrentEntry,
- DATA_SYMBOL,
- ListEntry);
- //
- // Check for an address-based match. Only look at absolute address
- // based symbols (not stack offset or register variables).
- //
- if (Address != (INTN)NULL) {
- if ((CurrentData->LocationType ==
- DataLocationAbsoluteAddress) &&
- (CurrentData->Location.Address == Address)) {
- Input->Variety = SymbolResultData;
- Input->U.DataResult = CurrentData;
- return Input;
- }
- } else {
- assert(Query != NULL);
- //
- // Check for a string-based match.
- //
- if (DbgpStringMatch(Query, CurrentData->Name) != FALSE) {
- Input->Variety = SymbolResultData;
- Input->U.DataResult = CurrentData;
- return Input;
- }
- }
- CurrentEntry = CurrentEntry->Next;
- }
- CurrentEntry = NULL;
- CurrentSourceEntry = CurrentSourceEntry->Next;
- }
- return NULL;
- }
- PSYMBOL_SEARCH_RESULT
- DbgFindFunctionSymbol (
- PDEBUG_SYMBOLS Module,
- PSTR Query,
- ULONGLONG Address,
- PSYMBOL_SEARCH_RESULT Input
- )
- /*++
- Routine Description:
- This routine searches for a function symbol in a module based on a search
- string or an address.
- Arguments:
- Module - Supplies a pointer to the module which contains the symbols to
- search through.
- Query - Supplies the search string. This parameter can be NULL if searching
- by address.
- Address - Supplies the search address. This parameter can be NULL if
- searching by query string.
- Input - Supplies a pointer to the search result structure. On input, the
- parameter contains the search result to start the search from. On
- output, contains the new found search result. To signify that the search
- should start from the beginning, set the Type member to ResultInvalid.
- Return Value:
- If a successful match is found, returns Input with the search results filled
- into the structure. If no result was found or an error occurred, NULL is
- returned.
- --*/
- {
- PLIST_ENTRY CurrentEntry;
- PFUNCTION_SYMBOL CurrentFunction;
- PSOURCE_FILE_SYMBOL CurrentSource;
- PLIST_ENTRY CurrentSourceEntry;
- //
- // Parameter checking.
- //
- if ((Module == NULL) || (Input == NULL)) {
- return NULL;
- }
- if ((Query == NULL) && (Address == (INTN)NULL)) {
- return NULL;
- }
- //
- // Initialize the search variables based on the input parameter.
- //
- CurrentEntry = NULL;
- if ((Input->Variety == SymbolResultFunction) &&
- (Input->U.FunctionResult != NULL)) {
- CurrentEntry = &(Input->U.FunctionResult->ListEntry);
- CurrentFunction = LIST_VALUE(CurrentEntry, FUNCTION_SYMBOL, ListEntry);
- CurrentSource = CurrentFunction->ParentSource;
- CurrentSourceEntry = &(CurrentSource->ListEntry);
- CurrentEntry = CurrentEntry->Next;
- } else {
- CurrentSourceEntry = Module->SourcesHead.Next;
- CurrentSource = LIST_VALUE(CurrentSourceEntry,
- SOURCE_FILE_SYMBOL,
- ListEntry);
- }
- //
- // Begin searching. Loop over all source files in the module.
- //
- while (CurrentSourceEntry != &(Module->SourcesHead)) {
- CurrentSource = LIST_VALUE(CurrentSourceEntry,
- SOURCE_FILE_SYMBOL,
- ListEntry);
- if (CurrentEntry == NULL) {
- CurrentEntry = CurrentSource->FunctionsHead.Next;
- }
- //
- // Loop over every function in the current source file.
- //
- while (CurrentEntry != &(CurrentSource->FunctionsHead)) {
- CurrentFunction = LIST_VALUE(CurrentEntry,
- FUNCTION_SYMBOL,
- ListEntry);
- //
- // For address based searching, determine if the function is within
- // range, and return if a match is found.
- //
- if (Address != (INTN)NULL) {
- if ((Address >= CurrentFunction->StartAddress) &&
- (Address < CurrentFunction->EndAddress)) {
- Input->Variety = SymbolResultFunction;
- Input->U.FunctionResult = CurrentFunction;
- return Input;
- }
- } else {
- //
- // Check for a string based match.
- //
- assert(Query != NULL);
- if (DbgpStringMatch(Query, CurrentFunction->Name) != FALSE) {
- Input->Variety = SymbolResultFunction;
- Input->U.FunctionResult = CurrentFunction;
- return Input;
- }
- }
- CurrentEntry = CurrentEntry->Next;
- }
- CurrentEntry = NULL;
- CurrentSourceEntry = CurrentSourceEntry->Next;
- }
- return NULL;
- }
- PSTR
- DbgGetRegisterName (
- IMAGE_MACHINE_TYPE MachineType,
- ULONG Register
- )
- /*++
- Routine Description:
- This routine returns a string containing the name of the given register.
- Arguments:
- MachineType - Supplies the machine type.
- Register - Supplies the register number.
- Return Value:
- Returns a pointer to a constant string containing the name of the register.
- --*/
- {
- ULONG Count;
- PSTR Name;
- Name = NULL;
- switch (MachineType) {
- case ImageMachineTypeX86:
- Count = sizeof(DbgX86RegisterSymbolNames) /
- sizeof(DbgX86RegisterSymbolNames[0]);
- if (Register < Count) {
- Name = DbgX86RegisterSymbolNames[Register];
- }
- break;
- case ImageMachineTypeArm32:
- Count = sizeof(DbgArmRegisterSymbolNames) /
- sizeof(DbgArmRegisterSymbolNames[0]);
- if (Register < Count) {
- Name = DbgArmRegisterSymbolNames[Register];
- break;
- }
- Count = sizeof(DbgArmVfpRegisterSymbolNames) /
- sizeof(DbgArmVfpRegisterSymbolNames[0]);
- if ((Register >= ArmRegisterD0) &&
- ((Register - ArmRegisterD0) < Count)) {
- Name = DbgArmVfpRegisterSymbolNames[Register - ArmRegisterD0];
- }
- break;
- default:
- break;
- }
- if (Name == NULL) {
- Name = "UNKNOWNREG";
- }
- return Name;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- BOOL
- DbgpStringMatch (
- PSTR Query,
- PSTR PossibleMatch
- )
- /*++
- Routine Description:
- This routine determines whether or not a string matches a query string. The
- query string may contain wildcard characters (*).
- Arguments:
- Query - Supplies the query string. This string may contain wildcard
- characters (*) signifying zero or more arbitrary characters.
- PossibleMatch - Supplies the test string. Wildcard characters in this string
- will be treated as regular characters.
- Return Value:
- Returns TRUE upon successful match. Returns FALSE if the strings do not
- match.
- --*/
- {
- PSTR CurrentMatch;
- PSTR CurrentQuery;
- BOOL InWildcard;
- UCHAR LowerMatch;
- UCHAR LowerQuery;
- InWildcard = FALSE;
- CurrentQuery = Query;
- CurrentMatch = PossibleMatch;
- if ((Query == NULL) || (PossibleMatch == NULL)) {
- return FALSE;
- }
- do {
- //
- // If the current query character is a wildcard, note that and advance
- // to the character after the wildcard.
- //
- if (*CurrentQuery == '*') {
- InWildcard = TRUE;
- CurrentQuery += 1;
- }
- //
- // If the entire query string has been processed, it's a match only if
- // the match string is finished as well, or a wildcard is being
- // processed.
- //
- if (*CurrentQuery == '\0') {
- if ((*CurrentMatch == '\0') || (InWildcard != FALSE)) {
- return TRUE;
- } else {
- return FALSE;
- }
- }
- //
- // If the match string ended, this must not be a match because the
- // query string hasn't ended. Whether or not search is inside a
- // wildcard is irrelevent because there must be match characters after
- // the wildcard that are not getting satisfied (if there weren't the
- // query string would be over.
- //
- if (*CurrentMatch == '\0') {
- return FALSE;
- }
- //
- // Convert to lowercase.
- //
- LowerQuery = *CurrentQuery;
- LowerMatch = *CurrentMatch;
- if ((LowerQuery >= 'A') && (LowerQuery <= 'Z')) {
- LowerQuery = LowerQuery - 'A' + 'a';
- }
- if ((LowerMatch >= 'A') && (LowerMatch <= 'Z')) {
- LowerMatch = LowerMatch - 'A' + 'a';
- }
- //
- // If the characters match, then either it's a normal match or a
- // character after the wildcard has been found. If it's the wildcard
- // case, attempt to match the rest of the string from here. If it does
- // not work, all is not lost, the correct match may be farther down the
- // string.
- //
- if (LowerQuery == LowerMatch) {
- if (InWildcard != FALSE) {
- if (DbgpStringMatch(CurrentQuery, CurrentMatch) != FALSE) {
- return TRUE;
- } else {
- CurrentMatch += 1;
- }
- } else {
- CurrentQuery += 1;
- CurrentMatch += 1;
- }
- //
- // If there's no match, but there's a wildcard being processed, advance
- // only the match string.
- //
- } else if (InWildcard != FALSE) {
- CurrentMatch += 1;
- //
- // It's not a match and there's no wildcard, the strings simply
- // disagree.
- //
- } else {
- return FALSE;
- }
- } while (TRUE);
- return FALSE;
- }
|