1
0

coff.c 23 KB

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