symbols.c 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974
  1. /*++
  2. Copyright (c) 2012 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. symbols.c
  5. Abstract:
  6. This module implements symbol translation helper routines used by the
  7. debugger.
  8. Author:
  9. Evan Green 2-Jul-2012
  10. Environment:
  11. Debugger client
  12. --*/
  13. //
  14. // ------------------------------------------------------------------- Includes
  15. //
  16. #include <minoca/lib/types.h>
  17. #include <minoca/lib/status.h>
  18. #include <minoca/lib/im.h>
  19. #include <minoca/debug/dbgext.h>
  20. #include "symbols.h"
  21. #include "stabs.h"
  22. #include "dwarf.h"
  23. #include <assert.h>
  24. #include <errno.h>
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include <sys/stat.h>
  28. //
  29. // ---------------------------------------------------------------- Definitions
  30. //
  31. #define MEMBER_NAME_SPACE 17
  32. #define MAX_RELATION_TYPE_DEPTH 50
  33. //
  34. // ----------------------------------------------- Internal Function Prototypes
  35. //
  36. BOOL
  37. DbgpStringMatch (
  38. PSTR Query,
  39. PSTR PossibleMatch
  40. );
  41. //
  42. // ------------------------------------------------------ Data Type Definitions
  43. //
  44. //
  45. // -------------------------------------------------------------------- Globals
  46. //
  47. //
  48. // Define the set of known symbol libraries.
  49. //
  50. PSYMBOLS_LOAD DbgSymbolLoaders[] = {
  51. DwarfLoadSymbols,
  52. DbgpStabsLoadSymbols,
  53. DbgpElfLoadSymbols,
  54. DbgpCoffLoadSymbols,
  55. NULL
  56. };
  57. //
  58. // Define a default void type that has a source file of NULL (this is unique)
  59. // and a type number of -1.
  60. //
  61. TYPE_SYMBOL DbgVoidType = {
  62. {NULL, NULL},
  63. NULL,
  64. -1,
  65. "void",
  66. NULL,
  67. DataTypeNumeric,
  68. {
  69. {
  70. FALSE,
  71. NULL,
  72. -1
  73. }
  74. }
  75. };
  76. //
  77. // Define the machine register names.
  78. //
  79. PSTR DbgX86RegisterSymbolNames[] = {
  80. "eax",
  81. "ecx",
  82. "edx",
  83. "ebx",
  84. "esp",
  85. "ebp",
  86. "esi",
  87. "edi",
  88. "eip",
  89. "eflags",
  90. "cs",
  91. "ss",
  92. "ds",
  93. "es",
  94. "fs",
  95. "gs",
  96. "st0",
  97. "st1",
  98. "st2",
  99. "st3",
  100. "st4",
  101. "st5",
  102. "st6",
  103. "st7",
  104. "xmm0",
  105. "xmm1",
  106. "xmm2",
  107. "xmm3",
  108. "xmm4",
  109. "xmm5",
  110. "xmm6",
  111. "xmm7",
  112. };
  113. PSTR DbgX64RegisterSymbolNames[] = {
  114. "rax",
  115. "rdx",
  116. "rcx",
  117. "rbx",
  118. "rsi",
  119. "rdi",
  120. "rbp",
  121. "rsp",
  122. "r8",
  123. "r9",
  124. "r10",
  125. "r11",
  126. "r12",
  127. "r13",
  128. "r14",
  129. "r15",
  130. "rip",
  131. "xmm0",
  132. "xmm1",
  133. "xmm2",
  134. "xmm3",
  135. "xmm4",
  136. "xmm5",
  137. "xmm6",
  138. "xmm7",
  139. "xmm8",
  140. "xmm9",
  141. "xmm10",
  142. "xmm11",
  143. "xmm12",
  144. "xmm13",
  145. "xmm14",
  146. "xmm15",
  147. "st0",
  148. "st1",
  149. "st2",
  150. "st3",
  151. "st4",
  152. "st5",
  153. "st6",
  154. "st7",
  155. NULL,
  156. NULL,
  157. NULL,
  158. NULL,
  159. NULL,
  160. NULL,
  161. NULL,
  162. NULL,
  163. "eflags",
  164. "es",
  165. "cs",
  166. "ss",
  167. "ds",
  168. "fs",
  169. "gs",
  170. };
  171. PSTR DbgArmRegisterSymbolNames[] = {
  172. "r0",
  173. "r1",
  174. "r2",
  175. "r3",
  176. "r4",
  177. "r5",
  178. "r6",
  179. "r7",
  180. "r8",
  181. "r9",
  182. "r10",
  183. "r11",
  184. "r12",
  185. "sp",
  186. "lr",
  187. "pc",
  188. "f0"
  189. "f1",
  190. "f2",
  191. "f3",
  192. "f4",
  193. "f5",
  194. "f6",
  195. "f7",
  196. "fps",
  197. "cpsr"
  198. };
  199. PSTR DbgArmVfpRegisterSymbolNames[] = {
  200. "d0",
  201. "d1",
  202. "d2",
  203. "d3",
  204. "d4",
  205. "d5",
  206. "d6",
  207. "d7",
  208. "d8",
  209. "d9",
  210. "d10",
  211. "d11",
  212. "d12",
  213. "d13",
  214. "d14",
  215. "d15",
  216. "d16",
  217. "d17",
  218. "d18",
  219. "d19",
  220. "d20",
  221. "d21",
  222. "d22",
  223. "d23",
  224. "d24",
  225. "d25",
  226. "d26",
  227. "d27",
  228. "d28",
  229. "d29",
  230. "d30",
  231. "d31",
  232. };
  233. //
  234. // ------------------------------------------------------------------ Functions
  235. //
  236. INT
  237. DbgLoadSymbols (
  238. PSTR Filename,
  239. IMAGE_MACHINE_TYPE MachineType,
  240. PVOID HostContext,
  241. PDEBUG_SYMBOLS *Symbols
  242. )
  243. /*++
  244. Routine Description:
  245. This routine loads debugging symbol information from the specified file.
  246. Arguments:
  247. Filename - Supplies the name of the binary to load symbols from.
  248. MachineType - Supplies the required machine type of the image. Set to
  249. unknown to allow the symbol library to load a file with any machine
  250. type.
  251. HostContext - Supplies the value to store in the host context field of the
  252. debug symbols.
  253. Symbols - Supplies an optional pointer where a pointer to the symbols will
  254. be returned on success.
  255. Return Value:
  256. 0 on success.
  257. Returns an error number on failure.
  258. --*/
  259. {
  260. PSYMBOLS_LOAD *LoadFunction;
  261. struct stat Stat;
  262. INT Status;
  263. //
  264. // Don't go through the whole process if the file isn't even there.
  265. //
  266. if (stat(Filename, &Stat) != 0) {
  267. return errno;
  268. }
  269. LoadFunction = &(DbgSymbolLoaders[0]);
  270. Status = ENOSYS;
  271. while (*LoadFunction != NULL) {
  272. Status = (*LoadFunction)(Filename,
  273. MachineType,
  274. 0,
  275. HostContext,
  276. Symbols);
  277. if (Status == 0) {
  278. break;
  279. }
  280. LoadFunction += 1;
  281. }
  282. return Status;
  283. }
  284. VOID
  285. DbgUnloadSymbols (
  286. PDEBUG_SYMBOLS Symbols
  287. )
  288. /*++
  289. Routine Description:
  290. This routine frees all memory associated with an instance of debugging
  291. symbols. Once called, the pointer passed in should not be dereferenced
  292. again by the caller.
  293. Arguments:
  294. Symbols - Supplies a pointer to the debugging symbols.
  295. Return Value:
  296. None.
  297. --*/
  298. {
  299. Symbols->Interface->Unload(Symbols);
  300. return;
  301. }
  302. VOID
  303. DbgPrintFunctionPrototype (
  304. PFUNCTION_SYMBOL Function,
  305. PSTR ModuleName,
  306. ULONGLONG Address
  307. )
  308. /*++
  309. Routine Description:
  310. This routine prints a C function prototype directly to the screen.
  311. Arguments:
  312. Function - Supplies a pointer to the function symbol to print.
  313. ModuleName - Supplies an optional string containing the module name.
  314. Address - Supplies the final address of the function.
  315. Return Value:
  316. None (information is printed directly to the standard output).
  317. --*/
  318. {
  319. PDATA_SYMBOL CurrentParameter;
  320. PTYPE_SYMBOL CurrentParameterType;
  321. BOOL FirstParameter;
  322. PLIST_ENTRY ParameterEntry;
  323. PTYPE_SYMBOL ReturnType;
  324. if (Function == NULL) {
  325. return;
  326. }
  327. ReturnType = DbgGetType(Function->ReturnTypeOwner,
  328. Function->ReturnTypeNumber);
  329. DbgPrintTypeName(ReturnType);
  330. if (ModuleName != NULL) {
  331. DbgOut(" %s!%s (", ModuleName, Function->Name);
  332. } else {
  333. DbgOut(" %s (", Function->Name);
  334. }
  335. ParameterEntry = Function->ParametersHead.Next;
  336. FirstParameter = TRUE;
  337. while (ParameterEntry != &(Function->ParametersHead)) {
  338. CurrentParameter = LIST_VALUE(ParameterEntry,
  339. DATA_SYMBOL,
  340. ListEntry);
  341. if (FirstParameter == FALSE) {
  342. DbgOut(", ");
  343. }
  344. CurrentParameterType = DbgGetType(CurrentParameter->TypeOwner,
  345. CurrentParameter->TypeNumber);
  346. if (CurrentParameterType == NULL) {
  347. DbgOut("UNKNOWN_TYPE");
  348. } else {
  349. DbgPrintTypeName(CurrentParameterType);
  350. }
  351. DbgOut(" %s", CurrentParameter->Name);
  352. FirstParameter = FALSE;
  353. ParameterEntry = ParameterEntry->Next;
  354. }
  355. DbgOut("); 0x%I64x", Address);
  356. return;
  357. }
  358. VOID
  359. DbgPrintTypeName (
  360. PTYPE_SYMBOL Type
  361. )
  362. /*++
  363. Routine Description:
  364. This routine prints a type name, formatted with any array an pointer
  365. decorations.
  366. Arguments:
  367. Type - Supplies a pointer to the type to print information about.
  368. Return Value:
  369. None (information is printed directly to the standard output).
  370. --*/
  371. {
  372. PDATA_TYPE_RELATION RelationData;
  373. PTYPE_SYMBOL Relative;
  374. switch (Type->Type) {
  375. case DataTypeStructure:
  376. if (Type->Name == NULL) {
  377. DbgOut("struct (anon)");
  378. } else {
  379. DbgOut("struct %s", Type->Name);
  380. }
  381. break;
  382. case DataTypeEnumeration:
  383. if ((Type->Name == NULL) || (strlen(Type->Name) == 0) ||
  384. (strcmp(Type->Name, " ") == 0)) {
  385. DbgOut("(unnamed enum)");
  386. } else {
  387. DbgOut(Type->Name);
  388. }
  389. break;
  390. case DataTypeNumeric:
  391. if ((Type->Name == NULL) || (strlen(Type->Name) == 0) ||
  392. (strcmp(Type->Name, " ") == 0)) {
  393. DbgOut("(unnamed numeric)");
  394. } else {
  395. DbgOut(Type->Name);
  396. }
  397. break;
  398. case DataTypeRelation:
  399. if ((Type->Name == NULL) || (strlen(Type->Name) == 0)) {
  400. RelationData = &(Type->U.Relation);
  401. Relative = DbgGetType(RelationData->OwningFile,
  402. RelationData->TypeNumber);
  403. DbgPrintTypeName(Relative);
  404. if (RelationData->Array.Minimum != RelationData->Array.Maximum) {
  405. assert(RelationData->Array.Maximum >
  406. RelationData->Array.Minimum);
  407. if (RelationData->Array.Minimum != 0) {
  408. DbgOut("[%I64d:%I64d]",
  409. RelationData->Array.Minimum,
  410. RelationData->Array.Maximum + 1);
  411. } else {
  412. DbgOut("[%I64d]", RelationData->Array.Maximum + 1);
  413. }
  414. }
  415. if (RelationData->Pointer != 0) {
  416. DbgOut("*");
  417. }
  418. } else {
  419. DbgOut(Type->Name);
  420. }
  421. break;
  422. case DataTypeFunctionPointer:
  423. DbgOut("(Function pointer)");
  424. break;
  425. default:
  426. assert(FALSE);
  427. return;
  428. }
  429. return;
  430. }
  431. ULONG
  432. DbgGetTypeSize (
  433. PTYPE_SYMBOL Type,
  434. ULONG RecursionDepth
  435. )
  436. /*++
  437. Routine Description:
  438. This routine determines the size in bytes of a given type.
  439. Arguments:
  440. Type - Supplies a pointer to the type to get the size of.
  441. RecursionDepth - Supplies the function recursion depth. Supply zero here.
  442. Return Value:
  443. Returns the size of the type in bytes. On error or on querying a void type,
  444. 0 is returned.
  445. --*/
  446. {
  447. ULONGLONG ArraySize;
  448. PDATA_TYPE_NUMERIC NumericData;
  449. PDATA_TYPE_RELATION RelationData;
  450. PTYPE_SYMBOL Relative;
  451. PDATA_TYPE_STRUCTURE StructureData;
  452. if (Type == NULL) {
  453. return 0;
  454. }
  455. switch (Type->Type) {
  456. case DataTypeEnumeration:
  457. return Type->U.Enumeration.SizeInBytes;
  458. case DataTypeNumeric:
  459. //
  460. // For a numeric type, return the size rounded up to the nearest byte.
  461. //
  462. NumericData = &(Type->U.Numeric);
  463. return (NumericData->BitSize + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
  464. case DataTypeStructure:
  465. StructureData = &(Type->U.Structure);
  466. return StructureData->SizeInBytes;
  467. case DataTypeRelation:
  468. RelationData = &(Type->U.Relation);
  469. Relative = DbgGetType(RelationData->OwningFile,
  470. RelationData->TypeNumber);
  471. ArraySize = 1;
  472. if (Relative == NULL) {
  473. assert(Relative != NULL);
  474. return 0;
  475. }
  476. if (RecursionDepth >= MAX_RELATION_TYPE_DEPTH) {
  477. DbgOut("Infinite recursion of type %s (%s, %d) to %s (%s, %d) "
  478. "...\n",
  479. Type->Name,
  480. Type->ParentSource->SourceFile,
  481. Type->TypeNumber,
  482. Relative->Name,
  483. Relative->ParentSource->SourceFile,
  484. Relative->TypeNumber);
  485. return 0;
  486. }
  487. //
  488. // If it is an array, all subsequent values must be multiplied by
  489. // the array length.
  490. //
  491. if (RelationData->Array.Minimum != RelationData->Array.Maximum) {
  492. assert(RelationData->Array.Maximum >
  493. RelationData->Array.Minimum);
  494. ArraySize = (RelationData->Array.Maximum + 1 -
  495. RelationData->Array.Minimum);
  496. }
  497. //
  498. // If in the end the relation is a pointer, then the data is only
  499. // as big as that pointer (or an array of them).
  500. //
  501. if (RelationData->Pointer != 0) {
  502. return ArraySize * RelationData->Pointer;
  503. }
  504. //
  505. // If its relation is itself, stop now.
  506. //
  507. if (Relative == Type) {
  508. return 0;
  509. }
  510. //
  511. // Recurse to get the size of the underlying type.
  512. //
  513. return ArraySize * DbgGetTypeSize(Relative, RecursionDepth + 1);
  514. case DataTypeFunctionPointer:
  515. return Type->U.FunctionPointer.SizeInBytes;
  516. default:
  517. return 0;
  518. }
  519. //
  520. // Execution should never get here.
  521. //
  522. assert(FALSE);
  523. return 0;
  524. }
  525. VOID
  526. DbgPrintTypeDescription (
  527. PTYPE_SYMBOL Type,
  528. ULONG SpaceLevel,
  529. ULONG RecursionDepth
  530. )
  531. /*++
  532. Routine Description:
  533. This routine prints a description of the structure of a given type.
  534. Arguments:
  535. Type - Supplies a pointer to the type to print information about.
  536. SpaceLevel - Supplies the number of spaces to print after every newline.
  537. Used for nesting types.
  538. RecursionDepth - Supplies how many times this should recurse on structure
  539. members. If 0, only the name of the type is printed.
  540. Return Value:
  541. None (information is printed directly to the standard output).
  542. --*/
  543. {
  544. ULONG BitRemainder;
  545. ULONG Bytes;
  546. PDATA_TYPE_ENUMERATION EnumerationData;
  547. PENUMERATION_MEMBER EnumerationMember;
  548. PSTR MemberName;
  549. CHAR MemberNameBuffer[256];
  550. PTYPE_SYMBOL MemberType;
  551. PDATA_TYPE_NUMERIC NumericData;
  552. PDATA_TYPE_RELATION RelationData;
  553. PTYPE_SYMBOL RelativeType;
  554. PDATA_TYPE_STRUCTURE StructureData;
  555. PSTRUCTURE_MEMBER StructureMember;
  556. //
  557. // Print only the type name if the recursion depth has reached 0.
  558. //
  559. if (RecursionDepth == 0) {
  560. DbgPrintTypeName(Type);
  561. return;
  562. }
  563. switch (Type->Type) {
  564. case DataTypeNumeric:
  565. NumericData = &(Type->U.Numeric);
  566. if (NumericData->Float != FALSE) {
  567. DbgOut("%d bit floating point number.", NumericData->BitSize);
  568. } else if (NumericData->Signed == FALSE) {
  569. DbgOut("U");
  570. }
  571. DbgOut("Int%d", NumericData->BitSize);
  572. break;
  573. case DataTypeRelation:
  574. //
  575. // Get the type this relation refers to.
  576. //
  577. RelationData = &(Type->U.Relation);
  578. RelativeType = DbgGetType(RelationData->OwningFile,
  579. RelationData->TypeNumber);
  580. //
  581. // If it cannot be found, this is an error.
  582. //
  583. if (RelativeType == NULL) {
  584. DbgOut("DANGLING RELATION %s, %d\n",
  585. RelationData->OwningFile->SourceFile,
  586. RelationData->TypeNumber);
  587. assert(RelativeType != NULL);
  588. return;
  589. }
  590. //
  591. // If it's a reference to itself, it's a void.
  592. //
  593. if (RelativeType == Type) {
  594. DbgOut("void type.");
  595. //
  596. // If the type is neither a pointer nor an array, print the description
  597. // of this type. This recurses until we actually print the description
  598. // of something that's *not* a relation, hit an array, or hit a pointer.
  599. // Note that simply following relations does not count against the
  600. // recursion depth since these types merely equal each other. This is
  601. // why the recursion depth is not decreased.
  602. //
  603. } else if ((RelationData->Array.Minimum ==
  604. RelationData->Array.Maximum) &&
  605. (RelationData->Pointer == 0)) {
  606. DbgPrintTypeDescription(RelativeType,
  607. SpaceLevel,
  608. RecursionDepth - 1);
  609. //
  610. // If the relation is a pointer or an array, print out that information
  611. // and do not recurse.
  612. //
  613. } else {
  614. //
  615. // Print the pointer symbol if this type is a pointer to another
  616. // type.
  617. //
  618. if (RelationData->Pointer != 0) {
  619. DbgOut("*");
  620. }
  621. //
  622. // Print the type's name. If this type has no name, this function
  623. // will follow the reference to a type that does have a name.
  624. //
  625. DbgPrintTypeName(RelativeType);
  626. //
  627. // If the type is an array, print that information.
  628. //
  629. if (RelationData->Array.Minimum != RelationData->Array.Maximum) {
  630. DbgOut("[");
  631. if (RelationData->Array.Minimum != 0) {
  632. DbgOut("%I64d:", RelationData->Array.Minimum);
  633. }
  634. DbgOut("%I64d]", RelationData->Array.Maximum + 1);
  635. }
  636. }
  637. break;
  638. case DataTypeEnumeration:
  639. SpaceLevel += 2;
  640. DbgOut("enum {\n");
  641. EnumerationData = &(Type->U.Enumeration);
  642. EnumerationMember = EnumerationData->FirstMember;
  643. while (EnumerationMember != NULL) {
  644. DbgOut("%*s", SpaceLevel, "");
  645. MemberName = EnumerationMember->Name;
  646. if (MemberName == NULL) {
  647. MemberName = "";
  648. }
  649. DbgOut("%-*s = %I64d\n",
  650. MEMBER_NAME_SPACE,
  651. MemberName,
  652. EnumerationMember->Value);
  653. EnumerationMember = EnumerationMember->NextMember;
  654. }
  655. SpaceLevel -= 2;
  656. DbgOut("%*s", SpaceLevel, "");
  657. DbgOut("}");
  658. break;
  659. case DataTypeStructure:
  660. DbgOut("struct {\n");
  661. SpaceLevel += 2;
  662. StructureData = &(Type->U.Structure);
  663. StructureMember = StructureData->FirstMember;
  664. while (StructureMember != NULL) {
  665. Bytes = StructureMember->BitOffset / BITS_PER_BYTE;
  666. BitRemainder = StructureMember->BitOffset % BITS_PER_BYTE;
  667. DbgOut("%*s", SpaceLevel, "");
  668. MemberName = StructureMember->Name;
  669. if (MemberName == NULL) {
  670. MemberName = "";
  671. }
  672. if (BitRemainder != 0) {
  673. snprintf(MemberNameBuffer,
  674. sizeof(MemberNameBuffer),
  675. "%s:%d",
  676. MemberName,
  677. BitRemainder);
  678. MemberNameBuffer[sizeof(MemberNameBuffer) - 1] = '\0';
  679. MemberName = MemberNameBuffer;
  680. }
  681. DbgOut("+0x%03x %-*s", Bytes, MEMBER_NAME_SPACE, MemberName);
  682. DbgOut(" : ");
  683. MemberType = DbgGetType(StructureMember->TypeFile,
  684. StructureMember->TypeNumber);
  685. if (MemberType == NULL) {
  686. DbgOut("DANGLING REFERENCE %s, %d\n",
  687. StructureMember->TypeFile->SourceFile,
  688. StructureMember->TypeNumber);
  689. assert(MemberType != NULL);
  690. StructureMember = StructureMember->NextMember;
  691. continue;
  692. }
  693. DbgPrintTypeDescription(MemberType, SpaceLevel, RecursionDepth - 1);
  694. DbgOut("\n");
  695. StructureMember = StructureMember->NextMember;
  696. }
  697. SpaceLevel -= 2;
  698. DbgOut("%*s}", SpaceLevel, "");
  699. if (SpaceLevel == 0) {
  700. DbgOut("\nType Size: %d Bytes.", StructureData->SizeInBytes);
  701. }
  702. break;
  703. case DataTypeFunctionPointer:
  704. DbgOut("(*)()");
  705. break;
  706. default:
  707. assert(FALSE);
  708. break;
  709. }
  710. }
  711. INT
  712. DbgGetMemberOffset (
  713. PTYPE_SYMBOL StructureType,
  714. PSTR FieldName,
  715. PULONG FieldOffset,
  716. PULONG FieldSize
  717. )
  718. /*++
  719. Routine Description:
  720. This routine returns the given field's offset (in bits) within the
  721. given structure.
  722. Arguments:
  723. StructureType - Supplies a pointer to a symbol structure type.
  724. FieldName - Supplies a string containing the name of the field whose offset
  725. will be returned.
  726. FieldOffset - Supplies a pointer that will receive the bit offset of the
  727. given field name within the given structure.
  728. FieldSize - Supplies a pointer that will receive the size of the field in
  729. bits.
  730. Return Value:
  731. 0 on success.
  732. ENOENT if no such field name exists.
  733. Other error codes on other errors.
  734. --*/
  735. {
  736. ULONG Index;
  737. INT Result;
  738. PDATA_TYPE_STRUCTURE StructureData;
  739. PSTRUCTURE_MEMBER StructureMember;
  740. //
  741. // Parameter checking.
  742. //
  743. if ((StructureType == NULL) ||
  744. (StructureType->Type != DataTypeStructure) ||
  745. (FieldOffset == NULL)) {
  746. return EINVAL;
  747. }
  748. //
  749. // Search for the field within the structure.
  750. //
  751. Result = ENOENT;
  752. StructureData = &(StructureType->U.Structure);
  753. StructureMember = StructureData->FirstMember;
  754. for (Index = 0; Index < StructureData->MemberCount; Index += 1) {
  755. if ((StructureMember->Name != NULL) &&
  756. (strcmp(FieldName, StructureMember->Name) == 0)) {
  757. if (FieldOffset != NULL) {
  758. *FieldOffset = StructureMember->BitOffset;
  759. }
  760. if (FieldSize != NULL) {
  761. *FieldSize = StructureMember->BitSize;
  762. }
  763. Result = 0;
  764. break;
  765. }
  766. StructureMember = StructureMember->NextMember;
  767. }
  768. if (Result != 0) {
  769. DbgOut("GetMemberOffset: %s has no member %s.\n",
  770. StructureType->Name,
  771. FieldName);
  772. }
  773. return Result;
  774. }
  775. PTYPE_SYMBOL
  776. DbgSkipTypedefs (
  777. PTYPE_SYMBOL Type
  778. )
  779. /*++
  780. Routine Description:
  781. This routine skips all relation types that aren't pointers or arrays.
  782. Arguments:
  783. Type - Supplies a pointer to the type to get to the bottom of.
  784. Return Value:
  785. NULL if the type ended up being void or not found.
  786. Returns a pointer to the root type on success.
  787. --*/
  788. {
  789. ULONG MaxCount;
  790. PDATA_TYPE_RELATION Relation;
  791. PTYPE_SYMBOL RelativeType;
  792. if (Type->Type != DataTypeRelation) {
  793. return Type;
  794. }
  795. Relation = &(Type->U.Relation);
  796. //
  797. // Loop scanning through typedefs.
  798. //
  799. MaxCount = 50;
  800. while ((MaxCount != 0) &&
  801. (Type->Type == DataTypeRelation) &&
  802. (Relation->Array.Minimum == Relation->Array.Maximum) &&
  803. (Relation->Pointer == 0)) {
  804. RelativeType = DbgGetType(Relation->OwningFile, Relation->TypeNumber);
  805. if ((RelativeType == NULL) || (RelativeType == Type)) {
  806. return NULL;
  807. }
  808. Type = RelativeType;
  809. Relation = &(Type->U.Relation);
  810. MaxCount -= 1;
  811. }
  812. if (MaxCount == 0) {
  813. return NULL;
  814. }
  815. return Type;
  816. }
  817. PTYPE_SYMBOL
  818. DbgGetType (
  819. PSOURCE_FILE_SYMBOL SourceFile,
  820. LONG TypeNumber
  821. )
  822. /*++
  823. Routine Description:
  824. This routine looks up a type symbol based on the type number and the source
  825. file the type is in.
  826. Arguments:
  827. SourceFile - Supplies a pointer to the source file containing the type.
  828. TypeNumber - Supplies the type number to look up.
  829. Return Value:
  830. Returns a pointer to the type on success, or NULL on error.
  831. --*/
  832. {
  833. PLIST_ENTRY CurrentEntry;
  834. PTYPE_SYMBOL CurrentType;
  835. if (SourceFile == NULL) {
  836. assert(TypeNumber == -1);
  837. return &DbgVoidType;
  838. }
  839. CurrentEntry = SourceFile->TypesHead.Next;
  840. while (CurrentEntry != &(SourceFile->TypesHead)) {
  841. CurrentType = LIST_VALUE(CurrentEntry, TYPE_SYMBOL, ListEntry);
  842. if (CurrentType->TypeNumber == TypeNumber) {
  843. return CurrentType;
  844. }
  845. CurrentEntry = CurrentEntry->Next;
  846. }
  847. DbgOut("Error: Failed to look up type %s:%x\n",
  848. SourceFile->SourceFile,
  849. TypeNumber);
  850. return NULL;
  851. }
  852. PSOURCE_LINE_SYMBOL
  853. DbgLookupSourceLine (
  854. PDEBUG_SYMBOLS Module,
  855. ULONGLONG Address
  856. )
  857. /*++
  858. Routine Description:
  859. This routine looks up a source line in a given module based on the address.
  860. Arguments:
  861. Module - Supplies a pointer to the module which contains the symbols to
  862. search through.
  863. Address - Supplies the query address to search the source line symbols for.
  864. Return Value:
  865. If a successful match is found, returns a pointer to the source line symbol.
  866. If a source line matching the address could not be found or an error
  867. occured, returns NULL.
  868. --*/
  869. {
  870. PLIST_ENTRY CurrentEntry;
  871. PSOURCE_LINE_SYMBOL CurrentLine;
  872. PSOURCE_FILE_SYMBOL CurrentSource;
  873. PLIST_ENTRY CurrentSourceEntry;
  874. //
  875. // Parameter checking.
  876. //
  877. if (Module == NULL) {
  878. return NULL;
  879. }
  880. //
  881. // Begin searching. Loop over all source files in the module.
  882. //
  883. CurrentSourceEntry = Module->SourcesHead.Next;
  884. CurrentEntry = NULL;
  885. while (CurrentSourceEntry != &(Module->SourcesHead)) {
  886. CurrentSource = LIST_VALUE(CurrentSourceEntry,
  887. SOURCE_FILE_SYMBOL,
  888. ListEntry);
  889. if (CurrentEntry == NULL) {
  890. CurrentEntry = CurrentSource->SourceLinesHead.Next;
  891. }
  892. //
  893. // Loop over every source line in the current source file.
  894. //
  895. while (CurrentEntry != &(CurrentSource->SourceLinesHead)) {
  896. CurrentLine = LIST_VALUE(CurrentEntry,
  897. SOURCE_LINE_SYMBOL,
  898. ListEntry);
  899. if ((Address >= CurrentLine->Start) &&
  900. (Address < CurrentLine->End)) {
  901. //
  902. // A match has been found!
  903. //
  904. return CurrentLine;
  905. }
  906. CurrentEntry = CurrentEntry->Next;
  907. }
  908. CurrentEntry = NULL;
  909. CurrentSourceEntry = CurrentSourceEntry->Next;
  910. }
  911. return NULL;
  912. }
  913. PSYMBOL_SEARCH_RESULT
  914. DbgLookupSymbol (
  915. PDEBUG_SYMBOLS Module,
  916. ULONGLONG Address,
  917. PSYMBOL_SEARCH_RESULT Input
  918. )
  919. /*++
  920. Routine Description:
  921. This routine looks up a symbol in a module based on the given address. It
  922. first searches through data symbols, then functions.
  923. Arguments:
  924. Module - Supplies a pointer to the module which contains the symbols to
  925. search through.
  926. Address - Supplies the address of the symbol to look up.
  927. Input - Supplies a pointer to the search result structure. On input, the
  928. parameter contains the search result to start the search from. On
  929. output, contains the new found search result. To signify that the search
  930. should start from the beginning, set the Type member to ResultInvalid.
  931. Return Value:
  932. If a successful match is found, returns Input with the search results filled
  933. into the structure. If no result was found or an error occurred, NULL is
  934. returned.
  935. --*/
  936. {
  937. //
  938. // Parameter checking.
  939. //
  940. if ((Module == NULL) || (Address == (INTN)NULL) || (Input == NULL)) {
  941. return NULL;
  942. }
  943. //
  944. // Start searching, depending on the input parameter. Note that fallthrough
  945. // *is* intended.
  946. //
  947. switch (Input->Variety) {
  948. case SymbolResultInvalid:
  949. case SymbolResultType:
  950. case SymbolResultData:
  951. if (DbgFindDataSymbol(Module, NULL, Address, Input) != NULL) {
  952. return Input;
  953. }
  954. case SymbolResultFunction:
  955. if (DbgFindFunctionSymbol(Module, NULL, Address, Input) != NULL) {
  956. return Input;
  957. }
  958. default:
  959. break;
  960. }
  961. return NULL;
  962. }
  963. PSYMBOL_SEARCH_RESULT
  964. DbgpFindSymbolInModule (
  965. PDEBUG_SYMBOLS Module,
  966. PSTR Query,
  967. PSYMBOL_SEARCH_RESULT Input
  968. )
  969. /*++
  970. Routine Description:
  971. This routine searches for a symbol in a module. It first searches through
  972. types, then data symbols, then functions.
  973. Arguments:
  974. Module - Supplies a pointer to the module which contains the symbols to
  975. search through.
  976. Query - Supplies the search string.
  977. Input - Supplies a pointer to the search result structure. On input, the
  978. parameter contains the search result to start the search from. On
  979. output, contains the new found search result. To signify that the search
  980. should start from the beginning, set the Type member to ResultInvalid.
  981. Return Value:
  982. If a successful match is found, returns Input with the search results filled
  983. into the structure. If no result was found or an error occurred, NULL is
  984. returned.
  985. --*/
  986. {
  987. //
  988. // Parameter checking.
  989. //
  990. if ((Module == NULL) || (Query == NULL) || (Input == NULL)) {
  991. return NULL;
  992. }
  993. //
  994. // Start searching, depending on the input parameter. Note that fallthrough
  995. // *is* intended.
  996. //
  997. switch (Input->Variety) {
  998. case SymbolResultInvalid:
  999. case SymbolResultType:
  1000. if (DbgFindTypeSymbol(Module, Query, Input) != NULL) {
  1001. return Input;
  1002. }
  1003. case SymbolResultData:
  1004. if (DbgFindDataSymbol(Module, Query, (INTN)NULL, Input) != NULL) {
  1005. return Input;
  1006. }
  1007. case SymbolResultFunction:
  1008. if (DbgFindFunctionSymbol(Module, Query, (INTN)NULL, Input) != NULL) {
  1009. return Input;
  1010. }
  1011. default:
  1012. break;
  1013. }
  1014. return NULL;
  1015. }
  1016. PSYMBOL_SEARCH_RESULT
  1017. DbgFindTypeSymbol (
  1018. PDEBUG_SYMBOLS Module,
  1019. PSTR Query,
  1020. PSYMBOL_SEARCH_RESULT Input
  1021. )
  1022. /*++
  1023. Routine Description:
  1024. This routine searches for a type symbol in a module.
  1025. Arguments:
  1026. Module - Supplies a pointer to the module which contains the symbols to
  1027. search through.
  1028. Query - Supplies the search string.
  1029. Input - Supplies a pointer to the search result structure. On input, the
  1030. parameter contains the search result to start the search from. On
  1031. output, contains the new found search result. To signify that the search
  1032. should start from the beginning, set the Type member to ResultInvalid.
  1033. Return Value:
  1034. If a successful match is found, returns Input with the search results filled
  1035. into the structure. If no result was found or an error occurred, NULL is
  1036. returned.
  1037. --*/
  1038. {
  1039. PLIST_ENTRY CurrentEntry;
  1040. PSOURCE_FILE_SYMBOL CurrentSource;
  1041. PLIST_ENTRY CurrentSourceEntry;
  1042. PTYPE_SYMBOL CurrentType;
  1043. //
  1044. // Parameter checking.
  1045. //
  1046. if ((Query == NULL) || (Module == NULL) || (Input == NULL)) {
  1047. return NULL;
  1048. }
  1049. //
  1050. // Initialize the search variables based on the input parameter.
  1051. //
  1052. CurrentEntry = NULL;
  1053. if ((Input->Variety == SymbolResultType) && (Input->U.TypeResult != NULL)) {
  1054. CurrentEntry = &(Input->U.TypeResult->ListEntry);
  1055. CurrentType = LIST_VALUE(CurrentEntry, TYPE_SYMBOL, ListEntry);
  1056. CurrentSource = CurrentType->ParentSource;
  1057. CurrentSourceEntry = &(CurrentSource->ListEntry);
  1058. CurrentEntry = CurrentEntry->Next;
  1059. } else {
  1060. CurrentSourceEntry = Module->SourcesHead.Next;
  1061. CurrentSource = LIST_VALUE(CurrentSourceEntry,
  1062. SOURCE_FILE_SYMBOL,
  1063. ListEntry);
  1064. }
  1065. //
  1066. // Begin searching. Loop over all source files in the module.
  1067. //
  1068. while (CurrentSourceEntry != &(Module->SourcesHead)) {
  1069. CurrentSource = LIST_VALUE(CurrentSourceEntry,
  1070. SOURCE_FILE_SYMBOL,
  1071. ListEntry);
  1072. if (CurrentEntry == NULL) {
  1073. CurrentEntry = CurrentSource->TypesHead.Next;
  1074. }
  1075. //
  1076. // Loop over every type in the current source file.
  1077. //
  1078. while (CurrentEntry != &(CurrentSource->TypesHead)) {
  1079. CurrentType = LIST_VALUE(CurrentEntry,
  1080. TYPE_SYMBOL,
  1081. ListEntry);
  1082. if (DbgpStringMatch(Query, CurrentType->Name) != FALSE) {
  1083. //
  1084. // A match has been found. Fill out the structure and return.
  1085. //
  1086. Input->Variety = SymbolResultType;
  1087. Input->U.TypeResult = CurrentType;
  1088. return Input;
  1089. }
  1090. CurrentEntry = CurrentEntry->Next;
  1091. }
  1092. CurrentEntry = NULL;
  1093. CurrentSourceEntry = CurrentSourceEntry->Next;
  1094. }
  1095. return NULL;
  1096. }
  1097. PSYMBOL_SEARCH_RESULT
  1098. DbgFindDataSymbol (
  1099. PDEBUG_SYMBOLS Module,
  1100. PSTR Query,
  1101. ULONGLONG Address,
  1102. PSYMBOL_SEARCH_RESULT Input
  1103. )
  1104. /*++
  1105. Routine Description:
  1106. This routine searches for a data symbol in a module based on a query string
  1107. or address.
  1108. Arguments:
  1109. Module - Supplies a pointer to the module which contains the symbols to
  1110. search through.
  1111. Query - Supplies the search string. This parameter can be NULL if searching
  1112. by address.
  1113. Address - Supplies the address of the symbol. Can be NULL if search by
  1114. query string is desired.
  1115. Input - Supplies a pointer to the search result structure. On input, the
  1116. parameter contains the search result to start the search from. On
  1117. output, contains the new found search result. To signify that the search
  1118. should start from the beginning, set the Type member to ResultInvalid.
  1119. Return Value:
  1120. If a successful match is found, returns Input with the search results filled
  1121. into the structure. If no result was found or an error occurred, NULL is
  1122. returned.
  1123. --*/
  1124. {
  1125. PDATA_SYMBOL CurrentData;
  1126. PLIST_ENTRY CurrentEntry;
  1127. PSOURCE_FILE_SYMBOL CurrentSource;
  1128. PLIST_ENTRY CurrentSourceEntry;
  1129. //
  1130. // Parameter checking.
  1131. //
  1132. if ((Module == NULL) || (Input == NULL)) {
  1133. return NULL;
  1134. }
  1135. if ((Query == NULL) && (Address == (INTN)NULL)) {
  1136. return NULL;
  1137. }
  1138. //
  1139. // Initialize the search variables based on the input parameter.
  1140. //
  1141. CurrentEntry = NULL;
  1142. if ((Input->Variety == SymbolResultData) && (Input->U.DataResult != NULL)) {
  1143. CurrentEntry = &(Input->U.DataResult->ListEntry);
  1144. CurrentData = LIST_VALUE(CurrentEntry, DATA_SYMBOL, ListEntry);
  1145. CurrentSource = CurrentData->ParentSource;
  1146. CurrentSourceEntry = &(CurrentSource->ListEntry);
  1147. CurrentEntry = CurrentEntry->Next;
  1148. } else {
  1149. CurrentSourceEntry = Module->SourcesHead.Next;
  1150. CurrentSource = LIST_VALUE(CurrentSourceEntry,
  1151. SOURCE_FILE_SYMBOL,
  1152. ListEntry);
  1153. }
  1154. //
  1155. // Begin searching. Loop over all source files in the module.
  1156. //
  1157. while (CurrentSourceEntry != &(Module->SourcesHead)) {
  1158. CurrentSource = LIST_VALUE(CurrentSourceEntry,
  1159. SOURCE_FILE_SYMBOL,
  1160. ListEntry);
  1161. //
  1162. // Set up the current symbol entry.
  1163. //
  1164. if (CurrentEntry == NULL) {
  1165. CurrentEntry = CurrentSource->DataSymbolsHead.Next;
  1166. }
  1167. //
  1168. // Loop over every data symbol in the current source file.
  1169. //
  1170. while (CurrentEntry != &(CurrentSource->DataSymbolsHead)) {
  1171. CurrentData = LIST_VALUE(CurrentEntry,
  1172. DATA_SYMBOL,
  1173. ListEntry);
  1174. //
  1175. // Check for an address-based match. Only look at absolute address
  1176. // based symbols (not stack offset or register variables).
  1177. //
  1178. if (Address != (INTN)NULL) {
  1179. if ((CurrentData->LocationType ==
  1180. DataLocationAbsoluteAddress) &&
  1181. (CurrentData->Location.Address == Address)) {
  1182. Input->Variety = SymbolResultData;
  1183. Input->U.DataResult = CurrentData;
  1184. return Input;
  1185. }
  1186. } else {
  1187. assert(Query != NULL);
  1188. //
  1189. // Check for a string-based match.
  1190. //
  1191. if (DbgpStringMatch(Query, CurrentData->Name) != FALSE) {
  1192. Input->Variety = SymbolResultData;
  1193. Input->U.DataResult = CurrentData;
  1194. return Input;
  1195. }
  1196. }
  1197. CurrentEntry = CurrentEntry->Next;
  1198. }
  1199. CurrentEntry = NULL;
  1200. CurrentSourceEntry = CurrentSourceEntry->Next;
  1201. }
  1202. return NULL;
  1203. }
  1204. PSYMBOL_SEARCH_RESULT
  1205. DbgFindFunctionSymbol (
  1206. PDEBUG_SYMBOLS Module,
  1207. PSTR Query,
  1208. ULONGLONG Address,
  1209. PSYMBOL_SEARCH_RESULT Input
  1210. )
  1211. /*++
  1212. Routine Description:
  1213. This routine searches for a function symbol in a module based on a search
  1214. string or an address.
  1215. Arguments:
  1216. Module - Supplies a pointer to the module which contains the symbols to
  1217. search through.
  1218. Query - Supplies the search string. This parameter can be NULL if searching
  1219. by address.
  1220. Address - Supplies the search address. This parameter can be NULL if
  1221. searching by query string.
  1222. Input - Supplies a pointer to the search result structure. On input, the
  1223. parameter contains the search result to start the search from. On
  1224. output, contains the new found search result. To signify that the search
  1225. should start from the beginning, set the Type member to ResultInvalid.
  1226. Return Value:
  1227. If a successful match is found, returns Input with the search results filled
  1228. into the structure. If no result was found or an error occurred, NULL is
  1229. returned.
  1230. --*/
  1231. {
  1232. PLIST_ENTRY CurrentEntry;
  1233. PFUNCTION_SYMBOL CurrentFunction;
  1234. PSOURCE_FILE_SYMBOL CurrentSource;
  1235. PLIST_ENTRY CurrentSourceEntry;
  1236. //
  1237. // Parameter checking.
  1238. //
  1239. if ((Module == NULL) || (Input == NULL)) {
  1240. return NULL;
  1241. }
  1242. if ((Query == NULL) && (Address == (INTN)NULL)) {
  1243. return NULL;
  1244. }
  1245. //
  1246. // Initialize the search variables based on the input parameter.
  1247. //
  1248. CurrentEntry = NULL;
  1249. if ((Input->Variety == SymbolResultFunction) &&
  1250. (Input->U.FunctionResult != NULL)) {
  1251. CurrentEntry = &(Input->U.FunctionResult->ListEntry);
  1252. CurrentFunction = LIST_VALUE(CurrentEntry, FUNCTION_SYMBOL, ListEntry);
  1253. CurrentSource = CurrentFunction->ParentSource;
  1254. CurrentSourceEntry = &(CurrentSource->ListEntry);
  1255. CurrentEntry = CurrentEntry->Next;
  1256. } else {
  1257. CurrentSourceEntry = Module->SourcesHead.Next;
  1258. CurrentSource = LIST_VALUE(CurrentSourceEntry,
  1259. SOURCE_FILE_SYMBOL,
  1260. ListEntry);
  1261. }
  1262. //
  1263. // Begin searching. Loop over all source files in the module.
  1264. //
  1265. while (CurrentSourceEntry != &(Module->SourcesHead)) {
  1266. CurrentSource = LIST_VALUE(CurrentSourceEntry,
  1267. SOURCE_FILE_SYMBOL,
  1268. ListEntry);
  1269. if (CurrentEntry == NULL) {
  1270. CurrentEntry = CurrentSource->FunctionsHead.Next;
  1271. }
  1272. //
  1273. // Loop over every function in the current source file.
  1274. //
  1275. while (CurrentEntry != &(CurrentSource->FunctionsHead)) {
  1276. CurrentFunction = LIST_VALUE(CurrentEntry,
  1277. FUNCTION_SYMBOL,
  1278. ListEntry);
  1279. //
  1280. // For address based searching, determine if the function is within
  1281. // range, and return if a match is found.
  1282. //
  1283. if (Address != (INTN)NULL) {
  1284. if ((Address >= CurrentFunction->StartAddress) &&
  1285. (Address < CurrentFunction->EndAddress)) {
  1286. Input->Variety = SymbolResultFunction;
  1287. Input->U.FunctionResult = CurrentFunction;
  1288. return Input;
  1289. }
  1290. } else {
  1291. //
  1292. // Check for a string based match.
  1293. //
  1294. assert(Query != NULL);
  1295. if (DbgpStringMatch(Query, CurrentFunction->Name) != FALSE) {
  1296. Input->Variety = SymbolResultFunction;
  1297. Input->U.FunctionResult = CurrentFunction;
  1298. return Input;
  1299. }
  1300. }
  1301. CurrentEntry = CurrentEntry->Next;
  1302. }
  1303. CurrentEntry = NULL;
  1304. CurrentSourceEntry = CurrentSourceEntry->Next;
  1305. }
  1306. return NULL;
  1307. }
  1308. PSTR
  1309. DbgGetRegisterName (
  1310. IMAGE_MACHINE_TYPE MachineType,
  1311. ULONG Register
  1312. )
  1313. /*++
  1314. Routine Description:
  1315. This routine returns a string containing the name of the given register.
  1316. Arguments:
  1317. MachineType - Supplies the machine type.
  1318. Register - Supplies the register number.
  1319. Return Value:
  1320. Returns a pointer to a constant string containing the name of the register.
  1321. --*/
  1322. {
  1323. ULONG Count;
  1324. PSTR Name;
  1325. Name = NULL;
  1326. switch (MachineType) {
  1327. case ImageMachineTypeX86:
  1328. Count = sizeof(DbgX86RegisterSymbolNames) /
  1329. sizeof(DbgX86RegisterSymbolNames[0]);
  1330. if (Register < Count) {
  1331. Name = DbgX86RegisterSymbolNames[Register];
  1332. }
  1333. break;
  1334. case ImageMachineTypeArm32:
  1335. Count = sizeof(DbgArmRegisterSymbolNames) /
  1336. sizeof(DbgArmRegisterSymbolNames[0]);
  1337. if (Register < Count) {
  1338. Name = DbgArmRegisterSymbolNames[Register];
  1339. break;
  1340. }
  1341. Count = sizeof(DbgArmVfpRegisterSymbolNames) /
  1342. sizeof(DbgArmVfpRegisterSymbolNames[0]);
  1343. if ((Register >= ArmRegisterD0) &&
  1344. ((Register - ArmRegisterD0) < Count)) {
  1345. Name = DbgArmVfpRegisterSymbolNames[Register - ArmRegisterD0];
  1346. }
  1347. break;
  1348. default:
  1349. break;
  1350. }
  1351. if (Name == NULL) {
  1352. Name = "UNKNOWNREG";
  1353. }
  1354. return Name;
  1355. }
  1356. //
  1357. // --------------------------------------------------------- Internal Functions
  1358. //
  1359. BOOL
  1360. DbgpStringMatch (
  1361. PSTR Query,
  1362. PSTR PossibleMatch
  1363. )
  1364. /*++
  1365. Routine Description:
  1366. This routine determines whether or not a string matches a query string. The
  1367. query string may contain wildcard characters (*).
  1368. Arguments:
  1369. Query - Supplies the query string. This string may contain wildcard
  1370. characters (*) signifying zero or more arbitrary characters.
  1371. PossibleMatch - Supplies the test string. Wildcard characters in this string
  1372. will be treated as regular characters.
  1373. Return Value:
  1374. Returns TRUE upon successful match. Returns FALSE if the strings do not
  1375. match.
  1376. --*/
  1377. {
  1378. PSTR CurrentMatch;
  1379. PSTR CurrentQuery;
  1380. BOOL InWildcard;
  1381. UCHAR LowerMatch;
  1382. UCHAR LowerQuery;
  1383. InWildcard = FALSE;
  1384. CurrentQuery = Query;
  1385. CurrentMatch = PossibleMatch;
  1386. if ((Query == NULL) || (PossibleMatch == NULL)) {
  1387. return FALSE;
  1388. }
  1389. do {
  1390. //
  1391. // If the current query character is a wildcard, note that and advance
  1392. // to the character after the wildcard.
  1393. //
  1394. if (*CurrentQuery == '*') {
  1395. InWildcard = TRUE;
  1396. CurrentQuery += 1;
  1397. }
  1398. //
  1399. // If the entire query string has been processed, it's a match only if
  1400. // the match string is finished as well, or a wildcard is being
  1401. // processed.
  1402. //
  1403. if (*CurrentQuery == '\0') {
  1404. if ((*CurrentMatch == '\0') || (InWildcard != FALSE)) {
  1405. return TRUE;
  1406. } else {
  1407. return FALSE;
  1408. }
  1409. }
  1410. //
  1411. // If the match string ended, this must not be a match because the
  1412. // query string hasn't ended. Whether or not search is inside a
  1413. // wildcard is irrelevent because there must be match characters after
  1414. // the wildcard that are not getting satisfied (if there weren't the
  1415. // query string would be over.
  1416. //
  1417. if (*CurrentMatch == '\0') {
  1418. return FALSE;
  1419. }
  1420. //
  1421. // Convert to lowercase.
  1422. //
  1423. LowerQuery = *CurrentQuery;
  1424. LowerMatch = *CurrentMatch;
  1425. if ((LowerQuery >= 'A') && (LowerQuery <= 'Z')) {
  1426. LowerQuery = LowerQuery - 'A' + 'a';
  1427. }
  1428. if ((LowerMatch >= 'A') && (LowerMatch <= 'Z')) {
  1429. LowerMatch = LowerMatch - 'A' + 'a';
  1430. }
  1431. //
  1432. // If the characters match, then either it's a normal match or a
  1433. // character after the wildcard has been found. If it's the wildcard
  1434. // case, attempt to match the rest of the string from here. If it does
  1435. // not work, all is not lost, the correct match may be farther down the
  1436. // string.
  1437. //
  1438. if (LowerQuery == LowerMatch) {
  1439. if (InWildcard != FALSE) {
  1440. if (DbgpStringMatch(CurrentQuery, CurrentMatch) != FALSE) {
  1441. return TRUE;
  1442. } else {
  1443. CurrentMatch += 1;
  1444. }
  1445. } else {
  1446. CurrentQuery += 1;
  1447. CurrentMatch += 1;
  1448. }
  1449. //
  1450. // If there's no match, but there's a wildcard being processed, advance
  1451. // only the match string.
  1452. //
  1453. } else if (InWildcard != FALSE) {
  1454. CurrentMatch += 1;
  1455. //
  1456. // It's not a match and there's no wildcard, the strings simply
  1457. // disagree.
  1458. //
  1459. } else {
  1460. return FALSE;
  1461. }
  1462. } while (TRUE);
  1463. return FALSE;
  1464. }