dwarf.c 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393
  1. /*++
  2. Copyright (c) 2015 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. dwarf.c
  5. Abstract:
  6. This module implements support for parsing DWARF symbols, versions 2+.
  7. Author:
  8. Evan Green 2-Dec-2015
  9. Environment:
  10. Debug
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include <minoca/lib/types.h>
  16. #include <minoca/lib/status.h>
  17. #include <minoca/lib/im.h>
  18. #include "dwarfp.h"
  19. #include <assert.h>
  20. #include <errno.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <sys/stat.h>
  25. //
  26. // --------------------------------------------------------------------- Macros
  27. //
  28. //
  29. // ---------------------------------------------------------------- Definitions
  30. //
  31. //
  32. // ------------------------------------------------------ Data Type Definitions
  33. //
  34. //
  35. // ----------------------------------------------- Internal Function Prototypes
  36. //
  37. VOID
  38. DwarfUnloadSymbols (
  39. PDEBUG_SYMBOLS Symbols
  40. );
  41. INT
  42. DwarfReadDataSymbol (
  43. PDEBUG_SYMBOLS Symbols,
  44. PDATA_SYMBOL Symbol,
  45. ULONGLONG DebasedPc,
  46. PVOID Data,
  47. ULONG DataSize,
  48. PSTR Location,
  49. ULONG LocationSize
  50. );
  51. INT
  52. DwarfGetAddressOfDataSymbol (
  53. PDEBUG_SYMBOLS Symbols,
  54. PDATA_SYMBOL Symbol,
  55. ULONGLONG DebasedPc,
  56. PULONGLONG Address
  57. );
  58. INT
  59. DwarfpProcessDebugInfo (
  60. PDWARF_CONTEXT Context
  61. );
  62. INT
  63. DwarfpProcessCompilationUnit (
  64. PDWARF_CONTEXT Context,
  65. PDWARF_COMPILATION_UNIT Unit
  66. );
  67. INT
  68. DwarfpProcessDie (
  69. PDWARF_CONTEXT Context,
  70. PDWARF_DIE Die
  71. );
  72. INT
  73. DwarfpProcessCompileUnit (
  74. PDWARF_CONTEXT Context,
  75. PDWARF_DIE Die
  76. );
  77. INT
  78. DwarfpProcessBaseType (
  79. PDWARF_CONTEXT Context,
  80. PDWARF_DIE Die
  81. );
  82. INT
  83. DwarfpProcessTypeRelation (
  84. PDWARF_CONTEXT Context,
  85. PDWARF_DIE Die
  86. );
  87. INT
  88. DwarfpProcessSubrangeType (
  89. PDWARF_CONTEXT Context,
  90. PDWARF_DIE Die
  91. );
  92. INT
  93. DwarfpProcessStructureUnionEnumerationType (
  94. PDWARF_CONTEXT Context,
  95. PDWARF_DIE Die
  96. );
  97. INT
  98. DwarfpProcessMember (
  99. PDWARF_CONTEXT Context,
  100. PDWARF_DIE Die
  101. );
  102. INT
  103. DwarfpProcessEnumerator (
  104. PDWARF_CONTEXT Context,
  105. PDWARF_DIE Die
  106. );
  107. INT
  108. DwarfpProcessSubroutineType (
  109. PDWARF_CONTEXT Context,
  110. PDWARF_DIE Die
  111. );
  112. INT
  113. DwarfpProcessSubprogram (
  114. PDWARF_CONTEXT Context,
  115. PDWARF_DIE Die
  116. );
  117. INT
  118. DwarfpProcessVariable (
  119. PDWARF_CONTEXT Context,
  120. PDWARF_DIE Die
  121. );
  122. INT
  123. DwarfpProcessGenericBlock (
  124. PDWARF_CONTEXT Context,
  125. PDWARF_DIE Die
  126. );
  127. //
  128. // -------------------------------------------------------------------- Globals
  129. //
  130. DEBUG_SYMBOL_INTERFACE DwarfSymbolInterface = {
  131. DwarfLoadSymbols,
  132. DwarfUnloadSymbols,
  133. DwarfStackUnwind,
  134. DwarfReadDataSymbol,
  135. DwarfGetAddressOfDataSymbol
  136. };
  137. //
  138. // ------------------------------------------------------------------ Functions
  139. //
  140. INT
  141. DwarfLoadSymbols (
  142. PSTR Filename,
  143. IMAGE_MACHINE_TYPE MachineType,
  144. ULONG Flags,
  145. PVOID HostContext,
  146. PDEBUG_SYMBOLS *Symbols
  147. )
  148. /*++
  149. Routine Description:
  150. This routine loads DWARF symbols for the given file.
  151. Arguments:
  152. Filename - Supplies the name of the binary to load symbols from.
  153. MachineType - Supplies the required machine type of the image. Set to
  154. unknown to allow the symbol library to load a file with any machine
  155. type.
  156. Flags - Supplies a bitfield of flags governing the behavior during load.
  157. These flags are specific to each symbol library.
  158. HostContext - Supplies the value to store in the host context field of the
  159. debug symbols.
  160. Symbols - Supplies an optional pointer where a pointer to the symbols will
  161. be returned on success.
  162. Return Value:
  163. 0 on success.
  164. Returns an error number on failure.
  165. --*/
  166. {
  167. UINTN AllocationSize;
  168. PDWARF_CONTEXT Context;
  169. PDEBUG_SYMBOLS DwarfSymbols;
  170. FILE *File;
  171. IMAGE_BUFFER ImageBuffer;
  172. IMAGE_INFORMATION ImageInformation;
  173. KSTATUS KStatus;
  174. size_t Read;
  175. PDWARF_DEBUG_SECTIONS Sections;
  176. struct stat Stat;
  177. INT Status;
  178. DwarfSymbols = NULL;
  179. Status = stat(Filename, &Stat);
  180. if (Status != 0) {
  181. Status = errno;
  182. return Status;
  183. }
  184. //
  185. // Allocate and initialize the top level data structures.
  186. //
  187. AllocationSize = sizeof(DEBUG_SYMBOLS) + sizeof(DWARF_CONTEXT);
  188. DwarfSymbols = malloc(AllocationSize);
  189. if (DwarfSymbols == NULL) {
  190. Status = ENOMEM;
  191. goto LoadSymbolsEnd;
  192. }
  193. memset(DwarfSymbols, 0, AllocationSize);
  194. INITIALIZE_LIST_HEAD(&(DwarfSymbols->SourcesHead));
  195. DwarfSymbols->Filename = strdup(Filename);
  196. DwarfSymbols->SymbolContext = DwarfSymbols + 1;
  197. DwarfSymbols->Interface = &DwarfSymbolInterface;
  198. DwarfSymbols->HostContext = HostContext;
  199. Context = DwarfSymbols->SymbolContext;
  200. Context->SourcesHead = &(DwarfSymbols->SourcesHead);
  201. Context->Flags = Flags;
  202. INITIALIZE_LIST_HEAD(&(Context->UnitList));
  203. Context->FileData = malloc(Stat.st_size);
  204. if (Context->FileData == NULL) {
  205. Status = errno;
  206. goto LoadSymbolsEnd;
  207. }
  208. Context->FileSize = Stat.st_size;
  209. //
  210. // Read in the file.
  211. //
  212. File = fopen(Filename, "rb");
  213. if (File == NULL) {
  214. Status = errno;
  215. goto LoadSymbolsEnd;
  216. }
  217. Read = fread(Context->FileData, 1, Stat.st_size, File);
  218. fclose(File);
  219. if (Read != Stat.st_size) {
  220. DWARF_ERROR("Read only %d of %d bytes.\n", Read, Stat.st_size);
  221. Status = errno;
  222. goto LoadSymbolsEnd;
  223. }
  224. //
  225. // Fill in the image information, and check against the desired machine
  226. // type if set before going to all the trouble of fully loading symbols.
  227. //
  228. ImageBuffer.Context = NULL;
  229. ImageBuffer.Data = Context->FileData;
  230. ImageBuffer.Size = Context->FileSize;
  231. KStatus = ImGetImageInformation(&ImageBuffer, &ImageInformation);
  232. if (!KSUCCESS(KStatus)) {
  233. Status = ENOEXEC;
  234. goto LoadSymbolsEnd;
  235. }
  236. DwarfSymbols->ImageBase = ImageInformation.ImageBase;
  237. DwarfSymbols->Machine = ImageInformation.Machine;
  238. DwarfSymbols->ImageFormat = ImageInformation.Format;
  239. if ((MachineType != ImageMachineTypeUnknown) &&
  240. (MachineType != DwarfSymbols->Machine)) {
  241. DWARF_ERROR("DWARF: File %s has machine type %d, expecting %d.\n",
  242. Filename,
  243. DwarfSymbols->Machine,
  244. MachineType);
  245. Status = ENOEXEC;
  246. goto LoadSymbolsEnd;
  247. }
  248. //
  249. // Find the important DWARF sections.
  250. //
  251. Sections = &(Context->Sections);
  252. ImGetImageSection(&ImageBuffer,
  253. ".debug_info",
  254. &(Sections->Info.Data),
  255. NULL,
  256. &(Sections->Info.Size),
  257. NULL);
  258. ImGetImageSection(&ImageBuffer,
  259. ".debug_abbrev",
  260. &(Sections->Abbreviations.Data),
  261. NULL,
  262. &(Sections->Abbreviations.Size),
  263. NULL);
  264. ImGetImageSection(&ImageBuffer,
  265. ".debug_str",
  266. &(Sections->Strings.Data),
  267. NULL,
  268. &(Sections->Strings.Size),
  269. NULL);
  270. ImGetImageSection(&ImageBuffer,
  271. ".debug_loc",
  272. &(Sections->Locations.Data),
  273. NULL,
  274. &(Sections->Locations.Size),
  275. NULL);
  276. ImGetImageSection(&ImageBuffer,
  277. ".debug_aranges",
  278. &(Sections->Aranges.Data),
  279. NULL,
  280. &(Sections->Aranges.Size),
  281. NULL);
  282. ImGetImageSection(&ImageBuffer,
  283. ".debug_ranges",
  284. &(Sections->Ranges.Data),
  285. NULL,
  286. &(Sections->Ranges.Size),
  287. NULL);
  288. ImGetImageSection(&ImageBuffer,
  289. ".debug_macinfo",
  290. &(Sections->Macros.Data),
  291. NULL,
  292. &(Sections->Macros.Size),
  293. NULL);
  294. ImGetImageSection(&ImageBuffer,
  295. ".debug_line",
  296. &(Sections->Lines.Data),
  297. NULL,
  298. &(Sections->Lines.Size),
  299. NULL);
  300. ImGetImageSection(&ImageBuffer,
  301. ".debug_pubnames",
  302. &(Sections->PubNames.Data),
  303. NULL,
  304. &(Sections->PubNames.Size),
  305. NULL);
  306. ImGetImageSection(&ImageBuffer,
  307. ".debug_pubtypes",
  308. &(Sections->PubTypes.Data),
  309. NULL,
  310. &(Sections->PubTypes.Size),
  311. NULL);
  312. ImGetImageSection(&ImageBuffer,
  313. ".debug_types",
  314. &(Sections->Types.Data),
  315. NULL,
  316. &(Sections->Types.Size),
  317. NULL);
  318. ImGetImageSection(&ImageBuffer,
  319. ".debug_frame",
  320. &(Sections->Frame.Data),
  321. NULL,
  322. &(Sections->Frame.Size),
  323. NULL);
  324. ImGetImageSection(&ImageBuffer,
  325. ".eh_frame",
  326. &(Sections->EhFrame.Data),
  327. &(Sections->EhFrameAddress),
  328. &(Sections->EhFrame.Size),
  329. NULL);
  330. if ((Sections->Info.Data == NULL) ||
  331. (Sections->Abbreviations.Data == NULL)) {
  332. Status = EINVAL;
  333. goto LoadSymbolsEnd;
  334. }
  335. //
  336. // Parse the .debug_info section, which contains most of the good bits.
  337. //
  338. Status = DwarfpProcessDebugInfo(Context);
  339. if (Status != 0) {
  340. goto LoadSymbolsEnd;
  341. }
  342. Status = 0;
  343. LoadSymbolsEnd:
  344. if (Status != 0) {
  345. if (DwarfSymbols != NULL) {
  346. DwarfUnloadSymbols(DwarfSymbols);
  347. DwarfSymbols = NULL;
  348. }
  349. }
  350. *Symbols = DwarfSymbols;
  351. return Status;
  352. }
  353. VOID
  354. DwarfUnloadSymbols (
  355. PDEBUG_SYMBOLS Symbols
  356. )
  357. /*++
  358. Routine Description:
  359. This routine frees all memory associated with an instance of debugging
  360. symbols, including the symbols structure itsefl.
  361. Arguments:
  362. Symbols - Supplies a pointer to the debugging symbols.
  363. Return Value:
  364. None.
  365. --*/
  366. {
  367. PDWARF_CONTEXT Context;
  368. PDATA_SYMBOL DataSymbol;
  369. PENUMERATION_MEMBER Enumeration;
  370. PFUNCTION_SYMBOL Function;
  371. PSOURCE_LINE_SYMBOL Line;
  372. PSTRUCTURE_MEMBER Member;
  373. PVOID Next;
  374. PSOURCE_FILE_SYMBOL SourceFile;
  375. PTYPE_SYMBOL Type;
  376. PDWARF_COMPILATION_UNIT Unit;
  377. Context = Symbols->SymbolContext;
  378. //
  379. // Destroy all the sources.
  380. //
  381. while (!LIST_EMPTY(Context->SourcesHead)) {
  382. SourceFile = LIST_VALUE(Context->SourcesHead->Next,
  383. SOURCE_FILE_SYMBOL,
  384. ListEntry);
  385. while (!LIST_EMPTY(&(SourceFile->TypesHead))) {
  386. Type = LIST_VALUE(SourceFile->TypesHead.Next,
  387. TYPE_SYMBOL,
  388. ListEntry);
  389. if (Type->Type == DataTypeStructure) {
  390. Member = Type->U.Structure.FirstMember;
  391. while (Member != NULL) {
  392. Next = Member->NextMember;
  393. free(Member);
  394. Member = Next;
  395. }
  396. } else if (Type->Type == DataTypeEnumeration) {
  397. Enumeration = Type->U.Enumeration.FirstMember;
  398. while (Enumeration != NULL) {
  399. Next = Enumeration->NextMember;
  400. free(Enumeration);
  401. Enumeration = Next;
  402. }
  403. }
  404. LIST_REMOVE(&(Type->ListEntry));
  405. free(Type);
  406. }
  407. while (!LIST_EMPTY(&(SourceFile->FunctionsHead))) {
  408. Function = LIST_VALUE(SourceFile->FunctionsHead.Next,
  409. FUNCTION_SYMBOL,
  410. ListEntry);
  411. while (!LIST_EMPTY(&(Function->ParametersHead))) {
  412. DataSymbol = LIST_VALUE(Function->ParametersHead.Next,
  413. DATA_SYMBOL,
  414. ListEntry);
  415. LIST_REMOVE(&(DataSymbol->ListEntry));
  416. free(DataSymbol);
  417. }
  418. while (!LIST_EMPTY(&(Function->LocalsHead))) {
  419. DataSymbol = LIST_VALUE(Function->LocalsHead.Next,
  420. DATA_SYMBOL,
  421. ListEntry);
  422. LIST_REMOVE(&(DataSymbol->ListEntry));
  423. free(DataSymbol);
  424. }
  425. LIST_REMOVE(&(Function->ListEntry));
  426. free(Function);
  427. }
  428. while (!LIST_EMPTY(&(SourceFile->DataSymbolsHead))) {
  429. DataSymbol = LIST_VALUE(SourceFile->DataSymbolsHead.Next,
  430. DATA_SYMBOL,
  431. ListEntry);
  432. LIST_REMOVE(&(DataSymbol->ListEntry));
  433. free(DataSymbol);
  434. }
  435. while (!LIST_EMPTY(&(SourceFile->SourceLinesHead))) {
  436. Line = LIST_VALUE(SourceFile->SourceLinesHead.Next,
  437. SOURCE_LINE_SYMBOL,
  438. ListEntry);
  439. LIST_REMOVE(&(Line->ListEntry));
  440. free(Line);
  441. }
  442. LIST_REMOVE(&(SourceFile->ListEntry));
  443. free(SourceFile);
  444. }
  445. //
  446. // Destroy all the compilation units.
  447. //
  448. if (Context->UnitList.Next != NULL) {
  449. while (!LIST_EMPTY(&(Context->UnitList))) {
  450. Unit = LIST_VALUE(Context->UnitList.Next,
  451. DWARF_COMPILATION_UNIT,
  452. ListEntry);
  453. LIST_REMOVE(&(Unit->ListEntry));
  454. Unit->ListEntry.Next = NULL;
  455. DwarfpDestroyCompilationUnit(Context, Unit);
  456. }
  457. }
  458. if (Context->FileData != NULL) {
  459. free(Context->FileData);
  460. Context->FileData = NULL;
  461. }
  462. Context->FileSize = 0;
  463. if (Symbols->Filename != NULL) {
  464. free(Symbols->Filename);
  465. }
  466. free(Symbols);
  467. return;
  468. }
  469. INT
  470. DwarfReadDataSymbol (
  471. PDEBUG_SYMBOLS Symbols,
  472. PDATA_SYMBOL Symbol,
  473. ULONGLONG DebasedPc,
  474. PVOID Data,
  475. ULONG DataSize,
  476. PSTR Location,
  477. ULONG LocationSize
  478. )
  479. /*++
  480. Routine Description:
  481. This routine reads the contents of a data symbol.
  482. Arguments:
  483. Symbols - Supplies a pointer to the debug symbols.
  484. Symbol - Supplies a pointer to the data symbol to read.
  485. DebasedPc - Supplies the program counter value, assuming the image were
  486. loaded at its preferred base address (that is, actual PC minus the
  487. loaded base difference of the module).
  488. Data - Supplies a pointer to the buffer where the symbol data will be
  489. returned on success.
  490. DataSize - Supplies the size of the data buffer in bytes.
  491. Location - Supplies a pointer where the symbol location will be described
  492. in text on success.
  493. LocationSize - Supplies the size of the location buffer in bytes.
  494. Return Value:
  495. 0 on success.
  496. Returns an error code on failure.
  497. --*/
  498. {
  499. PSTR Comma;
  500. PDWARF_COMPLEX_DATA_SYMBOL Complex;
  501. PDWARF_CONTEXT Context;
  502. PDWARF_LOCATION CurrentLocation;
  503. DWARF_LOCATION_CONTEXT LocationContext;
  504. ULONG MaxBit;
  505. CHAR PieceLocation[32];
  506. INT Printed;
  507. ULONG Size;
  508. INT Status;
  509. ULONGLONG Value;
  510. Comma = "";
  511. Context = Symbols->SymbolContext;
  512. assert(Symbol->LocationType == DataLocationComplex);
  513. Complex = Symbol->Location.Complex;
  514. memset(&LocationContext, 0, sizeof(DWARF_LOCATION_CONTEXT));
  515. memset(Data, 0, DataSize);
  516. LocationContext.Unit = Complex->Unit;
  517. LocationContext.CurrentFunction = Symbol->ParentFunction;
  518. LocationContext.Pc = DebasedPc;
  519. Status = DwarfpGetLocation(Context,
  520. &LocationContext,
  521. &(Complex->LocationAttribute));
  522. if (Status != 0) {
  523. if (Status != ENOENT) {
  524. DWARF_ERROR("DWARF: Failed to get location for symbol %s: %s.\n",
  525. Symbol->Name,
  526. strerror(Status));
  527. }
  528. goto ReadDataSymbolEnd;
  529. }
  530. CurrentLocation = &(LocationContext.Location);
  531. while (CurrentLocation != NULL) {
  532. //
  533. // Figure out the size to copy, without regard to the source size. Note
  534. // that if multiple bitwise fields came together, this loop would need
  535. // to be adjusted to take into account (as well as not clobber) the
  536. // previous bits.
  537. //
  538. Size = DataSize;
  539. if (CurrentLocation->BitSize != 0) {
  540. Size = CurrentLocation->BitSize / BITS_PER_BYTE;
  541. if (Size > DataSize) {
  542. Size = DataSize;
  543. }
  544. }
  545. switch (CurrentLocation->Form) {
  546. case DwarfLocationMemory:
  547. Status = DwarfTargetRead(Context,
  548. CurrentLocation->Value.Address,
  549. Size,
  550. 0,
  551. Data);
  552. if (Status != 0) {
  553. DWARF_ERROR("DWARF: Cannot read %d bytes at %I64x.\n",
  554. Size,
  555. CurrentLocation->Value.Address);
  556. goto ReadDataSymbolEnd;
  557. }
  558. snprintf(PieceLocation,
  559. sizeof(PieceLocation),
  560. "[0x%llx]",
  561. CurrentLocation->Value.Address);
  562. break;
  563. case DwarfLocationRegister:
  564. if (Size > Complex->Unit->AddressSize) {
  565. Size = Complex->Unit->AddressSize;
  566. }
  567. Status = DwarfTargetReadRegister(Context,
  568. CurrentLocation->Value.Register,
  569. &Value);
  570. if (Status != 0) {
  571. DWARF_ERROR("DWARF: Failed to get register %d.\n",
  572. CurrentLocation->Value.Register);
  573. goto ReadDataSymbolEnd;
  574. }
  575. memcpy(Data, &Value, Size);
  576. snprintf(
  577. PieceLocation,
  578. sizeof(PieceLocation),
  579. "@%s",
  580. DwarfGetRegisterName(Context, CurrentLocation->Value.Register));
  581. break;
  582. case DwarfLocationKnownValue:
  583. Value = CurrentLocation->Value.Value;
  584. if (Size > sizeof(ULONGLONG)) {
  585. Size = sizeof(ULONGLONG);
  586. }
  587. memcpy(Data, &Value, Size);
  588. strncpy(PieceLocation, "<const>", sizeof(PieceLocation));
  589. break;
  590. case DwarfLocationKnownData:
  591. if (Size > CurrentLocation->Value.Buffer.Size) {
  592. Size = CurrentLocation->Value.Buffer.Size;
  593. }
  594. memcpy(Data, CurrentLocation->Value.Buffer.Data, Size);
  595. strncpy(PieceLocation, "<const>", sizeof(PieceLocation));
  596. break;
  597. case DwarfLocationUndefined:
  598. strncpy(PieceLocation, "<undef>", sizeof(PieceLocation));
  599. break;
  600. default:
  601. assert(FALSE);
  602. Status = EINVAL;
  603. goto ReadDataSymbolEnd;
  604. }
  605. //
  606. // Shift the buffer over if needed. Again, this doesn't cut it for bit
  607. // fields.
  608. //
  609. if (CurrentLocation->BitOffset != 0) {
  610. memmove(Data,
  611. Data + (CurrentLocation->BitOffset / BITS_PER_BYTE),
  612. Size);
  613. }
  614. if (LocationSize > 1) {
  615. if ((CurrentLocation->BitOffset != 0) ||
  616. (CurrentLocation->BitSize != 0)) {
  617. MaxBit = CurrentLocation->BitOffset + CurrentLocation->BitSize;
  618. Printed = snprintf(Location,
  619. LocationSize,
  620. "%s%s[%d:%d]",
  621. Comma,
  622. PieceLocation,
  623. MaxBit,
  624. CurrentLocation->BitOffset);
  625. } else {
  626. Printed = snprintf(Location,
  627. LocationSize,
  628. "%s%s",
  629. Comma,
  630. PieceLocation);
  631. }
  632. if (Printed > 0) {
  633. Location += Printed;
  634. LocationSize -= Printed;
  635. }
  636. }
  637. Comma = ",";
  638. Data += Size;
  639. DataSize -= Size;
  640. CurrentLocation = CurrentLocation->NextPiece;
  641. }
  642. if (LocationSize != 0) {
  643. *Location = '\0';
  644. }
  645. ReadDataSymbolEnd:
  646. DwarfpDestroyLocationContext(Context, &LocationContext);
  647. return Status;
  648. }
  649. INT
  650. DwarfGetAddressOfDataSymbol (
  651. PDEBUG_SYMBOLS Symbols,
  652. PDATA_SYMBOL Symbol,
  653. ULONGLONG DebasedPc,
  654. PULONGLONG Address
  655. )
  656. /*++
  657. Routine Description:
  658. This routine gets the memory address of a data symbol.
  659. Arguments:
  660. Symbols - Supplies a pointer to the debug symbols.
  661. Symbol - Supplies a pointer to the data symbol to read.
  662. DebasedPc - Supplies the program counter value, assuming the image were
  663. loaded at its preferred base address (that is, actual PC minus the
  664. loaded base difference of the module).
  665. Address - Supplies a pointer where the address of the data symbol will be
  666. returned on success.
  667. Return Value:
  668. 0 on success.
  669. ENOENT if the data symbol is not currently valid.
  670. ERANGE if the data symbol is not stored in memory.
  671. Other error codes on other failures.
  672. --*/
  673. {
  674. PDWARF_COMPLEX_DATA_SYMBOL Complex;
  675. PDWARF_CONTEXT Context;
  676. PDWARF_LOCATION CurrentLocation;
  677. DWARF_LOCATION_CONTEXT LocationContext;
  678. INT Status;
  679. Context = Symbols->SymbolContext;
  680. assert(Symbol->LocationType == DataLocationComplex);
  681. Complex = Symbol->Location.Complex;
  682. memset(&LocationContext, 0, sizeof(DWARF_LOCATION_CONTEXT));
  683. LocationContext.Unit = Complex->Unit;
  684. LocationContext.CurrentFunction = Symbol->ParentFunction;
  685. LocationContext.Pc = DebasedPc;
  686. Status = DwarfpGetLocation(Context,
  687. &LocationContext,
  688. &(Complex->LocationAttribute));
  689. if (Status != 0) {
  690. if (Status != ENOENT) {
  691. DWARF_ERROR("DWARF: Failed to get location for symbol %s: %s.\n",
  692. Symbol->Name,
  693. strerror(Status));
  694. }
  695. goto GetAddressOfDataSymbolEnd;
  696. }
  697. CurrentLocation = &(LocationContext.Location);
  698. switch (CurrentLocation->Form) {
  699. case DwarfLocationMemory:
  700. *Address = CurrentLocation->Value.Address;
  701. Status = 0;
  702. break;
  703. default:
  704. Status = ERANGE;
  705. break;
  706. }
  707. GetAddressOfDataSymbolEnd:
  708. DwarfpDestroyLocationContext(Context, &LocationContext);
  709. return Status;
  710. }
  711. PSOURCE_FILE_SYMBOL
  712. DwarfpFindSource (
  713. PDWARF_CONTEXT Context,
  714. PSTR Directory,
  715. PSTR FileName,
  716. BOOL Create
  717. )
  718. /*++
  719. Routine Description:
  720. This routine searches for a source file symbol matching the given directory
  721. and file name.
  722. Arguments:
  723. Context - Supplies a pointer to the application context.
  724. Directory - Supplies a pointer to the source directory.
  725. FileName - Supplies a pointer to the source file name.
  726. Create - Supplies a boolean indicating if a source file should be
  727. created if none is found.
  728. Return Value:
  729. Returns a pointer to a source file symbol on success.
  730. NULL if no such file exists.
  731. --*/
  732. {
  733. PLIST_ENTRY CurrentEntry;
  734. PSOURCE_FILE_SYMBOL File;
  735. CurrentEntry = Context->SourcesHead->Next;
  736. while (CurrentEntry != Context->SourcesHead) {
  737. File = LIST_VALUE(CurrentEntry, SOURCE_FILE_SYMBOL, ListEntry);
  738. CurrentEntry = CurrentEntry->Next;
  739. //
  740. // Check the directory, being careful since one or both might be NULL.
  741. //
  742. if (Directory != NULL) {
  743. if (File->SourceDirectory == NULL) {
  744. continue;
  745. }
  746. if (strcmp(File->SourceDirectory, Directory) != 0) {
  747. continue;
  748. }
  749. } else if (File->SourceDirectory != NULL) {
  750. continue;
  751. }
  752. if (strcmp(File->SourceFile, FileName) == 0) {
  753. return File;
  754. }
  755. }
  756. if (Create == FALSE) {
  757. return NULL;
  758. }
  759. File = malloc(sizeof(SOURCE_FILE_SYMBOL));
  760. if (File == NULL) {
  761. return NULL;
  762. }
  763. memset(File, 0, sizeof(SOURCE_FILE_SYMBOL));
  764. INITIALIZE_LIST_HEAD(&(File->SourceLinesHead));
  765. INITIALIZE_LIST_HEAD(&(File->DataSymbolsHead));
  766. INITIALIZE_LIST_HEAD(&(File->FunctionsHead));
  767. INITIALIZE_LIST_HEAD(&(File->TypesHead));
  768. File->SourceDirectory = Directory;
  769. File->SourceFile = FileName;
  770. INSERT_BEFORE(&(File->ListEntry), Context->SourcesHead);
  771. return File;
  772. }
  773. //
  774. // --------------------------------------------------------- Internal Functions
  775. //
  776. INT
  777. DwarfpProcessDebugInfo (
  778. PDWARF_CONTEXT Context
  779. )
  780. /*++
  781. Routine Description:
  782. This routine processes the .debug_info section of DWARF symbols.
  783. Arguments:
  784. Context - Supplies a pointer to the application context.
  785. Return Value:
  786. 0 on success.
  787. Returns an error number on failure.
  788. --*/
  789. {
  790. PUCHAR Bytes;
  791. PDWARF_DIE Die;
  792. PUCHAR InfoStart;
  793. DWARF_LOADING_CONTEXT LoadState;
  794. ULONGLONG Size;
  795. INT Status;
  796. PDWARF_COMPILATION_UNIT Unit;
  797. Bytes = Context->Sections.Info.Data;
  798. InfoStart = Bytes;
  799. Size = Context->Sections.Info.Size;
  800. Status = 0;
  801. Unit = NULL;
  802. memset(&LoadState, 0, sizeof(DWARF_LOADING_CONTEXT));
  803. Context->LoadingContext = &LoadState;
  804. //
  805. // Load up and visit all the compilation units.
  806. //
  807. while (Size != 0) {
  808. Unit = malloc(sizeof(DWARF_COMPILATION_UNIT));
  809. if (Unit == NULL) {
  810. Status = errno;
  811. goto ProcessDebugInfoEnd;
  812. }
  813. memset(Unit, 0, sizeof(DWARF_COMPILATION_UNIT));
  814. INITIALIZE_LIST_HEAD(&(Unit->DieList));
  815. DwarfpReadCompilationUnit(&Bytes, &Size, Unit);
  816. if ((Context->Flags & DWARF_CONTEXT_DEBUG) != 0) {
  817. DWARF_PRINT("Compilation Unit %x: %s Version %d UnitLength %I64x "
  818. "AbbrevOffset %I64x AddressSize %d DIEs %x\n",
  819. Bytes - InfoStart,
  820. Unit->Is64Bit ? "64-bit" : "32-bit",
  821. Unit->Version,
  822. Unit->UnitLength,
  823. Unit->AbbreviationOffset,
  824. Unit->AddressSize,
  825. Unit->Dies - InfoStart);
  826. }
  827. Status = DwarfpLoadCompilationUnit(Context, Unit);
  828. if (Status != 0) {
  829. goto ProcessDebugInfoEnd;
  830. }
  831. //
  832. // Now visit the compilation unit now that the DIE tree has been formed.
  833. //
  834. Status = DwarfpProcessCompilationUnit(Context, Unit);
  835. if (Status != 0) {
  836. DWARF_ERROR("DWARF: Failed to process compilation unit.\n");
  837. goto ProcessDebugInfoEnd;
  838. }
  839. while (!LIST_EMPTY(&(Unit->DieList))) {
  840. Die = LIST_VALUE(Unit->DieList.Next, DWARF_DIE, ListEntry);
  841. LIST_REMOVE(&(Die->ListEntry));
  842. Die->ListEntry.Next = NULL;
  843. DwarfpDestroyDie(Context, Die);
  844. }
  845. INSERT_BEFORE(&(Unit->ListEntry), &(Context->UnitList));
  846. Unit = NULL;
  847. }
  848. Status = 0;
  849. ProcessDebugInfoEnd:
  850. Context->LoadingContext = NULL;
  851. if (Unit != NULL) {
  852. DwarfpDestroyCompilationUnit(Context, Unit);
  853. }
  854. return Status;
  855. }
  856. INT
  857. DwarfpProcessCompilationUnit (
  858. PDWARF_CONTEXT Context,
  859. PDWARF_COMPILATION_UNIT Unit
  860. )
  861. /*++
  862. Routine Description:
  863. This routine processes the a DWARF compilation unit.
  864. Arguments:
  865. Context - Supplies a pointer to the application context.
  866. Unit - Supplies a pointer to the compilation unit to process.
  867. Return Value:
  868. 0 on success.
  869. Returns an error number on failure.
  870. --*/
  871. {
  872. PLIST_ENTRY CurrentEntry;
  873. PDWARF_DIE Die;
  874. PDWARF_LOADING_CONTEXT LoadState;
  875. INT Status;
  876. Status = 0;
  877. LoadState = Context->LoadingContext;
  878. assert((LoadState->CurrentFile == NULL) &&
  879. (LoadState->CurrentFunction == NULL) &&
  880. (LoadState->CurrentType == NULL));
  881. LoadState->CurrentUnit = Unit;
  882. CurrentEntry = Unit->DieList.Next;
  883. while (CurrentEntry != &(Unit->DieList)) {
  884. Die = LIST_VALUE(CurrentEntry, DWARF_DIE, ListEntry);
  885. CurrentEntry = CurrentEntry->Next;
  886. assert(Die->Parent == NULL);
  887. Status = DwarfpProcessDie(Context, Die);
  888. if (Status != 0) {
  889. break;
  890. }
  891. }
  892. LoadState->CurrentUnit = NULL;
  893. return Status;
  894. }
  895. INT
  896. DwarfpProcessDie (
  897. PDWARF_CONTEXT Context,
  898. PDWARF_DIE Die
  899. )
  900. /*++
  901. Routine Description:
  902. This routine processes the a DWARF Debug Information Entry.
  903. Arguments:
  904. Context - Supplies a pointer to the application context.
  905. Die - Supplies a pointer to the DIE to process.
  906. Return Value:
  907. 0 on success.
  908. Returns an error number on failure.
  909. --*/
  910. {
  911. INT Status;
  912. switch (Die->Tag) {
  913. case DwarfTagCompileUnit:
  914. Status = DwarfpProcessCompileUnit(Context, Die);
  915. break;
  916. case DwarfTagBaseType:
  917. Status = DwarfpProcessBaseType(Context, Die);
  918. break;
  919. case DwarfTagTypedef:
  920. case DwarfTagPointerType:
  921. case DwarfTagArrayType:
  922. case DwarfTagVolatileType:
  923. case DwarfTagRestrictType:
  924. case DwarfTagConstType:
  925. case DwarfTagReferenceType:
  926. Status = DwarfpProcessTypeRelation(Context, Die);
  927. break;
  928. case DwarfTagSubrangeType:
  929. Status = DwarfpProcessSubrangeType(Context, Die);
  930. break;
  931. case DwarfTagStructureType:
  932. case DwarfTagUnionType:
  933. case DwarfTagEnumerationType:
  934. case DwarfTagClassType:
  935. Status = DwarfpProcessStructureUnionEnumerationType(Context, Die);
  936. break;
  937. case DwarfTagMember:
  938. Status = DwarfpProcessMember(Context, Die);
  939. break;
  940. case DwarfTagEnumerator:
  941. Status = DwarfpProcessEnumerator(Context, Die);
  942. break;
  943. case DwarfTagSubprogram:
  944. Status = DwarfpProcessSubprogram(Context, Die);
  945. break;
  946. case DwarfTagFormalParameter:
  947. case DwarfTagVariable:
  948. Status = DwarfpProcessVariable(Context, Die);
  949. break;
  950. case DwarfTagSubroutineType:
  951. Status = DwarfpProcessSubroutineType(Context, Die);
  952. break;
  953. case DwarfTagNamespace:
  954. case DwarfTagLexicalBlock:
  955. Status = DwarfpProcessGenericBlock(Context, Die);
  956. break;
  957. default:
  958. Status = 0;
  959. break;
  960. }
  961. if (Status != 0) {
  962. DWARF_ERROR("DWARF: Failed to process DIE %x.\n",
  963. DWARF_DIE_ID(Context, Die));
  964. }
  965. return Status;
  966. }
  967. INT
  968. DwarfpProcessChildDies (
  969. PDWARF_CONTEXT Context,
  970. PDWARF_DIE Die
  971. )
  972. /*++
  973. Routine Description:
  974. This routine processes the child DIEs of a given DIE.
  975. Arguments:
  976. Context - Supplies a pointer to the application context.
  977. Die - Supplies a pointer to the DIE whose children should be processed.
  978. Return Value:
  979. 0 on success.
  980. Returns an error number on failure.
  981. --*/
  982. {
  983. PDWARF_DIE Child;
  984. PLIST_ENTRY CurrentEntry;
  985. INT Status;
  986. CurrentEntry = Die->ChildList.Next;
  987. while (CurrentEntry != &(Die->ChildList)) {
  988. Child = LIST_VALUE(CurrentEntry, DWARF_DIE, ListEntry);
  989. CurrentEntry = CurrentEntry->Next;
  990. Status = DwarfpProcessDie(Context, Child);
  991. if (Status != 0) {
  992. break;
  993. }
  994. }
  995. return Status;
  996. }
  997. INT
  998. DwarfpProcessCompileUnit (
  999. PDWARF_CONTEXT Context,
  1000. PDWARF_DIE Die
  1001. )
  1002. /*++
  1003. Routine Description:
  1004. This routine processes a compile unit DIE.
  1005. Arguments:
  1006. Context - Supplies a pointer to the application context.
  1007. Die - Supplies a pointer to the DIE to process.
  1008. Return Value:
  1009. 0 on success.
  1010. Returns an error number on failure.
  1011. --*/
  1012. {
  1013. PDWARF_LOADING_CONTEXT LoadingContext;
  1014. BOOL Result;
  1015. PSOURCE_FILE_SYMBOL SourceFile;
  1016. INT Status;
  1017. LoadingContext = Context->LoadingContext;
  1018. SourceFile = DwarfpFindSource(Context,
  1019. DwarfpGetStringAttribute(Die, DwarfAtCompDir),
  1020. DwarfpGetStringAttribute(Die, DwarfAtName),
  1021. TRUE);
  1022. if (SourceFile == NULL) {
  1023. return ENOMEM;
  1024. }
  1025. SourceFile->Identifier = DWARF_DIE_ID(Context, Die);
  1026. SourceFile->SymbolContext = LoadingContext->CurrentUnit;
  1027. //
  1028. // Get the starting PC for the compilation unit. There might not be one
  1029. // if this compilation unit has no code (only data).
  1030. //
  1031. Result = DwarfpGetAddressAttribute(Die,
  1032. DwarfAtLowPc,
  1033. &(SourceFile->StartAddress));
  1034. if (Result != FALSE) {
  1035. SourceFile->EndAddress = SourceFile->StartAddress + 1;
  1036. Result = DwarfpGetAddressAttribute(Die,
  1037. DwarfAtHighPc,
  1038. &(SourceFile->EndAddress));
  1039. if (Result == FALSE) {
  1040. //
  1041. // DWARF4 also allows constant forms for high PC, in which case
  1042. // it's an offset from low PC.
  1043. //
  1044. Result = DwarfpGetIntegerAttribute(Die,
  1045. DwarfAtHighPc,
  1046. &(SourceFile->EndAddress));
  1047. if (Result != FALSE) {
  1048. SourceFile->EndAddress += SourceFile->StartAddress;
  1049. }
  1050. }
  1051. }
  1052. //
  1053. // Update the low and high PC values in the compilation unit structure.
  1054. // They're used by the location list search routine, for instance.
  1055. //
  1056. assert((LoadingContext->CurrentUnit != NULL) &&
  1057. (LoadingContext->CurrentUnit->LowPc == 0));
  1058. LoadingContext->CurrentUnit->LowPc = SourceFile->StartAddress;
  1059. LoadingContext->CurrentUnit->HighPc = SourceFile->EndAddress;
  1060. //
  1061. // Set the current file as this one, and process all children.
  1062. //
  1063. assert(LoadingContext->CurrentFile == NULL);
  1064. LoadingContext->CurrentFile = SourceFile;
  1065. Status = DwarfpProcessChildDies(Context, Die);
  1066. if (Status != 0) {
  1067. goto ProcessCompileUnitEnd;
  1068. }
  1069. //
  1070. // Process the line numbers if there are any.
  1071. //
  1072. Status = DwarfpProcessStatementList(Context, Die);
  1073. if (Status != 0) {
  1074. goto ProcessCompileUnitEnd;
  1075. }
  1076. ProcessCompileUnitEnd:
  1077. assert(LoadingContext->CurrentFile == SourceFile);
  1078. LoadingContext->CurrentFile = NULL;
  1079. return Status;
  1080. }
  1081. INT
  1082. DwarfpProcessBaseType (
  1083. PDWARF_CONTEXT Context,
  1084. PDWARF_DIE Die
  1085. )
  1086. /*++
  1087. Routine Description:
  1088. This routine processes a base type DIE.
  1089. Arguments:
  1090. Context - Supplies a pointer to the application context.
  1091. Die - Supplies a pointer to the DIE to process.
  1092. Return Value:
  1093. 0 on success.
  1094. Returns an error number on failure.
  1095. --*/
  1096. {
  1097. ULONGLONG Encoding;
  1098. PDWARF_LOADING_CONTEXT LoadingContext;
  1099. DATA_TYPE_NUMERIC Numeric;
  1100. PTYPE_SYMBOL PreviousType;
  1101. BOOL Result;
  1102. ULONGLONG Size;
  1103. INT Status;
  1104. PTYPE_SYMBOL Type;
  1105. LoadingContext = Context->LoadingContext;
  1106. memset(&Numeric, 0, sizeof(DATA_TYPE_NUMERIC));
  1107. Result = DwarfpGetIntegerAttribute(Die, DwarfAtEncoding, &Encoding);
  1108. if (Result != FALSE) {
  1109. switch ((ULONG)Encoding) {
  1110. case DwarfAteAddress:
  1111. Numeric.BitSize = LoadingContext->CurrentUnit->AddressSize *
  1112. BITS_PER_BYTE;
  1113. break;
  1114. case DwarfAteBoolean:
  1115. case DwarfAteUnsigned:
  1116. case DwarfAteUnsignedChar:
  1117. break;
  1118. case DwarfAteFloat:
  1119. Numeric.Float = TRUE;
  1120. break;
  1121. case DwarfAteSigned:
  1122. case DwarfAteSignedChar:
  1123. Numeric.Signed = TRUE;
  1124. break;
  1125. //
  1126. // Treat unhandled types like integers.
  1127. //
  1128. case DwarfAteComplexFloat:
  1129. case DwarfAteImaginaryFloat:
  1130. case DwarfAtePackedDecimal:
  1131. case DwarfAteNumericString:
  1132. case DwarfAteEdited:
  1133. case DwarfAteSignedFixed:
  1134. case DwarfAteUnsignedFixed:
  1135. case DwarfAteDecimalFloat:
  1136. case DwarfAteUtf:
  1137. default:
  1138. break;
  1139. }
  1140. } else {
  1141. DWARF_ERROR("DWARF: Failed to get base type attribute.\n");
  1142. return 0;
  1143. }
  1144. Result = DwarfpGetIntegerAttribute(Die, DwarfAtByteSize, &Size);
  1145. if (Result != FALSE) {
  1146. Size *= BITS_PER_BYTE;
  1147. } else {
  1148. Result = DwarfpGetIntegerAttribute(Die, DwarfAtBitSize, &Size);
  1149. }
  1150. if (Result == FALSE) {
  1151. DWARF_ERROR("DWARF: Unknown base type size.\n");
  1152. return 0;
  1153. }
  1154. Numeric.BitSize = Size;
  1155. Type = malloc(sizeof(TYPE_SYMBOL));
  1156. if (Type == NULL) {
  1157. return ENOMEM;
  1158. }
  1159. memset(Type, 0, sizeof(TYPE_SYMBOL));
  1160. Type->ParentSource = LoadingContext->CurrentFile;
  1161. PreviousType = LoadingContext->CurrentType;
  1162. LoadingContext->CurrentType = Type;
  1163. Type->ParentFunction = LoadingContext->CurrentFunction;
  1164. Type->Name = DwarfpGetStringAttribute(Die, DwarfAtName);
  1165. Type->TypeNumber = DWARF_DIE_ID(Context, Die);
  1166. Type->Type = DataTypeNumeric;
  1167. memcpy(&(Type->U.Numeric), &Numeric, sizeof(DATA_TYPE_NUMERIC));
  1168. INSERT_BEFORE(&(Type->ListEntry),
  1169. &(LoadingContext->CurrentFile->TypesHead));
  1170. Status = DwarfpProcessChildDies(Context, Die);
  1171. assert(LoadingContext->CurrentType == Type);
  1172. LoadingContext->CurrentType = PreviousType;
  1173. return Status;
  1174. }
  1175. INT
  1176. DwarfpProcessTypeRelation (
  1177. PDWARF_CONTEXT Context,
  1178. PDWARF_DIE Die
  1179. )
  1180. /*++
  1181. Routine Description:
  1182. This routine processes a typedef, pointer, or array.
  1183. Arguments:
  1184. Context - Supplies a pointer to the application context.
  1185. Die - Supplies a pointer to the DIE to process.
  1186. Return Value:
  1187. 0 on success.
  1188. Returns an error number on failure.
  1189. --*/
  1190. {
  1191. PDWARF_LOADING_CONTEXT LoadingContext;
  1192. PTYPE_SYMBOL PreviousType;
  1193. DATA_TYPE_RELATION Relation;
  1194. BOOL Result;
  1195. INT Status;
  1196. PTYPE_SYMBOL Type;
  1197. LoadingContext = Context->LoadingContext;
  1198. memset(&Relation, 0, sizeof(DATA_TYPE_RELATION));
  1199. if (Die->Tag == DwarfTagPointerType) {
  1200. Relation.Pointer = LoadingContext->CurrentUnit->AddressSize;
  1201. }
  1202. //
  1203. // Get the type information that corresponds to this reference.
  1204. //
  1205. Result = DwarfpGetTypeReferenceAttribute(Context,
  1206. Die,
  1207. DwarfAtType,
  1208. &(Relation.OwningFile),
  1209. &(Relation.TypeNumber));
  1210. if (Result == FALSE) {
  1211. DWARF_ERROR("DWARF: Unable to resolve type.\n");
  1212. return EINVAL;
  1213. }
  1214. Type = malloc(sizeof(TYPE_SYMBOL));
  1215. if (Type == NULL) {
  1216. return ENOMEM;
  1217. }
  1218. memset(Type, 0, sizeof(TYPE_SYMBOL));
  1219. Type->ParentSource = LoadingContext->CurrentFile;
  1220. PreviousType = LoadingContext->CurrentType;
  1221. LoadingContext->CurrentType = Type;
  1222. Type->ParentFunction = LoadingContext->CurrentFunction;
  1223. Type->Name = DwarfpGetStringAttribute(Die, DwarfAtName);
  1224. Type->TypeNumber = DWARF_DIE_ID(Context, Die);
  1225. Type->Type = DataTypeRelation;
  1226. memcpy(&(Type->U.Relation), &Relation, sizeof(DATA_TYPE_RELATION));
  1227. INSERT_BEFORE(&(Type->ListEntry),
  1228. &(LoadingContext->CurrentFile->TypesHead));
  1229. Status = DwarfpProcessChildDies(Context, Die);
  1230. assert(LoadingContext->CurrentType == Type);
  1231. LoadingContext->CurrentType = PreviousType;
  1232. return Status;
  1233. }
  1234. INT
  1235. DwarfpProcessSubrangeType (
  1236. PDWARF_CONTEXT Context,
  1237. PDWARF_DIE Die
  1238. )
  1239. /*++
  1240. Routine Description:
  1241. This routine processes a subrange type DIE.
  1242. Arguments:
  1243. Context - Supplies a pointer to the application context.
  1244. Die - Supplies a pointer to the DIE to process.
  1245. Return Value:
  1246. 0 on success.
  1247. Returns an error number on failure.
  1248. --*/
  1249. {
  1250. PDWARF_LOADING_CONTEXT LoadingContext;
  1251. BOOL Result;
  1252. INT Status;
  1253. ULONGLONG UpperBound;
  1254. LoadingContext = Context->LoadingContext;
  1255. //
  1256. // Try to get the upper bound of the array. If there is no upper bound,
  1257. // then make the array into a pointer.
  1258. //
  1259. Result = DwarfpGetIntegerAttribute(Die, DwarfAtUpperBound, &UpperBound);
  1260. if (Result == FALSE) {
  1261. LoadingContext->CurrentType->U.Relation.Pointer =
  1262. LoadingContext->CurrentUnit->AddressSize;
  1263. return 0;
  1264. }
  1265. if (LoadingContext->CurrentType != NULL) {
  1266. if (LoadingContext->CurrentType->Type != DataTypeRelation) {
  1267. DWARF_ERROR("DWARF: Subrange type on a non-relation data type.\n");
  1268. return EINVAL;
  1269. }
  1270. LoadingContext->CurrentType->U.Relation.Array.Maximum = UpperBound;
  1271. if (UpperBound == MAX_ULONGLONG) {
  1272. LoadingContext->CurrentType->U.Relation.Array.MaxUlonglong = TRUE;
  1273. }
  1274. } else {
  1275. DWARF_ERROR("DWARF: Subrange type not inside a type.\n");
  1276. return EINVAL;
  1277. }
  1278. Status = DwarfpProcessChildDies(Context, Die);
  1279. return Status;
  1280. }
  1281. INT
  1282. DwarfpProcessStructureUnionEnumerationType (
  1283. PDWARF_CONTEXT Context,
  1284. PDWARF_DIE Die
  1285. )
  1286. /*++
  1287. Routine Description:
  1288. This routine processes a structure, union, or enumeration DIE.
  1289. Arguments:
  1290. Context - Supplies a pointer to the application context.
  1291. Die - Supplies a pointer to the DIE to process.
  1292. Return Value:
  1293. 0 on success.
  1294. Returns an error number on failure.
  1295. --*/
  1296. {
  1297. PDWARF_LOADING_CONTEXT LoadingContext;
  1298. PTYPE_SYMBOL PreviousType;
  1299. BOOL Result;
  1300. ULONGLONG Size;
  1301. INT Status;
  1302. PTYPE_SYMBOL Type;
  1303. LoadingContext = Context->LoadingContext;
  1304. //
  1305. // Get the size. If this is a declaration, there might not be one.
  1306. //
  1307. Result = DwarfpGetIntegerAttribute(Die, DwarfAtByteSize, &Size);
  1308. if (Result == FALSE) {
  1309. Size = 0;
  1310. }
  1311. Type = malloc(sizeof(TYPE_SYMBOL));
  1312. if (Type == NULL) {
  1313. return ENOMEM;
  1314. }
  1315. memset(Type, 0, sizeof(TYPE_SYMBOL));
  1316. Type->ParentSource = LoadingContext->CurrentFile;
  1317. PreviousType = LoadingContext->CurrentType;
  1318. LoadingContext->CurrentType = Type;
  1319. Type->ParentFunction = LoadingContext->CurrentFunction;
  1320. Type->Name = DwarfpGetStringAttribute(Die, DwarfAtName);
  1321. Type->TypeNumber = DWARF_DIE_ID(Context, Die);
  1322. if ((Die->Tag == DwarfTagStructureType) ||
  1323. (Die->Tag == DwarfTagUnionType) ||
  1324. (Die->Tag == DwarfTagClassType)) {
  1325. Type->Type = DataTypeStructure;
  1326. Type->U.Structure.SizeInBytes = Size;
  1327. } else {
  1328. assert(Die->Tag == DwarfTagEnumerationType);
  1329. Type->Type = DataTypeEnumeration;
  1330. Type->U.Enumeration.SizeInBytes = Size;
  1331. }
  1332. INSERT_BEFORE(&(Type->ListEntry),
  1333. &(LoadingContext->CurrentFile->TypesHead));
  1334. Status = DwarfpProcessChildDies(Context, Die);
  1335. assert(LoadingContext->CurrentType == Type);
  1336. LoadingContext->CurrentType = PreviousType;
  1337. return Status;
  1338. }
  1339. INT
  1340. DwarfpProcessMember (
  1341. PDWARF_CONTEXT Context,
  1342. PDWARF_DIE Die
  1343. )
  1344. /*++
  1345. Routine Description:
  1346. This routine processes a structure or union member.
  1347. Arguments:
  1348. Context - Supplies a pointer to the application context.
  1349. Die - Supplies a pointer to the DIE to process.
  1350. Return Value:
  1351. 0 on success.
  1352. Returns an error number on failure.
  1353. --*/
  1354. {
  1355. ULONGLONG BitOffset;
  1356. ULONGLONG BitSize;
  1357. PDWARF_LOADING_CONTEXT LoadingContext;
  1358. PDWARF_ATTRIBUTE_VALUE LocationAttribute;
  1359. DWARF_LOCATION_CONTEXT LocationContext;
  1360. PSTRUCTURE_MEMBER Member;
  1361. PSTRUCTURE_MEMBER PreviousMember;
  1362. BOOL Result;
  1363. INT Status;
  1364. ULONGLONG StorageSize;
  1365. PTYPE_SYMBOL Structure;
  1366. BitOffset = 0;
  1367. BitSize = 0;
  1368. LoadingContext = Context->LoadingContext;
  1369. //
  1370. // Try to get the bit size, and if it's not there try to get the byte size.
  1371. //
  1372. Result = DwarfpGetIntegerAttribute(Die, DwarfAtBitSize, &BitSize);
  1373. if (Result == FALSE) {
  1374. Result = DwarfpGetIntegerAttribute(Die, DwarfAtByteSize, &BitSize);
  1375. if (Result != FALSE) {
  1376. BitSize *= BITS_PER_BYTE;
  1377. }
  1378. }
  1379. //
  1380. // Get the bit offset. Try for a data bit offset, and fall back to the
  1381. // older bit offset if not found.
  1382. //
  1383. Result = DwarfpGetIntegerAttribute(Die, DwarfAtDataBitOffset, &BitOffset);
  1384. if (Result == FALSE) {
  1385. Result = DwarfpGetIntegerAttribute(Die, DwarfAtBitOffset, &BitOffset);
  1386. if (Result != FALSE) {
  1387. //
  1388. // If there's a bit offset and a bit size, there needs to be a byte
  1389. // size to determine storage unit size.
  1390. //
  1391. Result = DwarfpGetIntegerAttribute(Die,
  1392. DwarfAtByteSize,
  1393. &StorageSize);
  1394. if (Result == FALSE) {
  1395. DWARF_ERROR("DWARF: BitOffset with no ByteOffset.\n");
  1396. return EINVAL;
  1397. }
  1398. StorageSize *= BITS_PER_BYTE;
  1399. //
  1400. // The old bit offset definition defines the highest order bit in
  1401. // use as an offset from the storage unit size. Turn that around
  1402. // into an offset from the start of the member.
  1403. //
  1404. assert(BitOffset + BitSize <= StorageSize);
  1405. BitOffset = StorageSize - (BitOffset + BitSize);
  1406. }
  1407. }
  1408. //
  1409. // Look for the data member location. This is not necessarily set for
  1410. // unions.
  1411. //
  1412. LocationAttribute = DwarfpGetAttribute(Die, DwarfAtDataMemberLocation);
  1413. if (LocationAttribute != NULL) {
  1414. memset(&LocationContext, 0, sizeof(DWARF_LOCATION_CONTEXT));
  1415. LocationContext.Unit = LoadingContext->CurrentUnit;
  1416. LocationContext.StackSize = 1;
  1417. Status = DwarfpGetLocation(Context,
  1418. &LocationContext,
  1419. LocationAttribute);
  1420. if (Status != 0) {
  1421. DwarfpDestroyLocationContext(Context, &LocationContext);
  1422. DWARF_ERROR("DWARF: Failed to evaluate member location.\n");
  1423. return Status;
  1424. }
  1425. assert((LocationContext.Location.BitSize == 0) &&
  1426. (LocationContext.Location.NextPiece == NULL));
  1427. if ((LocationContext.Location.Form == DwarfLocationKnownValue) ||
  1428. (LocationContext.Location.Form == DwarfLocationMemory)) {
  1429. BitOffset += LocationContext.Location.Value.Value * BITS_PER_BYTE;
  1430. } else {
  1431. DwarfpDestroyLocationContext(Context, &LocationContext);
  1432. DWARF_ERROR("DWARF: Unsupported member location %d.\n",
  1433. LocationContext.Location.Form);
  1434. return EINVAL;
  1435. }
  1436. DwarfpDestroyLocationContext(Context, &LocationContext);
  1437. }
  1438. //
  1439. // Get the type of the member.
  1440. //
  1441. Member = malloc(sizeof(STRUCTURE_MEMBER));
  1442. if (Member == NULL) {
  1443. return ENOMEM;
  1444. }
  1445. memset(Member, 0, sizeof(STRUCTURE_MEMBER));
  1446. Member->Name = DwarfpGetStringAttribute(Die, DwarfAtName);
  1447. Member->BitOffset = BitOffset;
  1448. Member->BitSize = BitSize;
  1449. Result = DwarfpGetTypeReferenceAttribute(Context,
  1450. Die,
  1451. DwarfAtType,
  1452. &(Member->TypeFile),
  1453. &(Member->TypeNumber));
  1454. if (Result == FALSE) {
  1455. free(Member);
  1456. DWARF_ERROR("DWARF: Unable to resolve type for member.\n");
  1457. return EINVAL;
  1458. }
  1459. //
  1460. // Add the member to the list.
  1461. //
  1462. Structure = LoadingContext->CurrentType;
  1463. assert((Structure != NULL) && (Structure->Type == DataTypeStructure));
  1464. PreviousMember = Structure->U.Structure.FirstMember;
  1465. if (PreviousMember == NULL) {
  1466. Structure->U.Structure.FirstMember = Member;
  1467. } else {
  1468. while (PreviousMember->NextMember != NULL) {
  1469. PreviousMember = PreviousMember->NextMember;
  1470. }
  1471. PreviousMember->NextMember = Member;
  1472. }
  1473. Structure->U.Structure.MemberCount += 1;
  1474. return 0;
  1475. }
  1476. INT
  1477. DwarfpProcessEnumerator (
  1478. PDWARF_CONTEXT Context,
  1479. PDWARF_DIE Die
  1480. )
  1481. /*++
  1482. Routine Description:
  1483. This routine processes an enumerator value.
  1484. Arguments:
  1485. Context - Supplies a pointer to the application context.
  1486. Die - Supplies a pointer to the DIE to process.
  1487. Return Value:
  1488. 0 on success.
  1489. Returns an error number on failure.
  1490. --*/
  1491. {
  1492. PENUMERATION_MEMBER Enumeration;
  1493. PTYPE_SYMBOL EnumeratorType;
  1494. PDWARF_LOADING_CONTEXT LoadingContext;
  1495. PENUMERATION_MEMBER Previous;
  1496. BOOL Result;
  1497. ULONGLONG Value;
  1498. LoadingContext = Context->LoadingContext;
  1499. Result = DwarfpGetIntegerAttribute(Die, DwarfAtConstValue, &Value);
  1500. if (Result == FALSE) {
  1501. DWARF_ERROR("DWARF: Enumerator with no value.\n");
  1502. return EINVAL;
  1503. }
  1504. //
  1505. // Get the type of the member.
  1506. //
  1507. Enumeration = malloc(sizeof(ENUMERATION_MEMBER));
  1508. if (Enumeration == NULL) {
  1509. return ENOMEM;
  1510. }
  1511. memset(Enumeration, 0, sizeof(ENUMERATION_MEMBER));
  1512. Enumeration->Name = DwarfpGetStringAttribute(Die, DwarfAtName);
  1513. Enumeration->Value = Value;
  1514. //
  1515. // Add the member to the list.
  1516. //
  1517. EnumeratorType = LoadingContext->CurrentType;
  1518. assert((EnumeratorType != NULL) &&
  1519. (EnumeratorType->Type == DataTypeEnumeration));
  1520. Previous = EnumeratorType->U.Enumeration.FirstMember;
  1521. if (Previous == NULL) {
  1522. EnumeratorType->U.Enumeration.FirstMember = Enumeration;
  1523. } else {
  1524. while (Previous->NextMember != NULL) {
  1525. Previous = Previous->NextMember;
  1526. }
  1527. Previous->NextMember = Enumeration;
  1528. }
  1529. EnumeratorType->U.Enumeration.MemberCount += 1;
  1530. return 0;
  1531. }
  1532. INT
  1533. DwarfpProcessSubroutineType (
  1534. PDWARF_CONTEXT Context,
  1535. PDWARF_DIE Die
  1536. )
  1537. /*++
  1538. Routine Description:
  1539. This routine processes a subroutine type (function pointer).
  1540. Arguments:
  1541. Context - Supplies a pointer to the application context.
  1542. Die - Supplies a pointer to the DIE to process.
  1543. Return Value:
  1544. 0 on success.
  1545. Returns an error number on failure.
  1546. --*/
  1547. {
  1548. PDWARF_LOADING_CONTEXT LoadingContext;
  1549. PTYPE_SYMBOL PreviousType;
  1550. PTYPE_SYMBOL Type;
  1551. LoadingContext = Context->LoadingContext;
  1552. assert(Die->Tag == DwarfTagSubroutineType);
  1553. Type = malloc(sizeof(TYPE_SYMBOL));
  1554. if (Type == NULL) {
  1555. return ENOMEM;
  1556. }
  1557. memset(Type, 0, sizeof(TYPE_SYMBOL));
  1558. Type->ParentSource = LoadingContext->CurrentFile;
  1559. PreviousType = LoadingContext->CurrentType;
  1560. LoadingContext->CurrentType = Type;
  1561. Type->ParentFunction = LoadingContext->CurrentFunction;
  1562. Type->Name = DwarfpGetStringAttribute(Die, DwarfAtName);
  1563. Type->TypeNumber = DWARF_DIE_ID(Context, Die);
  1564. Type->Type = DataTypeFunctionPointer;
  1565. Type->U.FunctionPointer.SizeInBytes =
  1566. LoadingContext->CurrentUnit->AddressSize;
  1567. INSERT_BEFORE(&(Type->ListEntry),
  1568. &(LoadingContext->CurrentFile->TypesHead));
  1569. //
  1570. // Process the child DIEs here to support getting the actual signature of
  1571. // the function pointer.
  1572. //
  1573. assert(LoadingContext->CurrentType == Type);
  1574. LoadingContext->CurrentType = PreviousType;
  1575. return 0;
  1576. }
  1577. INT
  1578. DwarfpProcessSubprogram (
  1579. PDWARF_CONTEXT Context,
  1580. PDWARF_DIE Die
  1581. )
  1582. /*++
  1583. Routine Description:
  1584. This routine processes a subprogram (function) DIE.
  1585. Arguments:
  1586. Context - Supplies a pointer to the application context.
  1587. Die - Supplies a pointer to the DIE to process.
  1588. Return Value:
  1589. 0 on success.
  1590. Returns an error number on failure.
  1591. --*/
  1592. {
  1593. ULONG AllocationSize;
  1594. ULONGLONG Declaration;
  1595. PDWARF_FUNCTION_SYMBOL DwarfFunction;
  1596. PDWARF_ATTRIBUTE_VALUE FrameBase;
  1597. PFUNCTION_SYMBOL Function;
  1598. PDWARF_LOADING_CONTEXT LoadingContext;
  1599. PFUNCTION_SYMBOL PreviousFunction;
  1600. BOOL Result;
  1601. INT Status;
  1602. LoadingContext = Context->LoadingContext;
  1603. //
  1604. // Ignore function declarations.
  1605. //
  1606. Declaration = 0;
  1607. DwarfpGetIntegerAttribute(Die, DwarfAtDeclaration, &Declaration);
  1608. if (Declaration != FALSE) {
  1609. return 0;
  1610. }
  1611. //
  1612. // Also ignore inlined functions. It seems that even a value of 0
  1613. // (indicating not inlined) results in no low-pc value.
  1614. //
  1615. if (DwarfpGetIntegerAttribute(Die, DwarfAtInline, &Declaration) != FALSE) {
  1616. return 0;
  1617. }
  1618. AllocationSize = sizeof(FUNCTION_SYMBOL) + sizeof(DWARF_FUNCTION_SYMBOL);
  1619. Function = malloc(AllocationSize);
  1620. if (Function == NULL) {
  1621. return ENOMEM;
  1622. }
  1623. memset(Function, 0, AllocationSize);
  1624. DwarfFunction = (PDWARF_FUNCTION_SYMBOL)(Function + 1);
  1625. Function->SymbolContext = DwarfFunction;
  1626. DwarfFunction->Unit = LoadingContext->CurrentUnit;
  1627. INITIALIZE_LIST_HEAD(&(Function->ParametersHead));
  1628. INITIALIZE_LIST_HEAD(&(Function->LocalsHead));
  1629. Function->ParentSource = LoadingContext->CurrentFile;
  1630. Result = DwarfpGetTypeReferenceAttribute(Context,
  1631. Die,
  1632. DwarfAtType,
  1633. &(Function->ReturnTypeOwner),
  1634. &(Function->ReturnTypeNumber));
  1635. if (Result == FALSE) {
  1636. free(Function);
  1637. DWARF_ERROR("DWARF: Failed to get return type.\n");
  1638. return EINVAL;
  1639. }
  1640. PreviousFunction = LoadingContext->CurrentFunction;
  1641. LoadingContext->CurrentFunction = Function;
  1642. Function->Name = DwarfpGetStringAttribute(Die, DwarfAtName);
  1643. Result = DwarfpGetAddressAttribute(Die,
  1644. DwarfAtLowPc,
  1645. &(Function->StartAddress));
  1646. if (Result == FALSE) {
  1647. DWARF_ERROR("DWARF: Warning: Failed to get low pc for function %s.\n",
  1648. Function->Name);
  1649. }
  1650. Result = DwarfpGetAddressAttribute(Die,
  1651. DwarfAtHighPc,
  1652. &(Function->EndAddress));
  1653. if (Result == FALSE) {
  1654. //
  1655. // DWARF4 also allows constant forms for high PC, in which case
  1656. // it's an offset from low PC.
  1657. //
  1658. Result = DwarfpGetIntegerAttribute(Die,
  1659. DwarfAtHighPc,
  1660. &(Function->EndAddress));
  1661. if (Result != FALSE) {
  1662. Function->EndAddress += Function->StartAddress;
  1663. }
  1664. }
  1665. if ((Function->EndAddress < Function->StartAddress) &&
  1666. (Function->StartAddress != 0)) {
  1667. Function->EndAddress = Function->StartAddress + 1;
  1668. }
  1669. FrameBase = DwarfpGetAttribute(Die, DwarfAtFrameBase);
  1670. if (FrameBase != NULL) {
  1671. memcpy(&(DwarfFunction->FrameBase),
  1672. FrameBase,
  1673. sizeof(DWARF_ATTRIBUTE_VALUE));
  1674. }
  1675. INSERT_BEFORE(&(Function->ListEntry),
  1676. &(LoadingContext->CurrentFile->FunctionsHead));
  1677. Status = DwarfpProcessChildDies(Context, Die);
  1678. assert(LoadingContext->CurrentFunction == Function);
  1679. LoadingContext->CurrentFunction = PreviousFunction;
  1680. return Status;
  1681. }
  1682. INT
  1683. DwarfpProcessVariable (
  1684. PDWARF_CONTEXT Context,
  1685. PDWARF_DIE Die
  1686. )
  1687. /*++
  1688. Routine Description:
  1689. This routine processes a variable or formal parameter DIE.
  1690. Arguments:
  1691. Context - Supplies a pointer to the application context.
  1692. Die - Supplies a pointer to the DIE to process.
  1693. Return Value:
  1694. 0 on success.
  1695. Returns an error number on failure.
  1696. --*/
  1697. {
  1698. UINTN AllocationSize;
  1699. PDWARF_COMPLEX_DATA_SYMBOL DwarfSymbol;
  1700. PDWARF_LOADING_CONTEXT LoadingContext;
  1701. PDWARF_ATTRIBUTE_VALUE Location;
  1702. BOOL Result;
  1703. PDWARF_COMPILATION_UNIT Unit;
  1704. PDATA_SYMBOL Variable;
  1705. LoadingContext = Context->LoadingContext;
  1706. Unit = LoadingContext->CurrentUnit;
  1707. Location = DwarfpGetAttribute(Die, DwarfAtLocation);
  1708. //
  1709. // Ignore variables with no location (optimized away probably).
  1710. //
  1711. if (Location == NULL) {
  1712. return 0;
  1713. }
  1714. if ((Location->Form != DwarfFormExprLoc) &&
  1715. (!DWARF_BLOCK_FORM(Location->Form)) &&
  1716. (!DWARF_SECTION_OFFSET_FORM(Location->Form, Unit))) {
  1717. DWARF_ERROR("DWARF: Variable with bad location form %d.\n",
  1718. Location->Form);
  1719. return EINVAL;
  1720. }
  1721. AllocationSize = sizeof(DATA_SYMBOL) + sizeof(DWARF_COMPLEX_DATA_SYMBOL);
  1722. Variable = malloc(AllocationSize);
  1723. if (Variable == NULL) {
  1724. return ENOMEM;
  1725. }
  1726. memset(Variable, 0, AllocationSize);
  1727. Variable->ParentSource = LoadingContext->CurrentFile;
  1728. Variable->ParentFunction = LoadingContext->CurrentFunction;
  1729. Result = DwarfpGetTypeReferenceAttribute(Context,
  1730. Die,
  1731. DwarfAtType,
  1732. &(Variable->TypeOwner),
  1733. &(Variable->TypeNumber));
  1734. if (Result == FALSE) {
  1735. DWARF_ERROR("DWARF: Failed to get variable type.\n");
  1736. free(Variable);
  1737. return EINVAL;
  1738. }
  1739. Variable->Name = DwarfpGetStringAttribute(Die, DwarfAtName);
  1740. DwarfSymbol = (PDWARF_COMPLEX_DATA_SYMBOL)(Variable + 1);
  1741. Variable->LocationType = DataLocationComplex;
  1742. Variable->Location.Complex = DwarfSymbol;
  1743. DwarfSymbol->Unit = LoadingContext->CurrentUnit;
  1744. memcpy(&(DwarfSymbol->LocationAttribute),
  1745. Location,
  1746. sizeof(DWARF_ATTRIBUTE_VALUE));
  1747. assert(LIST_EMPTY(&(Die->ChildList)));
  1748. if (Die->Tag == DwarfTagFormalParameter) {
  1749. assert(LoadingContext->CurrentFunction != NULL);
  1750. INSERT_BEFORE(&(Variable->ListEntry),
  1751. &(LoadingContext->CurrentFunction->ParametersHead));
  1752. } else {
  1753. if (LoadingContext->CurrentFunction != NULL) {
  1754. INSERT_BEFORE(&(Variable->ListEntry),
  1755. &(LoadingContext->CurrentFunction->LocalsHead));
  1756. } else {
  1757. INSERT_BEFORE(&(Variable->ListEntry),
  1758. &(LoadingContext->CurrentFile->DataSymbolsHead));
  1759. }
  1760. }
  1761. return 0;
  1762. }
  1763. INT
  1764. DwarfpProcessGenericBlock (
  1765. PDWARF_CONTEXT Context,
  1766. PDWARF_DIE Die
  1767. )
  1768. /*++
  1769. Routine Description:
  1770. This routine processes a generic block, including a lexical block or a
  1771. namespace. It simply recurses into its children.
  1772. Arguments:
  1773. Context - Supplies a pointer to the application context.
  1774. Die - Supplies a pointer to the DIE to process.
  1775. Return Value:
  1776. 0 on success.
  1777. Returns an error number on failure.
  1778. --*/
  1779. {
  1780. return DwarfpProcessChildDies(Context, Die);
  1781. }