coff.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990
  1. /*++
  2. Copyright (c) 2012 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. coff.c
  9. Abstract:
  10. This module handles parsing COFF symbol tables, used in PE images.
  11. Author:
  12. Evan Green 5-Sep-2012
  13. Environment:
  14. Debug
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include "dbgrtl.h"
  20. #include <minoca/lib/im.h>
  21. #include <minoca/debug/dbgext.h>
  22. #include "pe.h"
  23. #include "symbols.h"
  24. #include "stabs.h"
  25. #include <assert.h>
  26. #include <errno.h>
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. //
  31. // ---------------------------------------------------------------- Definitions
  32. //
  33. #define MALLOC(_x) malloc(_x)
  34. #define FREE(_x) free(_x)
  35. //
  36. // ------------------------------------------------------ Data Type Definitions
  37. //
  38. typedef struct _COFF_SECTION COFF_SECTION, *PCOFF_SECTION;
  39. struct _COFF_SECTION {
  40. PCOFF_SECTION Next;
  41. LONG SectionIndex;
  42. ULONG SectionAddress;
  43. };
  44. //
  45. // ----------------------------------------------- Internal Function Prototypes
  46. //
  47. LONG
  48. DbgpGetFileSize (
  49. FILE *File
  50. );
  51. VOID
  52. DbgpCoffFreeSymbols (
  53. PDEBUG_SYMBOLS Symbols
  54. );
  55. BOOL
  56. DbgpLoadCoffSymbolTable (
  57. PDEBUG_SYMBOLS Symbols,
  58. PSTR Filename,
  59. PCOFF_SECTION *SectionList
  60. );
  61. BOOL
  62. DbgpParseCoffSymbolTable (
  63. PDEBUG_SYMBOLS Symbols,
  64. PCOFF_SECTION SectionList
  65. );
  66. PSTR
  67. DbgpGetCoffSymbolName (
  68. PCOFF_SYMBOL Symbol,
  69. PDEBUG_SYMBOLS SymbolData,
  70. BOOL TruncateLeadingUnderscore
  71. );
  72. BOOL
  73. DbgpCreateOrUpdateCoffSymbol (
  74. PDEBUG_SYMBOLS Symbols,
  75. PCOFF_SYMBOL CoffSymbol,
  76. PSTR Name,
  77. ULONGLONG Value
  78. );
  79. //
  80. // -------------------------------------------------------------------- Globals
  81. //
  82. DEBUG_SYMBOL_INTERFACE DbgCoffSymbolInterface = {
  83. DbgpCoffLoadSymbols,
  84. DbgpCoffFreeSymbols,
  85. NULL,
  86. NULL,
  87. NULL,
  88. NULL
  89. };
  90. //
  91. // ------------------------------------------------------------------ Functions
  92. //
  93. INT
  94. DbgpCoffLoadSymbols (
  95. PSTR Filename,
  96. IMAGE_MACHINE_TYPE MachineType,
  97. ULONG Flags,
  98. PVOID HostContext,
  99. PDEBUG_SYMBOLS *Symbols
  100. )
  101. /*++
  102. Routine Description:
  103. This routine loads debugging symbol information from the specified file.
  104. Arguments:
  105. Filename - Supplies the name of the binary to load symbols from.
  106. MachineType - Supplies the required machine type of the image. Set to
  107. unknown to allow the symbol library to load a file with any machine
  108. type.
  109. Flags - Supplies a bitfield of flags governing the behavior during load.
  110. These flags are specific to each symbol library.
  111. HostContext - Supplies the value to store in the host context field of the
  112. debug symbols.
  113. Symbols - Supplies an optional pointer where a pointer to the symbols will
  114. be returned on success.
  115. Return Value:
  116. 0 on success.
  117. Returns an error number on failure.
  118. --*/
  119. {
  120. UINTN AllocationSize;
  121. PDEBUG_SYMBOLS CoffSymbols;
  122. BOOL Result;
  123. INT Status;
  124. AllocationSize = sizeof(DEBUG_SYMBOLS) + sizeof(STAB_CONTEXT);
  125. CoffSymbols = MALLOC(AllocationSize);
  126. if (CoffSymbols == NULL) {
  127. Status = ENOMEM;
  128. goto CoffLoadSymbolsEnd;
  129. }
  130. memset(CoffSymbols, 0, AllocationSize);
  131. INITIALIZE_LIST_HEAD(&(CoffSymbols->SourcesHead));
  132. CoffSymbols->Interface = &DbgCoffSymbolInterface;
  133. CoffSymbols->SymbolContext = CoffSymbols + 1;
  134. CoffSymbols->HostContext = HostContext;
  135. Result = DbgpLoadCoffSymbols(CoffSymbols, Filename);
  136. if (Result == FALSE) {
  137. Status = EINVAL;
  138. goto CoffLoadSymbolsEnd;
  139. }
  140. Status = 0;
  141. CoffLoadSymbolsEnd:
  142. if (Status != 0) {
  143. if (CoffSymbols != NULL) {
  144. DbgpCoffFreeSymbols(CoffSymbols);
  145. CoffSymbols = NULL;
  146. }
  147. }
  148. *Symbols = CoffSymbols;
  149. return 0;
  150. }
  151. BOOL
  152. DbgpLoadCoffSymbols (
  153. PDEBUG_SYMBOLS Symbols,
  154. PSTR Filename
  155. )
  156. /*++
  157. Routine Description:
  158. This routine loads COFF symbols into a pre-existing set of debug symbols.
  159. Arguments:
  160. Symbols - Supplies a pointer to debug symbols that are assumed to have
  161. already been allocated and initialized.
  162. Filename - Supplies the name of the file to load COFF symbols for.
  163. Return Value:
  164. TRUE on success.
  165. FALSE on failure.
  166. --*/
  167. {
  168. PCOFF_SECTION CurrentSection;
  169. PCOFF_SECTION NextSection;
  170. BOOL Result;
  171. PCOFF_SECTION SectionList;
  172. SectionList = NULL;
  173. Result = DbgpLoadCoffSymbolTable(Symbols, Filename, &SectionList);
  174. if (Result == FALSE) {
  175. goto LoadCoffSymbolsEnd;
  176. }
  177. Result = DbgpParseCoffSymbolTable(Symbols, SectionList);
  178. if (Result == FALSE) {
  179. goto LoadCoffSymbolsEnd;
  180. }
  181. LoadCoffSymbolsEnd:
  182. //
  183. // Free the section list if one was created.
  184. //
  185. CurrentSection = SectionList;
  186. while (CurrentSection != NULL) {
  187. NextSection = CurrentSection->Next;
  188. FREE(CurrentSection);
  189. CurrentSection = NextSection;
  190. }
  191. return Result;
  192. }
  193. //
  194. // --------------------------------------------------------- Internal Functions
  195. //
  196. VOID
  197. DbgpCoffFreeSymbols (
  198. PDEBUG_SYMBOLS Symbols
  199. )
  200. /*++
  201. Routine Description:
  202. This routine frees all memory associated with an instance of debugging
  203. symbols. Once called, the pointer passed in should not be dereferenced
  204. again by the caller.
  205. Arguments:
  206. Symbols - Supplies a pointer to the debugging symbols.
  207. Return Value:
  208. None.
  209. --*/
  210. {
  211. PLIST_ENTRY CurrentFunctionEntry;
  212. PLIST_ENTRY CurrentGlobalEntry;
  213. PLIST_ENTRY CurrentSourceEntry;
  214. PFUNCTION_SYMBOL Function;
  215. PDATA_SYMBOL GlobalVariable;
  216. PLIST_ENTRY NextFunctionEntry;
  217. PSOURCE_FILE_SYMBOL SourceFile;
  218. PSTAB_CONTEXT StabContext;
  219. StabContext = Symbols->SymbolContext;
  220. if (Symbols->Filename != NULL) {
  221. FREE(Symbols->Filename);
  222. }
  223. if (StabContext->RawSymbolTable != NULL) {
  224. FREE(StabContext->RawSymbolTable);
  225. }
  226. if (StabContext->RawSymbolTableStrings != NULL) {
  227. FREE(StabContext->RawSymbolTableStrings);
  228. }
  229. //
  230. // Free Source files.
  231. //
  232. CurrentSourceEntry = Symbols->SourcesHead.Next;
  233. while ((CurrentSourceEntry != &(Symbols->SourcesHead)) &&
  234. (CurrentSourceEntry != NULL)) {
  235. SourceFile = LIST_VALUE(CurrentSourceEntry,
  236. SOURCE_FILE_SYMBOL,
  237. ListEntry);
  238. assert(LIST_EMPTY(&(SourceFile->TypesHead)));
  239. //
  240. // Free functions.
  241. //
  242. CurrentFunctionEntry = SourceFile->FunctionsHead.Next;
  243. while (CurrentFunctionEntry != &(SourceFile->FunctionsHead)) {
  244. Function = LIST_VALUE(CurrentFunctionEntry,
  245. FUNCTION_SYMBOL,
  246. ListEntry);
  247. assert(LIST_EMPTY(&(Function->ParametersHead)));
  248. assert(LIST_EMPTY(&(Function->LocalsHead)));
  249. assert(LIST_EMPTY(&(Function->FunctionsHead)));
  250. if (Function->Name != NULL) {
  251. FREE(Function->Name);
  252. }
  253. NextFunctionEntry = CurrentFunctionEntry->Next;
  254. FREE(Function);
  255. CurrentFunctionEntry = NextFunctionEntry;
  256. }
  257. assert(LIST_EMPTY(&(SourceFile->SourceLinesHead)));
  258. //
  259. // Free global/static symbols.
  260. //
  261. CurrentGlobalEntry = SourceFile->DataSymbolsHead.Next;
  262. while (CurrentGlobalEntry != &(SourceFile->DataSymbolsHead)) {
  263. GlobalVariable = LIST_VALUE(CurrentGlobalEntry,
  264. DATA_SYMBOL,
  265. ListEntry);
  266. if (GlobalVariable->Name != NULL) {
  267. FREE(GlobalVariable->Name);
  268. }
  269. CurrentGlobalEntry = CurrentGlobalEntry->Next;
  270. FREE(GlobalVariable);
  271. }
  272. CurrentSourceEntry = CurrentSourceEntry->Next;
  273. FREE(SourceFile);
  274. }
  275. FREE(Symbols);
  276. return;
  277. }
  278. BOOL
  279. DbgpLoadCoffSymbolTable (
  280. PDEBUG_SYMBOLS Symbols,
  281. PSTR Filename,
  282. PCOFF_SECTION *SectionList
  283. )
  284. /*++
  285. Routine Description:
  286. This routine loads the raw COFF symbol table out of the file.
  287. Arguments:
  288. Symbols - Supplies a pointer to debug symbols that are assumed to have
  289. already been allocated and initialized.
  290. Filename - Supplies the name of the file to load COFF symbols for.
  291. SectionList - Supplies a pointer that will receive a pointer to the list of
  292. sections in the COFF file. Most COFF symbol values are relative to a
  293. section like .text or .bss.
  294. Return Value:
  295. TRUE on success.
  296. FALSE on failure.
  297. --*/
  298. {
  299. ULONG BytesRead;
  300. PIMAGE_SECTION_HEADER CurrentSection;
  301. FILE *File;
  302. PVOID FileBuffer;
  303. ULONG FileSize;
  304. PCOFF_SECTION FirstSection;
  305. ULONG ImageBase;
  306. IMAGE_BUFFER ImageBuffer;
  307. PCOFF_SECTION NewSectionEntry;
  308. PCOFF_SECTION NextSectionEntry;
  309. PIMAGE_NT_HEADERS PeHeader;
  310. BOOL Result;
  311. ULONG SectionIndex;
  312. PUCHAR Source;
  313. ULONG SourceSize;
  314. PSTAB_CONTEXT StabContext;
  315. StabContext = Symbols->SymbolContext;
  316. CurrentSection = NULL;
  317. FileBuffer = NULL;
  318. FirstSection = NULL;
  319. memset(&ImageBuffer, 0, sizeof(IMAGE_BUFFER));
  320. StabContext->RawSymbolTable = NULL;
  321. StabContext->RawSymbolTableStrings = NULL;
  322. //
  323. // Determine the file size and load the file into memory.
  324. //
  325. File = fopen(Filename, "rb");
  326. if (File == NULL) {
  327. Result = FALSE;
  328. goto LoadCoffSymbolTableEnd;
  329. }
  330. FileSize = DbgpGetFileSize(File);
  331. if (FileSize <= 0) {
  332. Result = FALSE;
  333. goto LoadCoffSymbolTableEnd;
  334. }
  335. FileBuffer = MALLOC(FileSize);
  336. if (FileBuffer == NULL) {
  337. Result = FALSE;
  338. goto LoadCoffSymbolTableEnd;
  339. }
  340. BytesRead = fread(FileBuffer, 1, FileSize, File);
  341. if (BytesRead != FileSize) {
  342. Result = FALSE;
  343. goto LoadCoffSymbolTableEnd;
  344. }
  345. ImageBuffer.Data = FileBuffer;
  346. ImageBuffer.Size = FileSize;
  347. //
  348. // Get the PE headers to determine the location of the symbol table.
  349. //
  350. Result = ImpPeGetHeaders(&ImageBuffer, &PeHeader);
  351. if (Result == FALSE) {
  352. goto LoadCoffSymbolTableEnd;
  353. }
  354. Source = FileBuffer;
  355. Source += PeHeader->FileHeader.PointerToSymbolTable;
  356. SourceSize = PeHeader->FileHeader.NumberOfSymbols * sizeof(COFF_SYMBOL);
  357. //
  358. // Allocate space for the symbol table and copy it in.
  359. //
  360. StabContext->RawSymbolTableSize = SourceSize;
  361. StabContext->RawSymbolTable = MALLOC(SourceSize);
  362. if (StabContext->RawSymbolTable == NULL) {
  363. Result = FALSE;
  364. goto LoadCoffSymbolTableEnd;
  365. }
  366. memcpy(StabContext->RawSymbolTable, Source, SourceSize);
  367. //
  368. // Find the string table, which is right after the symbol table, allocate
  369. // memory for it, and copy it in. Note that the first four bytes contain
  370. // the total size of the string table, but those four bytes should be
  371. // treated as 0 when reading strings from the string table.
  372. //
  373. Source += SourceSize;
  374. SourceSize = *((PULONG)Source);
  375. StabContext->RawSymbolTableStringsSize = SourceSize;
  376. StabContext->RawSymbolTableStrings = MALLOC(SourceSize);
  377. if (StabContext->RawSymbolTableStrings == NULL) {
  378. Result = FALSE;
  379. goto LoadCoffSymbolTableEnd;
  380. }
  381. memcpy(StabContext->RawSymbolTableStrings, Source, SourceSize);
  382. //
  383. // Set the first four bytes to 0.
  384. //
  385. *((PULONG)(StabContext->RawSymbolTableStrings)) = 0;
  386. //
  387. // Create the section list.
  388. //
  389. ImageBase = PeHeader->OptionalHeader.ImageBase;
  390. CurrentSection = (PIMAGE_SECTION_HEADER)(PeHeader + 1);
  391. for (SectionIndex = 0;
  392. SectionIndex < PeHeader->FileHeader.NumberOfSections;
  393. SectionIndex += 1) {
  394. //
  395. // Skip the section if its not even loaded into memory.
  396. //
  397. if ((CurrentSection->Characteristics &
  398. IMAGE_SCN_MEM_DISCARDABLE) != 0) {
  399. CurrentSection += 1;
  400. continue;
  401. }
  402. //
  403. // Allocate space for the new entry and fill it out. Sections according
  404. // to COFF symbols are 1 based.
  405. //
  406. NewSectionEntry = MALLOC(sizeof(COFF_SECTION));
  407. if (NewSectionEntry == NULL) {
  408. Result = FALSE;
  409. goto LoadCoffSymbolTableEnd;
  410. }
  411. RtlZeroMemory(NewSectionEntry, sizeof(COFF_SECTION));
  412. NewSectionEntry->SectionIndex = SectionIndex + 1;
  413. NewSectionEntry->SectionAddress = ImageBase +
  414. CurrentSection->VirtualAddress;
  415. //
  416. // Link the new section at the head of the list.
  417. //
  418. NewSectionEntry->Next = FirstSection;
  419. FirstSection = NewSectionEntry;
  420. //
  421. // Advance to the next section.
  422. //
  423. CurrentSection += 1;
  424. }
  425. Result = TRUE;
  426. LoadCoffSymbolTableEnd:
  427. if (FileBuffer != NULL) {
  428. FREE(FileBuffer);
  429. }
  430. if (Result == FALSE) {
  431. if (StabContext->RawSymbolTable != NULL) {
  432. FREE(StabContext->RawSymbolTable);
  433. }
  434. if (StabContext->RawSymbolTableStrings != NULL) {
  435. FREE(StabContext->RawSymbolTableStrings);
  436. }
  437. //
  438. // Free all section entries.
  439. //
  440. if (FirstSection != NULL) {
  441. NewSectionEntry = FirstSection;
  442. while (NewSectionEntry != NULL) {
  443. NextSectionEntry = NewSectionEntry->Next;
  444. FREE(NewSectionEntry);
  445. NewSectionEntry = NextSectionEntry;
  446. }
  447. }
  448. //
  449. // If successful, return the section list.
  450. //
  451. } else {
  452. *SectionList = FirstSection;
  453. }
  454. if (File != NULL) {
  455. fclose(File);
  456. }
  457. return Result;
  458. }
  459. BOOL
  460. DbgpParseCoffSymbolTable (
  461. PDEBUG_SYMBOLS Symbols,
  462. PCOFF_SECTION SectionList
  463. )
  464. /*++
  465. Routine Description:
  466. This routine parses COFF symbol tables and combines them with existing
  467. debug symbols.
  468. Arguments:
  469. Symbols - Supplies a pointer to debug symbols that are assumed to have
  470. already been allocated and initialized. The raw symbol tables and
  471. string table are expected to be valid.
  472. SectionList - Supplies a list of all loadable section in the image. Most
  473. COFF symbols are relative to a section, so this is needed to determine
  474. the real address.
  475. Return Value:
  476. TRUE on success.
  477. FALSE on failure.
  478. --*/
  479. {
  480. ULONG BytesRead;
  481. PCOFF_SECTION CurrentSection;
  482. PSTR Name;
  483. PSTAB_CONTEXT StabContext;
  484. PCOFF_SYMBOL Symbol;
  485. BOOL SymbolCreated;
  486. ULONGLONG SymbolValue;
  487. BytesRead = 0;
  488. StabContext = Symbols->SymbolContext;
  489. //
  490. // Validate that the symbol tables are there.
  491. //
  492. if ((Symbols == NULL) || (StabContext->RawSymbolTable == NULL) ||
  493. (StabContext->RawSymbolTableStrings == NULL)) {
  494. return FALSE;
  495. }
  496. Symbol = (PCOFF_SYMBOL)(StabContext->RawSymbolTable);
  497. while (BytesRead + sizeof(COFF_SYMBOL) <= StabContext->RawSymbolTableSize) {
  498. SymbolValue = 0;
  499. //
  500. // Attempt to find the section matching this symbol. If none can be
  501. // found, ignore the symbol. Negative section indices are possible, but
  502. // these symbols are usually not that useful.
  503. //
  504. if ((SHORT)Symbol->Section > 0) {
  505. CurrentSection = SectionList;
  506. while (CurrentSection != NULL) {
  507. if (CurrentSection->SectionIndex == Symbol->Section) {
  508. break;
  509. }
  510. CurrentSection = CurrentSection->Next;
  511. }
  512. if (CurrentSection != NULL) {
  513. SymbolValue = Symbol->Value + CurrentSection->SectionAddress;
  514. }
  515. }
  516. //
  517. // Skip all symbols except class 2 symbols, which represent C_EXT
  518. // external symbols.
  519. //
  520. if (Symbol->Class != 2) {
  521. SymbolValue = 0;
  522. }
  523. //
  524. // If a valid value was found for the symbol, attempt to get its name.
  525. //
  526. if (SymbolValue != 0) {
  527. Name = DbgpGetCoffSymbolName(Symbol, Symbols, TRUE);
  528. //
  529. // If the symbol has a valid name, attempt to add it.
  530. //
  531. if (Name != NULL) {
  532. SymbolCreated = DbgpCreateOrUpdateCoffSymbol(Symbols,
  533. Symbol,
  534. Name,
  535. SymbolValue);
  536. if (SymbolCreated == FALSE) {
  537. FREE(Name);
  538. }
  539. }
  540. }
  541. //
  542. // Skip over any extra data this symbol may have in multiples of
  543. // COFF symbol entries.
  544. //
  545. if (Symbol->AuxCount != 0) {
  546. BytesRead += Symbol->AuxCount * sizeof(COFF_SYMBOL);
  547. Symbol += Symbol->AuxCount;
  548. }
  549. //
  550. // Go to the next symbol in the table.
  551. //
  552. BytesRead += sizeof(COFF_SYMBOL);
  553. Symbol += 1;
  554. }
  555. return TRUE;
  556. }
  557. PSTR
  558. DbgpGetCoffSymbolName (
  559. PCOFF_SYMBOL Symbol,
  560. PDEBUG_SYMBOLS SymbolData,
  561. BOOL TruncateLeadingUnderscore
  562. )
  563. /*++
  564. Routine Description:
  565. This routine gets the name of the given COFF symbol. The caller is
  566. responsible for freeing memory returned here.
  567. Arguments:
  568. Symbol - Supplies a pointer to the COFF symbol to get the name of.
  569. SymbolData - Supplies a pointer to debug symbols containing a valid
  570. symbol table and string table.
  571. TruncateLeadingUnderscore - Supplies a boolean indicating whether or not
  572. to truncate leading underscores at the beginning of symbol names. If
  573. this flag is TRUE and the symbol name is found to begin with an
  574. underscore, this underscore will be removed.
  575. Return Value:
  576. Returns a pointer to a newly allocated buffer containing the name of the
  577. symbol on success.
  578. NULL on failure or if the symbol has no name.
  579. --*/
  580. {
  581. ULONG Length;
  582. PSTR Name;
  583. PSTAB_CONTEXT StabContext;
  584. PSTR StringTable;
  585. StabContext = SymbolData->SymbolContext;
  586. Name = NULL;
  587. StringTable = StabContext->RawSymbolTableStrings;
  588. //
  589. // If the symbol name has its zeroes field zeroed, then use the offset
  590. // into the symbol table.
  591. //
  592. if (Symbol->Zeroes == 0) {
  593. if (StringTable == NULL) {
  594. goto GetCoffSymbolNameEnd;
  595. }
  596. if (Symbol->Offset >= StabContext->RawSymbolTableStringsSize) {
  597. goto GetCoffSymbolNameEnd;
  598. }
  599. Length = strlen(StringTable + Symbol->Offset);
  600. Name = MALLOC(Length + 1);
  601. if (Name == NULL) {
  602. goto GetCoffSymbolNameEnd;
  603. }
  604. strcpy(Name, StringTable + Symbol->Offset);
  605. Name[Length] = '\0';
  606. //
  607. // If the symbol name does not have its zeroes field zeroed, then the name
  608. // is baked right into the symbol. Note that it is only NULL terminated if
  609. // there is room for the NULL terminator.
  610. //
  611. } else {
  612. Name = MALLOC(COFF_SYMBOL_NAME_LENGTH + 1);
  613. if (Name == NULL) {
  614. goto GetCoffSymbolNameEnd;
  615. }
  616. strncpy(Name, Symbol->Name, COFF_SYMBOL_NAME_LENGTH);
  617. Name[COFF_SYMBOL_NAME_LENGTH] = '\0';
  618. }
  619. //
  620. // If leading underscores are to be truncated, look for that now.
  621. //
  622. if ((TruncateLeadingUnderscore != FALSE) && (Name != NULL) &&
  623. (Name[0] == '_')) {
  624. strcpy(Name, Name + 1);
  625. }
  626. GetCoffSymbolNameEnd:
  627. return Name;
  628. }
  629. BOOL
  630. DbgpCreateOrUpdateCoffSymbol (
  631. PDEBUG_SYMBOLS Symbols,
  632. PCOFF_SYMBOL CoffSymbol,
  633. PSTR Name,
  634. ULONGLONG Value
  635. )
  636. /*++
  637. Routine Description:
  638. This routine adds a symbol to the debug symbols or updates a value if its
  639. currently set as NULL given the COFF symbol.
  640. Arguments:
  641. Symbols - Supplies a pointer to the debug symbols where the new symbol will
  642. be stored.
  643. CoffSymbol - Supplies a pointer to the new COFF symbol to be put in.
  644. Name - Supplies a pointer to the symbol name.
  645. Value - Supplies a pointer to the symbol value.
  646. Return Value:
  647. TRUE if a new symbol was created and the Name buffer should not be freed.
  648. FALSE if an existing symbol was updated, or no symbol was generated at all.
  649. --*/
  650. {
  651. PSOURCE_FILE_SYMBOL CurrentSource;
  652. PLIST_ENTRY CurrentSourceEntry;
  653. PSOURCE_FILE_SYMBOL FunctionParent;
  654. PFUNCTION_SYMBOL NewFunction;
  655. SYMBOL_SEARCH_RESULT Result;
  656. PSYMBOL_SEARCH_RESULT ResultPointer;
  657. BOOL SymbolAdded;
  658. RtlZeroMemory(&Result, sizeof(SYMBOL_SEARCH_RESULT));
  659. Result.Variety = SymbolResultInvalid;
  660. SymbolAdded = FALSE;
  661. //
  662. // A symbol with type 0x20 indicates a function.
  663. //
  664. if ((CoffSymbol->Type & 0xF0) == 0x20) {
  665. ResultPointer = DbgFindFunctionSymbol(Symbols, Name, 0, &Result);
  666. //
  667. // If the function does not exist, create it. For now, only create new
  668. // functions, don't update existing ones.
  669. //
  670. if (ResultPointer == NULL) {
  671. //
  672. // Attempt to find the source file this belongs under. Loop through
  673. // all source files looking for one whose address range contains
  674. // this function.
  675. //
  676. CurrentSourceEntry = Symbols->SourcesHead.Next;
  677. FunctionParent = NULL;
  678. while (CurrentSourceEntry != &(Symbols->SourcesHead)) {
  679. CurrentSource = LIST_VALUE(CurrentSourceEntry,
  680. SOURCE_FILE_SYMBOL,
  681. ListEntry);
  682. if ((CurrentSource->StartAddress <= Value) &&
  683. (CurrentSource->EndAddress > Value)) {
  684. FunctionParent = CurrentSource;
  685. break;
  686. }
  687. CurrentSourceEntry = CurrentSourceEntry->Next;
  688. }
  689. //
  690. // If a parent source could not be found, there's nowhere to add
  691. // this function to.
  692. //
  693. if (FunctionParent == NULL) {
  694. goto CreateOrUpdateCoffSymbolEnd;
  695. }
  696. NewFunction = MALLOC(sizeof(FUNCTION_SYMBOL));
  697. if (NewFunction == NULL) {
  698. goto CreateOrUpdateCoffSymbolEnd;
  699. }
  700. RtlZeroMemory(NewFunction, sizeof(FUNCTION_SYMBOL));
  701. NewFunction->ParentSource = FunctionParent;
  702. NewFunction->Name = Name;
  703. NewFunction->FunctionNumber = 1000;
  704. INITIALIZE_LIST_HEAD(&(NewFunction->ParametersHead));
  705. INITIALIZE_LIST_HEAD(&(NewFunction->LocalsHead));
  706. INITIALIZE_LIST_HEAD(&(NewFunction->FunctionsHead));
  707. NewFunction->StartAddress = Value;
  708. NewFunction->EndAddress = Value + 0x20;
  709. NewFunction->ReturnTypeNumber = 0;
  710. NewFunction->ReturnTypeOwner = NULL;
  711. //
  712. // Insert the function into the current source file's list of
  713. // functions.
  714. //
  715. INSERT_BEFORE(&(NewFunction->ListEntry),
  716. &(FunctionParent->FunctionsHead));
  717. SymbolAdded = TRUE;
  718. }
  719. //
  720. // Assume everything that's not a function is data, a global.
  721. //
  722. } else {
  723. ResultPointer = DbgFindDataSymbol(Symbols, Name, 0, &Result);
  724. //
  725. // If it exists and it's current value is NULL, update it. For now,
  726. // only update, do not create globals.
  727. //
  728. if ((ResultPointer != NULL) &&
  729. (Result.U.DataResult->LocationType ==
  730. DataLocationAbsoluteAddress) &&
  731. (Result.U.DataResult->Location.Address == 0)) {
  732. Result.U.DataResult->Location.Address = Value;
  733. }
  734. }
  735. CreateOrUpdateCoffSymbolEnd:
  736. return SymbolAdded;
  737. }