symbols.c 48 KB

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