dwread.c 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554
  1. /*++
  2. Copyright (c) 2015 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. dwread.c
  9. Abstract:
  10. This module implements support for reading DWARF structures.
  11. Author:
  12. Evan Green 4-Dec-2015
  13. Environment:
  14. Debug
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include <minoca/lib/types.h>
  20. #include <minoca/lib/status.h>
  21. #include <minoca/lib/im.h>
  22. #include "dwarfp.h"
  23. #include <assert.h>
  24. #include <errno.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. //
  29. // --------------------------------------------------------------------- Macros
  30. //
  31. //
  32. // ---------------------------------------------------------------- Definitions
  33. //
  34. //
  35. // ------------------------------------------------------ Data Type Definitions
  36. //
  37. //
  38. // ----------------------------------------------- Internal Function Prototypes
  39. //
  40. INT
  41. DwarfpIndexAbbreviations (
  42. PDWARF_CONTEXT Context,
  43. ULONGLONG Offset,
  44. PUCHAR **AbbreviationsIndex,
  45. PUINTN IndexSize,
  46. PUINTN MaxAttributes
  47. );
  48. INT
  49. DwarfpReadDie (
  50. PDWARF_CONTEXT Context,
  51. PDWARF_COMPILATION_UNIT Unit,
  52. PUCHAR *Data,
  53. PUCHAR Abbreviation,
  54. PDWARF_DIE Die
  55. );
  56. INT
  57. DwarfpReadFormValue (
  58. PDWARF_CONTEXT Context,
  59. PDWARF_COMPILATION_UNIT Unit,
  60. PUCHAR *Data,
  61. PDWARF_ATTRIBUTE_VALUE Attribute
  62. );
  63. VOID
  64. DwarfpPrintFormValue (
  65. PDWARF_ATTRIBUTE_VALUE Attribute
  66. );
  67. PSTR
  68. DwarfpGetTagName (
  69. DWARF_TAG Tag
  70. );
  71. PSTR
  72. DwarfpGetAttributeName (
  73. DWARF_ATTRIBUTE Attribute
  74. );
  75. PSTR
  76. DwarfpGetFormName (
  77. DWARF_FORM Form
  78. );
  79. PSTR
  80. DwarfpGetHasChildrenName (
  81. DWARF_CHILDREN_VALUE Value
  82. );
  83. PDWARF_DIE
  84. DwarfpFindDie (
  85. PDWARF_COMPILATION_UNIT Unit,
  86. PUCHAR DieStart
  87. );
  88. //
  89. // -------------------------------------------------------------------- Globals
  90. //
  91. PSTR DwarfTagNames[] = {
  92. "NullTag",
  93. "DwarfTagArrayType",
  94. "DwarfTagClassType",
  95. "DwarfTagEntryPoint",
  96. "DwarfTagEnumerationType",
  97. "DwarfTagFormalParameter",
  98. NULL,
  99. NULL,
  100. "DwarfTagImportedDeclaration",
  101. NULL,
  102. "DwarfTagLabel",
  103. "DwarfTagLexicalBlock",
  104. NULL,
  105. "DwarfTagMember",
  106. NULL,
  107. "DwarfTagPointerType",
  108. "DwarfTagReferenceType",
  109. "DwarfTagCompileUnit",
  110. "DwarfTagStringType",
  111. "DwarfTagStructureType",
  112. NULL,
  113. "DwarfTagSubroutineType",
  114. "DwarfTagTypedef",
  115. "DwarfTagUnionType",
  116. "DwarfTagUnspecifiedParameters",
  117. "DwarfTagVariant",
  118. "DwarfTagCommonBlock",
  119. "DwarfTagCommonInclusion",
  120. "DwarfTagInheritance",
  121. "DwarfTagInlinedSubroutine",
  122. "DwarfTagModule",
  123. "DwarfTagPointerToMemberType",
  124. "DwarfTagSetType",
  125. "DwarfTagSubrangeType",
  126. "DwarfTagWithStatement",
  127. "DwarfTagAccessDeclaration",
  128. "DwarfTagBaseType",
  129. "DwarfTagCatchBlock",
  130. "DwarfTagConstType",
  131. "DwarfTagConstant",
  132. "DwarfTagEnumerator",
  133. "DwarfTagFileType",
  134. "DwarfTagFriend",
  135. "DwarfTagNameList",
  136. "DwarfTagNameListItem",
  137. "DwarfTagPackedType",
  138. "DwarfTagSubprogram",
  139. "DwarfTagTemplateTypeParameter",
  140. "DwarfTagTemplateValueParameter",
  141. "DwarfTagThrownType",
  142. "DwarfTagTryBlock",
  143. "DwarfTagVariantPart",
  144. "DwarfTagVariable",
  145. "DwarfTagVolatileType",
  146. "DwarfTagDwarfProcedure",
  147. "DwarfTagRestrictType",
  148. "DwarfTagInterfaceType",
  149. "DwarfTagNamespace",
  150. "DwarfTagImportedModule",
  151. "DwarfTagUnspecifiedType",
  152. "DwarfTagPartialUnit",
  153. "DwarfTagImportedUnit",
  154. NULL,
  155. "DwarfTagCondition",
  156. "DwarfTagSharedType",
  157. "DwarfTagTypeUnit",
  158. "DwarfTagRvalueReferenceType",
  159. "DwarfTagTemplateAlias",
  160. };
  161. PSTR DwarfHasChildrenNames[] = {
  162. "NoChildren",
  163. "HasChildren",
  164. };
  165. PSTR DwarfAttributeNames[] = {
  166. "DwarfAtNull",
  167. "DwarfAtSibling",
  168. "DwarfAtLocation",
  169. "DwarfAtName",
  170. NULL,
  171. NULL,
  172. NULL,
  173. NULL,
  174. NULL,
  175. "DwarfAtOrdering",
  176. NULL,
  177. "DwarfAtByteSize",
  178. "DwarfAtBitOffset",
  179. "DwarfAtBitSize",
  180. NULL,
  181. NULL,
  182. "DwarfAtStatementList",
  183. "DwarfAtLowPc",
  184. "DwarfAtHighPc",
  185. "DwarfAtLanguage",
  186. NULL,
  187. "DwarfAtDiscr",
  188. "DwarfAtDiscrValue",
  189. "DwarfAtVisibility",
  190. "DwarfAtImport",
  191. "DwarfAtStringLength",
  192. "DwarfAtCommonReference",
  193. "DwarfAtCompDir",
  194. "DwarfAtConstValue",
  195. "DwarfAtContainingType",
  196. "DwarfAtDefaultValue",
  197. NULL,
  198. "DwarfAtInline",
  199. "DwarfAtIsOptional",
  200. "DwarfAtLowerBound",
  201. NULL,
  202. NULL,
  203. "DwarfAtProducer",
  204. NULL,
  205. "DwarfAtPrototyped",
  206. NULL,
  207. NULL,
  208. "DwarfAtReturnAddress",
  209. NULL,
  210. "DwarfAtStartScope",
  211. NULL,
  212. "DwarfAtBitStride",
  213. "DwarfAtUpperBound",
  214. NULL,
  215. "DwarfAtAbstractOrigin",
  216. "DwarfAtAccessibility",
  217. "DwarfAtAddressClass",
  218. "DwarfAtArtificial",
  219. "DwarfAtBaseTypes",
  220. "DwarfAtCallingConvention",
  221. "DwarfAtCount",
  222. "DwarfAtDataMemberLocation",
  223. "DwarfAtDeclColumn",
  224. "DwarfAtDeclFile",
  225. "DwarfAtDeclLine",
  226. "DwarfAtDeclaration",
  227. "DwarfAtDiscrList",
  228. "DwarfAtEncoding",
  229. "DwarfAtExternal",
  230. "DwarfAtFrameBase",
  231. "DwarfAtFriend",
  232. "DwarfAtIdentifierCase",
  233. "DwarfAtMacroInfo",
  234. "DwarfAtNameListItem",
  235. "DwarfAtPriority",
  236. "DwarfAtSegment",
  237. "DwarfAtSpecification",
  238. "DwarfAtStaticLink",
  239. "DwarfAtType",
  240. "DwarfAtUseLocation",
  241. "DwarfAtVariableParameter",
  242. "DwarfAtVirtuality",
  243. "DwarfAtVtableElementLocation",
  244. "DwarfAtAllocated",
  245. "DwarfAtAssociated",
  246. "DwarfAtDataLocation",
  247. "DwarfAtByteStride",
  248. "DwarfAtEntryPc",
  249. "DwarfAtUseUtf8",
  250. "DwarfAtExtension",
  251. "DwarfAtRanges",
  252. "DwarfAtTrampoline",
  253. "DwarfAtCallColumn",
  254. "DwarfAtCallFile",
  255. "DwarfAtCallLine",
  256. "DwarfAtDescription",
  257. "DwarfAtBinaryScale",
  258. "DwarfAtDecimalScale",
  259. "DwarfAtSmall",
  260. "DwarfAtDecimalSign",
  261. "DwarfAtDigitCount",
  262. "DwarfAtPictureString",
  263. "DwarfAtMutable",
  264. "DwarfAtThreadsScaled",
  265. "DwarfAtExplicit",
  266. "DwarfAtObjectPointer",
  267. "DwarfAtEndianity",
  268. "DwarfAtElemental",
  269. "DwarfAtPure",
  270. "DwarfAtRecursive",
  271. "DwarfAtSignature",
  272. "DwarfAtMainSubprogram",
  273. "DwarfAtDataBitOffset",
  274. "DwarfAtConstExpression",
  275. "DwarfAtEnumClass",
  276. "DwarfAtLinkageName",
  277. };
  278. PSTR DwarfFormNames[] = {
  279. "DwarfFormNull",
  280. "DwarfFormAddress",
  281. NULL,
  282. "DwarfFormBlock2",
  283. "DwarfFormBlock4",
  284. "DwarfFormData2",
  285. "DwarfFormData4",
  286. "DwarfFormData8",
  287. "DwarfFormString",
  288. "DwarfFormBlock",
  289. "DwarfFormBlock1",
  290. "DwarfFormData1",
  291. "DwarfFormFlag",
  292. "DwarfFormSData",
  293. "DwarfFormStringPointer",
  294. "DwarfFormUData",
  295. "DwarfFormRefAddress",
  296. "DwarfFormRef1",
  297. "DwarfFormRef2",
  298. "DwarfFormRef4",
  299. "DwarfFormRef8",
  300. "DwarfFormRefUData",
  301. "DwarfFormIndirect",
  302. "DwarfFormSecOffset",
  303. "DwarfFormExprLoc",
  304. "DwarfFormFlagPresent",
  305. NULL,
  306. NULL,
  307. NULL,
  308. NULL,
  309. NULL,
  310. NULL,
  311. "DwarfFormRefSig8"
  312. };
  313. //
  314. // ------------------------------------------------------------------ Functions
  315. //
  316. VOID
  317. DwarfpReadCompilationUnit (
  318. PUCHAR *Data,
  319. PULONGLONG Size,
  320. PDWARF_COMPILATION_UNIT Unit
  321. )
  322. /*++
  323. Routine Description:
  324. This routine reads a DWARF compilation unit header, and pieces it out into
  325. a structure.
  326. Arguments:
  327. Data - Supplies a pointer that on input contains a pointer to the header.
  328. On output this pointer will be advanced past the header and the DIEs,
  329. meaning it will point at the next compilation unit.
  330. Size - Supplies a pointer that on input contains the size of the section.
  331. On output this will be decreased by the amount that the data was
  332. advanced.
  333. Unit - Supplies a pointer where the header information will be filled in.
  334. Return Value:
  335. None.
  336. --*/
  337. {
  338. ULONGLONG Delta;
  339. ULONGLONG RemainingSize;
  340. Unit->Start = *Data;
  341. RemainingSize = *Size;
  342. DwarfpReadInitialLength(Data, &(Unit->Is64Bit), &(Unit->UnitLength));
  343. Unit->Version = DwarfpRead2(Data);
  344. Unit->AbbreviationOffset = DWARF_READN(Data, Unit->Is64Bit);
  345. Unit->AddressSize = DwarfpRead1(Data);
  346. Unit->Dies = *Data;
  347. //
  348. // Advance past the DIEs themselves as well.
  349. //
  350. *Data = Unit->Start + Unit->UnitLength + sizeof(ULONG);
  351. if (Unit->Is64Bit != FALSE) {
  352. *Data += sizeof(ULONGLONG);
  353. }
  354. Unit->DiesEnd = *Data;
  355. Delta = *Data - Unit->Start;
  356. assert(Delta <= RemainingSize);
  357. RemainingSize -= Delta;
  358. *Size = RemainingSize;
  359. return;
  360. }
  361. INT
  362. DwarfpLoadCompilationUnit (
  363. PDWARF_CONTEXT Context,
  364. PDWARF_COMPILATION_UNIT Unit
  365. )
  366. /*++
  367. Routine Description:
  368. This routine processes all the DIEs within a DWARF compilation unit.
  369. Arguments:
  370. Context - Supplies a pointer to the application context.
  371. Unit - Supplies a pointer to the compilation unit.
  372. Return Value:
  373. 0 on success.
  374. Returns an error number on failure.
  375. --*/
  376. {
  377. PUCHAR Abbreviation;
  378. DWARF_LEB128 AbbreviationNumber;
  379. PUCHAR *Abbreviations;
  380. UINTN AbbreviationsCount;
  381. UINTN AllocationSize;
  382. ULONG Depth;
  383. PDWARF_DIE Die;
  384. PUCHAR DieBytes;
  385. PUCHAR End;
  386. UINTN MaxAttributes;
  387. PDWARF_DIE Parent;
  388. INT Status;
  389. Abbreviations = NULL;
  390. Depth = 0;
  391. Die = NULL;
  392. End = Unit->DiesEnd;
  393. Parent = NULL;
  394. //
  395. // Index the abbreviations for this compilation unit.
  396. //
  397. Status = DwarfpIndexAbbreviations(Context,
  398. Unit->AbbreviationOffset,
  399. &Abbreviations,
  400. &AbbreviationsCount,
  401. &MaxAttributes);
  402. if (Status != 0) {
  403. goto ProcessCompilationUnitEnd;
  404. }
  405. AllocationSize = sizeof(DWARF_DIE) +
  406. (MaxAttributes * sizeof(DWARF_ATTRIBUTE_VALUE));
  407. //
  408. // Loop through all the DIEs.
  409. //
  410. DieBytes = Unit->Dies;
  411. while (DieBytes < End) {
  412. Die = malloc(AllocationSize);
  413. if (Die == NULL) {
  414. Status = errno;
  415. goto ProcessCompilationUnitEnd;
  416. }
  417. memset(Die, 0, AllocationSize);
  418. INITIALIZE_LIST_HEAD(&(Die->ChildList));
  419. Die->Capacity = MaxAttributes;
  420. Die->Attributes = (PDWARF_ATTRIBUTE_VALUE)(Die + 1);
  421. Die->Start = DieBytes;
  422. Die->Depth = Depth;
  423. AbbreviationNumber = DwarfpReadLeb128(&DieBytes);
  424. Die->AbbreviationNumber = AbbreviationNumber;
  425. Die->Parent = Parent;
  426. //
  427. // Skip null entries.
  428. //
  429. if (AbbreviationNumber == 0) {
  430. if ((Context->Flags & DWARF_CONTEXT_DEBUG) != 0) {
  431. DWARF_PRINT(" <%x> Null Entry\n",
  432. Die->Start - (PUCHAR)(Context->Sections.Info.Data));
  433. }
  434. if (Depth != 0) {
  435. Depth -= 1;
  436. Parent = Parent->Parent;
  437. }
  438. continue;
  439. }
  440. if ((AbbreviationNumber >= AbbreviationsCount) ||
  441. (Abbreviations[AbbreviationNumber] == NULL)) {
  442. DWARF_ERROR("DWARF: Bad abbreviation number %I64d\n",
  443. AbbreviationNumber);
  444. Status = EINVAL;
  445. goto ProcessCompilationUnitEnd;
  446. }
  447. Abbreviation = Abbreviations[AbbreviationNumber];
  448. Status = DwarfpReadDie(Context,
  449. Unit,
  450. &DieBytes,
  451. Abbreviation,
  452. Die);
  453. if (Status != 0) {
  454. DWARF_ERROR("DWARF: Invalid DIE.\n");
  455. goto ProcessCompilationUnitEnd;
  456. }
  457. if (Parent != NULL) {
  458. INSERT_BEFORE(&(Die->ListEntry), &(Parent->ChildList));
  459. } else {
  460. INSERT_BEFORE(&(Die->ListEntry), &(Unit->DieList));
  461. }
  462. if ((Die->Flags & DWARF_DIE_HAS_CHILDREN) != 0) {
  463. Depth += 1;
  464. Parent = Die;
  465. }
  466. }
  467. Die = NULL;
  468. Status = 0;
  469. ProcessCompilationUnitEnd:
  470. if (Abbreviations != NULL) {
  471. free(Abbreviations);
  472. }
  473. if (Die != NULL) {
  474. DwarfpDestroyDie(Context, Die);
  475. }
  476. return Status;
  477. }
  478. VOID
  479. DwarfpDestroyCompilationUnit (
  480. PDWARF_CONTEXT Context,
  481. PDWARF_COMPILATION_UNIT Unit
  482. )
  483. /*++
  484. Routine Description:
  485. This routine destroys a compilation unit. It's assumed it's already off the
  486. list.
  487. Arguments:
  488. Context - Supplies a pointer to the application context.
  489. Unit - Supplies a pointer to the compilation unit to destroy.
  490. Return Value:
  491. None.
  492. --*/
  493. {
  494. PDWARF_DIE Die;
  495. assert(Unit->ListEntry.Next == NULL);
  496. while (!LIST_EMPTY(&(Unit->DieList))) {
  497. Die = LIST_VALUE(Unit->DieList.Next, DWARF_DIE, ListEntry);
  498. LIST_REMOVE(&(Die->ListEntry));
  499. Die->ListEntry.Next = NULL;
  500. DwarfpDestroyDie(Context, Die);
  501. }
  502. free(Unit);
  503. return;
  504. }
  505. VOID
  506. DwarfpDestroyDie (
  507. PDWARF_CONTEXT Context,
  508. PDWARF_DIE Die
  509. )
  510. /*++
  511. Routine Description:
  512. This routine destroys a Debug Information Entry.
  513. Arguments:
  514. Context - Supplies a pointer to the application context.
  515. Die - Supplies a pointer to the DIE to destroy.
  516. Return Value:
  517. None.
  518. --*/
  519. {
  520. PDWARF_DIE Child;
  521. assert(Die->ListEntry.Next == NULL);
  522. while (!LIST_EMPTY(&(Die->ChildList))) {
  523. Child = LIST_VALUE(Die->ChildList.Next, DWARF_DIE, ListEntry);
  524. LIST_REMOVE(&(Child->ListEntry));
  525. Child->ListEntry.Next = NULL;
  526. DwarfpDestroyDie(Context, Child);
  527. }
  528. free(Die);
  529. return;
  530. }
  531. PSTR
  532. DwarfpGetStringAttribute (
  533. PDWARF_CONTEXT Context,
  534. PDWARF_DIE Die,
  535. DWARF_ATTRIBUTE Attribute
  536. )
  537. /*++
  538. Routine Description:
  539. This routine returns the given attribute with type string.
  540. Arguments:
  541. Context - Supplies a pointer to the DWARF context.
  542. Die - Supplies a pointer to the DIE to get the attribute from.
  543. Attribute - Supplies the attribute to retrieve.
  544. Return Value:
  545. Returns a pointer to the string on success.
  546. NULL if no such attribute exists, or its type is not a string.
  547. --*/
  548. {
  549. PDWARF_ATTRIBUTE_VALUE Value;
  550. Value = DwarfpGetAttribute(Context, Die, Attribute);
  551. if ((Value != NULL) &&
  552. ((Value->Form == DwarfFormString) ||
  553. (Value->Form == DwarfFormStringPointer))) {
  554. return Value->Value.String;
  555. }
  556. return NULL;
  557. }
  558. BOOL
  559. DwarfpGetAddressAttribute (
  560. PDWARF_CONTEXT Context,
  561. PDWARF_DIE Die,
  562. DWARF_ATTRIBUTE Attribute,
  563. PULONGLONG Address
  564. )
  565. /*++
  566. Routine Description:
  567. This routine returns the given attribute, ensuring it is of type address.
  568. Arguments:
  569. Context - Supplies a pointer to the DWARF context.
  570. Die - Supplies a pointer to the DIE to get the attribute from.
  571. Attribute - Supplies the attribute to retrieve.
  572. Address - Supplies a pointer where the address is returned on success.
  573. Return Value:
  574. TRUE if an address was retrieved.
  575. FALSE if no address was retrieved or it was not of type address.
  576. --*/
  577. {
  578. PDWARF_ATTRIBUTE_VALUE Value;
  579. Value = DwarfpGetAttribute(Context, Die, Attribute);
  580. if ((Value != NULL) && (Value->Form == DwarfFormAddress)) {
  581. *Address = Value->Value.Address;
  582. return TRUE;
  583. }
  584. return FALSE;
  585. }
  586. BOOL
  587. DwarfpGetIntegerAttribute (
  588. PDWARF_CONTEXT Context,
  589. PDWARF_DIE Die,
  590. DWARF_ATTRIBUTE Attribute,
  591. PULONGLONG Integer
  592. )
  593. /*++
  594. Routine Description:
  595. This routine returns the given attribute, ensuring it is of type integer
  596. (data or flag).
  597. Arguments:
  598. Context - Supplies a pointer to the DWARF context.
  599. Die - Supplies a pointer to the DIE to get the attribute from.
  600. Attribute - Supplies the attribute to retrieve.
  601. Integer - Supplies a pointer where the integer is returned on success.
  602. Return Value:
  603. TRUE if an address was retrieved.
  604. FALSE if no address was retrieved or it was not of type address.
  605. --*/
  606. {
  607. BOOL Result;
  608. PDWARF_ATTRIBUTE_VALUE Value;
  609. Result = FALSE;
  610. Value = DwarfpGetAttribute(Context, Die, Attribute);
  611. if (Value != NULL) {
  612. Result = TRUE;
  613. switch (Value->Form) {
  614. case DwarfFormData1:
  615. case DwarfFormData2:
  616. case DwarfFormData4:
  617. case DwarfFormData8:
  618. case DwarfFormSData:
  619. case DwarfFormUData:
  620. *Integer = Value->Value.UnsignedConstant;
  621. break;
  622. case DwarfFormFlag:
  623. case DwarfFormFlagPresent:
  624. *Integer = Value->Value.Flag;
  625. break;
  626. default:
  627. Result = FALSE;
  628. break;
  629. }
  630. }
  631. return Result;
  632. }
  633. BOOL
  634. DwarfpGetTypeReferenceAttribute (
  635. PDWARF_CONTEXT Context,
  636. PDWARF_DIE Die,
  637. DWARF_ATTRIBUTE Attribute,
  638. PSOURCE_FILE_SYMBOL *File,
  639. PLONG Identifier
  640. )
  641. /*++
  642. Routine Description:
  643. This routine reads a given attribute and converts that reference into a
  644. symbol type reference tuple.
  645. Arguments:
  646. Context - Supplies a pointer to the parsing context.
  647. Die - Supplies a pointer to the DIE to get the attribute from.
  648. Attribute - Supplies the attribute to retrieve.
  649. File - Supplies a pointer where a pointer to the file will be returned on
  650. success.
  651. Identifier - Supplies a pointer where the type identifier will be returned
  652. on success.
  653. Return Value:
  654. TRUE if a value was retrieved.
  655. FALSE if no value was retrieved or it was not of type reference.
  656. --*/
  657. {
  658. PDWARF_LOADING_CONTEXT LoadingContext;
  659. BOOL Result;
  660. ULONGLONG TypeOffset;
  661. LoadingContext = Context->LoadingContext;
  662. assert(LoadingContext != NULL);
  663. Result = DwarfpGetLocalReferenceAttribute(Context,
  664. Die,
  665. Attribute,
  666. &TypeOffset);
  667. if (Result != FALSE) {
  668. assert(LoadingContext->CurrentFile != NULL);
  669. *File = LoadingContext->CurrentFile;
  670. //
  671. // Make the local reference, which is an offset from the start of the
  672. // compilation unit header, global to the entire debug info section.
  673. //
  674. TypeOffset += (PVOID)(LoadingContext->CurrentUnit->Start) -
  675. Context->Sections.Info.Data;
  676. *Identifier = TypeOffset;
  677. } else {
  678. Result = DwarfpGetGlobalReferenceAttribute(Context,
  679. Die,
  680. DwarfAtType,
  681. &TypeOffset);
  682. if (Result == FALSE) {
  683. //
  684. // Void types don't have a type attribute.
  685. //
  686. *File = NULL;
  687. *Identifier = -1;
  688. return TRUE;
  689. }
  690. //
  691. // Consider supporting this type that is global to the whole .debug_info
  692. // section. The tricky bit is figuring out which source file
  693. // (compilation unit) the offset belongs to.
  694. //
  695. assert(FALSE);
  696. return FALSE;
  697. }
  698. return TRUE;
  699. }
  700. PDWARF_DIE
  701. DwarfpGetDieReferenceAttribute (
  702. PDWARF_CONTEXT Context,
  703. PDWARF_DIE Die,
  704. DWARF_ATTRIBUTE Attribute
  705. )
  706. /*++
  707. Routine Description:
  708. This routine returns a pointer to the DIE referred to by the given
  709. attribute.
  710. Arguments:
  711. Context - Supplies a pointer to the DWARF context.
  712. Die - Supplies a pointer to the DIE to get the attribute from.
  713. Attribute - Supplies the attribute to retrieve.
  714. Return Value:
  715. Returns a pointer to the DIE on success.
  716. NULL on failure.
  717. --*/
  718. {
  719. PDWARF_LOADING_CONTEXT LoadingContext;
  720. ULONGLONG Offset;
  721. BOOL Result;
  722. PDWARF_DIE ResultDie;
  723. ResultDie = NULL;
  724. Result = DwarfpGetLocalReferenceAttribute(Context,
  725. Die,
  726. Attribute,
  727. &Offset);
  728. if (Result != FALSE) {
  729. LoadingContext = Context->LoadingContext;
  730. ResultDie = DwarfpFindDie(LoadingContext->CurrentUnit,
  731. LoadingContext->CurrentUnit->Start + Offset);
  732. }
  733. return ResultDie;
  734. }
  735. BOOL
  736. DwarfpGetLocalReferenceAttribute (
  737. PDWARF_CONTEXT Context,
  738. PDWARF_DIE Die,
  739. DWARF_ATTRIBUTE Attribute,
  740. PULONGLONG Offset
  741. )
  742. /*++
  743. Routine Description:
  744. This routine returns the given attribute, ensuring it is of type reference.
  745. Arguments:
  746. Context - Supplies a pointer to the DWARF context.
  747. Die - Supplies a pointer to the DIE to get the attribute from.
  748. Attribute - Supplies the attribute to retrieve.
  749. Offset - Supplies a pointer where the DIE offset is returned on success.
  750. Return Value:
  751. TRUE if a value was retrieved.
  752. FALSE if no value was retrieved or it was not of type reference.
  753. --*/
  754. {
  755. BOOL Result;
  756. PDWARF_ATTRIBUTE_VALUE Value;
  757. Result = FALSE;
  758. Value = DwarfpGetAttribute(Context, Die, Attribute);
  759. if (Value != NULL) {
  760. Result = TRUE;
  761. switch (Value->Form) {
  762. case DwarfFormRef1:
  763. case DwarfFormRef2:
  764. case DwarfFormRef4:
  765. case DwarfFormRef8:
  766. case DwarfFormRefUData:
  767. case DwarfFormData1:
  768. case DwarfFormData2:
  769. case DwarfFormData4:
  770. case DwarfFormData8:
  771. case DwarfFormUData:
  772. *Offset = Value->Value.Offset;
  773. break;
  774. default:
  775. Result = FALSE;
  776. break;
  777. }
  778. }
  779. return Result;
  780. }
  781. BOOL
  782. DwarfpGetGlobalReferenceAttribute (
  783. PDWARF_CONTEXT Context,
  784. PDWARF_DIE Die,
  785. DWARF_ATTRIBUTE Attribute,
  786. PULONGLONG Offset
  787. )
  788. /*++
  789. Routine Description:
  790. This routine returns the given attribute, ensuring it is of type reference
  791. address.
  792. Arguments:
  793. Context - Supplies a pointer to the DWARF context.
  794. Die - Supplies a pointer to the DIE to get the attribute from.
  795. Attribute - Supplies the attribute to retrieve.
  796. Offset - Supplies a pointer where the DIE offset is returned on success.
  797. Return Value:
  798. TRUE if a value was retrieved.
  799. FALSE if no value was retrieved or it was not of type reference.
  800. --*/
  801. {
  802. PDWARF_ATTRIBUTE_VALUE Value;
  803. Value = DwarfpGetAttribute(Context, Die, Attribute);
  804. if ((Value != NULL) && (Value->Form == DwarfFormRefAddress)) {
  805. *Offset = Value->Value.Offset;
  806. return TRUE;
  807. }
  808. return FALSE;
  809. }
  810. PVOID
  811. DwarfpGetRangeList (
  812. PDWARF_CONTEXT Context,
  813. PDWARF_DIE Die,
  814. DWARF_ATTRIBUTE Attribute
  815. )
  816. /*++
  817. Routine Description:
  818. This routine looks up the given attribute as a range list pointer.
  819. Arguments:
  820. Context - Supplies a pointer to the DWARF context.
  821. Die - Supplies a pointer to the DIE to get the attribute from.
  822. Attribute - Supplies the attribute to retrieve.
  823. Return Value:
  824. Returns a pointer within the .debug_ranges structure on success.
  825. NULL if there was no attribute, the attribute was not of the right type, or
  826. there is no .debug_ranges section.
  827. --*/
  828. {
  829. PDWARF_LOADING_CONTEXT LoadingContext;
  830. PDWARF_ATTRIBUTE_VALUE Value;
  831. LoadingContext = Context->LoadingContext;
  832. Value = DwarfpGetAttribute(Context, Die, Attribute);
  833. if ((Value == NULL) ||
  834. (Value->Value.Offset >= Context->Sections.Ranges.Size)) {
  835. return NULL;
  836. }
  837. if (!DWARF_SECTION_OFFSET_FORM(Value->Form, LoadingContext->CurrentUnit)) {
  838. return NULL;
  839. }
  840. return Context->Sections.Ranges.Data + Value->Value.Offset;
  841. }
  842. PDWARF_ATTRIBUTE_VALUE
  843. DwarfpGetAttribute (
  844. PDWARF_CONTEXT Context,
  845. PDWARF_DIE Die,
  846. DWARF_ATTRIBUTE Attribute
  847. )
  848. /*++
  849. Routine Description:
  850. This routine returns the requested attribute from a DIE. This will follow
  851. a Specification attribute if needed.
  852. Arguments:
  853. Context - Supplies a pointer to the DWARF context.
  854. Die - Supplies a pointer to the DIE to get the attribute from.
  855. Attribute - Supplies the attribute to retrieve.
  856. Return Value:
  857. Returns a pointer to the attribute value on success.
  858. NULL if no such attribute exists.
  859. --*/
  860. {
  861. UINTN Index;
  862. PDWARF_DIE Specification;
  863. for (Index = 0; Index < Die->Count; Index += 1) {
  864. if (Die->Attributes[Index].Name == Attribute) {
  865. return &(Die->Attributes[Index]);
  866. }
  867. }
  868. //
  869. // Avoid infinite recursion.
  870. //
  871. if (Attribute == DwarfAtSpecification) {
  872. return NULL;
  873. }
  874. //
  875. // Try to find a specification attribute. It's currently expensive to find
  876. // one, so the result is cached.
  877. //
  878. Specification = Die->Specification;
  879. if (Specification == NULL) {
  880. //
  881. // See if there's a specification attribute, and go search that DIE if
  882. // so.
  883. //
  884. Specification = DwarfpGetDieReferenceAttribute(Context,
  885. Die,
  886. DwarfAtSpecification);
  887. Die->Specification = Specification;
  888. }
  889. //
  890. // If there's a specification attribute, return all its attributes as if
  891. // they were present here.
  892. //
  893. if (Specification != NULL) {
  894. return DwarfpGetAttribute(Context, Specification, Attribute);
  895. }
  896. return NULL;
  897. }
  898. INT
  899. DwarfpSearchLocationList (
  900. PDWARF_CONTEXT Context,
  901. PDWARF_COMPILATION_UNIT Unit,
  902. UINTN Offset,
  903. ULONGLONG Pc,
  904. PUCHAR *LocationExpression,
  905. PUINTN LocationExpressionSize
  906. )
  907. /*++
  908. Routine Description:
  909. This routine searches a location list and returns the expression that
  910. matches the given PC value.
  911. Arguments:
  912. Context - Supplies a pointer to the DWARF symbol context.
  913. Unit - Supplies a pointer to the current compilation unit.
  914. Offset - Supplies the byte offset into the location list section of the
  915. list to search.
  916. Pc - Supplies the current PC value to match against.
  917. LocationExpression - Supplies a pointer where a pointer to the location
  918. expression that matched will be returned.
  919. LocationExpressionSize - Supplies a pointer where the size of the location
  920. expression will be returned on success.
  921. Return Value:
  922. 0 if an expression matched.
  923. EAGAIN if the locations section is missing.
  924. ENOENT if none of the entries matched the current PC value.
  925. --*/
  926. {
  927. ULONGLONG Base;
  928. PUCHAR Bytes;
  929. ULONGLONG End;
  930. USHORT Length;
  931. ULONGLONG Start;
  932. Base = Unit->LowPc;
  933. if (Context->Sections.Locations.Size == 0) {
  934. DWARF_ERROR("DWARF: Missing .debug_loc section.\n");
  935. return EAGAIN;
  936. }
  937. assert(Context->Sections.Locations.Size > Offset);
  938. Bytes = Context->Sections.Locations.Data + Offset;
  939. while (TRUE) {
  940. if (Unit->AddressSize == 8) {
  941. Start = DwarfpRead8(&Bytes);
  942. End = DwarfpRead8(&Bytes);
  943. //
  944. // If the start is the max address, then it's a base address update.
  945. //
  946. if (Start == MAX_ULONGLONG) {
  947. Base = End;
  948. continue;
  949. }
  950. } else {
  951. assert(Unit->AddressSize == 4);
  952. Start = DwarfpRead4(&Bytes);
  953. End = DwarfpRead4(&Bytes);
  954. if (Start == MAX_ULONG) {
  955. Base = End;
  956. continue;
  957. }
  958. }
  959. //
  960. // If the start and end are both zero, this is a termination entry.
  961. //
  962. if ((Start == 0) && (End == 0)) {
  963. break;
  964. }
  965. Length = DwarfpRead2(&Bytes);
  966. //
  967. // If the PC fits in these bounds, then return the entry contents.
  968. //
  969. if ((Pc >= Start + Base) && (Pc < End + Base)) {
  970. *LocationExpression = Bytes;
  971. *LocationExpressionSize = Length;
  972. return 0;
  973. }
  974. Bytes += Length;
  975. }
  976. return ENOENT;
  977. }
  978. VOID
  979. DwarfpGetRangeSpan (
  980. PDWARF_CONTEXT Context,
  981. PVOID Ranges,
  982. PDWARF_COMPILATION_UNIT Unit,
  983. PULONGLONG Start,
  984. PULONGLONG End
  985. )
  986. /*++
  987. Routine Description:
  988. This routine runs through a range list to figure out the maximum and
  989. minimum values.
  990. Arguments:
  991. Context - Supplies a pointer to the application context.
  992. Ranges - Supplies the range list pointer.
  993. Unit - Supplies the current compilation unit.
  994. Start - Supplies a pointer where the lowest address in the range will be
  995. returned.
  996. End - Supplies a pointer where the first address just beyond the range will
  997. be returned.
  998. Return Value:
  999. None.
  1000. --*/
  1001. {
  1002. ULONGLONG Base;
  1003. PUCHAR Bytes;
  1004. BOOL Is64Bit;
  1005. ULONGLONG Max;
  1006. ULONGLONG Min;
  1007. ULONGLONG RangeEnd;
  1008. ULONGLONG RangeStart;
  1009. Bytes = Ranges;
  1010. Min = MAX_ULONGLONG;
  1011. Max = 0;
  1012. Is64Bit = Unit->Is64Bit;
  1013. Base = Unit->LowPc;
  1014. while (TRUE) {
  1015. RangeStart = DWARF_READN(&Bytes, Is64Bit);
  1016. RangeEnd = DWARF_READN(&Bytes, Is64Bit);
  1017. if ((RangeStart == 0) && (RangeEnd == 0)) {
  1018. break;
  1019. }
  1020. //
  1021. // If the first value is the max address, then the second value is a
  1022. // new base.
  1023. //
  1024. if (((Is64Bit != FALSE) && (RangeStart == MAX_ULONGLONG)) ||
  1025. ((Is64Bit == FALSE) && (RangeStart == MAX_ULONG))) {
  1026. Base = RangeEnd;
  1027. continue;
  1028. }
  1029. if (Min > RangeStart + Base) {
  1030. Min = RangeStart + Base;
  1031. }
  1032. if (Max < RangeEnd + Base) {
  1033. Max = RangeEnd + Base;
  1034. }
  1035. }
  1036. *Start = Min;
  1037. *End = Max;
  1038. return;
  1039. }
  1040. DWARF_LEB128
  1041. DwarfpReadLeb128 (
  1042. PUCHAR *Data
  1043. )
  1044. /*++
  1045. Routine Description:
  1046. This routine reads a DWARF unsigned LEB128 variable length encoded value.
  1047. Arguments:
  1048. Data - Supplies a pointer that on input contains a pointer to the data.
  1049. On output this pointer will be advanced past the value read.
  1050. Return Value:
  1051. Returns the read value.
  1052. --*/
  1053. {
  1054. UCHAR Byte;
  1055. DWARF_LEB128 Result;
  1056. ULONG Shift;
  1057. //
  1058. // LEB128 numbers encode 7 bits in each byte, with the upper bit signifying
  1059. // whether there are more bytes (1) or this is the last byte (0).
  1060. //
  1061. Result = 0;
  1062. Shift = 0;
  1063. while (TRUE) {
  1064. Byte = DwarfpRead1(Data);
  1065. Result |= ((ULONGLONG)(Byte & 0x7F)) << Shift;
  1066. Shift += 7;
  1067. if ((Byte & 0x80) == 0) {
  1068. break;
  1069. }
  1070. }
  1071. //
  1072. // Anything larger than a 64-bit integer would overflow the current
  1073. // data representation. 64 doesn't divide by 7, so move to the next integer
  1074. // that does.
  1075. //
  1076. assert(Shift <= 70);
  1077. return Result;
  1078. }
  1079. DWARF_SLEB128
  1080. DwarfpReadSleb128 (
  1081. PUCHAR *Data
  1082. )
  1083. /*++
  1084. Routine Description:
  1085. This routine reads a DWARF signed LEB128 variable length encoded value.
  1086. Arguments:
  1087. Data - Supplies a pointer that on input contains a pointer to the data.
  1088. On output this pointer will be advanced past the value read.
  1089. Return Value:
  1090. Returns the read value.
  1091. --*/
  1092. {
  1093. UCHAR Byte;
  1094. DWARF_SLEB128 Result;
  1095. ULONG Shift;
  1096. //
  1097. // LEB128 numbers encode 7 bits in each byte, with the upper bit signifying
  1098. // whether there are more bytes (1) or this is the last byte (0).
  1099. //
  1100. Result = 0;
  1101. Shift = 0;
  1102. while (TRUE) {
  1103. Byte = DwarfpRead1(Data);
  1104. Result |= ((ULONGLONG)(Byte & 0x7F)) << Shift;
  1105. Shift += 7;
  1106. if ((Byte & 0x80) == 0) {
  1107. break;
  1108. }
  1109. }
  1110. //
  1111. // If the high order bit of the last byte is set, sign extend to the
  1112. // remainder of the value.
  1113. //
  1114. if ((Shift < (sizeof(DWARF_SLEB128) * BITS_PER_BYTE)) &&
  1115. ((Byte & 0x40) != 0)) {
  1116. Result |= -(1LL << Shift);
  1117. }
  1118. //
  1119. // Anything larger than a 64-bit integer would overflow the current
  1120. // data representation. 64 doesn't divide by 7, so move to the next integer
  1121. // that does.
  1122. //
  1123. assert(Shift <= 70);
  1124. return Result;
  1125. }
  1126. VOID
  1127. DwarfpReadInitialLength (
  1128. PUCHAR *Data,
  1129. PBOOL Is64Bit,
  1130. PULONGLONG Value
  1131. )
  1132. /*++
  1133. Routine Description:
  1134. This routine reads an initial length member from a DWARF header. The
  1135. initial length is either 32-bits for 32-bit sections, or 96-bits for
  1136. 64-bit sections.
  1137. Arguments:
  1138. Data - Supplies a pointer that on input contains a pointer to the header.
  1139. On output this pointer will be advanced past the initial length.
  1140. Is64Bit - Supplies a pointer where a boolean will be returned indicating
  1141. whether or not this is a 64-bit section. Most sections, even in 64-bit
  1142. code, are not.
  1143. Value - Supplies a pointer where the actual initial length value will be
  1144. returned.
  1145. Return Value:
  1146. None.
  1147. --*/
  1148. {
  1149. *Is64Bit = FALSE;
  1150. *Value = DwarfpRead4(Data);
  1151. if (*Value == 0xFFFFFFFF) {
  1152. *Is64Bit = TRUE;
  1153. *Value = DwarfpRead8(Data);
  1154. }
  1155. return;
  1156. }
  1157. UCHAR
  1158. DwarfpRead1 (
  1159. PUCHAR *Data
  1160. )
  1161. /*++
  1162. Routine Description:
  1163. This routine reads a byte from the DWARF data stream and advances the
  1164. stream.
  1165. Arguments:
  1166. Data - Supplies a pointer that on input contains a pointer to the data.
  1167. On output this pointer will be advanced past the value read.
  1168. Return Value:
  1169. Returns the read value.
  1170. --*/
  1171. {
  1172. UCHAR Value;
  1173. Value = *(*Data);
  1174. *Data += sizeof(UCHAR);
  1175. return Value;
  1176. }
  1177. USHORT
  1178. DwarfpRead2 (
  1179. PUCHAR *Data
  1180. )
  1181. /*++
  1182. Routine Description:
  1183. This routine reads two bytes from the DWARF data stream and advances the
  1184. stream.
  1185. Arguments:
  1186. Data - Supplies a pointer that on input contains a pointer to the data.
  1187. On output this pointer will be advanced past the value read.
  1188. Return Value:
  1189. Returns the read value.
  1190. --*/
  1191. {
  1192. USHORT Value;
  1193. Value = *((PUSHORT)*Data);
  1194. *Data += sizeof(USHORT);
  1195. return Value;
  1196. }
  1197. ULONG
  1198. DwarfpRead4 (
  1199. PUCHAR *Data
  1200. )
  1201. /*++
  1202. Routine Description:
  1203. This routine reads four bytes from the DWARF data stream and advances the
  1204. stream.
  1205. Arguments:
  1206. Data - Supplies a pointer that on input contains a pointer to the data.
  1207. On output this pointer will be advanced past the value read.
  1208. Return Value:
  1209. Returns the read value.
  1210. --*/
  1211. {
  1212. ULONG Value;
  1213. Value = *((PULONG)*Data);
  1214. *Data += sizeof(ULONG);
  1215. return Value;
  1216. }
  1217. ULONGLONG
  1218. DwarfpRead8 (
  1219. PUCHAR *Data
  1220. )
  1221. /*++
  1222. Routine Description:
  1223. This routine reads eight bytes from the DWARF data stream and advances the
  1224. stream.
  1225. Arguments:
  1226. Data - Supplies a pointer that on input contains a pointer to the data.
  1227. On output this pointer will be advanced past the value read.
  1228. Return Value:
  1229. Returns the read value.
  1230. --*/
  1231. {
  1232. ULONGLONG Value;
  1233. Value = *((PULONGLONG)*Data);
  1234. *Data += sizeof(ULONGLONG);
  1235. return Value;
  1236. }
  1237. //
  1238. // --------------------------------------------------------- Internal Functions
  1239. //
  1240. INT
  1241. DwarfpIndexAbbreviations (
  1242. PDWARF_CONTEXT Context,
  1243. ULONGLONG Offset,
  1244. PUCHAR **AbbreviationsIndex,
  1245. PUINTN IndexSize,
  1246. PUINTN MaxAttributes
  1247. )
  1248. /*++
  1249. Routine Description:
  1250. This routine creates an array of pointers to abbreviation numbers for
  1251. the abbreviations in a compilation unit. The index makes abbreviation
  1252. lookup instant instead of O(N).
  1253. Arguments:
  1254. Context - Supplies a pointer to tha parsing context.
  1255. Offset - Supplies the offset into the abbreviation section where
  1256. abbreviations for this compilation unit begin.
  1257. AbbreviationsIndex - Supplies a pointer where an array of pointers will be
  1258. returned, indexed by abbreviation number. The caller is responsible
  1259. for freeing this memory.
  1260. IndexSize - Supplies a pointer where the number of elements in the array
  1261. will be returned.
  1262. MaxAttributes - Supplies a pointer where the maximum number of attributes
  1263. in any DIE template found will be returned.
  1264. Return Value:
  1265. 0 on success.
  1266. ENOMEM on failure.
  1267. --*/
  1268. {
  1269. PUCHAR *Array;
  1270. PUCHAR Bytes;
  1271. UINTN Count;
  1272. DWARF_LEB128 Form;
  1273. UCHAR HasChildren;
  1274. UINTN MaxIndex;
  1275. DWARF_LEB128 Name;
  1276. PVOID NewArray;
  1277. UINTN NewSize;
  1278. DWARF_LEB128 Number;
  1279. UINTN Size;
  1280. DWARF_LEB128 Tag;
  1281. *MaxAttributes = 0;
  1282. Bytes = Context->Sections.Abbreviations.Data + Offset;
  1283. if (Offset >= Context->Sections.Abbreviations.Size) {
  1284. return ERANGE;
  1285. }
  1286. MaxIndex = 0;
  1287. Size = 64;
  1288. Array = malloc(Size * sizeof(PVOID));
  1289. if (Array == NULL) {
  1290. return ENOMEM;
  1291. }
  1292. memset(Array, 0, Size * sizeof(PVOID));
  1293. if ((Context->Flags & DWARF_CONTEXT_DEBUG_ABBREVIATIONS) != 0) {
  1294. DWARF_PRINT("Abbreviations at offset %I64x:\n", Offset);
  1295. }
  1296. //
  1297. // Loop processing abbreviations.
  1298. //
  1299. while (TRUE) {
  1300. Number = DwarfpReadLeb128(&Bytes);
  1301. if (Number == 0) {
  1302. break;
  1303. }
  1304. //
  1305. // Reallocate the array if needed.
  1306. //
  1307. if (Number >= Size) {
  1308. NewSize = Size * 2;
  1309. while (NewSize <= Number) {
  1310. NewSize *= 2;
  1311. }
  1312. NewArray = realloc(Array, NewSize * sizeof(PVOID));
  1313. if (NewArray == NULL) {
  1314. free(Array);
  1315. return ENOMEM;
  1316. }
  1317. memset(NewArray + (Size * sizeof(PVOID)),
  1318. 0,
  1319. (NewSize - Size) * sizeof(PVOID));
  1320. Size = NewSize;
  1321. Array = NewArray;
  1322. }
  1323. //
  1324. // Abbreviations should not collide.
  1325. //
  1326. assert(Array[Number] == NULL);
  1327. Array[Number] = Bytes;
  1328. if (Number > MaxIndex) {
  1329. MaxIndex = Number;
  1330. }
  1331. //
  1332. // Get past the tag and the children byte.
  1333. //
  1334. Tag = DwarfpReadLeb128(&Bytes);
  1335. HasChildren = DwarfpRead1(&Bytes);
  1336. if ((Context->Flags & DWARF_CONTEXT_DEBUG_ABBREVIATIONS) != 0) {
  1337. DWARF_PRINT(" %I64d: %s %s\n",
  1338. Number,
  1339. DwarfpGetTagName(Tag),
  1340. DwarfpGetHasChildrenName(HasChildren));
  1341. }
  1342. //
  1343. // Now get past the attributes specifications.
  1344. //
  1345. Count = 0;
  1346. while (TRUE) {
  1347. Name = DwarfpReadLeb128(&Bytes);
  1348. Form = DwarfpReadLeb128(&Bytes);
  1349. if ((Name == 0) && (Form == 0)) {
  1350. break;
  1351. }
  1352. if ((Context->Flags & DWARF_CONTEXT_DEBUG_ABBREVIATIONS) != 0) {
  1353. DWARF_PRINT(" %s %s\n",
  1354. DwarfpGetAttributeName(Name),
  1355. DwarfpGetFormName(Form));
  1356. }
  1357. Count += 1;
  1358. }
  1359. if (Count > *MaxAttributes) {
  1360. *MaxAttributes = Count;
  1361. }
  1362. }
  1363. *AbbreviationsIndex = Array;
  1364. *IndexSize = MaxIndex + 1;
  1365. return 0;
  1366. }
  1367. INT
  1368. DwarfpReadDie (
  1369. PDWARF_CONTEXT Context,
  1370. PDWARF_COMPILATION_UNIT Unit,
  1371. PUCHAR *Data,
  1372. PUCHAR Abbreviation,
  1373. PDWARF_DIE Die
  1374. )
  1375. /*++
  1376. Routine Description:
  1377. This routine reads a single Debug Information Unit using the abbreviation
  1378. template.
  1379. Arguments:
  1380. Context - Supplies a pointer to the application context.
  1381. Unit - Supplies a pointer to the compilation unit.
  1382. Data - Supplies a pointer that on input contains a pointer to the values.
  1383. On output this pointer will be advanced past the contents.
  1384. Abbreviation - Supplies a pointer to the abbreviation, which marks out the
  1385. form of the data.
  1386. Die - Supplies a pointer where the DIE is returned on success.
  1387. Return Value:
  1388. 0 on success.
  1389. Returns an error number on failure.
  1390. --*/
  1391. {
  1392. PDWARF_ATTRIBUTE_VALUE Attribute;
  1393. DWARF_FORM Form;
  1394. DWARF_CHILDREN_VALUE HasChildren;
  1395. DWARF_ATTRIBUTE Name;
  1396. INT Status;
  1397. DWARF_LEB128 Tag;
  1398. //
  1399. // Get past the tag and the children byte.
  1400. //
  1401. Tag = DwarfpReadLeb128(&Abbreviation);
  1402. Die->Tag = Tag;
  1403. HasChildren = DwarfpRead1(&Abbreviation);
  1404. if ((Context->Flags & DWARF_CONTEXT_DEBUG) != 0) {
  1405. DWARF_PRINT(" <%x><%x> %s %s Abbrev. %I64d\n",
  1406. Die->Depth,
  1407. (PVOID)(Die->Start) - Context->Sections.Info.Data,
  1408. DwarfpGetTagName(Tag),
  1409. DwarfpGetHasChildrenName(HasChildren),
  1410. Die->AbbreviationNumber);
  1411. }
  1412. if (HasChildren == DwarfChildrenYes) {
  1413. Die->Flags |= DWARF_DIE_HAS_CHILDREN;
  1414. }
  1415. Attribute = &(Die->Attributes[Die->Count]);
  1416. //
  1417. // Read in each attribute value.
  1418. //
  1419. while (TRUE) {
  1420. Name = DwarfpReadLeb128(&Abbreviation);
  1421. Form = DwarfpReadLeb128(&Abbreviation);
  1422. if ((Name == 0) && (Form == 0)) {
  1423. break;
  1424. }
  1425. assert(Die->Count < Die->Capacity);
  1426. Attribute->Name = Name;
  1427. Attribute->Form = Form;
  1428. if ((Context->Flags & DWARF_CONTEXT_DEBUG) != 0) {
  1429. DWARF_PRINT(" <%x> %s : ",
  1430. *Data - (PUCHAR)(Context->Sections.Info.Data),
  1431. DwarfpGetAttributeName(Name));
  1432. }
  1433. Status = DwarfpReadFormValue(Context, Unit, Data, Attribute);
  1434. if (Status != 0) {
  1435. DWARF_ERROR("DWARF: Failed to read attribute.\n");
  1436. continue;
  1437. }
  1438. if ((Context->Flags & DWARF_CONTEXT_DEBUG) != 0) {
  1439. DwarfpPrintFormValue(Attribute);
  1440. //
  1441. // Print the expression if it's an expression or it's a block and
  1442. // has a known name.
  1443. //
  1444. if ((Attribute->Form == DwarfFormExprLoc) ||
  1445. ((DWARF_BLOCK_FORM(Attribute->Form)) &&
  1446. ((Attribute->Name == DwarfAtDataLocation) ||
  1447. (Attribute->Name == DwarfAtDataMemberLocation)))) {
  1448. DWARF_PRINT(" (");
  1449. DwarfpPrintExpression(Context,
  1450. Unit->AddressSize,
  1451. Unit,
  1452. Attribute->Value.Block.Data,
  1453. Attribute->Value.Block.Size);
  1454. DWARF_PRINT(")");
  1455. }
  1456. DWARF_PRINT("\n");
  1457. }
  1458. Die->Count += 1;
  1459. Attribute += 1;
  1460. }
  1461. return 0;
  1462. }
  1463. INT
  1464. DwarfpReadFormValue (
  1465. PDWARF_CONTEXT Context,
  1466. PDWARF_COMPILATION_UNIT Unit,
  1467. PUCHAR *Data,
  1468. PDWARF_ATTRIBUTE_VALUE Attribute
  1469. )
  1470. /*++
  1471. Routine Description:
  1472. This routine reads a DWARF attribute based on its form.
  1473. Arguments:
  1474. Context - Supplies a pointer to the application context.
  1475. Unit - Supplies a pointer to the compilation unit.
  1476. Data - Supplies a pointer that on input contains a pointer to the values.
  1477. On output this pointer will be advanced past the contents.
  1478. Attribute - Supplies a pointer to the attribute to read the value for. The
  1479. form is expected to have already been filled in.
  1480. Return Value:
  1481. 0 on success.
  1482. Returns an error number on failure.
  1483. --*/
  1484. {
  1485. INT Status;
  1486. PDWARF_FORM_VALUE Value;
  1487. Status = 0;
  1488. Value = &(Attribute->Value);
  1489. switch (Attribute->Form) {
  1490. case DwarfFormAddress:
  1491. if (Unit->AddressSize == 8) {
  1492. Value->Address = DwarfpRead8(Data);
  1493. } else {
  1494. assert(Unit->AddressSize == 4);
  1495. Value->Address = DwarfpRead4(Data);
  1496. }
  1497. break;
  1498. //
  1499. // This form is just a generic block of bytes, but its size can be defined
  1500. // in a number of different ways.
  1501. //
  1502. case DwarfFormBlock1:
  1503. case DwarfFormBlock2:
  1504. case DwarfFormBlock4:
  1505. case DwarfFormBlock:
  1506. switch (Attribute->Form) {
  1507. case DwarfFormBlock1:
  1508. Value->Block.Size = DwarfpRead1(Data);
  1509. break;
  1510. case DwarfFormBlock2:
  1511. Value->Block.Size = DwarfpRead2(Data);
  1512. break;
  1513. case DwarfFormBlock4:
  1514. Value->Block.Size = DwarfpRead4(Data);
  1515. break;
  1516. case DwarfFormBlock:
  1517. Value->Block.Size = DwarfpReadLeb128(Data);
  1518. break;
  1519. default:
  1520. assert(FALSE);
  1521. break;
  1522. }
  1523. Value->Block.Data = *Data;
  1524. *Data += Value->Block.Size;
  1525. break;
  1526. //
  1527. // Then there are the constants.
  1528. //
  1529. case DwarfFormData1:
  1530. Value->UnsignedConstant = DwarfpRead1(Data);
  1531. break;
  1532. case DwarfFormData2:
  1533. Value->UnsignedConstant = DwarfpRead2(Data);
  1534. break;
  1535. case DwarfFormData4:
  1536. Value->UnsignedConstant = DwarfpRead4(Data);
  1537. break;
  1538. case DwarfFormData8:
  1539. case DwarfFormRefSig8:
  1540. Value->UnsignedConstant = DwarfpRead8(Data);
  1541. break;
  1542. case DwarfFormSData:
  1543. Value->SignedConstant = DwarfpReadSleb128(Data);
  1544. break;
  1545. case DwarfFormUData:
  1546. Value->UnsignedConstant = DwarfpReadLeb128(Data);
  1547. break;
  1548. //
  1549. // The expression location form uses the same members as the block. It
  1550. // represents a DWARF expression.
  1551. //
  1552. case DwarfFormExprLoc:
  1553. Value->Block.Size = DwarfpReadLeb128(Data);
  1554. Value->Block.Data = *Data;
  1555. *Data += Value->Block.Size;
  1556. break;
  1557. //
  1558. // Handle the flag forms.
  1559. //
  1560. case DwarfFormFlag:
  1561. Value->Flag = DwarfpRead1(Data);
  1562. break;
  1563. case DwarfFormFlagPresent:
  1564. Value->Flag = TRUE;
  1565. break;
  1566. //
  1567. // The pointers to other sections all look the same from a data perspective.
  1568. //
  1569. case DwarfFormSecOffset:
  1570. case DwarfFormRefAddress:
  1571. Value->Offset = DWARF_READN(Data, Unit->Is64Bit);
  1572. break;
  1573. //
  1574. // Handle references to other DIEs within this compilation unit.
  1575. //
  1576. case DwarfFormRef1:
  1577. Value->Offset = DwarfpRead1(Data);
  1578. break;
  1579. case DwarfFormRef2:
  1580. Value->Offset = DwarfpRead2(Data);
  1581. break;
  1582. case DwarfFormRef4:
  1583. Value->Offset = DwarfpRead4(Data);
  1584. break;
  1585. case DwarfFormRef8:
  1586. Value->Offset = DwarfpReadLeb128(Data);
  1587. break;
  1588. case DwarfFormRefUData:
  1589. Value->Offset = DwarfpReadLeb128(Data);
  1590. break;
  1591. case DwarfFormString:
  1592. Value->String = (PSTR)*Data;
  1593. *Data += strlen((PSTR)*Data) + 1;
  1594. break;
  1595. case DwarfFormStringPointer:
  1596. Value->Offset = DWARF_READN(Data, Unit->Is64Bit);
  1597. assert(Value->Offset < Context->Sections.Strings.Size);
  1598. Value->String = Context->Sections.Strings.Data + Value->Offset;
  1599. break;
  1600. default:
  1601. DWARF_ERROR("DWARF: Unknown form %d.\n", Attribute->Form);
  1602. Status = EINVAL;
  1603. break;
  1604. }
  1605. return Status;
  1606. }
  1607. VOID
  1608. DwarfpPrintFormValue (
  1609. PDWARF_ATTRIBUTE_VALUE Attribute
  1610. )
  1611. /*++
  1612. Routine Description:
  1613. This routine prints a form value.
  1614. Arguments:
  1615. Attribute - Supplies a pointer to the attribute, whose form and value
  1616. should already be filled in.
  1617. Return Value:
  1618. None.
  1619. --*/
  1620. {
  1621. PUCHAR Bytes;
  1622. UINTN Index;
  1623. PDWARF_FORM_VALUE Value;
  1624. Value = &(Attribute->Value);
  1625. switch (Attribute->Form) {
  1626. case DwarfFormAddress:
  1627. DWARF_PRINT("%I64x", Value->Address);
  1628. break;
  1629. //
  1630. // This form is just a generic block of bytes, but its size can be defined
  1631. // in a number of different ways.
  1632. //
  1633. case DwarfFormBlock1:
  1634. case DwarfFormBlock2:
  1635. case DwarfFormBlock4:
  1636. case DwarfFormBlock:
  1637. DWARF_PRINT("%I64u byte block: ", Value->Block.Size);
  1638. Bytes = Value->Block.Data;
  1639. for (Index = 0; Index < Value->Block.Size; Index += 1) {
  1640. DWARF_PRINT("%02x ", Bytes[Index]);
  1641. }
  1642. break;
  1643. //
  1644. // Then there are the constants.
  1645. //
  1646. case DwarfFormData1:
  1647. case DwarfFormData2:
  1648. case DwarfFormData4:
  1649. case DwarfFormData8:
  1650. case DwarfFormUData:
  1651. DWARF_PRINT("%I64u", Value->UnsignedConstant);
  1652. break;
  1653. case DwarfFormRefSig8:
  1654. DWARF_PRINT("TypeSig %I64x", Value->TypeSignature);
  1655. break;
  1656. case DwarfFormSData:
  1657. DWARF_PRINT("%+I64d", Value->SignedConstant);
  1658. break;
  1659. //
  1660. // The expression location form uses the same members as the block. It
  1661. // represents a DWARF expression.
  1662. //
  1663. case DwarfFormExprLoc:
  1664. DWARF_PRINT("%I64u byte expression: ", Value->Block.Size);
  1665. Bytes = Value->Block.Data;
  1666. for (Index = 0; Index < Value->Block.Size; Index += 1) {
  1667. DWARF_PRINT("%02x ", Bytes[Index]);
  1668. }
  1669. break;
  1670. //
  1671. // Handle the flag forms.
  1672. //
  1673. case DwarfFormFlag:
  1674. case DwarfFormFlagPresent:
  1675. DWARF_PRINT("%d", Value->Flag);
  1676. break;
  1677. //
  1678. // The pointers to other sections all look the same from a data perspective.
  1679. //
  1680. case DwarfFormSecOffset:
  1681. DWARF_PRINT("SectionOffset %I64x", Value->Offset);
  1682. break;
  1683. case DwarfFormRefAddress:
  1684. DWARF_PRINT("RefAddress %I64x", Value->Offset);
  1685. break;
  1686. case DwarfFormRef1:
  1687. case DwarfFormRef2:
  1688. case DwarfFormRef4:
  1689. case DwarfFormRef8:
  1690. case DwarfFormRefUData:
  1691. DWARF_PRINT("<%I64x>", Value->Offset);
  1692. break;
  1693. case DwarfFormString:
  1694. case DwarfFormStringPointer:
  1695. DWARF_PRINT("\"%s\"", Value->String);
  1696. break;
  1697. default:
  1698. DWARF_ERROR("DWARF: Unknown form %d.\n", Attribute->Form);
  1699. break;
  1700. }
  1701. return;
  1702. }
  1703. PSTR
  1704. DwarfpGetTagName (
  1705. DWARF_TAG Tag
  1706. )
  1707. /*++
  1708. Routine Description:
  1709. This routine returns the string description of a given dwarf tag.
  1710. Arguments:
  1711. Tag - Supplies the tag to convert.
  1712. Return Value:
  1713. Returns the tag name string.
  1714. --*/
  1715. {
  1716. PSTR Name;
  1717. Name = NULL;
  1718. if (Tag <= DwarfTagTemplateAlias) {
  1719. Name = DwarfTagNames[Tag];
  1720. } else if ((Tag >= DwarfTagLowUser) && (Tag <= DwarfTagHighUser)) {
  1721. Name = "DwarfTagUser";
  1722. }
  1723. if (Name == NULL) {
  1724. Name = "DwarfTagUNKNOWN";
  1725. }
  1726. return Name;
  1727. }
  1728. PSTR
  1729. DwarfpGetAttributeName (
  1730. DWARF_ATTRIBUTE Attribute
  1731. )
  1732. /*++
  1733. Routine Description:
  1734. This routine returns the string description of a given dwarf attribute.
  1735. Arguments:
  1736. Attribute - Supplies the attribute to convert.
  1737. Return Value:
  1738. Returns the attribute name string.
  1739. --*/
  1740. {
  1741. PSTR Name;
  1742. Name = NULL;
  1743. if (Attribute <= DwarfAtLinkageName) {
  1744. Name = DwarfAttributeNames[Attribute];
  1745. } else if ((Attribute >= DwarfAtLowUser) &&
  1746. (Attribute <= DwarfAtHighUser)) {
  1747. Name = "DwarfAtUser";
  1748. }
  1749. if (Name == NULL) {
  1750. Name = "DwarfAtUNKNOWN";
  1751. }
  1752. return Name;
  1753. }
  1754. PSTR
  1755. DwarfpGetFormName (
  1756. DWARF_FORM Form
  1757. )
  1758. /*++
  1759. Routine Description:
  1760. This routine returns the string description of a given dwarf form.
  1761. Arguments:
  1762. Form - Supplies the form to convert.
  1763. Return Value:
  1764. Returns the form name string.
  1765. --*/
  1766. {
  1767. PSTR Name;
  1768. Name = NULL;
  1769. if (Form <= DwarfFormRefSig8) {
  1770. Name = DwarfFormNames[Form];
  1771. }
  1772. if (Name == NULL) {
  1773. Name = "DwarfFormUNKNOWN";
  1774. }
  1775. return Name;
  1776. }
  1777. PSTR
  1778. DwarfpGetHasChildrenName (
  1779. DWARF_CHILDREN_VALUE Value
  1780. )
  1781. /*++
  1782. Routine Description:
  1783. This routine returns the string description of a given dwarf form.
  1784. Arguments:
  1785. Value - Supplies the value to convert.
  1786. Return Value:
  1787. Returns the has children name string.
  1788. --*/
  1789. {
  1790. if (Value <= DwarfChildrenYes) {
  1791. return DwarfHasChildrenNames[Value];
  1792. }
  1793. return "DwarfChildrenINVALID";
  1794. }
  1795. PDWARF_DIE
  1796. DwarfpFindDie (
  1797. PDWARF_COMPILATION_UNIT Unit,
  1798. PUCHAR DieStart
  1799. )
  1800. /*++
  1801. Routine Description:
  1802. This routine finds a pointer to the DIE that starts at the given offset.
  1803. Arguments:
  1804. Unit - Supplies a pointer to the compilation unit to search through.
  1805. DieStart - Supplies the start of raw DIE.
  1806. Return Value:
  1807. Returns a pointer to the read DIE on success.
  1808. NULL on failure.
  1809. --*/
  1810. {
  1811. PLIST_ENTRY CurrentEntry;
  1812. PDWARF_DIE Die;
  1813. PLIST_ENTRY ListHead;
  1814. if ((DieStart < Unit->Dies) || (DieStart >= Unit->DiesEnd)) {
  1815. return NULL;
  1816. }
  1817. //
  1818. // Search backwards through the list. The tree is sorted by offset, so the
  1819. // DIE is going to be in the first element of each list whose start is not
  1820. // greater than the pointer. This search is linear in the worst case where
  1821. // the tree is one long chain of elements, and log(n) in the best case
  1822. // where the tree is nicely balanced with evenly thick branches.
  1823. //
  1824. ListHead = &(Unit->DieList);
  1825. while (!LIST_EMPTY(ListHead)) {
  1826. //
  1827. // Find the element with the largest start that is less than or equal
  1828. // to the DIE being searched for.
  1829. //
  1830. CurrentEntry = ListHead->Previous;
  1831. while (CurrentEntry != ListHead) {
  1832. Die = LIST_VALUE(CurrentEntry, DWARF_DIE, ListEntry);
  1833. if (Die->Start <= DieStart) {
  1834. //
  1835. // Return if this is the DIE being searched for.
  1836. //
  1837. if (Die->Start == DieStart) {
  1838. return Die;
  1839. }
  1840. break;
  1841. }
  1842. CurrentEntry = CurrentEntry->Previous;
  1843. }
  1844. //
  1845. // In the unexpected case where all DIEs are greater than the one
  1846. // being searched for (which shouldn't happen), bail.
  1847. //
  1848. if (CurrentEntry == ListHead) {
  1849. assert(FALSE);
  1850. break;
  1851. }
  1852. //
  1853. // Now search in all the children of this DIE.
  1854. //
  1855. ListHead = &(Die->ChildList);
  1856. }
  1857. return NULL;
  1858. }