X-Git-Url: http://git.hcoop.net/clinton/Virtual-Jaguar-Rx.git/blobdiff_plain/41d6f5f7b28e5424b8cbc4244486dd294009faab..5c5de885abe55954d853a213261ea853f990d01e:/src/debugger/DWARFManager.cpp diff --git a/src/debugger/DWARFManager.cpp b/src/debugger/DWARFManager.cpp index dfc2ffc..a90bf39 100644 --- a/src/debugger/DWARFManager.cpp +++ b/src/debugger/DWARFManager.cpp @@ -4,27 +4,69 @@ // by Jean-Paul Mari // // JPM = Jean-Paul Mari +// RG = Richard Goedeken // // WHO WHEN WHAT // --- ---------- ------------------------------------------------------------ -// JPM 12/03/2016 Created this file -// JPM 12/03/2016 DWARF format support +// JPM Dec./2016 Created this file, and added the DWARF format support +// JPM Sept./2018 Added LEB128 decoding features, and improve the DWARF parsing information +// JPM Oct./2018 Improve the DWARF parsing information, and the source file text reading; support the used source lines from DWARF structure, and the search paths for the files +// JPM Aug./2019 Added new functions to handle DWARF information, full filename fix +// JPM Mar./2020 Fix a random crash when reading the source lines information +// JPM Aug./2020 Added a source code file date check +// RG Jan./2021 Linux build fixes +// JPM Apr./2021 Support the structure and union members +// + +// To Do +// To use pointers instead of arrays usage (originally done to check if values are set at the right places) +// #include #include #include #include -#include -#include - - -// -//#define DEBUG_NumCU 0x42 // CU number to debug or undefine it - +#include +#include +#include +#include "libdwarf.h" +#include "dwarf.h" +#include "LEB128.h" +#include "DWARFManager.h" + +// Definitions for debugging +//#define DEBUG_NumCU 0x2 // CU number to debug or undefine it +//#define DEBUG_VariableName "cvar_vars" // Variable name to look for or undefine it +//#define DEBUG_TypeName "edict_t" // Type name to look for or undefine it +//#define DEBUG_TypeDef DW_TAG_typedef // Type def to look for or undefine it (not used / not supported) +//#define DEBUG_Filename "crt0" // Filename to look for or undefine it + +// Definitions for handling data +//#define CONVERT_QT_HML // Text will be converted as HTML + +// Definitions for the variables's typetag +#define TypeTag_structure 0x01 // structure +#define TypeTag_pointer 0x02 // pointer +#define TypeTag_subrange 0x04 // (subrange_type?) +#define TypeTag_arraytype 0x08 // array type +#define TypeTag_consttype 0x10 // const type +#define TypeTag_typedef 0x20 // typedef +#define TypeTag_enumeration_type 0x40 // enumeration +#define TypeTag_subroutine_type 0x80 // subroutine +#define TypeTag_union 0x100 // union + + +// Source line CU structure +typedef struct CUStruct_LineSrc +{ + size_t StartPC; + size_t NumLineSrc; + char *PtrLineSrc; +}S_CUStruct_LineSrc; // Source line internal structure -struct DMIStruct_LineSrc +typedef struct DMIStruct_LineSrc { size_t Tag; size_t StartPC; @@ -32,59 +74,99 @@ struct DMIStruct_LineSrc char *PtrLineSrc; }S_DMIStruct_LineSrc; +// Enumeration structure +typedef struct EnumerationStruct +{ + char *PtrName; // Enumeration's name + size_t value; // Enumeration's value +}S_EnumerationStruct; + +// Structure members structure +typedef struct StructureMembersStruct +{ + char *PtrName; // Structure member's name + size_t TypeOffset; // Structure member's offset on another type + size_t DataMemberLocation; // Structure member's data member +}S_StructureMembersStruct; + // Base type internal structure -struct BaseTypeStruct +typedef struct BaseTypeStruct { - size_t Tag; // Type's Tag - size_t Offset; // Type's offset - size_t TypeOffset; // Type's offset on another type - size_t ByteSize; // Type's Byte Size - size_t Encoding; // Type's encoding - char *PtrName; // Type's name + size_t Tag; // Type's Tag + size_t Offset; // Type's offset + size_t TypeOffset; // Type's offset on another type + size_t ByteSize; // Type's Byte Size + size_t Encoding; // Type's encoding + char *PtrName; // Type's name + size_t NbEnumerations; // Type's enumeration numbers + EnumerationStruct *PtrEnumerations; // Type's enumeration + size_t NbStructureMembers; // Type's numbers of structure members + StructureMembersStruct *PtrStructureMembers; // Type's structure members }S_BaseTypeStruct; // Variables internal structure -struct VariablesStruct +typedef struct VariablesStruct { - size_t Addr; // Variable memory address - char *PtrName; // Variable's name - size_t TypeOffset; // Offset pointing on the Variable's Type - size_t TypeByteSize; // Variable's Type byte size - size_t TypeTag; // Variable's Type Tag - size_t TypeEncoding; // Variable's Type encoding - char *PtrTypeName; // Variable's Type name + size_t Op; // Variable's DW_OP + union + { + size_t Addr; // Variable memory address + int Offset; // Variable stack offset (signed) + }; + char *PtrName; // Variable's name + size_t TypeOffset; // Offset pointing on the Variable's Type + size_t TypeByteSize; // Variable's Type byte size + size_t TypeTag; // Variable's Type Tag + size_t TypeEncoding; // Variable's Type encoding + char *PtrTypeName; // Variable's Type name + size_t NbTabVariables; // Number of Variable's members + VariablesStruct **TabVariables; // Variable's Members (used for structures at the moment) }S_VariablesStruct; // Sub program internal structure -struct SubProgStruct +typedef struct SubProgStruct { size_t Tag; size_t NumLineSrc; size_t StartPC; size_t LowPC, HighPC; + size_t FrameBase; char *PtrLineSrc; - char *PtrSubprogramName; - size_t NbLinesSrc; - DMIStruct_LineSrc *PtrLinesSrc; + char *PtrSubprogramName; // Sub program name + size_t NbLinesSrc; // Number of lines source used by the sub program + DMIStruct_LineSrc *PtrLinesSrc; // Pointer of the lines source for the sub program + size_t NbVariables; // Variables number + VariablesStruct *PtrVariables; // Pointer to the local variables list information structure }S_SubProgStruct; // Compilation Unit internal structure -struct CUStruct +typedef struct CUStruct { size_t Tag; - size_t LowPC, HighPC; - char *PtrProducer; // Pointer to the "Producer" information (compiler and compilation options used) + size_t Language; // Language (C, etc.) used by the source code + size_t LowPC, HighPC; // Memory range for the code + char *PtrProducer; // "Producer" text information (mostly compiler and compilation options used) + char *PtrSourceFilename; // Source file name + char *PtrSourceFileDirectory; // Directory of the source file char *PtrFullFilename; // Pointer to full namefile (directory & filename) - size_t SizeLoadSrc; // Source code size - char *PtrLoadSrc; // Pointer to loaded source code - size_t NbLinesLoadSrc; // Lines source number + size_t SizeLoadSrc; // Source code text size + char *PtrLoadSrc; // Pointer to the source code text + size_t NbLinesLoadSrc; // Total number of lines in the source code text char **PtrLinesLoadSrc; // Pointer lists to each source line put in QT html/text conformity size_t NbSubProgs; // Number of sub programs / routines - SubProgStruct *PtrSubProgs; // Pointer to the sub programs / routines information structure - size_t NbTypes; - BaseTypeStruct *PtrTypes; + SubProgStruct *PtrSubProgs; // Pointer to the sub programs / routines structure + size_t NbTypes; // Number of types + BaseTypeStruct *PtrTypes; // Pointer to types size_t NbVariables; // Variables number - VariablesStruct *PtrVariables; // Pointer to the variables list information structure + VariablesStruct *PtrVariables; // Pointer to the global variables list structure + size_t NbFrames; // Frames number + size_t NbUsedLinesSrc; // Number of used source lines + size_t LastNumUsedLinesSrc; // Last number line used + CUStruct_LineSrc *PtrUsedLinesSrc; // Pointer to the used source lines list structure + char **PtrUsedLinesLoadSrc; // Pointer lists to each used source line referenced by the CUStruct_LineSrc structure + size_t *PtrUsedNumLines; // List of the number lines used + struct stat _statbuf; // File information + DWARFstatus Status; // File status }S_CUStruct; @@ -95,33 +177,79 @@ Dwarf_Ptr errarg; Dwarf_Error error; Dwarf_Debug dbg; CUStruct *PtrCU; +char **ListSearchPaths; +size_t NbSearchPaths; +struct stat FileElfExeInfo; -// +// Function declarations Dwarf_Handler DWARFManager_ErrorHandler(Dwarf_Ptr perrarg); void DWARFManager_InitDMI(void); void DWARFManager_CloseDMI(void); bool DWARFManager_ElfClose(void); char *DWARFManager_GetLineSrcFromNumLine(char *PtrSrcFile, size_t NumLine); +void DWARFManager_InitInfosVariable(VariablesStruct *PtrVariables); +void DWARFManager_SourceFileSearchPathsInit(void); +void DWARFManager_SourceFileSearchPathsReset(void); +void DWARFManager_SourceFileSearchPathsClose(void); +void DWARFManager_ConformSlachesBackslashes(char *Ptr); +#if 0 +size_t DWARFManager_GetNbGlobalVariables(void); +size_t DWARFManager_GetNbLocalVariables(size_t Adr); +#endif // -Dwarf_Handler DWARFManager_ErrorHandler(Dwarf_Ptr perrarg) +Dwarf_Handler DWARFManager_ErrorHandler(Dwarf_Ptr /* perrarg */) { return 0; } +// Dwarf manager list search paths init +void DWARFManager_SourceFileSearchPathsInit(void) +{ + ListSearchPaths = NULL; + NbSearchPaths = 0; +} + + +// Dwarf manager list search paths reset +void DWARFManager_SourceFileSearchPathsReset(void) +{ + ListSearchPaths = NULL; + NbSearchPaths = 0; +} + + +// Dwarf manager list search paths close +void DWARFManager_SourceFileSearchPathsClose(void) +{ + DWARFManager_SourceFileSearchPathsReset(); +} + + // Dwarf manager init void DWARFManager_Init(void) { + DWARFManager_SourceFileSearchPathsInit(); LibDwarf = DW_DLV_NO_ENTRY; } +// Dwarf manager settings +void DWARFManager_Set(size_t NbPathsInList, char **PtrListPaths) +{ + // Search paths init + ListSearchPaths = PtrListPaths; + NbSearchPaths = NbPathsInList; +} + + // Dwarf manager Reset bool DWARFManager_Reset(void) { + DWARFManager_SourceFileSearchPathsReset(); return DWARFManager_ElfClose(); } @@ -129,15 +257,17 @@ bool DWARFManager_Reset(void) // Dwarf manager Close bool DWARFManager_Close(void) { + DWARFManager_SourceFileSearchPathsClose(); return(DWARFManager_Reset()); } // Dwarf manager Elf init -int DWARFManager_ElfInit(Elf *ElfPtr) +int DWARFManager_ElfInit(Elf *ElfPtr, struct stat FileElfInfo) { if ((LibDwarf = dwarf_elf_init(ElfPtr, DW_DLC_READ, (Dwarf_Handler)DWARFManager_ErrorHandler, errarg, &dbg, &error)) == DW_DLV_OK) { + FileElfExeInfo = FileElfInfo; DWARFManager_InitDMI(); } @@ -172,39 +302,71 @@ bool DWARFManager_ElfClose(void) // Dwarf manager Compilation Units close void DWARFManager_CloseDMI(void) { + // loop on all CU while (NbCU--) { + // free pointers free(PtrCU[NbCU].PtrFullFilename); free(PtrCU[NbCU].PtrLoadSrc); free(PtrCU[NbCU].PtrProducer); + free(PtrCU[NbCU].PtrSourceFilename); + free(PtrCU[NbCU].PtrSourceFileDirectory); + free(PtrCU[NbCU].PtrUsedLinesSrc); + free(PtrCU[NbCU].PtrUsedLinesLoadSrc); + free(PtrCU[NbCU].PtrUsedNumLines); + // free lines from the source code while (PtrCU[NbCU].NbLinesLoadSrc--) { free(PtrCU[NbCU].PtrLinesLoadSrc[PtrCU[NbCU].NbLinesLoadSrc]); } free(PtrCU[NbCU].PtrLinesLoadSrc); + // free the functions information while (PtrCU[NbCU].NbSubProgs--) { + while (PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables--) + { + free(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].PtrName); + free(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].PtrTypeName); + } + free(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables); + free(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc); free(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrSubprogramName); } free(PtrCU[NbCU].PtrSubProgs); + // free the types while (PtrCU[NbCU].NbTypes--) { free(PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName); + + // free the structure's members + while (PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].NbStructureMembers--) + { + free(PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrStructureMembers[PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].NbStructureMembers].PtrName); + } + free(PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrStructureMembers); } free(PtrCU[NbCU].PtrTypes); + // free variables while (PtrCU[NbCU].NbVariables--) { free(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName); free(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrTypeName); + + // free the variable's members + while (PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].NbTabVariables--) + { + free(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].TabVariables[PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].NbTabVariables]); + } } free(PtrCU[NbCU].PtrVariables); } + // free the CU free(PtrCU); } @@ -217,26 +379,24 @@ void DWARFManager_InitDMI(void) Dwarf_Attribute *atlist; Dwarf_Attribute return_attr1; Dwarf_Half return_tagval, return_attr; + Dwarf_Half version, offset_size; Dwarf_Addr return_lowpc, return_highpc, return_lineaddr; Dwarf_Block *return_block; - Dwarf_Signed atcnt, cnt; - Dwarf_Die return_sib, return_die; + Dwarf_Signed atcnt, cnt, return_value; + Dwarf_Die return_sib, return_die, return_sub, return_subdie; Dwarf_Off return_offset; Dwarf_Line *linebuf; + Dwarf_Half form; FILE *SrcFile; - size_t i, j, k, TypeOffset; char *return_string; - char *Ptr; - char *SourceFilename = NULL; - char *SourceFileDirectory = NULL; - char *SourceFullFilename = NULL; + char *Ptr, *Ptr1; // Initialisation for the Compilation Units table NbCU = 0; PtrCU = NULL; // loop on the available Compilation Unit - while (dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, &next_cu_header, &error) == DW_DLV_OK) + while (dwarf_next_cu_header_b(dbg, NULL, &version, NULL, NULL, &offset_size, NULL, &next_cu_header, &error) == DW_DLV_OK) { // Allocation of an additional Compilation Unit structure in the table if (Ptr = (char *)realloc(PtrCU, ((NbCU + 1) * sizeof(CUStruct)))) @@ -261,7 +421,7 @@ void DWARFManager_InitDMI(void) // Die type detection switch (return_tagval) { - case DW_TAG_compile_unit: + case DW_TAG_compile_unit: if (dwarf_attrlist(return_sib, &atlist, &atcnt, &error) == DW_DLV_OK) { for (Dwarf_Signed i = 0; i < atcnt; ++i) @@ -270,21 +430,24 @@ void DWARFManager_InitDMI(void) { switch (return_attr) { - case DW_AT_low_pc: + // Start address + case DW_AT_low_pc: if (dwarf_lowpc(return_sib, &return_lowpc, &error) == DW_DLV_OK) { PtrCU[NbCU].LowPC = return_lowpc; } break; - case DW_AT_high_pc: + // End address + case DW_AT_high_pc: if (dwarf_highpc(return_sib, &return_highpc, &error) == DW_DLV_OK) { PtrCU[NbCU].HighPC = return_highpc; } break; - case DW_AT_producer: + // compilation information + case DW_AT_producer: if (dwarf_formstring(atlist[i], &return_string, &error) == DW_DLV_OK) { PtrCU[NbCU].PtrProducer = (char *)calloc(strlen(return_string) + 1, 1); @@ -293,24 +456,39 @@ void DWARFManager_InitDMI(void) } break; - case DW_AT_name: + // Filename + case DW_AT_name: if (dwarf_formstring(atlist[i], &return_string, &error) == DW_DLV_OK) { - SourceFilename = (char *)realloc(SourceFilename, strlen(return_string) + 1); - strcpy(SourceFilename, return_string); +#ifdef DEBUG_Filename + if (strstr(return_string, DEBUG_Filename)) +#endif + { + PtrCU[NbCU].PtrSourceFilename = (char *)calloc((strlen(return_string) + 1), 1); + strcpy(PtrCU[NbCU].PtrSourceFilename, return_string); + } dwarf_dealloc(dbg, return_string, DW_DLA_STRING); } break; - case DW_AT_comp_dir: + // Directory name + case DW_AT_comp_dir: if (dwarf_formstring(atlist[i], &return_string, &error) == DW_DLV_OK) { - SourceFileDirectory = (char *)realloc(SourceFileDirectory, strlen(return_string) + 1); - strcpy(SourceFileDirectory, return_string); + PtrCU[NbCU].PtrSourceFileDirectory = (char *)calloc((strlen(return_string) + 1), 1); + strcpy(PtrCU[NbCU].PtrSourceFileDirectory, return_string); dwarf_dealloc(dbg, return_string, DW_DLA_STRING); } break; + // Language + case DW_AT_language: + if (dwarf_formudata(atlist[i], &return_uvalue, &error) == DW_DLV_OK) + { + PtrCU[NbCU].Language = return_uvalue; + } + break; + default: break; } @@ -320,53 +498,170 @@ void DWARFManager_InitDMI(void) dwarf_dealloc(dbg, atlist, DW_DLA_LIST); } - Ptr = SourceFullFilename = (char *)realloc(SourceFullFilename, strlen(SourceFilename) + strlen(SourceFileDirectory) + 2); - sprintf(SourceFullFilename, "%s\\%s", SourceFileDirectory, SourceFilename); - while (*Ptr) + // Check filename presence + if (!PtrCU[NbCU].PtrSourceFilename) { - if (*Ptr == '/') + PtrCU[NbCU].PtrSourceFilename = (char *)calloc(1, 1); + } + + // Check directory presence + if (!PtrCU[NbCU].PtrSourceFileDirectory) + { + // Check if file exists in the search paths + for (size_t i = 0; i < NbSearchPaths; i++) + { + PtrCU[NbCU].PtrFullFilename = (char *)realloc(PtrCU[NbCU].PtrFullFilename, strlen(PtrCU[NbCU].PtrSourceFilename) + strlen((const char *)ListSearchPaths[i]) + 2); +#if defined(_WIN32) + sprintf(PtrCU[NbCU].PtrFullFilename, "%s\\%s", ListSearchPaths[i], PtrCU[NbCU].PtrSourceFilename); + if (!fopen_s(&SrcFile, PtrCU[NbCU].PtrFullFilename, "rb")) +#else + sprintf(PtrCU[NbCU].PtrFullFilename, "%s/%s", ListSearchPaths[i], PtrCU[NbCU].PtrSourceFilename); + SrcFile = fopen(PtrCU[NbCU].PtrFullFilename, "rb"); + if (SrcFile == NULL) +#endif + { + PtrCU[NbCU].PtrSourceFileDirectory = (char *)realloc(PtrCU[NbCU].PtrSourceFileDirectory, strlen(ListSearchPaths[i]) + 1); + strcpy(PtrCU[NbCU].PtrSourceFileDirectory, ListSearchPaths[i]); + } + } + + // File directory doesn't exits + if (!PtrCU[NbCU].PtrSourceFileDirectory) { - *Ptr = '\\'; + PtrCU[NbCU].PtrSourceFileDirectory = (char *)realloc(PtrCU[NbCU].PtrSourceFileDirectory, 2); + strcpy(PtrCU[NbCU].PtrSourceFileDirectory, "."); } - Ptr++; } - PtrCU[NbCU].PtrFullFilename = (char *)calloc(strlen(SourceFullFilename) + 1, 1); - strcpy((char *)PtrCU[NbCU].PtrFullFilename, SourceFullFilename); -#ifndef __CYGWIN__ - if (!fopen_s(&SrcFile, SourceFullFilename, "rt")) + // Conform slashes / backslashes for the filename + DWARFManager_ConformSlachesBackslashes(PtrCU[NbCU].PtrSourceFilename); + + // Check if filename contains already the complete directory + if (PtrCU[NbCU].PtrSourceFilename[1] == ':') + { + // Copy the filename as the full filename + PtrCU[NbCU].PtrFullFilename = (char *)realloc(PtrCU[NbCU].PtrFullFilename, strlen(PtrCU[NbCU].PtrSourceFilename) + 1); + strcpy(PtrCU[NbCU].PtrFullFilename, PtrCU[NbCU].PtrSourceFilename); + } + else + { + // Create full filename and Conform slashes / backslashes + PtrCU[NbCU].PtrFullFilename = (char *)realloc(PtrCU[NbCU].PtrFullFilename, strlen(PtrCU[NbCU].PtrSourceFilename) + strlen(PtrCU[NbCU].PtrSourceFileDirectory) + 2); +#if defined(_WIN32) + sprintf(PtrCU[NbCU].PtrFullFilename, "%s\\%s", PtrCU[NbCU].PtrSourceFileDirectory, PtrCU[NbCU].PtrSourceFilename); +#else + sprintf(PtrCU[NbCU].PtrFullFilename, "%s/%s", PtrCU[NbCU].PtrSourceFileDirectory, PtrCU[NbCU].PtrSourceFilename); +#endif + } + + DWARFManager_ConformSlachesBackslashes(PtrCU[NbCU].PtrFullFilename); + + // Directory path clean-up +#if defined(_WIN32) + while ((Ptr1 = Ptr = strstr(PtrCU[NbCU].PtrFullFilename, "\\..\\"))) +#else + while ((Ptr1 = Ptr = strstr(PtrCU[NbCU].PtrFullFilename, "/../"))) +#endif + { +#if defined(_WIN32) + while (*--Ptr1 != '\\'); #else - if (!(SrcFile = fopen(SourceFullFilename, "rt"))) + while (*--Ptr1 != '/'); #endif + strcpy((Ptr1 + 1), (Ptr + 4)); + } + + // Get the source file information + if (!stat(PtrCU[NbCU].PtrFullFilename, &PtrCU[NbCU]._statbuf)) { - if (!fseek(SrcFile, 0, SEEK_END)) + // check the time stamp with the executable + if (PtrCU[NbCU]._statbuf.st_mtime <= FileElfExeInfo.st_mtime) { - if ((PtrCU[NbCU].SizeLoadSrc = ftell(SrcFile)) > 0) + // Open the source file as a binary file +#if defined(_WIN32) + if (!fopen_s(&SrcFile, PtrCU[NbCU].PtrFullFilename, "rb")) +#else + SrcFile = fopen(PtrCU[NbCU].PtrFullFilename, "rb"); + if (SrcFile == NULL) +#endif { - if (PtrCU[NbCU].PtrLoadSrc = Ptr = (char *)calloc((PtrCU[NbCU].SizeLoadSrc + 1), 1)) + if (!fseek(SrcFile, 0, SEEK_END)) { - rewind(SrcFile); - if (PtrCU[NbCU].SizeLoadSrc < fread(Ptr, 1, PtrCU[NbCU].SizeLoadSrc, SrcFile)) - { - free(PtrCU[NbCU].PtrLoadSrc); - PtrCU[NbCU].PtrLoadSrc = NULL; - PtrCU[NbCU].SizeLoadSrc = 0; - } - else + if ((PtrCU[NbCU].SizeLoadSrc = ftell(SrcFile)) > 0) { - do + if (!fseek(SrcFile, 0, SEEK_SET)) { - if (*Ptr == 0xa) + if (PtrCU[NbCU].PtrLoadSrc = Ptr = Ptr1 = (char *)calloc(1, (PtrCU[NbCU].SizeLoadSrc + 2))) { - PtrCU[NbCU].NbLinesLoadSrc++; - *Ptr = 0; + // Read whole file +#if defined(_WIN32) + if (fread_s(PtrCU[NbCU].PtrLoadSrc, PtrCU[NbCU].SizeLoadSrc, PtrCU[NbCU].SizeLoadSrc, 1, SrcFile) != 1) +#else + if (fread(PtrCU[NbCU].PtrLoadSrc, PtrCU[NbCU].SizeLoadSrc, 1, SrcFile) != 1) +#endif + { + free(PtrCU[NbCU].PtrLoadSrc); + PtrCU[NbCU].PtrLoadSrc = NULL; + PtrCU[NbCU].SizeLoadSrc = 0; + } + else + { + // Eliminate all carriage return code '\r' (oxd) + do + { + if ((*Ptr = *Ptr1) != '\r') + { + Ptr++; + } + } while (*Ptr1++); + + // Get back the new text file size + PtrCU[NbCU].SizeLoadSrc = strlen(Ptr = PtrCU[NbCU].PtrLoadSrc); + + // Make sure the text file finish with a new line code '\n' (0xa) + if (PtrCU[NbCU].PtrLoadSrc[PtrCU[NbCU].SizeLoadSrc - 1] != '\n') + { + PtrCU[NbCU].PtrLoadSrc[PtrCU[NbCU].SizeLoadSrc++] = '\n'; + PtrCU[NbCU].PtrLoadSrc[PtrCU[NbCU].SizeLoadSrc] = 0; + } + + // Reallocate text file + if (PtrCU[NbCU].PtrLoadSrc = Ptr = (char *)realloc(PtrCU[NbCU].PtrLoadSrc, (PtrCU[NbCU].SizeLoadSrc + 1))) + { + // Count line numbers, based on the new line code '\n' (0xa), and finish each line with 0 + do + { + if (*Ptr == '\n') + { + PtrCU[NbCU].NbLinesLoadSrc++; + *Ptr = 0; + } + } while (*++Ptr); + } + } } - } while (*++Ptr); + } } } + + fclose(SrcFile); + } + else + { + // Source file doesn't exist + PtrCU[NbCU].Status = DWARFSTATUS_NOFILE; } } - fclose(SrcFile); + else + { + // Source file is outdated + PtrCU[NbCU].Status = DWARFSTATUS_OUTDATEDFILE; + } + } + else + { + // Source file doesn't have information + PtrCU[NbCU].Status = DWARFSTATUS_NOFILEINFO; } break; @@ -375,11 +670,36 @@ void DWARFManager_InitDMI(void) } } - // Get the source lines table located in the Compilation Unit - if (dwarf_srclines(return_sib, &linebuf, &cnt, &error) == DW_DLV_OK) + // Get the source lines table located in the CU + if ((dwarf_srclines(return_sib, &linebuf, &cnt, &error) == DW_DLV_OK) && (PtrCU[NbCU].Status == DWARFSTATUS_OK)) { + if (cnt) + { + PtrCU[NbCU].NbUsedLinesSrc = cnt; + PtrCU[NbCU].PtrUsedLinesSrc = (CUStruct_LineSrc *)calloc(cnt, sizeof(CUStruct_LineSrc)); + PtrCU[NbCU].PtrUsedLinesLoadSrc = (char **)calloc(cnt, sizeof(char *)); + PtrCU[NbCU].PtrUsedNumLines = (size_t *)calloc(cnt, sizeof(size_t)); + + // Get the addresses and their source line numbers + for (Dwarf_Signed i = 0; i < cnt; i++) + { + if (dwarf_lineaddr(linebuf[i], &return_lineaddr, &error) == DW_DLV_OK) + { + // Get the source line number + if (dwarf_lineno(linebuf[i], &return_uvalue, &error) == DW_DLV_OK) + { + PtrCU[NbCU].PtrUsedLinesSrc[i].StartPC = return_lineaddr; + PtrCU[NbCU].PtrUsedLinesSrc[i].NumLineSrc = return_uvalue; + } + } + } + } + + // Release the memory used by the source lines table located in the CU + dwarf_srclines_dealloc(dbg, linebuf, cnt); } + // Check if the CU has child if (dwarf_child(return_sib, &return_die, &error) == DW_DLV_OK) { do @@ -389,10 +709,10 @@ void DWARFManager_InitDMI(void) { switch (return_tagval) { - case DW_TAG_lexical_block: + case DW_TAG_lexical_block: break; - case DW_TAG_variable: + case DW_TAG_variable: if (dwarf_attrlist(return_die, &atlist, &atcnt, &error) == DW_DLV_OK) { PtrCU[NbCU].PtrVariables = (VariablesStruct *)realloc(PtrCU[NbCU].PtrVariables, ((PtrCU[NbCU].NbVariables + 1) * sizeof(VariablesStruct))); @@ -406,34 +726,47 @@ void DWARFManager_InitDMI(void) { switch (return_attr) { - case DW_AT_location: + case DW_AT_location: if (dwarf_formblock(return_attr1, &return_block, &error) == DW_DLV_OK) { - if (return_block->bl_len == 5) + PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].Op = (*((unsigned char *)(return_block->bl_data))); + + switch (return_block->bl_len) { + case 5: PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].Addr = (*((unsigned char *)(return_block->bl_data) + 1) << 24) + (*((unsigned char *)(return_block->bl_data) + 2) << 16) + (*((unsigned char *)(return_block->bl_data) + 3) << 8) + (*((unsigned char *)(return_block->bl_data) + 4)); + break; + + default: + break; } dwarf_dealloc(dbg, return_block, DW_DLA_BLOCK); } break; - case DW_AT_type: + case DW_AT_type: if (dwarf_global_formref(return_attr1, &return_offset, &error) == DW_DLV_OK) { PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].TypeOffset = return_offset; } break; - case DW_AT_name: + // Variable name + case DW_AT_name: if (dwarf_formstring(return_attr1, &return_string, &error) == DW_DLV_OK) { - PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName = (char *)calloc(strlen(return_string) + 1, 1); - strcpy(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName, return_string); +#ifdef DEBUG_VariableName + if (!strcmp(return_string, DEBUG_VariableName)) +#endif + { + PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName = (char *)calloc(strlen(return_string) + 1, 1); + strcpy(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName, return_string); + } dwarf_dealloc(dbg, return_string, DW_DLA_STRING); } break; - default: + default: break; } } @@ -442,22 +775,40 @@ void DWARFManager_InitDMI(void) dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR); } - PtrCU[NbCU].NbVariables++; + // Check variable's name validity + if (PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName) + { + // Check variable's memory address validity + if (PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].Addr) + { + // Valid variable + PtrCU[NbCU].NbVariables++; + } + else + { + // Invalid variable + free(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName); + PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName = NULL; + } + } dwarf_dealloc(dbg, atlist, DW_DLA_LIST); } break; - case DW_TAG_base_type: - case DW_TAG_typedef: - case DW_TAG_structure_type: - case DW_TAG_pointer_type: - case DW_TAG_const_type: - case DW_TAG_array_type: - case DW_TAG_subrange_type: - case DW_TAG_subroutine_type: + case DW_TAG_base_type: + case DW_TAG_typedef: + case DW_TAG_union_type: + case DW_TAG_structure_type: + case DW_TAG_pointer_type: + case DW_TAG_const_type: + case DW_TAG_array_type: + case DW_TAG_subrange_type: + case DW_TAG_subroutine_type: + case DW_TAG_enumeration_type: if (dwarf_attrlist(return_die, &atlist, &atcnt, &error) == DW_DLV_OK) { + // Allocate memory for this type PtrCU[NbCU].PtrTypes = (BaseTypeStruct *)realloc(PtrCU[NbCU].PtrTypes, ((PtrCU[NbCU].NbTypes + 1) * sizeof(BaseTypeStruct))); memset(PtrCU[NbCU].PtrTypes + PtrCU[NbCU].NbTypes, 0, sizeof(BaseTypeStruct)); PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].Tag = return_tagval; @@ -475,36 +826,57 @@ void DWARFManager_InitDMI(void) { switch (return_attr) { - case DW_AT_type: + // + case DW_AT_sibling: + break; + + // Type's type offset + case DW_AT_type: if (dwarf_global_formref(return_attr1, &return_offset, &error) == DW_DLV_OK) { PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].TypeOffset = return_offset; } break; - case DW_AT_byte_size: + // Type's byte size + case DW_AT_byte_size: if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK) { PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].ByteSize = return_uvalue; } break; - case DW_AT_encoding: + // Type's encoding + case DW_AT_encoding: if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK) { PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].Encoding = return_uvalue; } break; - case DW_AT_name: + // Type's name + case DW_AT_name: if (dwarf_formstring(return_attr1, &return_string, &error) == DW_DLV_OK) { - PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName = (char *)calloc(strlen(return_string) + 1, 1); - strcpy(PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName, return_string); +#ifdef DEBUG_TypeName + if (!strcmp(return_string, DEBUG_TypeName)) +#endif + { + PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName = (char *)calloc(strlen(return_string) + 1, 1); + strcpy(PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName, return_string); + } dwarf_dealloc(dbg, return_string, DW_DLA_STRING); } break; + // Type's file number + case DW_AT_decl_file: + break; + + // Type's line number + case DW_AT_decl_line: + break; + default: break; } @@ -514,13 +886,127 @@ void DWARFManager_InitDMI(void) dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR); } - PtrCU[NbCU].NbTypes++; - dwarf_dealloc(dbg, atlist, DW_DLA_LIST); + + switch (return_tagval) + { + case DW_TAG_structure_type: + case DW_TAG_union_type: + if (dwarf_child(return_die, &return_subdie, &error) == DW_DLV_OK) + { + do + { + return_sub = return_subdie; + if ((dwarf_tag(return_subdie, &return_tagval, &error) == DW_DLV_OK)) + { + switch (return_tagval) + { + case DW_TAG_member: + if (dwarf_attrlist(return_subdie, &atlist, &atcnt, &error) == DW_DLV_OK) + { + // Allocate memory for this member + PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrStructureMembers = (StructureMembersStruct *)realloc(PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrStructureMembers, ((PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].NbStructureMembers + 1) * sizeof(StructureMembersStruct))); + memset(PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrStructureMembers + PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].NbStructureMembers, 0, sizeof(StructureMembersStruct)); + + for (Dwarf_Signed i = 0; i < atcnt; ++i) + { + if (dwarf_whatattr(atlist[i], &return_attr, &error) == DW_DLV_OK) + { + if (dwarf_attr(return_subdie, return_attr, &return_attr1, &error) == DW_DLV_OK) + { + switch (return_attr) + { + case DW_AT_data_member_location: + if (dwarf_whatform(return_attr1, &form, &error) == DW_DLV_OK) + { + if ((form == DW_FORM_data1) || (form == DW_FORM_data2) || (form == DW_FORM_data2) || (form == DW_FORM_data4) || (form == DW_FORM_data8) || (form == DW_FORM_udata)) + { + if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK) + { + PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrStructureMembers[PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].NbStructureMembers].DataMemberLocation = return_uvalue; + } + } + else + { + if (form == DW_FORM_sdata) + { + if (dwarf_formsdata(return_attr1, &return_value, &error) == DW_DLV_OK) + { + PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrStructureMembers[PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].NbStructureMembers].DataMemberLocation = return_value; + } + } + else + { + if (dwarf_formblock(return_attr1, &return_block, &error) == DW_DLV_OK) + { + switch (return_block->bl_len) + { + case 2: + case 3: + case 4: + PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrStructureMembers[PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].NbStructureMembers].DataMemberLocation = ReadULEB128((char *)return_block->bl_data + 1); + break; + + default: + break; + } + + dwarf_dealloc(dbg, return_block, DW_DLA_BLOCK); + } + } + } + } + break; + + case DW_AT_type: + //dwarf_whatform(return_attr1, &form, &error); + if (dwarf_global_formref(return_attr1, &return_uvalue, &error) == DW_DLV_OK) + { + PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrStructureMembers[PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].NbStructureMembers].TypeOffset = return_uvalue; + } + break; + + case DW_AT_name: + if (dwarf_formstring(return_attr1, &return_string, &error) == DW_DLV_OK) + { + PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrStructureMembers[PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].NbStructureMembers].PtrName = (char *)calloc(strlen(return_string) + 1, 1); + strcpy(PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrStructureMembers[PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].NbStructureMembers].PtrName, return_string); + + dwarf_dealloc(dbg, return_string, DW_DLA_STRING); + } + break; + + // Member's file number + case DW_AT_decl_file: + break; + + // Member's line number + case DW_AT_decl_line: + break; + + default: + break; + } + } + } + } + dwarf_dealloc(dbg, atlist, DW_DLA_LIST); + + PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].NbStructureMembers++; + } + break; + } + } + } while (dwarf_siblingof(dbg, return_sub, &return_subdie, &error) == DW_DLV_OK); + } + break; + } + + PtrCU[NbCU].NbTypes++; } break; - case DW_TAG_subprogram: + case DW_TAG_subprogram: if (dwarf_attrlist(return_die, &atlist, &atcnt, &error) == DW_DLV_OK) { PtrCU[NbCU].PtrSubProgs = (SubProgStruct *)realloc(PtrCU[NbCU].PtrSubProgs, ((PtrCU[NbCU].NbSubProgs + 1) * sizeof(SubProgStruct))); @@ -535,7 +1021,8 @@ void DWARFManager_InitDMI(void) { switch (return_attr) { - case DW_AT_low_pc: + // start address + case DW_AT_low_pc: if (dwarf_lowpc(return_die, &return_lowpc, &error) == DW_DLV_OK) { PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].StartPC = return_lowpc; @@ -543,21 +1030,33 @@ void DWARFManager_InitDMI(void) } break; - case DW_AT_high_pc: + // end address + case DW_AT_high_pc: if (dwarf_highpc(return_die, &return_highpc, &error) == DW_DLV_OK) { PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].HighPC = return_highpc; } break; - case DW_AT_decl_line: + // Line number + case DW_AT_decl_line: if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK) { PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NumLineSrc = return_uvalue; } break; - case DW_AT_name: + // Frame + case DW_AT_frame_base: + if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK) + { + PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].FrameBase = return_uvalue; + PtrCU[NbCU].NbFrames++; + } + break; + + // function name + case DW_AT_name: if (dwarf_formstring(return_attr1, &return_string, &error) == DW_DLV_OK) { PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrSubprogramName = (char *)calloc(strlen(return_string) + 1, 1); @@ -566,6 +1065,25 @@ void DWARFManager_InitDMI(void) } break; + case DW_AT_sibling: + break; + + case DW_AT_GNU_all_tail_call_sites: + break; + + case DW_AT_type: + break; + + case DW_AT_prototyped: + break; + + // File number + case DW_AT_decl_file: + break; + + case DW_AT_external: + break; + default: break; } @@ -575,22 +1093,129 @@ void DWARFManager_InitDMI(void) } dwarf_dealloc(dbg, atlist, DW_DLA_LIST); - for (i = 0; i < (size_t)cnt; ++i) + // Get source line number and associated block of address + for (Dwarf_Signed i = 0; i < cnt; ++i) + { + // Check the presence of the line in the memory frame + if (PtrCU[NbCU].PtrUsedLinesSrc && (PtrCU[NbCU].PtrUsedLinesSrc[i].StartPC >= return_lowpc) && (PtrCU[NbCU].PtrUsedLinesSrc[i].StartPC <= return_highpc)) + { + PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc = (DMIStruct_LineSrc *)realloc(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc, (PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc + 1) * sizeof(DMIStruct_LineSrc)); + memset((void *)(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc + PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc), 0, sizeof(DMIStruct_LineSrc)); + PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc].StartPC = PtrCU[NbCU].PtrUsedLinesSrc[i].StartPC; + PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc].NumLineSrc = PtrCU[NbCU].PtrUsedLinesSrc[i].NumLineSrc; + PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc++; + } + } + + if (dwarf_child(return_die, &return_subdie, &error) == DW_DLV_OK) { - if (dwarf_lineaddr(linebuf[i], &return_lineaddr, &error) == DW_DLV_OK) + do { - if (dwarf_lineno(linebuf[i], &return_uvalue, &error) == DW_DLV_OK) + return_sub = return_subdie; + if ((dwarf_tag(return_subdie, &return_tagval, &error) == DW_DLV_OK)) { - if ((return_lineaddr >= return_lowpc) && (return_lineaddr <= return_highpc)) + switch (return_tagval) { - PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc = (DMIStruct_LineSrc *)realloc(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc, (PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc + 1) * sizeof(DMIStruct_LineSrc)); - memset((void *)(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc + PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc), 0, sizeof(DMIStruct_LineSrc)); - PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc].StartPC = return_lineaddr; - PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc].NumLineSrc = return_uvalue; - PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc++; + case DW_TAG_formal_parameter: + case DW_TAG_variable: + if (dwarf_attrlist(return_subdie, &atlist, &atcnt, &error) == DW_DLV_OK) + { + PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables = (VariablesStruct *)realloc(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables, ((PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables + 1) * sizeof(VariablesStruct))); + memset(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables + PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables, 0, sizeof(VariablesStruct)); + + for (Dwarf_Signed i = 0; i < atcnt; ++i) + { + if (dwarf_whatattr(atlist[i], &return_attr, &error) == DW_DLV_OK) + { + if (dwarf_attr(return_subdie, return_attr, &return_attr1, &error) == DW_DLV_OK) + { + switch (return_attr) + { + case DW_AT_location: + if (dwarf_formblock(return_attr1, &return_block, &error) == DW_DLV_OK) + { + PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].Op = *((unsigned char *)(return_block->bl_data)); + + switch (return_block->bl_len) + { + case 1: + break; + + case 2: + case 3: + switch (return_tagval) + { + case DW_TAG_variable: + PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].Offset = ReadLEB128((char *)return_block->bl_data + 1); + break; + + case DW_TAG_formal_parameter: + PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].Offset = ReadULEB128((char *)return_block->bl_data + 1); + break; + + default: + break; + } + break; + + default: + break; + } + dwarf_dealloc(dbg, return_block, DW_DLA_BLOCK); + } + break; + + case DW_AT_type: + if (dwarf_global_formref(return_attr1, &return_offset, &error) == DW_DLV_OK) + { + PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].TypeOffset = return_offset; + } + break; + + case DW_AT_name: + if (dwarf_formstring(return_attr1, &return_string, &error) == DW_DLV_OK) + { +#ifdef DEBUG_VariableName + if (!strcmp(return_string, DEBUG_VariableName)) +#endif + { + PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].PtrName = (char *)calloc(strlen(return_string) + 1, 1); + strcpy(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].PtrName, return_string); + } + dwarf_dealloc(dbg, return_string, DW_DLA_STRING); + } + break; + + case DW_AT_decl_file: + break; + + case DW_AT_decl_line: + break; + + default: + break; + } + } + } + + dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR); + } + + PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables++; + + dwarf_dealloc(dbg, atlist, DW_DLA_LIST); + } + break; + + case DW_TAG_label: + break; + + default: + break; } } } + while (dwarf_siblingof(dbg, return_sub, &return_subdie, &error) == DW_DLV_OK); } PtrCU[NbCU].NbSubProgs++; @@ -601,27 +1226,26 @@ void DWARFManager_InitDMI(void) break; } } - } while (dwarf_siblingof(dbg, return_sib, &return_die, &error) == DW_DLV_OK); + } + while (dwarf_siblingof(dbg, return_sib, &return_die, &error) == DW_DLV_OK); } - - // Release the memory used by the source lines - for (i = 0; i < (size_t)cnt; ++i) - dwarf_dealloc(dbg, linebuf[i], DW_DLA_LINE); - dwarf_dealloc(dbg, linebuf, DW_DLA_LIST); } - // Set the source code lines for QT html/text conformity + // Set the source code lines if (PtrCU[NbCU].NbLinesLoadSrc) { if (PtrCU[NbCU].PtrLinesLoadSrc = (char **)calloc(PtrCU[NbCU].NbLinesLoadSrc, sizeof(char *))) { - for (j = 0; j < PtrCU[NbCU].NbLinesLoadSrc; j++) + for (size_t j = 0; j < PtrCU[NbCU].NbLinesLoadSrc; j++) { if (PtrCU[NbCU].PtrLinesLoadSrc[j] = (char *)calloc(10000, sizeof(char))) { if (Ptr = DWARFManager_GetLineSrcFromNumLine(PtrCU[NbCU].PtrLoadSrc, (j + 1))) { - i = 0; +#ifndef CONVERT_QT_HML + strcpy(PtrCU[NbCU].PtrLinesLoadSrc[j], Ptr); +#else + size_t i = 0; while (*Ptr) { @@ -629,17 +1253,17 @@ void DWARFManager_InitDMI(void) { case 9: strcat(PtrCU[NbCU].PtrLinesLoadSrc[j], " "); - i += strlen(" "); + i += 6; break; case '<': strcat(PtrCU[NbCU].PtrLinesLoadSrc[j], "<"); - i += strlen("<"); + i += 4; break; case '>': strcat(PtrCU[NbCU].PtrLinesLoadSrc[j], ">"); - i += strlen(">"); + i += 4; break; #if 0 case '&': @@ -659,8 +1283,27 @@ void DWARFManager_InitDMI(void) } Ptr++; } +#endif + } + PtrCU[NbCU].PtrLinesLoadSrc[j] = (char *)realloc(PtrCU[NbCU].PtrLinesLoadSrc[j], strlen(PtrCU[NbCU].PtrLinesLoadSrc[j]) + 1); + } + } + + // Init lines source information for each source code line numbers and for each subprogs + for (size_t j = 0; j < PtrCU[NbCU].NbSubProgs; j++) + { + // Check if the subprog / function's line exists in the source code + if (PtrCU[NbCU].PtrSubProgs[j].NumLineSrc <= PtrCU[NbCU].NbLinesLoadSrc) + { + PtrCU[NbCU].PtrSubProgs[j].PtrLineSrc = PtrCU[NbCU].PtrLinesLoadSrc[PtrCU[NbCU].PtrSubProgs[j].NumLineSrc - 1]; + } + + for (size_t k = 0; k < PtrCU[NbCU].PtrSubProgs[j].NbLinesSrc; k++) + { + if (PtrCU[NbCU].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc <= PtrCU[NbCU].NbLinesLoadSrc) + { + PtrCU[NbCU].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc = PtrCU[NbCU].PtrLinesLoadSrc[PtrCU[NbCU].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc - 1]; } - PtrCU[NbCU].PtrLinesLoadSrc[j] = (char *)realloc(PtrCU[NbCU].PtrLinesLoadSrc[j], i + 1); } } } @@ -670,124 +1313,59 @@ void DWARFManager_InitDMI(void) // Set each source lines pointer to NULL if (PtrCU[NbCU].NbSubProgs) { - i = PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs - 1].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs - 1].NbLinesSrc - 1].NumLineSrc; - if (PtrCU[NbCU].PtrLinesLoadSrc = (char **)calloc(i, sizeof(char *))) + // Check the presence of source lines dedicated to the sub progs + if (PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs - 1].NbLinesSrc) { - for (j = 0; j < i; j++) + size_t i = PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs - 1].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs - 1].NbLinesSrc - 1].NumLineSrc; + if (PtrCU[NbCU].PtrLinesLoadSrc = (char **)calloc(i, sizeof(char *))) { - PtrCU[NbCU].PtrLinesLoadSrc[j] = NULL; + for (size_t j = 0; j < i; j++) + { + PtrCU[NbCU].PtrLinesLoadSrc[j] = NULL; + } } } } } - // Init lines source information based on each source code line numbers - for (j = 0; j < PtrCU[NbCU].NbSubProgs; j++) + // Check validity between used number lines and number lines in the source file + if (PtrCU[NbCU].LastNumUsedLinesSrc <= PtrCU[NbCU].NbLinesLoadSrc) { - // Check if the subprog / function's line exists in the source code - if (PtrCU[NbCU].PtrSubProgs[j].NumLineSrc <= PtrCU[NbCU].NbLinesLoadSrc) + // Set information based on used line numbers + if (PtrCU[NbCU].PtrUsedLinesSrc) { - PtrCU[NbCU].PtrSubProgs[j].PtrLineSrc = PtrCU[NbCU].PtrLinesLoadSrc[PtrCU[NbCU].PtrSubProgs[j].NumLineSrc - 1]; - } + // Set the line source pointers for each used line numbers + if (PtrCU[NbCU].PtrLinesLoadSrc) + { + for (size_t i = 0; i < PtrCU[NbCU].NbUsedLinesSrc; i++) + { + PtrCU[NbCU].PtrUsedNumLines[i] = PtrCU[NbCU].PtrUsedLinesSrc[i].NumLineSrc - 1; + PtrCU[NbCU].PtrUsedLinesLoadSrc[i] = PtrCU[NbCU].PtrUsedLinesSrc[i].PtrLineSrc = PtrCU[NbCU].PtrLinesLoadSrc[PtrCU[NbCU].PtrUsedLinesSrc[i].NumLineSrc - 1]; + } - for (k = 0; k < PtrCU[NbCU].PtrSubProgs[j].NbLinesSrc; k++) - { - PtrCU[NbCU].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc = PtrCU[NbCU].PtrLinesLoadSrc[PtrCU[NbCU].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc - 1]; + // Setup memory range for the code if CU doesn't have already this information + // It is taken from the used lines structure + if (!PtrCU[NbCU].LowPC && (!PtrCU[NbCU].HighPC || (PtrCU[NbCU].HighPC == ~0))) + { + PtrCU[NbCU].LowPC = PtrCU[NbCU].PtrUsedLinesSrc[0].StartPC; + PtrCU[NbCU].HighPC = PtrCU[NbCU].PtrUsedLinesSrc[PtrCU[NbCU].NbUsedLinesSrc - 1].StartPC; + } + } } } - // Init variables information based on types information - for (i = 0; i < PtrCU[NbCU].NbVariables; i++) + // Init global variables information based on types information + for (size_t i = 0; i < PtrCU[NbCU].NbVariables; i++) { - PtrCU[NbCU].PtrVariables[i].PtrTypeName = (char *)calloc(1000, 1); - TypeOffset = PtrCU[NbCU].PtrVariables[i].TypeOffset; + DWARFManager_InitInfosVariable(PtrCU[NbCU].PtrVariables + i); + } - for (j = 0; j < PtrCU[NbCU].NbTypes; j++) + // Init local variables information based on types information + for (size_t i = 0; i < PtrCU[NbCU].NbSubProgs; i++) + { + for (size_t j = 0; j < PtrCU[NbCU].PtrSubProgs[i].NbVariables; j++) { - if (TypeOffset == PtrCU[NbCU].PtrTypes[j].Offset) - { - switch (PtrCU[NbCU].PtrTypes[j].Tag) - { - case DW_TAG_structure_type: - PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x1; - if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset)) - { - j = -1; - } - else - { - if ((PtrCU[NbCU].PtrVariables[i].TypeTag & 0x2)) - { - strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, " *"); - } - } - break; - - case DW_TAG_pointer_type: - PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x2; - PtrCU[NbCU].PtrVariables[i].TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize; - PtrCU[NbCU].PtrVariables[i].TypeEncoding = 0x10; - if (!(TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset)) - { - strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, "void *"); - } - else - { - j = -1; - } - break; - - case DW_TAG_typedef: - PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x20; - strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName); - if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset)) - { - j = -1; - } - break; - - case DW_TAG_subrange_type: - PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x4; - break; - - case DW_TAG_array_type: - PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x8; - if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset)) - { - j = -1; - } - break; - - case DW_TAG_const_type: - PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x10; - strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, "const "); - if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset)) - { - j = -1; - } - break; - - case DW_TAG_base_type: - strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName); - if ((PtrCU[NbCU].PtrVariables[i].TypeTag & 0x2)) - { - strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, " *"); - } - else - { - PtrCU[NbCU].PtrVariables[i].TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize; - PtrCU[NbCU].PtrVariables[i].TypeEncoding = PtrCU[NbCU].PtrTypes[j].Encoding; - } - if ((PtrCU[NbCU].PtrVariables[i].TypeTag & 0x8)) - { - strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, "[]"); - } - break; - - default: - break; - } - } + DWARFManager_InitInfosVariable(PtrCU[NbCU].PtrSubProgs[i].PtrVariables + j); } } } @@ -795,24 +1373,202 @@ void DWARFManager_InitDMI(void) ++NbCU; } } - - free(SourceFilename); - free(SourceFileDirectory); - free(SourceFullFilename); } -// Get symbol name based from address -// Return NULL if no symbol name exists -char *DWARFManager_GetSymbolnameFromAdr(size_t Adr) +// Conform slashes and backslashes +void DWARFManager_ConformSlachesBackslashes(char *Ptr) +{ + while (*Ptr) + { +#if defined(_WIN32) + if (*Ptr == '/') + { + *Ptr = '\\'; + } +#else + if (*Ptr == '\\') + { + *Ptr = '/'; + } +#endif + Ptr++; + } +} + + +// Variables information initialisation +void DWARFManager_InitInfosVariable(VariablesStruct *PtrVariables) { - size_t i, j; +#ifdef DEBUG_VariableName + if (PtrVariables->PtrName && !strcmp(PtrVariables->PtrName, DEBUG_VariableName)) +#endif + { + PtrVariables->PtrTypeName = (char *)calloc(1000, 1); + size_t TypeOffset = PtrVariables->TypeOffset; + + for (size_t j = 0; j < PtrCU[NbCU].NbTypes; j++) + { + if (TypeOffset == PtrCU[NbCU].PtrTypes[j].Offset) + { + switch (PtrCU[NbCU].PtrTypes[j].Tag) + { + // subroutine / function pointer + case DW_TAG_subroutine_type: + PtrVariables->TypeTag |= TypeTag_subroutine_type; + strcat(PtrVariables->PtrTypeName, " (* ) ()"); + break; + + // structure & union type tag + case DW_TAG_structure_type: + case DW_TAG_union_type: + PtrVariables->TypeTag |= (PtrCU[NbCU].PtrTypes[j].Tag == DW_TAG_structure_type) ? TypeTag_structure : TypeTag_union; + if (!(PtrVariables->TypeTag & TypeTag_typedef)) + { + if (PtrCU[NbCU].PtrTypes[j].PtrName) + { + strcat(PtrVariables->PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName); + } + } + if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset)) + { + j = -1; + } + else + { + if ((PtrVariables->TypeTag & TypeTag_pointer)) + { + strcat(PtrVariables->PtrTypeName, "* "); + } + + if (PtrVariables->Op) + { + // fill the structure members + PtrVariables->TabVariables = (VariablesStruct**)calloc(PtrCU[NbCU].PtrTypes[j].NbStructureMembers, sizeof(VariablesStruct*)); + for (size_t i = 0; i < PtrCU[NbCU].PtrTypes[j].NbStructureMembers; i++) + { + //if (PtrVariables->PtrName != PtrCU[NbCU].PtrTypes[j].PtrStructureMembers[i].PtrName) + { + PtrVariables->TabVariables[PtrVariables->NbTabVariables] = (VariablesStruct*)calloc(1, sizeof(VariablesStruct)); + PtrVariables->TabVariables[PtrVariables->NbTabVariables]->PtrName = PtrCU[NbCU].PtrTypes[j].PtrStructureMembers[i].PtrName; + PtrVariables->TabVariables[PtrVariables->NbTabVariables]->TypeOffset = PtrCU[NbCU].PtrTypes[j].PtrStructureMembers[i].TypeOffset; + PtrVariables->TabVariables[PtrVariables->NbTabVariables]->Offset = (int)PtrCU[NbCU].PtrTypes[j].PtrStructureMembers[i].DataMemberLocation; + DWARFManager_InitInfosVariable(PtrVariables->TabVariables[PtrVariables->NbTabVariables++]); + } + } + } + } + break; + + // pointer type tag + case DW_TAG_pointer_type: + PtrVariables->TypeTag |= TypeTag_pointer; + PtrVariables->TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize; + PtrVariables->TypeEncoding = 0x10; + if (!(TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset)) + { + strcat(PtrVariables->PtrTypeName, "void* "); + } + else + { + j = -1; + } + break; + + case DW_TAG_enumeration_type: + PtrVariables->TypeTag |= TypeTag_enumeration_type; + PtrVariables->TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize; + if (!(PtrVariables->TypeEncoding = PtrCU[NbCU].PtrTypes[j].Encoding)) + { + // Try to determine the possible size + switch (PtrVariables->TypeByteSize) + { + case 4: + PtrVariables->TypeEncoding = 0x7; + break; + + default: + break; + } + } + break; + + // Typedef type tag + case DW_TAG_typedef: + if (!(PtrVariables->TypeTag & TypeTag_typedef)) + { + PtrVariables->TypeTag |= TypeTag_typedef; + strcat(PtrVariables->PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName); + } + if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset)) + { + j = -1; + } + break; - for (i = 0; i < NbCU; i++) + // ? type tag + case DW_TAG_subrange_type: + PtrVariables->TypeTag |= TypeTag_subrange; + break; + + // Array type tag + case DW_TAG_array_type: + PtrVariables->TypeTag |= TypeTag_arraytype; + if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset)) + { + j = -1; + } + break; + + // Const type tag + case DW_TAG_const_type: + PtrVariables->TypeTag |= TypeTag_consttype; + strcat(PtrVariables->PtrTypeName, "const "); + if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset)) + { + j = -1; + } + break; + + // Base type tag + case DW_TAG_base_type: + if (!(PtrVariables->TypeTag & TypeTag_typedef)) + { + strcat(PtrVariables->PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName); + } + if ((PtrVariables->TypeTag & TypeTag_pointer)) + { + strcat(PtrVariables->PtrTypeName, "* "); + } + else + { + PtrVariables->TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize; + PtrVariables->TypeEncoding = PtrCU[NbCU].PtrTypes[j].Encoding; + } + if ((PtrVariables->TypeTag & TypeTag_arraytype)) + { + strcat(PtrVariables->PtrTypeName, "[]"); + } + break; + + default: + break; + } + } + } + } +} + + +// Get symbol name based from address +// Return NULL if no symbol name exists +char *DWARFManager_GetSymbolnameFromAdr(size_t Adr) +{ + for (size_t i = 0; i < NbCU; i++) { if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC)) { - for (j = 0; (j < PtrCU[i].NbSubProgs); j++) + for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++) { if ((PtrCU[i].PtrSubProgs[j].StartPC == Adr)) { @@ -828,16 +1584,18 @@ char *DWARFManager_GetSymbolnameFromAdr(size_t Adr) // Get complete source filename based from address // Return NULL if no source filename exists -// Return the existence status (true or false) in Error -char *DWARFManager_GetFullSourceFilenameFromAdr(size_t Adr, bool *Error) +// Return the existence status in Status if pointer not NULL +char *DWARFManager_GetFullSourceFilenameFromAdr(size_t Adr, DWARFstatus *Status) { - size_t i; - - for (i = 0; i < NbCU; i++) + for (size_t i = 0; i < NbCU; i++) { if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC)) { - *Error = PtrCU[i].PtrLoadSrc ? true : false; + if (Status) + { + *Status = PtrCU[i].Status; + } + return PtrCU[i].PtrFullFilename; } } @@ -846,7 +1604,7 @@ char *DWARFManager_GetFullSourceFilenameFromAdr(size_t Adr, bool *Error) } -// Get text line source based on line number (starting by 1) +// Get text line source based on line number (starting from 1) // Return NULL if no text line exists or if line number is 0 char *DWARFManager_GetLineSrcFromNumLine(char *PtrSrcFile, size_t NumLine) { @@ -867,13 +1625,142 @@ char *DWARFManager_GetLineSrcFromNumLine(char *PtrSrcFile, size_t NumLine) } -// Get Compilation Unit / External variables numbers -// Return variables number -size_t DWARFManager_GetNbExternalVariables(void) +// Get number of variables +// A NULL address will return the numbre of global variables, otherwise it will return the number of local variables +size_t DWARFManager_GetNbVariables(size_t Adr) { - size_t NbVariables = 0, i; + // check the address + if (Adr) + { + for (size_t i = 0; i < NbCU; i++) + { + if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC)) + { + for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++) + { + if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC)) + { + return PtrCU[i].PtrSubProgs[j].NbVariables; + } + } + } + } + } + else + { + size_t NbVariables = 0; + + for (size_t i = 0; i < NbCU; i++) + { + NbVariables += PtrCU[i].NbVariables; + } + + return NbVariables; + } + + return 0; +#if 0 + return Adr ? DWARFManager_GetNbLocalVariables(Adr) : DWARFManager_GetNbGlobalVariables(); +#endif +} + - for (i = 0; i < NbCU; i++) +// Get variable's information +// A NULL address will return the pointer to the global variable structure, otherwise it will return the local's one +void* DWARFManager_GetInfosVariable(size_t Adr, size_t Index) +{ + // check the address + if (Adr) + { + // get the pointer's information from a local variable + for (size_t i = 0; i < NbCU; i++) + { + if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC)) + { + for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++) + { + if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC)) + { + return &PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1]; + } + } + } + } + } + else + { + // get the pointer's information from a global variable + for (size_t i = 0; i < NbCU; i++) + { + if (PtrCU[i].NbVariables) + { + if (Index <= PtrCU[i].NbVariables) + { + return &PtrCU[i].PtrVariables[Index - 1]; + } + else + { + Index -= PtrCU[i].NbVariables; + } + } + } + } + + return NULL; +} + + +// Get global variable memory address based on his name +// Return 0 if not found, or will return the first occurence found +size_t DWARFManager_GetGlobalVariableAdrFromName(char *VariableName) +{ + for (size_t i = 0; i < NbCU; i++) + { + if (PtrCU[i].NbVariables) + { + for (size_t j = 0; j < PtrCU[i].NbVariables; j++) + { + if (!strcmp(PtrCU[i].PtrVariables[j].PtrName, VariableName)) + { + return PtrCU[i].PtrVariables[j].Addr; + } + } + } + } + + return 0; +} + + +#if 0 +// Get number of variables referenced by the function range address +size_t DWARFManager_GetNbLocalVariables(size_t Adr) +{ + for (size_t i = 0; i < NbCU; i++) + { + if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC)) + { + for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++) + { + if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC)) + { + return PtrCU[i].PtrSubProgs[j].NbVariables; + } + } + } + } + + return 0; +} + + +// Get Compilation Unit / global variables numbers +// Return number of variables +size_t DWARFManager_GetNbGlobalVariables(void) +{ + size_t NbVariables = 0; + + for (size_t i = 0; i < NbCU; i++) { NbVariables += PtrCU[i].NbVariables; } @@ -882,45 +1769,175 @@ size_t DWARFManager_GetNbExternalVariables(void) } -// Get external variable type name based on his index (starting by 1) +// Get local variable name based on his index (starting from 1) +// Return name's pointer text found // Return NULL if not found -// May return NULL if there is not type linked to the variable's index -char *DWARFManager_GetExternalVariableTypeName(size_t Index) +char *DWARFManager_GetLocalVariableName(size_t Adr, size_t Index) { - size_t i; + for (size_t i = 0; i < NbCU; i++) + { + if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC)) + { + for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++) + { + if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC)) + { + return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].PtrName; + } + } + } + } + + return NULL; +} - for (i = 0; i < NbCU; i++) + +// Get local variable's type tag based on his index (starting from 1) +// Return 0 if not found +size_t DWARFManager_GetLocalVariableTypeTag(size_t Adr, size_t Index) +{ + for (size_t i = 0; i < NbCU; i++) { - if (PtrCU[i].NbVariables) + if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC)) { - if (Index <= PtrCU[i].NbVariables) + for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++) { - return PtrCU[i].PtrVariables[Index - 1].PtrTypeName; + if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC)) + { + return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].TypeTag; + } } - else + } + } + + return 0; +} + + +// Get the local variable's offset based on a index (starting from 1) +// Return 0 if no offset has been found +int DWARFManager_GetLocalVariableOffset(size_t Adr, size_t Index) +{ + for (size_t i = 0; i < NbCU; i++) + { + if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC)) + { + for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++) { - Index -= PtrCU[i].NbVariables; + if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC)) + { + return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].Offset; + } } } } - return NULL; + return 0; } -// Get external variable's type tag based on his index (starting by 1) +// Get local variable Type Byte Size based on his address and index (starting from 1) // Return 0 if not found -size_t DWARFManager_GetExternalVariableTypeTag(size_t Index) +// May return 0 if there is no Type Byte Size linked to the variable's address and index +size_t DWARFManager_GetLocalVariableTypeByteSize(size_t Adr, size_t Index) { - size_t i; + for (size_t i = 0; i < NbCU; i++) + { + if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC)) + { + for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++) + { + if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC)) + { + return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].TypeByteSize; + } + } + } + } + + return 0; +} + - for (i = 0; i < NbCU; i++) +// Get local variable Type Encoding based on his address and index (starting from 1) +// Return 0 if not found +// May return 0 if there is no Type Encoding linked to the variable's address and index +size_t DWARFManager_GetLocalVariableTypeEncoding(size_t Adr, size_t Index) +{ + for (size_t i = 0; i < NbCU; i++) + { + if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC)) + { + for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++) + { + if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC)) + { + return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].TypeEncoding; + } + } + } + } + + return 0; +} + + +// Get local variable Op based on his address and index (starting from 1) +// Return 0 if not found, may return 0 if there isn't Op linked to the variable's index +size_t DWARFManager_GetLocalVariableOp(size_t Adr, size_t Index) +{ + for (size_t i = 0; i < NbCU; i++) + { + if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC)) + { + for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++) + { + if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC)) + { + return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].Op; + } + } + } + } + + return 0; +} + + +// Get local variable type name based on his index (starting from 1) and an address +// Return NULL if not found, may also return NULL if there is no type linked to the variable's index +char *DWARFManager_GetLocalVariableTypeName(size_t Adr, size_t Index) +{ + for (size_t i = 0; i < NbCU; i++) + { + if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC)) + { + for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++) + { + if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC)) + { + return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].PtrTypeName; + } + } + } + } + + return NULL; +} + + +// Get global variable type name based on his index (starting from 1) +// Return NULL if not found +// May return NULL if there is not type linked to the variable's index +char *DWARFManager_GetGlobalVariableTypeName(size_t Index) +{ + for (size_t i = 0; i < NbCU; i++) { if (PtrCU[i].NbVariables) { if (Index <= PtrCU[i].NbVariables) { - return PtrCU[i].PtrVariables[Index - 1].TypeTag; + return PtrCU[i].PtrVariables[Index - 1].PtrTypeName; } else { @@ -929,23 +1946,21 @@ size_t DWARFManager_GetExternalVariableTypeTag(size_t Index) } } - return 0; + return NULL; } -// Get external variable byte size based on his index (starting by 1) +// Get global variable's type tag based on his index (starting from 1) // Return 0 if not found -size_t DWARFManager_GetExternalVariableTypeByteSize(size_t Index) +size_t DWARFManager_GetGlobalVariableTypeTag(size_t Index) { - size_t i; - - for (i = 0; i < NbCU; i++) + for (size_t i = 0; i < NbCU; i++) { if (PtrCU[i].NbVariables) { if (Index <= PtrCU[i].NbVariables) { - return PtrCU[i].PtrVariables[Index - 1].TypeByteSize; + return PtrCU[i].PtrVariables[Index - 1].TypeTag; } else { @@ -958,19 +1973,17 @@ size_t DWARFManager_GetExternalVariableTypeByteSize(size_t Index) } -// Get external variable encoding based on his index (starting by 1) +// Get global variable byte size based on his index (starting from 1) // Return 0 if not found -size_t DWARFManager_GetExternalVariableTypeEncoding(size_t Index) +size_t DWARFManager_GetGlobalVariableTypeByteSize(size_t Index) { - size_t i; - - for (i = 0; i < NbCU; i++) + for (size_t i = 0; i < NbCU; i++) { if (PtrCU[i].NbVariables) { if (Index <= PtrCU[i].NbVariables) { - return PtrCU[i].PtrVariables[Index - 1].TypeEncoding; + return PtrCU[i].PtrVariables[Index - 1].TypeByteSize; } else { @@ -983,19 +1996,17 @@ size_t DWARFManager_GetExternalVariableTypeEncoding(size_t Index) } -// Get external variable address based on his index (starting by 1) +// Get global variable encoding based on his index (starting from 1) // Return 0 if not found -size_t DWARFManager_GetExternalVariableAdr(size_t Index) +size_t DWARFManager_GetGlobalVariableTypeEncoding(size_t Index) { - size_t i; - - for (i = 0; i < NbCU; i++) + for (size_t i = 0; i < NbCU; i++) { if (PtrCU[i].NbVariables) { if (Index <= PtrCU[i].NbVariables) { - return PtrCU[i].PtrVariables[Index - 1].Addr; + return PtrCU[i].PtrVariables[Index - 1].TypeEncoding; } else { @@ -1008,23 +2019,21 @@ size_t DWARFManager_GetExternalVariableAdr(size_t Index) } -// Get external variable memory address based on his name +// Get global variable memory address based on his index (starting from 1) // Return 0 if not found -// Note: Return the first occurence found -size_t DWARFManager_GetExternalVariableAdrFromName(char *VariableName) +size_t DWARFManager_GetGlobalVariableAdr(size_t Index) { - size_t i, j; - - for (i = 0; i < NbCU; i++) + for (size_t i = 0; i < NbCU; i++) { if (PtrCU[i].NbVariables) { - for (j = 0; j < PtrCU[i].NbVariables; j++) + if (Index <= PtrCU[i].NbVariables) { - if (!strcmp(PtrCU[i].PtrVariables[j].PtrName,VariableName)) - { - return PtrCU[i].PtrVariables[j].Addr; - } + return PtrCU[i].PtrVariables[Index - 1].Addr; + } + else + { + Index -= PtrCU[i].NbVariables; } } } @@ -1033,14 +2042,11 @@ size_t DWARFManager_GetExternalVariableAdrFromName(char *VariableName) } -// Get external variable name based on his index (starting by 1) -// Return name's pointer text found -// Return NULL if not found -char *DWARFManager_GetExternalVariableName(size_t Index) +// Get global variable name based on his index (starting from 1) +// Return name's pointer text found, or will return NULL if no variable can be found +char *DWARFManager_GetGlobalVariableName(size_t Index) { - size_t i; - - for (i = 0; i < NbCU; i++) + for (size_t i = 0; i < NbCU; i++) { if (PtrCU[i].NbVariables) { @@ -1057,19 +2063,20 @@ char *DWARFManager_GetExternalVariableName(size_t Index) return NULL; } +#endif // Get text line from source based on address and his tag +// A tag can be either 0 or a DW_TAG_subprogram +// DW_TAG_subprogram will look for the line pointing to the function // Return NULL if no text line has been found char *DWARFManager_GetLineSrcFromAdr(size_t Adr, size_t Tag) { - size_t i, j, k; - - for (i = 0; i < NbCU; i++) + for (size_t i = 0; i < NbCU; i++) { if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC)) { - for (j = 0; j < PtrCU[i].NbSubProgs; j++) + for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++) { if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC)) { @@ -1079,11 +2086,18 @@ char *DWARFManager_GetLineSrcFromAdr(size_t Adr, size_t Tag) } else { - for (k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++) + for (size_t k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++) { - if ((PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC == Adr) && (!Tag || (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].Tag == Tag))) + if (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC <= Adr) { - return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc; + if ((PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC == Adr) && (!Tag || (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].Tag == Tag))) + { + return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc; + } + } + else + { + return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k - 1].PtrLineSrc; } } } @@ -1096,17 +2110,17 @@ char *DWARFManager_GetLineSrcFromAdr(size_t Adr, size_t Tag) } -// Get line number based on the address and the tag +// Get line number based on the address and a tag +// A tag can be either 0 or a DW_TAG_subprogram +// DW_TAG_subprogram will look for the line pointing to the function name as described in the source code // Return 0 if no line number has been found size_t DWARFManager_GetNumLineFromAdr(size_t Adr, size_t Tag) { - size_t i, j, k; - - for (i = 0; i < NbCU; i++) + for (size_t i = 0; i < NbCU; i++) { if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC)) { - for (j = 0; (j < PtrCU[i].NbSubProgs); j++) + for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++) { if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC)) { @@ -1116,11 +2130,18 @@ size_t DWARFManager_GetNumLineFromAdr(size_t Adr, size_t Tag) } else { - for (k = 0; (k < PtrCU[i].PtrSubProgs[j].NbLinesSrc); k++) + for (size_t k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++) { - if ((PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC == Adr) && (!Tag || (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].Tag == Tag))) + if (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC <= Adr) { - return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc; + if ((PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC == Adr) && (!Tag || (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].Tag == Tag))) + { + return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc; + } + } + else + { + return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k - 1].NumLineSrc; } } } @@ -1132,6 +2153,15 @@ size_t DWARFManager_GetNumLineFromAdr(size_t Adr, size_t Tag) #endif } } + + // Check if a used line is found with the address + for (size_t j = 0; j < PtrCU[i].NbUsedLinesSrc; j++) + { + if (PtrCU[i].PtrUsedLinesSrc[j].StartPC == Adr) + { + return PtrCU[i].PtrUsedLinesSrc[j].NumLineSrc; + } + } } } @@ -1139,17 +2169,88 @@ size_t DWARFManager_GetNumLineFromAdr(size_t Adr, size_t Tag) } -// Get text line from source based on address and num line (starting by 1) +// Get function name based on an address +// Return NULL if no function name has been found, otherwise will return the function name in the range of the provided address +char *DWARFManager_GetFunctionName(size_t Adr) +{ + for (size_t i = 0; i < NbCU; i++) + { + if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC)) + { + for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++) + { + if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC)) + { + return PtrCU[i].PtrSubProgs[j].PtrSubprogramName; + } + } + } + } + + return NULL; +} + + +// Get number of lines of texts source list from source index +size_t DWARFManager_GetSrcNbListPtrFromIndex(size_t Index, bool Used) +{ + if (!Used) + { + return PtrCU[Index].NbLinesLoadSrc; + } + else + { + return PtrCU[Index].NbUsedLinesSrc; + } +} + + +// Get text source line number list pointer from source index +// Return NULL for the text source used list +size_t *DWARFManager_GetSrcNumLinesPtrFromIndex(size_t Index, bool Used) +{ + if (Used) + { + return PtrCU[Index].PtrUsedNumLines; + } + else + { + return NULL; + } +} + + +// Get text source list pointers from source index +// Return NULL for the text source used list +char **DWARFManager_GetSrcListPtrFromIndex(size_t Index, bool Used) +{ + if (!Used) + { + return PtrCU[Index].PtrLinesLoadSrc; + } + else + { + return PtrCU[Index].PtrUsedLinesLoadSrc; + } +} + + +// Get source language +size_t DWARFManager_GetSrcLanguageFromIndex(size_t Index) +{ + return PtrCU[Index].Language; +} + + +// Get text line from source based on address and num line (starting from 1) // Return NULL if no text line has been found char *DWARFManager_GetLineSrcFromAdrNumLine(size_t Adr, size_t NumLine) { - size_t i, j, k; - - for (i = 0; i < NbCU; i++) + for (size_t i = 0; i < NbCU; i++) { if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC)) { - for (j = 0; j < PtrCU[i].NbSubProgs; j++) + for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++) { if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC)) { @@ -1159,7 +2260,7 @@ char *DWARFManager_GetLineSrcFromAdrNumLine(size_t Adr, size_t NumLine) } else { - for (k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++) + for (size_t k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++) { if (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc == NumLine) { @@ -1176,13 +2277,11 @@ char *DWARFManager_GetLineSrcFromAdrNumLine(size_t Adr, size_t NumLine) } -// Get text line from source based on address and num line (starting by 1) -// Return NULL if no text line has been found +// Get text line pointer from source, based on address and line number (starting from 1) +// Return NULL if no text line has been found, or if requested number line is above the source total number of lines char *DWARFManager_GetLineSrcFromNumLineBaseAdr(size_t Adr, size_t NumLine) { - size_t i; - - for (i = 0; i < NbCU; i++) + for (size_t i = 0; i < NbCU; i++) { if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC)) { @@ -1200,3 +2299,24 @@ char *DWARFManager_GetLineSrcFromNumLineBaseAdr(size_t Adr, size_t NumLine) return NULL; } + +// Get number of source code filenames +size_t DWARFManager_GetNbSources(void) +{ + return NbCU; +} + + +// Get source code filename, including his directory, based on index (starting from 0) +char *DWARFManager_GetNumFullSourceFilename(size_t Index) +{ + return (PtrCU[Index].PtrFullFilename); +} + + +// Get source code filename based on index (starting from 0) +char *DWARFManager_GetNumSourceFilename(size_t Index) +{ + return (PtrCU[Index].PtrSourceFilename); +} +