123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982 |
- /*++
- Copyright (c) 2012 Minoca Corp. All Rights Reserved
- Module Name:
- coff.c
- Abstract:
- This module handles parsing COFF symbol tables, used in PE images.
- Author:
- Evan Green 5-Sep-2012
- Environment:
- Debug
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include "dbgrtl.h"
- #include <minoca/lib/im.h>
- #include <minoca/debug/dbgext.h>
- #include "pe.h"
- #include "symbols.h"
- #include "stabs.h"
- #include <assert.h>
- #include <errno.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- //
- // ---------------------------------------------------------------- Definitions
- //
- #define MALLOC(_x) malloc(_x)
- #define FREE(_x) free(_x)
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- typedef struct _COFF_SECTION COFF_SECTION, *PCOFF_SECTION;
- struct _COFF_SECTION {
- PCOFF_SECTION Next;
- LONG SectionIndex;
- ULONG SectionAddress;
- };
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- LONG
- DbgpGetFileSize (
- FILE *File
- );
- VOID
- DbgpCoffFreeSymbols (
- PDEBUG_SYMBOLS Symbols
- );
- BOOL
- DbgpLoadCoffSymbolTable (
- PDEBUG_SYMBOLS Symbols,
- PSTR Filename,
- PCOFF_SECTION *SectionList
- );
- BOOL
- DbgpParseCoffSymbolTable (
- PDEBUG_SYMBOLS Symbols,
- PCOFF_SECTION SectionList
- );
- PSTR
- DbgpGetCoffSymbolName (
- PCOFF_SYMBOL Symbol,
- PDEBUG_SYMBOLS SymbolData,
- BOOL TruncateLeadingUnderscore
- );
- BOOL
- DbgpCreateOrUpdateCoffSymbol (
- PDEBUG_SYMBOLS Symbols,
- PCOFF_SYMBOL CoffSymbol,
- PSTR Name,
- ULONGLONG Value
- );
- //
- // -------------------------------------------------------------------- Globals
- //
- DEBUG_SYMBOL_INTERFACE DbgCoffSymbolInterface = {
- DbgpCoffLoadSymbols,
- DbgpCoffFreeSymbols,
- NULL,
- NULL,
- NULL
- };
- //
- // ------------------------------------------------------------------ Functions
- //
- INT
- DbgpCoffLoadSymbols (
- PSTR Filename,
- IMAGE_MACHINE_TYPE MachineType,
- ULONG Flags,
- PVOID HostContext,
- PDEBUG_SYMBOLS *Symbols
- )
- /*++
- Routine Description:
- This routine loads debugging symbol information from the specified file.
- Arguments:
- Filename - Supplies the name of the binary to load symbols from.
- MachineType - Supplies the required machine type of the image. Set to
- unknown to allow the symbol library to load a file with any machine
- type.
- Flags - Supplies a bitfield of flags governing the behavior during load.
- These flags are specific to each symbol library.
- HostContext - Supplies the value to store in the host context field of the
- debug symbols.
- Symbols - Supplies an optional pointer where a pointer to the symbols will
- be returned on success.
- Return Value:
- 0 on success.
- Returns an error number on failure.
- --*/
- {
- UINTN AllocationSize;
- PDEBUG_SYMBOLS CoffSymbols;
- BOOL Result;
- INT Status;
- AllocationSize = sizeof(DEBUG_SYMBOLS) + sizeof(STAB_CONTEXT);
- CoffSymbols = MALLOC(AllocationSize);
- if (CoffSymbols == NULL) {
- Status = ENOMEM;
- goto CoffLoadSymbolsEnd;
- }
- memset(CoffSymbols, 0, AllocationSize);
- INITIALIZE_LIST_HEAD(&(CoffSymbols->SourcesHead));
- CoffSymbols->Interface = &DbgCoffSymbolInterface;
- CoffSymbols->SymbolContext = CoffSymbols + 1;
- CoffSymbols->HostContext = HostContext;
- Result = DbgpLoadCoffSymbols(CoffSymbols, Filename);
- if (Result == FALSE) {
- Status = EINVAL;
- goto CoffLoadSymbolsEnd;
- }
- Status = 0;
- CoffLoadSymbolsEnd:
- if (Status != 0) {
- if (CoffSymbols != NULL) {
- DbgpCoffFreeSymbols(CoffSymbols);
- CoffSymbols = NULL;
- }
- }
- *Symbols = CoffSymbols;
- return 0;
- }
- BOOL
- DbgpLoadCoffSymbols (
- PDEBUG_SYMBOLS Symbols,
- PSTR Filename
- )
- /*++
- Routine Description:
- This routine loads COFF symbols into a pre-existing set of debug symbols.
- Arguments:
- Symbols - Supplies a pointer to debug symbols that are assumed to have
- already been allocated and initialized.
- Filename - Supplies the name of the file to load COFF symbols for.
- Return Value:
- TRUE on success.
- FALSE on failure.
- --*/
- {
- PCOFF_SECTION CurrentSection;
- PCOFF_SECTION NextSection;
- BOOL Result;
- PCOFF_SECTION SectionList;
- SectionList = NULL;
- Result = DbgpLoadCoffSymbolTable(Symbols, Filename, &SectionList);
- if (Result == FALSE) {
- goto LoadCoffSymbolsEnd;
- }
- Result = DbgpParseCoffSymbolTable(Symbols, SectionList);
- if (Result == FALSE) {
- goto LoadCoffSymbolsEnd;
- }
- LoadCoffSymbolsEnd:
- //
- // Free the section list if one was created.
- //
- CurrentSection = SectionList;
- while (CurrentSection != NULL) {
- NextSection = CurrentSection->Next;
- FREE(CurrentSection);
- CurrentSection = NextSection;
- }
- return Result;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- VOID
- DbgpCoffFreeSymbols (
- PDEBUG_SYMBOLS Symbols
- )
- /*++
- Routine Description:
- This routine frees all memory associated with an instance of debugging
- symbols. Once called, the pointer passed in should not be dereferenced
- again by the caller.
- Arguments:
- Symbols - Supplies a pointer to the debugging symbols.
- Return Value:
- None.
- --*/
- {
- PLIST_ENTRY CurrentFunctionEntry;
- PLIST_ENTRY CurrentGlobalEntry;
- PLIST_ENTRY CurrentSourceEntry;
- PFUNCTION_SYMBOL Function;
- PDATA_SYMBOL GlobalVariable;
- PLIST_ENTRY NextFunctionEntry;
- PSOURCE_FILE_SYMBOL SourceFile;
- PSTAB_CONTEXT StabContext;
- StabContext = Symbols->SymbolContext;
- if (Symbols->Filename != NULL) {
- FREE(Symbols->Filename);
- }
- if (StabContext->RawSymbolTable != NULL) {
- FREE(StabContext->RawSymbolTable);
- }
- if (StabContext->RawSymbolTableStrings != NULL) {
- FREE(StabContext->RawSymbolTableStrings);
- }
- //
- // Free Source files.
- //
- CurrentSourceEntry = Symbols->SourcesHead.Next;
- while ((CurrentSourceEntry != &(Symbols->SourcesHead)) &&
- (CurrentSourceEntry != NULL)) {
- SourceFile = LIST_VALUE(CurrentSourceEntry,
- SOURCE_FILE_SYMBOL,
- ListEntry);
- assert(LIST_EMPTY(&(SourceFile->TypesHead)));
- //
- // Free functions.
- //
- CurrentFunctionEntry = SourceFile->FunctionsHead.Next;
- while (CurrentFunctionEntry != &(SourceFile->FunctionsHead)) {
- Function = LIST_VALUE(CurrentFunctionEntry,
- FUNCTION_SYMBOL,
- ListEntry);
- assert(LIST_EMPTY(&(Function->ParametersHead)));
- assert(LIST_EMPTY(&(Function->LocalsHead)));
- if (Function->Name != NULL) {
- FREE(Function->Name);
- }
- NextFunctionEntry = CurrentFunctionEntry->Next;
- FREE(Function);
- CurrentFunctionEntry = NextFunctionEntry;
- }
- assert(LIST_EMPTY(&(SourceFile->SourceLinesHead)));
- //
- // Free global/static symbols.
- //
- CurrentGlobalEntry = SourceFile->DataSymbolsHead.Next;
- while (CurrentGlobalEntry != &(SourceFile->DataSymbolsHead)) {
- GlobalVariable = LIST_VALUE(CurrentGlobalEntry,
- DATA_SYMBOL,
- ListEntry);
- if (GlobalVariable->Name != NULL) {
- FREE(GlobalVariable->Name);
- }
- CurrentGlobalEntry = CurrentGlobalEntry->Next;
- FREE(GlobalVariable);
- }
- CurrentSourceEntry = CurrentSourceEntry->Next;
- FREE(SourceFile);
- }
- FREE(Symbols);
- return;
- }
- BOOL
- DbgpLoadCoffSymbolTable (
- PDEBUG_SYMBOLS Symbols,
- PSTR Filename,
- PCOFF_SECTION *SectionList
- )
- /*++
- Routine Description:
- This routine loads the raw COFF symbol table out of the file.
- Arguments:
- Symbols - Supplies a pointer to debug symbols that are assumed to have
- already been allocated and initialized.
- Filename - Supplies the name of the file to load COFF symbols for.
- SectionList - Supplies a pointer that will receive a pointer to the list of
- sections in the COFF file. Most COFF symbol values are relative to a
- section like .text or .bss.
- Return Value:
- TRUE on success.
- FALSE on failure.
- --*/
- {
- ULONG BytesRead;
- PIMAGE_SECTION_HEADER CurrentSection;
- FILE *File;
- PVOID FileBuffer;
- ULONG FileSize;
- PCOFF_SECTION FirstSection;
- ULONG ImageBase;
- IMAGE_BUFFER ImageBuffer;
- PCOFF_SECTION NewSectionEntry;
- PCOFF_SECTION NextSectionEntry;
- PIMAGE_NT_HEADERS PeHeader;
- BOOL Result;
- ULONG SectionIndex;
- PUCHAR Source;
- ULONG SourceSize;
- PSTAB_CONTEXT StabContext;
- StabContext = Symbols->SymbolContext;
- CurrentSection = NULL;
- FileBuffer = NULL;
- FirstSection = NULL;
- memset(&ImageBuffer, 0, sizeof(IMAGE_BUFFER));
- StabContext->RawSymbolTable = NULL;
- StabContext->RawSymbolTableStrings = NULL;
- //
- // Determine the file size and load the file into memory.
- //
- File = fopen(Filename, "rb");
- if (File == NULL) {
- Result = FALSE;
- goto LoadCoffSymbolTableEnd;
- }
- FileSize = DbgpGetFileSize(File);
- if (FileSize <= 0) {
- Result = FALSE;
- goto LoadCoffSymbolTableEnd;
- }
- FileBuffer = MALLOC(FileSize);
- if (FileBuffer == NULL) {
- Result = FALSE;
- goto LoadCoffSymbolTableEnd;
- }
- BytesRead = fread(FileBuffer, 1, FileSize, File);
- if (BytesRead != FileSize) {
- Result = FALSE;
- goto LoadCoffSymbolTableEnd;
- }
- ImageBuffer.Data = FileBuffer;
- ImageBuffer.Size = FileSize;
- //
- // Get the PE headers to determine the location of the symbol table.
- //
- Result = ImpPeGetHeaders(&ImageBuffer, &PeHeader);
- if (Result == FALSE) {
- goto LoadCoffSymbolTableEnd;
- }
- Source = FileBuffer;
- Source += PeHeader->FileHeader.PointerToSymbolTable;
- SourceSize = PeHeader->FileHeader.NumberOfSymbols * sizeof(COFF_SYMBOL);
- //
- // Allocate space for the symbol table and copy it in.
- //
- StabContext->RawSymbolTableSize = SourceSize;
- StabContext->RawSymbolTable = MALLOC(SourceSize);
- if (StabContext->RawSymbolTable == NULL) {
- Result = FALSE;
- goto LoadCoffSymbolTableEnd;
- }
- memcpy(StabContext->RawSymbolTable, Source, SourceSize);
- //
- // Find the string table, which is right after the symbol table, allocate
- // memory for it, and copy it in. Note that the first four bytes contain
- // the total size of the string table, but those four bytes should be
- // treated as 0 when reading strings from the string table.
- //
- Source += SourceSize;
- SourceSize = *((PULONG)Source);
- StabContext->RawSymbolTableStringsSize = SourceSize;
- StabContext->RawSymbolTableStrings = MALLOC(SourceSize);
- if (StabContext->RawSymbolTableStrings == NULL) {
- Result = FALSE;
- goto LoadCoffSymbolTableEnd;
- }
- memcpy(StabContext->RawSymbolTableStrings, Source, SourceSize);
- //
- // Set the first four bytes to 0.
- //
- *((PULONG)(StabContext->RawSymbolTableStrings)) = 0;
- //
- // Create the section list.
- //
- ImageBase = PeHeader->OptionalHeader.ImageBase;
- CurrentSection = (PIMAGE_SECTION_HEADER)(PeHeader + 1);
- for (SectionIndex = 0;
- SectionIndex < PeHeader->FileHeader.NumberOfSections;
- SectionIndex += 1) {
- //
- // Skip the section if its not even loaded into memory.
- //
- if ((CurrentSection->Characteristics &
- IMAGE_SCN_MEM_DISCARDABLE) != 0) {
- CurrentSection += 1;
- continue;
- }
- //
- // Allocate space for the new entry and fill it out. Sections according
- // to COFF symbols are 1 based.
- //
- NewSectionEntry = MALLOC(sizeof(COFF_SECTION));
- if (NewSectionEntry == NULL) {
- Result = FALSE;
- goto LoadCoffSymbolTableEnd;
- }
- RtlZeroMemory(NewSectionEntry, sizeof(COFF_SECTION));
- NewSectionEntry->SectionIndex = SectionIndex + 1;
- NewSectionEntry->SectionAddress = ImageBase +
- CurrentSection->VirtualAddress;
- //
- // Link the new section at the head of the list.
- //
- NewSectionEntry->Next = FirstSection;
- FirstSection = NewSectionEntry;
- //
- // Advance to the next section.
- //
- CurrentSection += 1;
- }
- Result = TRUE;
- LoadCoffSymbolTableEnd:
- if (FileBuffer != NULL) {
- FREE(FileBuffer);
- }
- if (Result == FALSE) {
- if (StabContext->RawSymbolTable != NULL) {
- FREE(StabContext->RawSymbolTable);
- }
- if (StabContext->RawSymbolTableStrings != NULL) {
- FREE(StabContext->RawSymbolTableStrings);
- }
- //
- // Free all section entries.
- //
- if (FirstSection != NULL) {
- NewSectionEntry = FirstSection;
- while (NewSectionEntry != NULL) {
- NextSectionEntry = NewSectionEntry->Next;
- FREE(NewSectionEntry);
- NewSectionEntry = NextSectionEntry;
- }
- }
- //
- // If successful, return the section list.
- //
- } else {
- *SectionList = FirstSection;
- }
- if (File != NULL) {
- fclose(File);
- }
- return Result;
- }
- BOOL
- DbgpParseCoffSymbolTable (
- PDEBUG_SYMBOLS Symbols,
- PCOFF_SECTION SectionList
- )
- /*++
- Routine Description:
- This routine parses COFF symbol tables and combines them with existing
- debug symbols.
- Arguments:
- Symbols - Supplies a pointer to debug symbols that are assumed to have
- already been allocated and initialized. The raw symbol tables and
- string table are expected to be valid.
- SectionList - Supplies a list of all loadable section in the image. Most
- COFF symbols are relative to a section, so this is needed to determine
- the real address.
- Return Value:
- TRUE on success.
- FALSE on failure.
- --*/
- {
- ULONG BytesRead;
- PCOFF_SECTION CurrentSection;
- PSTR Name;
- PSTAB_CONTEXT StabContext;
- PCOFF_SYMBOL Symbol;
- BOOL SymbolCreated;
- ULONGLONG SymbolValue;
- BytesRead = 0;
- StabContext = Symbols->SymbolContext;
- //
- // Validate that the symbol tables are there.
- //
- if ((Symbols == NULL) || (StabContext->RawSymbolTable == NULL) ||
- (StabContext->RawSymbolTableStrings == NULL)) {
- return FALSE;
- }
- Symbol = (PCOFF_SYMBOL)(StabContext->RawSymbolTable);
- while (BytesRead + sizeof(COFF_SYMBOL) <= StabContext->RawSymbolTableSize) {
- SymbolValue = 0;
- //
- // Attempt to find the section matching this symbol. If none can be
- // found, ignore the symbol. Negative section indices are possible, but
- // these symbols are usually not that useful.
- //
- if ((SHORT)Symbol->Section > 0) {
- CurrentSection = SectionList;
- while (CurrentSection != NULL) {
- if (CurrentSection->SectionIndex == Symbol->Section) {
- break;
- }
- CurrentSection = CurrentSection->Next;
- }
- if (CurrentSection != NULL) {
- SymbolValue = Symbol->Value + CurrentSection->SectionAddress;
- }
- }
- //
- // Skip all symbols except class 2 symbols, which represent C_EXT
- // external symbols.
- //
- if (Symbol->Class != 2) {
- SymbolValue = 0;
- }
- //
- // If a valid value was found for the symbol, attempt to get its name.
- //
- if (SymbolValue != 0) {
- Name = DbgpGetCoffSymbolName(Symbol, Symbols, TRUE);
- //
- // If the symbol has a valid name, attempt to add it.
- //
- if (Name != NULL) {
- SymbolCreated = DbgpCreateOrUpdateCoffSymbol(Symbols,
- Symbol,
- Name,
- SymbolValue);
- if (SymbolCreated == FALSE) {
- FREE(Name);
- }
- }
- }
- //
- // Skip over any extra data this symbol may have in multiples of
- // COFF symbol entries.
- //
- if (Symbol->AuxCount != 0) {
- BytesRead += Symbol->AuxCount * sizeof(COFF_SYMBOL);
- Symbol += Symbol->AuxCount;
- }
- //
- // Go to the next symbol in the table.
- //
- BytesRead += sizeof(COFF_SYMBOL);
- Symbol += 1;
- }
- return TRUE;
- }
- PSTR
- DbgpGetCoffSymbolName (
- PCOFF_SYMBOL Symbol,
- PDEBUG_SYMBOLS SymbolData,
- BOOL TruncateLeadingUnderscore
- )
- /*++
- Routine Description:
- This routine gets the name of the given COFF symbol. The caller is
- responsible for freeing memory returned here.
- Arguments:
- Symbol - Supplies a pointer to the COFF symbol to get the name of.
- SymbolData - Supplies a pointer to debug symbols containing a valid
- symbol table and string table.
- TruncateLeadingUnderscore - Supplies a boolean indicating whether or not
- to truncate leading underscores at the beginning of symbol names. If
- this flag is TRUE and the symbol name is found to begin with an
- underscore, this underscore will be removed.
- Return Value:
- Returns a pointer to a newly allocated buffer containing the name of the
- symbol on success.
- NULL on failure or if the symbol has no name.
- --*/
- {
- ULONG Length;
- PSTR Name;
- PSTAB_CONTEXT StabContext;
- PSTR StringTable;
- StabContext = SymbolData->SymbolContext;
- Name = NULL;
- StringTable = StabContext->RawSymbolTableStrings;
- //
- // If the symbol name has its zeroes field zeroed, then use the offset
- // into the symbol table.
- //
- if (Symbol->Zeroes == 0) {
- if (StringTable == NULL) {
- goto GetCoffSymbolNameEnd;
- }
- if (Symbol->Offset >= StabContext->RawSymbolTableStringsSize) {
- goto GetCoffSymbolNameEnd;
- }
- Length = strlen(StringTable + Symbol->Offset);
- Name = MALLOC(Length + 1);
- if (Name == NULL) {
- goto GetCoffSymbolNameEnd;
- }
- strcpy(Name, StringTable + Symbol->Offset);
- Name[Length] = '\0';
- //
- // If the symbol name does not have its zeroes field zeroed, then the name
- // is baked right into the symbol. Note that it is only NULL terminated if
- // there is room for the NULL terminator.
- //
- } else {
- Name = MALLOC(COFF_SYMBOL_NAME_LENGTH + 1);
- if (Name == NULL) {
- goto GetCoffSymbolNameEnd;
- }
- strncpy(Name, Symbol->Name, COFF_SYMBOL_NAME_LENGTH);
- Name[COFF_SYMBOL_NAME_LENGTH] = '\0';
- }
- //
- // If leading underscores are to be truncated, look for that now.
- //
- if ((TruncateLeadingUnderscore != FALSE) && (Name != NULL) &&
- (Name[0] == '_')) {
- strcpy(Name, Name + 1);
- }
- GetCoffSymbolNameEnd:
- return Name;
- }
- BOOL
- DbgpCreateOrUpdateCoffSymbol (
- PDEBUG_SYMBOLS Symbols,
- PCOFF_SYMBOL CoffSymbol,
- PSTR Name,
- ULONGLONG Value
- )
- /*++
- Routine Description:
- This routine adds a symbol to the debug symbols or updates a value if its
- currently set as NULL given the COFF symbol.
- Arguments:
- Symbols - Supplies a pointer to the debug symbols where the new symbol will
- be stored.
- CoffSymbol - Supplies a pointer to the new COFF symbol to be put in.
- Name - Supplies a pointer to the symbol name.
- Value - Supplies a pointer to the symbol value.
- Return Value:
- TRUE if a new symbol was created and the Name buffer should not be freed.
- FALSE if an existing symbol was updated, or no symbol was generated at all.
- --*/
- {
- PSOURCE_FILE_SYMBOL CurrentSource;
- PLIST_ENTRY CurrentSourceEntry;
- PSOURCE_FILE_SYMBOL FunctionParent;
- PFUNCTION_SYMBOL NewFunction;
- SYMBOL_SEARCH_RESULT Result;
- PSYMBOL_SEARCH_RESULT ResultPointer;
- BOOL SymbolAdded;
- RtlZeroMemory(&Result, sizeof(SYMBOL_SEARCH_RESULT));
- Result.Variety = SymbolResultInvalid;
- SymbolAdded = FALSE;
- //
- // A symbol with type 0x20 indicates a function.
- //
- if ((CoffSymbol->Type & 0xF0) == 0x20) {
- ResultPointer = DbgFindFunctionSymbol(Symbols, Name, 0, &Result);
- //
- // If the function does not exist, create it. For now, only create new
- // functions, don't update existing ones.
- //
- if (ResultPointer == NULL) {
- //
- // Attempt to find the source file this belongs under. Loop through
- // all source files looking for one whose address range contains
- // this function.
- //
- CurrentSourceEntry = Symbols->SourcesHead.Next;
- FunctionParent = NULL;
- while (CurrentSourceEntry != &(Symbols->SourcesHead)) {
- CurrentSource = LIST_VALUE(CurrentSourceEntry,
- SOURCE_FILE_SYMBOL,
- ListEntry);
- if ((CurrentSource->StartAddress <= Value) &&
- (CurrentSource->EndAddress > Value)) {
- FunctionParent = CurrentSource;
- break;
- }
- CurrentSourceEntry = CurrentSourceEntry->Next;
- }
- //
- // If a parent source could not be found, there's nowhere to add
- // this function to.
- //
- if (FunctionParent == NULL) {
- goto CreateOrUpdateCoffSymbolEnd;
- }
- NewFunction = MALLOC(sizeof(FUNCTION_SYMBOL));
- if (NewFunction == NULL) {
- goto CreateOrUpdateCoffSymbolEnd;
- }
- RtlZeroMemory(NewFunction, sizeof(FUNCTION_SYMBOL));
- NewFunction->ParentSource = FunctionParent;
- NewFunction->Name = Name;
- NewFunction->FunctionNumber = 1000;
- INITIALIZE_LIST_HEAD(&(NewFunction->ParametersHead));
- INITIALIZE_LIST_HEAD(&(NewFunction->LocalsHead));
- NewFunction->StartAddress = Value;
- NewFunction->EndAddress = Value + 0x20;
- NewFunction->ReturnTypeNumber = 0;
- NewFunction->ReturnTypeOwner = NULL;
- //
- // Insert the function into the current source file's list of
- // functions.
- //
- INSERT_BEFORE(&(NewFunction->ListEntry),
- &(FunctionParent->FunctionsHead));
- SymbolAdded = TRUE;
- }
- //
- // Assume everything that's not a function is data, a global.
- //
- } else {
- ResultPointer = DbgFindDataSymbol(Symbols, Name, 0, &Result);
- //
- // If it exists and it's current value is NULL, update it. For now,
- // only update, do not create globals.
- //
- if ((ResultPointer != NULL) &&
- (Result.U.DataResult->LocationType ==
- DataLocationAbsoluteAddress) &&
- (Result.U.DataResult->Location.Address == 0)) {
- Result.U.DataResult->Location.Address = Value;
- }
- }
- CreateOrUpdateCoffSymbolEnd:
- return SymbolAdded;
- }
|