1
0

dwarf.c 66 KB

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