// by Jean-Paul Mari\r
//\r
// JPM = Jean-Paul Mari <djipi.mari@gmail.com>\r
+// RG = Richard Goedeken\r
//\r
// WHO WHEN WHAT\r
// --- ---------- ------------------------------------------------------------\r
-// JPM 12/03/2016 Created this file\r
-// JPM 12/03/2016 DWARF format support\r
+// JPM Dec./2016 Created this file, and added the DWARF format support\r
+// JPM Sept./2018 Added LEB128 decoding features, and improve the DWARF parsing information\r
+// 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\r
+// JPM Aug./2019 Added new functions to handle DWARF information, full filename fix\r
+// JPM Mar./2020 Fix a random crash when reading the source lines information\r
+// JPM Aug./2020 Added a source code file date check when reading DWARF information\r
+// RG Jan./2021 Linux build fixes\r
+//\r
+\r
+// To Do\r
+// To use pointers instead of arrays usage\r
+// \r
\r
\r
#include <stdlib.h>\r
#include <stdio.h>\r
#include <stdint.h>\r
#include <string.h>\r
-#include <libdwarf.h>\r
-#include <dwarf.h>\r
-\r
-\r
-//\r
-//#define DEBUG_NumCU 0x6 // CU number to debug or undefine it\r
-\r
+#include <time.h>\r
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
+#include "libdwarf.h"\r
+#include "dwarf.h"\r
+#include "LEB128.h"\r
+#include "DWARFManager.h"\r
+\r
+// Definitions for debugging\r
+//#define DEBUG_NumCU 0x3 // CU number to debug or undefine it\r
+//#define DEBUG_VariableName "sound_death" // Variable name to look for or undefine it\r
+//#define DEBUG_TypeName "Cbuf_Execute" // Type name to look for or undefine it\r
+//#define DEBUG_TypeDef DW_TAG_typedef // Type def to look for or undefine it (not supported)\r
+//#define DEBUG_Filename "crt0" // Filename to look for or undefine it\r
+\r
+// Definitions for handling data\r
+//#define CONVERT_QT_HML // Text will be converted as HTML\r
+\r
+// Definitions for the variables's typetag\r
+#define TypeTag_structure 0x01 // structure\r
+#define TypeTag_pointer 0x02 // pointer\r
+#define TypeTag_subrange 0x04 // (subrange_type?)\r
+#define TypeTag_arraytype 0x08 // array type\r
+#define TypeTag_consttype 0x10 // const type\r
+#define TypeTag_typedef 0x20 // typedef\r
+#define TypeTag_enumeration_type 0x40 // enumeration\r
+#define TypeTag_subroutine_type 0x80 // subroutine\r
+\r
+\r
+// Source line CU structure\r
+typedef struct CUStruct_LineSrc\r
+{\r
+ size_t StartPC;\r
+ size_t NumLineSrc;\r
+ char *PtrLineSrc;\r
+}S_CUStruct_LineSrc;\r
\r
// Source line internal structure\r
-struct DMIStruct_LineSrc\r
+typedef struct DMIStruct_LineSrc\r
{\r
size_t Tag;\r
size_t StartPC;\r
char *PtrLineSrc;\r
}S_DMIStruct_LineSrc;\r
\r
+// Enumeration structure\r
+typedef struct EnumerationStruct\r
+{\r
+ char *PtrName; // Enumeration's name\r
+ size_t value; // Enumeration's value\r
+}S_EnumerationStruct;\r
+\r
+// Structure members structure\r
+//typedef struct StructureMembersStruct\r
+//{\r
+//}S_StructureMembersStruct;\r
+\r
// Base type internal structure\r
-struct BaseTypeStruct\r
+typedef struct BaseTypeStruct\r
{\r
- size_t Tag; // Type's Tag\r
- size_t Offset; // Type's offset\r
- size_t TypeOffset; // Type's offset on another type\r
- size_t ByteSize; // Type's Byte Size\r
- size_t Encoding; // Type's encoding\r
- char *PtrName; // Type's name\r
+ size_t Tag; // Type's Tag\r
+ size_t Offset; // Type's offset\r
+ size_t TypeOffset; // Type's offset on another type\r
+ size_t ByteSize; // Type's Byte Size\r
+ size_t Encoding; // Type's encoding\r
+ char *PtrName; // Type's name\r
+ size_t NbEnumeration; // Type's enumeration numbers\r
+ EnumerationStruct *PtrEnumeration; // Type's enumeration\r
+// StructureMembersStruct *PtrStructureMembers; // Type's structure members\r
}S_BaseTypeStruct;\r
\r
// Variables internal structure\r
-struct VariablesStruct\r
+typedef struct VariablesStruct\r
{\r
- size_t Addr; // Variable memory address\r
+ size_t Op; // Variable's DW_OP\r
+ union\r
+ {\r
+ size_t Addr; // Variable memory address\r
+ int Offset; // Variable stack offset (signed)\r
+ };\r
char *PtrName; // Variable's name\r
size_t TypeOffset; // Offset pointing on the Variable's Type\r
size_t TypeByteSize; // Variable's Type byte size\r
}S_VariablesStruct;\r
\r
// Sub program internal structure\r
-struct SubProgStruct\r
+typedef struct SubProgStruct\r
{\r
size_t Tag;\r
size_t NumLineSrc;\r
size_t StartPC;\r
size_t LowPC, HighPC;\r
+ size_t FrameBase;\r
char *PtrLineSrc;\r
- char *PtrSubprogramName;\r
- size_t NbLinesSrc;\r
- DMIStruct_LineSrc *PtrLinesSrc;\r
+ char *PtrSubprogramName; // Sub program name\r
+ size_t NbLinesSrc; // Number of lines source used by the sub program\r
+ DMIStruct_LineSrc *PtrLinesSrc; // Pointer of the lines source for the sub program\r
+ size_t NbVariables; // Variables number\r
+ VariablesStruct *PtrVariables; // Pointer to the local variables list information structure\r
}S_SubProgStruct;\r
\r
// Compilation Unit internal structure\r
-struct CUStruct\r
+typedef struct CUStruct\r
{\r
size_t Tag;\r
- size_t LowPC, HighPC;\r
- char *PtrProducer; // Pointer to the "Producer" information (compiler and compilation options used)\r
+ size_t Language; // Language (C, etc.) used by the source code\r
+ size_t LowPC, HighPC; // Memory range for the code\r
+ char *PtrProducer; // "Producer" text information (mostly compiler and compilation options used)\r
+ char *PtrSourceFilename; // Source file name\r
+ char *PtrSourceFileDirectory; // Directory of the source file\r
char *PtrFullFilename; // Pointer to full namefile (directory & filename)\r
- size_t SizeLoadSrc; // Source code size\r
- char *PtrLoadSrc; // Pointer to loaded source code\r
- size_t NbLinesLoadSrc; // Lines source number\r
+ size_t SizeLoadSrc; // Source code text size\r
+ char *PtrLoadSrc; // Pointer to the source code text\r
+ size_t NbLinesLoadSrc; // Total number of lines in the source code text\r
char **PtrLinesLoadSrc; // Pointer lists to each source line put in QT html/text conformity\r
size_t NbSubProgs; // Number of sub programs / routines\r
- SubProgStruct *PtrSubProgs; // Pointer to the sub programs / routines information structure\r
- size_t NbTypes;\r
- BaseTypeStruct *PtrTypes;\r
+ SubProgStruct *PtrSubProgs; // Pointer to the sub programs / routines structure\r
+ size_t NbTypes; // Number of types\r
+ BaseTypeStruct *PtrTypes; // Pointer to types\r
size_t NbVariables; // Variables number\r
- VariablesStruct *PtrVariables; // Pointer to the variables list information structure\r
+ VariablesStruct *PtrVariables; // Pointer to the global variables list structure\r
+ size_t NbFrames; // Frames number\r
+ size_t NbUsedLinesSrc; // Number of used source lines\r
+ size_t LastNumUsedLinesSrc; // Last number line used\r
+ CUStruct_LineSrc *PtrUsedLinesSrc; // Pointer to the used source lines list structure\r
+ char **PtrUsedLinesLoadSrc; // Pointer lists to each used source line referenced by the CUStruct_LineSrc structure\r
+ size_t *PtrUsedNumLines; // List of the number lines used\r
+ struct stat _statbuf; // File information\r
+ DWARFstatus Status; // File status\r
}S_CUStruct;\r
\r
\r
Dwarf_Error error;\r
Dwarf_Debug dbg;\r
CUStruct *PtrCU;\r
+char **ListSearchPaths;\r
+size_t NbSearchPaths;\r
+struct stat FileElfExeInfo;\r
\r
\r
//\r
void DWARFManager_CloseDMI(void);\r
bool DWARFManager_ElfClose(void);\r
char *DWARFManager_GetLineSrcFromNumLine(char *PtrSrcFile, size_t NumLine);\r
+void DWARFManager_InitInfosVariable(VariablesStruct *PtrVariables);\r
+void DWARFManager_SourceFileSearchPathsInit(void);\r
+void DWARFManager_SourceFileSearchPathsReset(void);\r
+void DWARFManager_SourceFileSearchPathsClose(void);\r
+void DWARFManager_ConformSlachesBackslashes(char *Ptr);\r
\r
\r
//\r
}\r
\r
\r
+// Dwarf manager list search paths init\r
+void DWARFManager_SourceFileSearchPathsInit(void)\r
+{\r
+ ListSearchPaths = NULL;\r
+ NbSearchPaths = 0;\r
+}\r
+\r
+\r
+// Dwarf manager list search paths reset\r
+void DWARFManager_SourceFileSearchPathsReset(void)\r
+{\r
+ ListSearchPaths = NULL;\r
+ NbSearchPaths = 0;\r
+}\r
+\r
+\r
+// Dwarf manager list search paths close\r
+void DWARFManager_SourceFileSearchPathsClose(void)\r
+{\r
+ DWARFManager_SourceFileSearchPathsReset();\r
+}\r
+\r
+\r
// Dwarf manager init\r
void DWARFManager_Init(void)\r
{\r
+ DWARFManager_SourceFileSearchPathsInit();\r
LibDwarf = DW_DLV_NO_ENTRY;\r
}\r
\r
\r
+// Dwarf manager settings\r
+void DWARFManager_Set(size_t NbPathsInList, char **PtrListPaths)\r
+{\r
+ // Search paths init\r
+ ListSearchPaths = PtrListPaths;\r
+ NbSearchPaths = NbPathsInList;\r
+}\r
+\r
+\r
// Dwarf manager Reset\r
bool DWARFManager_Reset(void)\r
{\r
+ DWARFManager_SourceFileSearchPathsReset();\r
return DWARFManager_ElfClose();\r
}\r
\r
// Dwarf manager Close\r
bool DWARFManager_Close(void)\r
{\r
+ DWARFManager_SourceFileSearchPathsClose();\r
return(DWARFManager_Reset());\r
}\r
\r
\r
// Dwarf manager Elf init\r
-int DWARFManager_ElfInit(Elf *ElfPtr)\r
+int DWARFManager_ElfInit(Elf *ElfPtr, struct stat FileElfInfo)\r
{\r
if ((LibDwarf = dwarf_elf_init(ElfPtr, DW_DLC_READ, (Dwarf_Handler)DWARFManager_ErrorHandler, errarg, &dbg, &error)) == DW_DLV_OK)\r
{\r
+ FileElfExeInfo = FileElfInfo;\r
DWARFManager_InitDMI();\r
}\r
\r
free(PtrCU[NbCU].PtrFullFilename);\r
free(PtrCU[NbCU].PtrLoadSrc);\r
free(PtrCU[NbCU].PtrProducer);\r
+ free(PtrCU[NbCU].PtrSourceFilename);\r
+ free(PtrCU[NbCU].PtrSourceFileDirectory);\r
+ free(PtrCU[NbCU].PtrUsedLinesSrc);\r
+ free(PtrCU[NbCU].PtrUsedLinesLoadSrc);\r
+ free(PtrCU[NbCU].PtrUsedNumLines);\r
\r
while (PtrCU[NbCU].NbLinesLoadSrc--)\r
{\r
\r
while (PtrCU[NbCU].NbSubProgs--)\r
{\r
+ while (PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables--)\r
+ {\r
+ free(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].PtrName);\r
+ free(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].PtrTypeName);\r
+ }\r
+ free(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables);\r
+\r
free(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc);\r
free(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrSubprogramName);\r
}\r
Dwarf_Addr return_lowpc, return_highpc, return_lineaddr;\r
Dwarf_Block *return_block;\r
Dwarf_Signed atcnt, cnt;\r
- Dwarf_Die return_sib, return_die;\r
+ Dwarf_Die return_sib, return_die, return_sub, return_subdie;\r
Dwarf_Off return_offset;\r
Dwarf_Line *linebuf;\r
FILE *SrcFile;\r
- size_t i, j, k, TypeOffset;\r
char *return_string;\r
- char *Ptr;\r
- char *SourceFilename = NULL;\r
- char *SourceFileDirectory = NULL;\r
- char *SourceFullFilename = NULL;\r
+ char *Ptr, *Ptr1;\r
\r
// Initialisation for the Compilation Units table\r
NbCU = 0;\r
// Die type detection\r
switch (return_tagval)\r
{\r
- case DW_TAG_compile_unit:\r
+ case DW_TAG_compile_unit:\r
if (dwarf_attrlist(return_sib, &atlist, &atcnt, &error) == DW_DLV_OK)\r
{\r
for (Dwarf_Signed i = 0; i < atcnt; ++i)\r
{\r
switch (return_attr)\r
{\r
- case DW_AT_low_pc:\r
+ // Start address\r
+ case DW_AT_low_pc:\r
if (dwarf_lowpc(return_sib, &return_lowpc, &error) == DW_DLV_OK)\r
{\r
PtrCU[NbCU].LowPC = return_lowpc;\r
}\r
break;\r
\r
- case DW_AT_high_pc:\r
+ // End address\r
+ case DW_AT_high_pc:\r
if (dwarf_highpc(return_sib, &return_highpc, &error) == DW_DLV_OK)\r
{\r
PtrCU[NbCU].HighPC = return_highpc;\r
}\r
break;\r
\r
- case DW_AT_producer:\r
+ // compilation information\r
+ case DW_AT_producer:\r
if (dwarf_formstring(atlist[i], &return_string, &error) == DW_DLV_OK)\r
{\r
PtrCU[NbCU].PtrProducer = (char *)calloc(strlen(return_string) + 1, 1);\r
}\r
break;\r
\r
- case DW_AT_name:\r
+ // Filename\r
+ case DW_AT_name:\r
if (dwarf_formstring(atlist[i], &return_string, &error) == DW_DLV_OK)\r
{\r
- SourceFilename = (char *)realloc(SourceFilename, strlen(return_string) + 1);\r
- strcpy(SourceFilename, return_string);\r
+#ifdef DEBUG_Filename\r
+ if (strstr(return_string, DEBUG_Filename))\r
+#endif\r
+ {\r
+ PtrCU[NbCU].PtrSourceFilename = (char *)calloc((strlen(return_string) + 1), 1);\r
+ strcpy(PtrCU[NbCU].PtrSourceFilename, return_string);\r
+ }\r
dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
}\r
break;\r
\r
- case DW_AT_comp_dir:\r
+ // Directory name\r
+ case DW_AT_comp_dir:\r
if (dwarf_formstring(atlist[i], &return_string, &error) == DW_DLV_OK)\r
{\r
- SourceFileDirectory = (char *)realloc(SourceFileDirectory, strlen(return_string) + 1);\r
- strcpy(SourceFileDirectory, return_string);\r
+ PtrCU[NbCU].PtrSourceFileDirectory = (char *)calloc((strlen(return_string) + 1), 1);\r
+ strcpy(PtrCU[NbCU].PtrSourceFileDirectory, return_string);\r
dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
}\r
break;\r
\r
+ // Language\r
+ case DW_AT_language:\r
+ if (dwarf_formudata(atlist[i], &return_uvalue, &error) == DW_DLV_OK)\r
+ {\r
+ PtrCU[NbCU].Language = return_uvalue;\r
+ }\r
+ break;\r
+\r
default:\r
break;\r
}\r
dwarf_dealloc(dbg, atlist, DW_DLA_LIST);\r
}\r
\r
- Ptr = SourceFullFilename = (char *)realloc(SourceFullFilename, strlen(SourceFilename) + strlen(SourceFileDirectory) + 2);\r
- sprintf(SourceFullFilename, "%s\\%s", SourceFileDirectory, SourceFilename);\r
- while (*Ptr)\r
+ // Check filename presence\r
+ if (!PtrCU[NbCU].PtrSourceFilename)\r
+ {\r
+ PtrCU[NbCU].PtrSourceFilename = (char *)calloc(1, 1);\r
+ }\r
+\r
+ // Check directory presence\r
+ if (!PtrCU[NbCU].PtrSourceFileDirectory)\r
{\r
- if (*Ptr == '/')\r
+ // Check if file exists in the search paths\r
+ for (size_t i = 0; i < NbSearchPaths; i++)\r
+ {\r
+ PtrCU[NbCU].PtrFullFilename = (char *)realloc(PtrCU[NbCU].PtrFullFilename, strlen(PtrCU[NbCU].PtrSourceFilename) + strlen((const char *)ListSearchPaths[i]) + 2);\r
+#if defined(_WIN32)\r
+ sprintf(PtrCU[NbCU].PtrFullFilename, "%s\\%s", ListSearchPaths[i], PtrCU[NbCU].PtrSourceFilename);\r
+ if (!fopen_s(&SrcFile, PtrCU[NbCU].PtrFullFilename, "rb"))\r
+#else\r
+ sprintf(PtrCU[NbCU].PtrFullFilename, "%s/%s", ListSearchPaths[i], PtrCU[NbCU].PtrSourceFilename);\r
+ SrcFile = fopen(PtrCU[NbCU].PtrFullFilename, "rb");\r
+ if (SrcFile == NULL)\r
+#endif\r
+ {\r
+ PtrCU[NbCU].PtrSourceFileDirectory = (char *)realloc(PtrCU[NbCU].PtrSourceFileDirectory, strlen(ListSearchPaths[i]) + 1);\r
+ strcpy(PtrCU[NbCU].PtrSourceFileDirectory, ListSearchPaths[i]);\r
+ }\r
+ }\r
+\r
+ // File directory doesn't exits\r
+ if (!PtrCU[NbCU].PtrSourceFileDirectory)\r
{\r
- *Ptr = '\\';\r
+ PtrCU[NbCU].PtrSourceFileDirectory = (char *)realloc(PtrCU[NbCU].PtrSourceFileDirectory, 2);\r
+ strcpy(PtrCU[NbCU].PtrSourceFileDirectory, ".");\r
}\r
- Ptr++;\r
}\r
- PtrCU[NbCU].PtrFullFilename = (char *)calloc(strlen(SourceFullFilename) + 1, 1);\r
- strcpy((char *)PtrCU[NbCU].PtrFullFilename, SourceFullFilename);\r
\r
-#ifndef __CYGWIN__\r
- if (!fopen_s(&SrcFile, SourceFullFilename, "rt"))\r
+ // Conform slashes / backslashes for the filename\r
+ DWARFManager_ConformSlachesBackslashes(PtrCU[NbCU].PtrSourceFilename);\r
+\r
+ // Check if filename contains already the complete directory\r
+ if (PtrCU[NbCU].PtrSourceFilename[1] == ':')\r
+ {\r
+ // Copy the filename as the full filename\r
+ PtrCU[NbCU].PtrFullFilename = (char *)realloc(PtrCU[NbCU].PtrFullFilename, strlen(PtrCU[NbCU].PtrSourceFilename) + 1);\r
+ strcpy(PtrCU[NbCU].PtrFullFilename, PtrCU[NbCU].PtrSourceFilename);\r
+ }\r
+ else\r
+ {\r
+ // Create full filename and Conform slashes / backslashes\r
+ PtrCU[NbCU].PtrFullFilename = (char *)realloc(PtrCU[NbCU].PtrFullFilename, strlen(PtrCU[NbCU].PtrSourceFilename) + strlen(PtrCU[NbCU].PtrSourceFileDirectory) + 2);\r
+#if defined(_WIN32)\r
+ sprintf(PtrCU[NbCU].PtrFullFilename, "%s\\%s", PtrCU[NbCU].PtrSourceFileDirectory, PtrCU[NbCU].PtrSourceFilename);\r
+#else\r
+ sprintf(PtrCU[NbCU].PtrFullFilename, "%s/%s", PtrCU[NbCU].PtrSourceFileDirectory, PtrCU[NbCU].PtrSourceFilename);\r
+#endif\r
+ }\r
+\r
+ DWARFManager_ConformSlachesBackslashes(PtrCU[NbCU].PtrFullFilename);\r
+\r
+ // Directory path clean-up\r
+#if defined(_WIN32)\r
+ while ((Ptr1 = Ptr = strstr(PtrCU[NbCU].PtrFullFilename, "\\..\\")))\r
#else\r
- if (!(SrcFile = fopen(SourceFullFilename, "rt")))\r
+ while ((Ptr1 = Ptr = strstr(PtrCU[NbCU].PtrFullFilename, "/../")))\r
#endif\r
{\r
- if (!fseek(SrcFile, 0, SEEK_END))\r
+#if defined(_WIN32)\r
+ while (*--Ptr1 != '\\');\r
+#else\r
+ while (*--Ptr1 != '/');\r
+#endif\r
+ strcpy((Ptr1 + 1), (Ptr + 4));\r
+ }\r
+\r
+ // Get the source file information\r
+ if (!stat(PtrCU[NbCU].PtrFullFilename, &PtrCU[NbCU]._statbuf))\r
+ {\r
+ // check the time stamp with the executable\r
+ if (PtrCU[NbCU]._statbuf.st_mtime <= FileElfExeInfo.st_mtime)\r
{\r
- if ((PtrCU[NbCU].SizeLoadSrc = ftell(SrcFile)) > 0)\r
+ // Open the source file as a binary file\r
+#if defined(_WIN32)\r
+ if (!fopen_s(&SrcFile, PtrCU[NbCU].PtrFullFilename, "rb"))\r
+#else\r
+ SrcFile = fopen(PtrCU[NbCU].PtrFullFilename, "rb");\r
+ if (SrcFile == NULL)\r
+#endif\r
{\r
- if (PtrCU[NbCU].PtrLoadSrc = Ptr = (char *)calloc((PtrCU[NbCU].SizeLoadSrc + 1), 1))\r
+ if (!fseek(SrcFile, 0, SEEK_END))\r
{\r
- rewind(SrcFile);\r
- if (PtrCU[NbCU].SizeLoadSrc < fread(Ptr, 1, PtrCU[NbCU].SizeLoadSrc, SrcFile))\r
+ if ((PtrCU[NbCU].SizeLoadSrc = ftell(SrcFile)) > 0)\r
{\r
- free(PtrCU[NbCU].PtrLoadSrc);\r
- PtrCU[NbCU].PtrLoadSrc = NULL;\r
- PtrCU[NbCU].SizeLoadSrc = 0;\r
- }\r
- else\r
- {\r
- do\r
+ if (!fseek(SrcFile, 0, SEEK_SET))\r
{\r
- if (*Ptr == 0xa)\r
+ if (PtrCU[NbCU].PtrLoadSrc = Ptr = Ptr1 = (char *)calloc(1, (PtrCU[NbCU].SizeLoadSrc + 2)))\r
{\r
- PtrCU[NbCU].NbLinesLoadSrc++;\r
- *Ptr = 0;\r
+ // Read whole file\r
+#if defined(_WIN32) \r
+ if (fread_s(PtrCU[NbCU].PtrLoadSrc, PtrCU[NbCU].SizeLoadSrc, PtrCU[NbCU].SizeLoadSrc, 1, SrcFile) != 1)\r
+#else\r
+ if (fread(PtrCU[NbCU].PtrLoadSrc, PtrCU[NbCU].SizeLoadSrc, 1, SrcFile) != 1)\r
+#endif\r
+ {\r
+ free(PtrCU[NbCU].PtrLoadSrc);\r
+ PtrCU[NbCU].PtrLoadSrc = NULL;\r
+ PtrCU[NbCU].SizeLoadSrc = 0;\r
+ }\r
+ else\r
+ {\r
+ // Eliminate all carriage return code '\r' (oxd)\r
+ do\r
+ {\r
+ if ((*Ptr = *Ptr1) != '\r')\r
+ {\r
+ Ptr++;\r
+ }\r
+ } while (*Ptr1++);\r
+\r
+ // Get back the new text file size\r
+ PtrCU[NbCU].SizeLoadSrc = strlen(Ptr = PtrCU[NbCU].PtrLoadSrc);\r
+\r
+ // Make sure the text file finish with a new line code '\n' (0xa)\r
+ if (PtrCU[NbCU].PtrLoadSrc[PtrCU[NbCU].SizeLoadSrc - 1] != '\n')\r
+ {\r
+ PtrCU[NbCU].PtrLoadSrc[PtrCU[NbCU].SizeLoadSrc++] = '\n';\r
+ PtrCU[NbCU].PtrLoadSrc[PtrCU[NbCU].SizeLoadSrc] = 0;\r
+ }\r
+\r
+ // Reallocate text file\r
+ if (PtrCU[NbCU].PtrLoadSrc = Ptr = (char *)realloc(PtrCU[NbCU].PtrLoadSrc, (PtrCU[NbCU].SizeLoadSrc + 1)))\r
+ {\r
+ // Count line numbers, based on the new line code '\n' (0xa), and finish each line with 0\r
+ do\r
+ {\r
+ if (*Ptr == '\n')\r
+ {\r
+ PtrCU[NbCU].NbLinesLoadSrc++;\r
+ *Ptr = 0;\r
+ }\r
+ } while (*++Ptr);\r
+ }\r
+ }\r
}\r
- } while (*++Ptr);\r
+ }\r
}\r
}\r
+\r
+ fclose(SrcFile);\r
+ }\r
+ else\r
+ {\r
+ // Source file doesn't exist\r
+ PtrCU[NbCU].Status = DWARFSTATUS_NOFILE;\r
}\r
}\r
- fclose(SrcFile);\r
+ else\r
+ {\r
+ // Source file is outdated\r
+ PtrCU[NbCU].Status = DWARFSTATUS_OUTDATEDFILE;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // Source file doesn't have information\r
+ PtrCU[NbCU].Status = DWARFSTATUS_NOFILEINFO;\r
}\r
break;\r
\r
}\r
}\r
\r
- // Get the source lines table located in the Compilation Unit\r
- if (dwarf_srclines(return_sib, &linebuf, &cnt, &error) == DW_DLV_OK)\r
+ // Get the source lines table located in the CU\r
+ if ((dwarf_srclines(return_sib, &linebuf, &cnt, &error) == DW_DLV_OK) && (PtrCU[NbCU].Status == DWARFSTATUS_OK))\r
{\r
+ if (cnt)\r
+ {\r
+ PtrCU[NbCU].NbUsedLinesSrc = cnt;\r
+ PtrCU[NbCU].PtrUsedLinesSrc = (CUStruct_LineSrc *)calloc(cnt, sizeof(CUStruct_LineSrc));\r
+ PtrCU[NbCU].PtrUsedLinesLoadSrc = (char **)calloc(cnt, sizeof(char *));\r
+ PtrCU[NbCU].PtrUsedNumLines = (size_t *)calloc(cnt, sizeof(size_t));\r
+\r
+ // Get the addresses and their source line numbers\r
+ for (Dwarf_Signed i = 0; i < cnt; i++)\r
+ {\r
+ if (dwarf_lineaddr(linebuf[i], &return_lineaddr, &error) == DW_DLV_OK)\r
+ {\r
+ // Get the source line number\r
+ if (dwarf_lineno(linebuf[i], &return_uvalue, &error) == DW_DLV_OK)\r
+ {\r
+ PtrCU[NbCU].PtrUsedLinesSrc[i].StartPC = return_lineaddr;\r
+ PtrCU[NbCU].PtrUsedLinesSrc[i].NumLineSrc = return_uvalue;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ // Release the memory used by the source lines table located in the CU\r
+ dwarf_srclines_dealloc(dbg, linebuf, cnt);\r
}\r
\r
+ // Check if the CU has child\r
if (dwarf_child(return_sib, &return_die, &error) == DW_DLV_OK)\r
{\r
do\r
{\r
switch (return_tagval)\r
{\r
- case DW_TAG_lexical_block:\r
+ case DW_TAG_lexical_block:\r
break;\r
\r
- case DW_TAG_variable:\r
+ case DW_TAG_variable:\r
if (dwarf_attrlist(return_die, &atlist, &atcnt, &error) == DW_DLV_OK)\r
{\r
PtrCU[NbCU].PtrVariables = (VariablesStruct *)realloc(PtrCU[NbCU].PtrVariables, ((PtrCU[NbCU].NbVariables + 1) * sizeof(VariablesStruct)));\r
{\r
switch (return_attr)\r
{\r
- case DW_AT_location:\r
+ case DW_AT_location:\r
if (dwarf_formblock(return_attr1, &return_block, &error) == DW_DLV_OK)\r
{\r
- if (return_block->bl_len == 5)\r
+ PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].Op = (*((unsigned char *)(return_block->bl_data)));\r
+\r
+ switch (return_block->bl_len)\r
{\r
+ case 5:\r
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));\r
+ break;\r
+\r
+ default:\r
+ break;\r
}\r
dwarf_dealloc(dbg, return_block, DW_DLA_BLOCK);\r
}\r
break;\r
\r
- case DW_AT_type:\r
+ case DW_AT_type:\r
if (dwarf_global_formref(return_attr1, &return_offset, &error) == DW_DLV_OK)\r
{\r
PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].TypeOffset = return_offset;\r
}\r
break;\r
\r
- case DW_AT_name:\r
+ // Variable name\r
+ case DW_AT_name:\r
if (dwarf_formstring(return_attr1, &return_string, &error) == DW_DLV_OK)\r
{\r
- PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName = (char *)calloc(strlen(return_string) + 1, 1);\r
- strcpy(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName, return_string);\r
+#ifdef DEBUG_VariableName\r
+ if (!strcmp(return_string, DEBUG_VariableName))\r
+#endif\r
+ {\r
+ PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName = (char *)calloc(strlen(return_string) + 1, 1);\r
+ strcpy(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName, return_string);\r
+ }\r
dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
}\r
break;\r
\r
- default:\r
+ default:\r
break;\r
}\r
}\r
dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);\r
}\r
\r
- PtrCU[NbCU].NbVariables++;\r
+ // Check variable's name validity\r
+ if (PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName)\r
+ {\r
+ // Check variable's memory address validity\r
+ if (PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].Addr)\r
+ {\r
+ // Valid variable\r
+ PtrCU[NbCU].NbVariables++;\r
+ }\r
+ else\r
+ {\r
+ // Invalid variable\r
+ free(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName);\r
+ PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName = NULL;\r
+ }\r
+ }\r
\r
dwarf_dealloc(dbg, atlist, DW_DLA_LIST);\r
}\r
break;\r
\r
- case DW_TAG_base_type:\r
- case DW_TAG_typedef:\r
- case DW_TAG_structure_type:\r
- case DW_TAG_pointer_type:\r
- case DW_TAG_const_type:\r
- case DW_TAG_array_type:\r
- case DW_TAG_subrange_type:\r
- case DW_TAG_subroutine_type:\r
+ case DW_TAG_base_type:\r
+ case DW_TAG_typedef:\r
+ case DW_TAG_structure_type:\r
+ case DW_TAG_pointer_type:\r
+ case DW_TAG_const_type:\r
+ case DW_TAG_array_type:\r
+ case DW_TAG_subrange_type:\r
+ case DW_TAG_subroutine_type:\r
+ case DW_TAG_enumeration_type:\r
if (dwarf_attrlist(return_die, &atlist, &atcnt, &error) == DW_DLV_OK)\r
{\r
+ // Allocate memory for this type\r
PtrCU[NbCU].PtrTypes = (BaseTypeStruct *)realloc(PtrCU[NbCU].PtrTypes, ((PtrCU[NbCU].NbTypes + 1) * sizeof(BaseTypeStruct)));\r
memset(PtrCU[NbCU].PtrTypes + PtrCU[NbCU].NbTypes, 0, sizeof(BaseTypeStruct));\r
PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].Tag = return_tagval;\r
{\r
switch (return_attr)\r
{\r
- case DW_AT_type:\r
+ // \r
+ case DW_AT_sibling:\r
+ break;\r
+\r
+ // Type's type offset\r
+ case DW_AT_type:\r
if (dwarf_global_formref(return_attr1, &return_offset, &error) == DW_DLV_OK)\r
{\r
PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].TypeOffset = return_offset;\r
}\r
break;\r
\r
- case DW_AT_byte_size:\r
+ // Type's byte size\r
+ case DW_AT_byte_size:\r
if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK)\r
{\r
PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].ByteSize = return_uvalue;\r
}\r
break;\r
\r
- case DW_AT_encoding:\r
+ // Type's encoding\r
+ case DW_AT_encoding:\r
if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK)\r
{\r
PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].Encoding = return_uvalue;\r
}\r
break;\r
\r
- case DW_AT_name:\r
+ // Type's name\r
+ case DW_AT_name:\r
if (dwarf_formstring(return_attr1, &return_string, &error) == DW_DLV_OK)\r
{\r
- PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName = (char *)calloc(strlen(return_string) + 1, 1);\r
- strcpy(PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName, return_string);\r
+#ifdef DEBUG_TypeName\r
+ if (!strcmp(return_string, DEBUG_TypeName))\r
+#endif\r
+ {\r
+ PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName = (char *)calloc(strlen(return_string) + 1, 1);\r
+ strcpy(PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName, return_string);\r
+ }\r
dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
}\r
break;\r
\r
+ // Type's file number\r
+ case DW_AT_decl_file:\r
+ break;\r
+\r
+ // Type's line number\r
+ case DW_AT_decl_line:\r
+ break;\r
+\r
default:\r
break;\r
}\r
}\r
break;\r
\r
- case DW_TAG_subprogram:\r
+ case DW_TAG_subprogram:\r
if (dwarf_attrlist(return_die, &atlist, &atcnt, &error) == DW_DLV_OK)\r
{\r
PtrCU[NbCU].PtrSubProgs = (SubProgStruct *)realloc(PtrCU[NbCU].PtrSubProgs, ((PtrCU[NbCU].NbSubProgs + 1) * sizeof(SubProgStruct)));\r
{\r
switch (return_attr)\r
{\r
- case DW_AT_low_pc:\r
+ // start address\r
+ case DW_AT_low_pc:\r
if (dwarf_lowpc(return_die, &return_lowpc, &error) == DW_DLV_OK)\r
{\r
PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].StartPC = return_lowpc;\r
}\r
break;\r
\r
- case DW_AT_high_pc:\r
+ // end address\r
+ case DW_AT_high_pc:\r
if (dwarf_highpc(return_die, &return_highpc, &error) == DW_DLV_OK)\r
{\r
PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].HighPC = return_highpc;\r
}\r
break;\r
\r
- case DW_AT_decl_line:\r
+ // Line number\r
+ case DW_AT_decl_line:\r
if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK)\r
{\r
PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NumLineSrc = return_uvalue;\r
}\r
break;\r
\r
- case DW_AT_name:\r
+ // Frame\r
+ case DW_AT_frame_base:\r
+ if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK)\r
+ {\r
+ PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].FrameBase = return_uvalue;\r
+ PtrCU[NbCU].NbFrames++;\r
+ }\r
+ break;\r
+\r
+ // function name\r
+ case DW_AT_name:\r
if (dwarf_formstring(return_attr1, &return_string, &error) == DW_DLV_OK)\r
{\r
PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrSubprogramName = (char *)calloc(strlen(return_string) + 1, 1);\r
}\r
break;\r
\r
+ case DW_AT_sibling:\r
+ break;\r
+\r
+ case DW_AT_GNU_all_tail_call_sites:\r
+ break;\r
+\r
+ case DW_AT_type:\r
+ break;\r
+\r
+ case DW_AT_prototyped:\r
+ break;\r
+\r
+ // File number\r
+ case DW_AT_decl_file:\r
+ break;\r
+\r
+ case DW_AT_external:\r
+ break;\r
+\r
default:\r
break;\r
}\r
}\r
dwarf_dealloc(dbg, atlist, DW_DLA_LIST);\r
\r
- for (i = 0; i < (size_t)cnt; ++i)\r
+ // Get source line number and associated block of address\r
+ for (Dwarf_Signed i = 0; i < cnt; ++i)\r
{\r
- if (dwarf_lineaddr(linebuf[i], &return_lineaddr, &error) == DW_DLV_OK)\r
+ // Check the presence of the line in the memory frame\r
+ if (PtrCU[NbCU].PtrUsedLinesSrc && (PtrCU[NbCU].PtrUsedLinesSrc[i].StartPC >= return_lowpc) && (PtrCU[NbCU].PtrUsedLinesSrc[i].StartPC <= return_highpc))\r
{\r
- if (dwarf_lineno(linebuf[i], &return_uvalue, &error) == DW_DLV_OK)\r
+ 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));\r
+ memset((void *)(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc + PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc), 0, sizeof(DMIStruct_LineSrc));\r
+ PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc].StartPC = PtrCU[NbCU].PtrUsedLinesSrc[i].StartPC;\r
+ PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc].NumLineSrc = PtrCU[NbCU].PtrUsedLinesSrc[i].NumLineSrc;\r
+ PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc++;\r
+ }\r
+ }\r
+\r
+ if (dwarf_child(return_die, &return_subdie, &error) == DW_DLV_OK)\r
+ {\r
+ do\r
+ {\r
+ return_sub = return_subdie;\r
+ if ((dwarf_tag(return_subdie, &return_tagval, &error) == DW_DLV_OK))\r
{\r
- if ((return_lineaddr >= return_lowpc) && (return_lineaddr <= return_highpc))\r
+ switch (return_tagval)\r
{\r
- 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));\r
- memset((void *)(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc + PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc), 0, sizeof(DMIStruct_LineSrc));\r
- PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc].StartPC = return_lineaddr;\r
- PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc].NumLineSrc = return_uvalue;\r
- PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc++;\r
+ case DW_TAG_formal_parameter:\r
+ case DW_TAG_variable:\r
+ if (dwarf_attrlist(return_subdie, &atlist, &atcnt, &error) == DW_DLV_OK)\r
+ {\r
+ 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)));\r
+ memset(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables + PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables, 0, sizeof(VariablesStruct));\r
+\r
+ for (Dwarf_Signed i = 0; i < atcnt; ++i)\r
+ {\r
+ if (dwarf_whatattr(atlist[i], &return_attr, &error) == DW_DLV_OK)\r
+ {\r
+ if (dwarf_attr(return_subdie, return_attr, &return_attr1, &error) == DW_DLV_OK)\r
+ {\r
+ switch (return_attr)\r
+ {\r
+ case DW_AT_location:\r
+ if (dwarf_formblock(return_attr1, &return_block, &error) == DW_DLV_OK)\r
+ {\r
+ PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].Op = *((unsigned char *)(return_block->bl_data));\r
+\r
+ switch (return_block->bl_len)\r
+ {\r
+ case 1:\r
+ break;\r
+\r
+ case 2:\r
+ case 3:\r
+ switch (return_tagval)\r
+ {\r
+ case DW_TAG_variable:\r
+ PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].Offset = ReadLEB128((char *)return_block->bl_data + 1);\r
+ break;\r
+\r
+ case DW_TAG_formal_parameter:\r
+ PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].Offset = ReadULEB128((char *)return_block->bl_data + 1);\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ dwarf_dealloc(dbg, return_block, DW_DLA_BLOCK);\r
+ }\r
+ break;\r
+\r
+ case DW_AT_type:\r
+ if (dwarf_global_formref(return_attr1, &return_offset, &error) == DW_DLV_OK)\r
+ {\r
+ PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].TypeOffset = return_offset;\r
+ }\r
+ break;\r
+\r
+ case DW_AT_name:\r
+ if (dwarf_formstring(return_attr1, &return_string, &error) == DW_DLV_OK)\r
+ {\r
+#ifdef DEBUG_VariableName\r
+ if (!strcmp(return_string, DEBUG_VariableName))\r
+#endif\r
+ {\r
+ PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].PtrName = (char *)calloc(strlen(return_string) + 1, 1);\r
+ strcpy(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].PtrName, return_string);\r
+ }\r
+ dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
+ }\r
+ break;\r
+\r
+ case DW_AT_decl_file:\r
+ break;\r
+\r
+ case DW_AT_decl_line:\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);\r
+ }\r
+\r
+ PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables++;\r
+\r
+ dwarf_dealloc(dbg, atlist, DW_DLA_LIST);\r
+ }\r
+ break;\r
+\r
+ case DW_TAG_label:\r
+ break;\r
+\r
+ default:\r
+ break;\r
}\r
}\r
}\r
+ while (dwarf_siblingof(dbg, return_sub, &return_subdie, &error) == DW_DLV_OK);\r
}\r
\r
PtrCU[NbCU].NbSubProgs++;\r
break;\r
}\r
}\r
- } while (dwarf_siblingof(dbg, return_sib, &return_die, &error) == DW_DLV_OK);\r
+ }\r
+ while (dwarf_siblingof(dbg, return_sib, &return_die, &error) == DW_DLV_OK);\r
}\r
-\r
- // Release the memory used by the source lines\r
- for (i = 0; i < (size_t)cnt; ++i)\r
- dwarf_dealloc(dbg, linebuf[i], DW_DLA_LINE);\r
- dwarf_dealloc(dbg, linebuf, DW_DLA_LIST);\r
}\r
\r
- // Set the source code lines for QT html/text conformity\r
+ // Set the source code lines\r
if (PtrCU[NbCU].NbLinesLoadSrc)\r
{\r
if (PtrCU[NbCU].PtrLinesLoadSrc = (char **)calloc(PtrCU[NbCU].NbLinesLoadSrc, sizeof(char *)))\r
{\r
- for (j = 0; j < PtrCU[NbCU].NbLinesLoadSrc; j++)\r
+ for (size_t j = 0; j < PtrCU[NbCU].NbLinesLoadSrc; j++)\r
{\r
if (PtrCU[NbCU].PtrLinesLoadSrc[j] = (char *)calloc(10000, sizeof(char)))\r
{\r
if (Ptr = DWARFManager_GetLineSrcFromNumLine(PtrCU[NbCU].PtrLoadSrc, (j + 1)))\r
{\r
- i = 0;\r
+#ifndef CONVERT_QT_HML\r
+ strcpy(PtrCU[NbCU].PtrLinesLoadSrc[j], Ptr);\r
+#else\r
+ size_t i = 0;\r
\r
while (*Ptr)\r
{\r
{\r
case 9:\r
strcat(PtrCU[NbCU].PtrLinesLoadSrc[j], " ");\r
- i += strlen(" ");\r
+ i += 6;\r
break;\r
\r
case '<':\r
strcat(PtrCU[NbCU].PtrLinesLoadSrc[j], "<");\r
- i += strlen("<");\r
+ i += 4;\r
break;\r
\r
case '>':\r
strcat(PtrCU[NbCU].PtrLinesLoadSrc[j], ">");\r
- i += strlen(">");\r
+ i += 4;\r
break;\r
#if 0\r
case '&':\r
}\r
Ptr++;\r
}\r
+#endif\r
}\r
- PtrCU[NbCU].PtrLinesLoadSrc[j] = (char *)realloc(PtrCU[NbCU].PtrLinesLoadSrc[j], i + 1);\r
+ PtrCU[NbCU].PtrLinesLoadSrc[j] = (char *)realloc(PtrCU[NbCU].PtrLinesLoadSrc[j], strlen(PtrCU[NbCU].PtrLinesLoadSrc[j]) + 1);\r
}\r
}\r
\r
- // Init lines source information based on each source code line numbers\r
- for (j = 0; j < PtrCU[NbCU].NbSubProgs; j++)\r
+ // Init lines source information for each source code line numbers and for each subprogs\r
+ for (size_t j = 0; j < PtrCU[NbCU].NbSubProgs; j++)\r
{\r
// Check if the subprog / function's line exists in the source code\r
if (PtrCU[NbCU].PtrSubProgs[j].NumLineSrc <= PtrCU[NbCU].NbLinesLoadSrc)\r
PtrCU[NbCU].PtrSubProgs[j].PtrLineSrc = PtrCU[NbCU].PtrLinesLoadSrc[PtrCU[NbCU].PtrSubProgs[j].NumLineSrc - 1];\r
}\r
\r
- for (k = 0; k < PtrCU[NbCU].PtrSubProgs[j].NbLinesSrc; k++)\r
+ for (size_t k = 0; k < PtrCU[NbCU].PtrSubProgs[j].NbLinesSrc; k++)\r
{\r
if (PtrCU[NbCU].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc <= PtrCU[NbCU].NbLinesLoadSrc)\r
{\r
// Check the presence of source lines dedicated to the sub progs\r
if (PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs - 1].NbLinesSrc)\r
{\r
- i = PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs - 1].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs - 1].NbLinesSrc - 1].NumLineSrc;\r
+ size_t i = PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs - 1].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs - 1].NbLinesSrc - 1].NumLineSrc;\r
if (PtrCU[NbCU].PtrLinesLoadSrc = (char **)calloc(i, sizeof(char *)))\r
{\r
- for (j = 0; j < i; j++)\r
+ for (size_t j = 0; j < i; j++)\r
{\r
PtrCU[NbCU].PtrLinesLoadSrc[j] = NULL;\r
}\r
}\r
}\r
\r
- // Init variables information based on types information\r
- for (i = 0; i < PtrCU[NbCU].NbVariables; i++)\r
+ // Check validity between used number lines and number lines in the source file\r
+ if (PtrCU[NbCU].LastNumUsedLinesSrc <= PtrCU[NbCU].NbLinesLoadSrc)\r
{\r
- PtrCU[NbCU].PtrVariables[i].PtrTypeName = (char *)calloc(1000, 1);\r
- TypeOffset = PtrCU[NbCU].PtrVariables[i].TypeOffset;\r
-\r
- for (j = 0; j < PtrCU[NbCU].NbTypes; j++)\r
+ // Set information based on used line numbers\r
+ if (PtrCU[NbCU].PtrUsedLinesSrc)\r
{\r
- if (TypeOffset == PtrCU[NbCU].PtrTypes[j].Offset)\r
+ // Set the line source pointers for each used line numbers\r
+ if (PtrCU[NbCU].PtrLinesLoadSrc)\r
{\r
- switch (PtrCU[NbCU].PtrTypes[j].Tag)\r
+ for (size_t i = 0; i < PtrCU[NbCU].NbUsedLinesSrc; i++)\r
{\r
- case DW_TAG_structure_type:\r
- PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x1;\r
- if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
- {\r
- j = -1;\r
- }\r
- else\r
- {\r
- if ((PtrCU[NbCU].PtrVariables[i].TypeTag & 0x2))\r
- {\r
- strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, " *");\r
- }\r
- }\r
- break;\r
+ PtrCU[NbCU].PtrUsedNumLines[i] = PtrCU[NbCU].PtrUsedLinesSrc[i].NumLineSrc - 1;\r
+ PtrCU[NbCU].PtrUsedLinesLoadSrc[i] = PtrCU[NbCU].PtrUsedLinesSrc[i].PtrLineSrc = PtrCU[NbCU].PtrLinesLoadSrc[PtrCU[NbCU].PtrUsedLinesSrc[i].NumLineSrc - 1];\r
+ }\r
\r
- case DW_TAG_pointer_type:\r
- PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x2;\r
- PtrCU[NbCU].PtrVariables[i].TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;\r
- PtrCU[NbCU].PtrVariables[i].TypeEncoding = 0x10;\r
- if (!(TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
- {\r
- strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, "void *");\r
- }\r
- else\r
- {\r
- j = -1;\r
- }\r
- break;\r
+ // Setup memory range for the code if CU doesn't have already this information\r
+ // It is taken from the used lines structure\r
+ if (!PtrCU[NbCU].LowPC && (!PtrCU[NbCU].HighPC || (PtrCU[NbCU].HighPC == ~0)))\r
+ {\r
+ PtrCU[NbCU].LowPC = PtrCU[NbCU].PtrUsedLinesSrc[0].StartPC;\r
+ PtrCU[NbCU].HighPC = PtrCU[NbCU].PtrUsedLinesSrc[PtrCU[NbCU].NbUsedLinesSrc - 1].StartPC;\r
+ }\r
+ }\r
+ }\r
+ }\r
\r
- case DW_TAG_typedef:\r
- PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x20;\r
- strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);\r
- if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
- {\r
- j = -1;\r
- }\r
- break;\r
+ // Init global variables information based on types information\r
+ for (size_t i = 0; i < PtrCU[NbCU].NbVariables; i++)\r
+ {\r
+ DWARFManager_InitInfosVariable(PtrCU[NbCU].PtrVariables + i);\r
+ }\r
\r
- case DW_TAG_subrange_type:\r
- PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x4;\r
- break;\r
+ // Init local variables information based on types information\r
+ for (size_t i = 0; i < PtrCU[NbCU].NbSubProgs; i++)\r
+ {\r
+ for (size_t j = 0; j < PtrCU[NbCU].PtrSubProgs[i].NbVariables; j++)\r
+ {\r
+ DWARFManager_InitInfosVariable(PtrCU[NbCU].PtrSubProgs[i].PtrVariables + j);\r
+ }\r
+ }\r
+ }\r
\r
- case DW_TAG_array_type:\r
- PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x8;\r
- if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
- {\r
- j = -1;\r
- }\r
- break;\r
+ ++NbCU;\r
+ }\r
+ } \r
+}\r
\r
- case DW_TAG_const_type:\r
- PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x10;\r
- strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, "const ");\r
- if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
- {\r
- j = -1;\r
- }\r
- break;\r
\r
- case DW_TAG_base_type:\r
- strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);\r
- if ((PtrCU[NbCU].PtrVariables[i].TypeTag & 0x2))\r
- {\r
- strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, " *");\r
- }\r
- else\r
- {\r
- PtrCU[NbCU].PtrVariables[i].TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;\r
- PtrCU[NbCU].PtrVariables[i].TypeEncoding = PtrCU[NbCU].PtrTypes[j].Encoding;\r
- }\r
- if ((PtrCU[NbCU].PtrVariables[i].TypeTag & 0x8))\r
- {\r
- strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, "[]");\r
- }\r
- break;\r
+// Conform slashes and backslashes\r
+void DWARFManager_ConformSlachesBackslashes(char *Ptr)\r
+{\r
+ while (*Ptr)\r
+ {\r
+#if defined(_WIN32)\r
+ if (*Ptr == '/')\r
+ {\r
+ *Ptr = '\\';\r
+ }\r
+#else\r
+ if (*Ptr == '\\')\r
+ {\r
+ *Ptr = '/';\r
+ }\r
+#endif\r
+ Ptr++;\r
+ }\r
+}\r
\r
- default:\r
- break;\r
- }\r
+\r
+// Variables information initialisation\r
+void DWARFManager_InitInfosVariable(VariablesStruct *PtrVariables)\r
+{\r
+ size_t j, TypeOffset;\r
+\r
+#ifdef DEBUG_VariableName\r
+ if (PtrVariables->PtrName && !strcmp(PtrVariables->PtrName, DEBUG_VariableName))\r
+#endif\r
+ {\r
+ PtrVariables->PtrTypeName = (char *)calloc(1000, 1);\r
+ TypeOffset = PtrVariables->TypeOffset;\r
+\r
+ for (j = 0; j < PtrCU[NbCU].NbTypes; j++)\r
+ {\r
+ if (TypeOffset == PtrCU[NbCU].PtrTypes[j].Offset)\r
+ {\r
+ switch (PtrCU[NbCU].PtrTypes[j].Tag)\r
+ {\r
+ case DW_TAG_subroutine_type:\r
+ PtrVariables->TypeTag |= TypeTag_subroutine_type;\r
+ strcat(PtrVariables->PtrTypeName, " (* ) ()");\r
+ break;\r
+\r
+ // Structure type tag\r
+ case DW_TAG_structure_type:\r
+ PtrVariables->TypeTag |= TypeTag_structure;\r
+ if (!(PtrVariables->TypeTag & TypeTag_typedef))\r
+ {\r
+ if (PtrCU[NbCU].PtrTypes[j].PtrName)\r
+ {\r
+ strcat(PtrVariables->PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);\r
}\r
}\r
+ if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
+ {\r
+ j = -1;\r
+ }\r
+ else\r
+ {\r
+ if ((PtrVariables->TypeTag & TypeTag_pointer))\r
+ {\r
+ strcat(PtrVariables->PtrTypeName, " *");\r
+ }\r
+ }\r
+ break;\r
+\r
+ // Pointer type tag\r
+ case DW_TAG_pointer_type:\r
+ PtrVariables->TypeTag |= TypeTag_pointer;\r
+ PtrVariables->TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;\r
+ PtrVariables->TypeEncoding = 0x10;\r
+ if (!(TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
+ {\r
+ strcat(PtrVariables->PtrTypeName, "void *");\r
+ }\r
+ else\r
+ {\r
+ j = -1;\r
+ }\r
+ break;\r
+\r
+ case DW_TAG_enumeration_type:\r
+ PtrVariables->TypeTag |= TypeTag_enumeration_type;\r
+ PtrVariables->TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;\r
+ if (!(PtrVariables->TypeEncoding = PtrCU[NbCU].PtrTypes[j].Encoding))\r
+ {\r
+ // Try to determine the possible size\r
+ switch (PtrVariables->TypeByteSize)\r
+ {\r
+ case 4:\r
+ PtrVariables->TypeEncoding = 0x7;\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+\r
+ // Typedef type tag\r
+ case DW_TAG_typedef:\r
+ if (!(PtrVariables->TypeTag & TypeTag_typedef))\r
+ {\r
+ PtrVariables->TypeTag |= TypeTag_typedef;\r
+ strcat(PtrVariables->PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);\r
+ }\r
+ if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
+ {\r
+ j = -1;\r
+ }\r
+ break;\r
+\r
+ // ? type tag\r
+ case DW_TAG_subrange_type:\r
+ PtrVariables->TypeTag |= TypeTag_subrange;\r
+ break;\r
+\r
+ // Array type tag\r
+ case DW_TAG_array_type:\r
+ PtrVariables->TypeTag |= TypeTag_arraytype;\r
+ if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
+ {\r
+ j = -1;\r
+ }\r
+ break;\r
+\r
+ // Const type tag\r
+ case DW_TAG_const_type:\r
+ PtrVariables->TypeTag |= TypeTag_consttype;\r
+ strcat(PtrVariables->PtrTypeName, "const ");\r
+ if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
+ {\r
+ j = -1;\r
+ }\r
+ break;\r
+\r
+ // Base type tag\r
+ case DW_TAG_base_type:\r
+ if (!(PtrVariables->TypeTag & TypeTag_typedef))\r
+ {\r
+ strcat(PtrVariables->PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);\r
+ }\r
+ if ((PtrVariables->TypeTag & TypeTag_pointer))\r
+ {\r
+ strcat(PtrVariables->PtrTypeName, " *");\r
+ }\r
+ else\r
+ {\r
+ PtrVariables->TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;\r
+ PtrVariables->TypeEncoding = PtrCU[NbCU].PtrTypes[j].Encoding;\r
+ }\r
+ if ((PtrVariables->TypeTag & TypeTag_arraytype))\r
+ {\r
+ strcat(PtrVariables->PtrTypeName, "[]");\r
+ }\r
+ break;\r
+\r
+ default:\r
+ break;\r
}\r
}\r
-\r
- ++NbCU;\r
}\r
- } \r
-\r
- free(SourceFilename);\r
- free(SourceFileDirectory);\r
- free(SourceFullFilename);\r
+ }\r
}\r
\r
\r
// Return NULL if no symbol name exists\r
char *DWARFManager_GetSymbolnameFromAdr(size_t Adr)\r
{\r
- size_t i, j;\r
-\r
- for (i = 0; i < NbCU; i++)\r
+ for (size_t i = 0; i < NbCU; i++)\r
{\r
if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
{\r
- for (j = 0; (j < PtrCU[i].NbSubProgs); j++)\r
+ for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
{\r
if ((PtrCU[i].PtrSubProgs[j].StartPC == Adr))\r
{\r
\r
// Get complete source filename based from address\r
// Return NULL if no source filename exists\r
-// Return the existence status (true or false) in Error\r
-char *DWARFManager_GetFullSourceFilenameFromAdr(size_t Adr, bool *Error)\r
+// Return the existence status in Status if pointer not NULL\r
+char *DWARFManager_GetFullSourceFilenameFromAdr(size_t Adr, DWARFstatus *Status)\r
{\r
- size_t i;\r
-\r
- for (i = 0; i < NbCU; i++)\r
+ for (size_t i = 0; i < NbCU; i++)\r
{\r
if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
{\r
- *Error = PtrCU[i].PtrLoadSrc ? true : false;\r
+ if (Status)\r
+ {\r
+ *Status = PtrCU[i].Status;\r
+ }\r
+\r
return PtrCU[i].PtrFullFilename;\r
}\r
}\r
}\r
\r
\r
-// Get text line source based on line number (starting by 1)\r
+// Get text line source based on line number (starting from 1)\r
// Return NULL if no text line exists or if line number is 0\r
char *DWARFManager_GetLineSrcFromNumLine(char *PtrSrcFile, size_t NumLine)\r
{\r
}\r
\r
\r
-// Get Compilation Unit / External variables numbers\r
-// Return variables number\r
-size_t DWARFManager_GetNbExternalVariables(void)\r
+// Get number of variables referenced by the function range address\r
+size_t DWARFManager_GetNbLocalVariables(size_t Adr)\r
{\r
- size_t NbVariables = 0, i;\r
+ for (size_t i = 0; i < NbCU; i++)\r
+ {\r
+ if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
+ {\r
+ for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
+ {\r
+ if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
+ {\r
+ return PtrCU[i].PtrSubProgs[j].NbVariables;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ return 0;\r
+}\r
\r
- for (i = 0; i < NbCU; i++)\r
+\r
+// Get local variable name based on his index (starting from 1)\r
+// Return name's pointer text found\r
+// Return NULL if not found\r
+char *DWARFManager_GetLocalVariableName(size_t Adr, size_t Index)\r
+{\r
+ for (size_t i = 0; i < NbCU; i++)\r
+ {\r
+ if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
+ {\r
+ for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
+ {\r
+ if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
+ {\r
+ return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].PtrName;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+\r
+// Get local variable's type tag based on his index (starting from 1)\r
+// Return 0 if not found\r
+size_t DWARFManager_GetLocalVariableTypeTag(size_t Adr, size_t Index)\r
+{\r
+ for (size_t i = 0; i < NbCU; i++)\r
+ {\r
+ if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
+ {\r
+ for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
+ {\r
+ if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
+ {\r
+ return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].TypeTag;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+// Get the local variable's offset based on a index (starting from 1)\r
+// Return 0 if no offset has been found\r
+int DWARFManager_GetLocalVariableOffset(size_t Adr, size_t Index)\r
+{\r
+ for (size_t i = 0; i < NbCU; i++)\r
+ {\r
+ if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
+ {\r
+ for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
+ {\r
+ if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
+ {\r
+ return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].Offset;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+// Get local variable Type Byte Size based on his address and index (starting from 1)\r
+// Return 0 if not found\r
+// May return 0 if there is no Type Byte Size linked to the variable's address and index\r
+size_t DWARFManager_GetLocalVariableTypeByteSize(size_t Adr, size_t Index)\r
+{\r
+ for (size_t i = 0; i < NbCU; i++)\r
+ {\r
+ if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
+ {\r
+ for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
+ {\r
+ if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
+ {\r
+ return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].TypeByteSize;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+// Get local variable Type Encoding based on his address and index (starting from 1)\r
+// Return 0 if not found\r
+// May return 0 if there is no Type Encoding linked to the variable's address and index\r
+size_t DWARFManager_GetLocalVariableTypeEncoding(size_t Adr, size_t Index)\r
+{\r
+ for (size_t i = 0; i < NbCU; i++)\r
+ {\r
+ if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
+ {\r
+ for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
+ {\r
+ if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
+ {\r
+ return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].TypeEncoding;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+// Get local variable Op based on his address and index (starting from 1)\r
+// Return 0 if not found, may return 0 if there isn't Op linked to the variable's index\r
+size_t DWARFManager_GetLocalVariableOp(size_t Adr, size_t Index)\r
+{\r
+ for (size_t i = 0; i < NbCU; i++)\r
+ {\r
+ if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
+ {\r
+ for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
+ {\r
+ if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
+ {\r
+ return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].Op;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+// Get local variable type name based on his index (starting from 1) and an address\r
+// Return NULL if not found, may also return NULL if there is no type linked to the variable's index\r
+char *DWARFManager_GetLocalVariableTypeName(size_t Adr, size_t Index)\r
+{\r
+ for (size_t i = 0; i < NbCU; i++)\r
+ {\r
+ if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
+ {\r
+ for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
+ {\r
+ if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
+ {\r
+ return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].PtrTypeName;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+\r
+// Get Compilation Unit / global variables numbers\r
+// Return number of variables\r
+size_t DWARFManager_GetNbGlobalVariables(void)\r
+{\r
+ size_t NbVariables = 0;\r
+\r
+ for (size_t i = 0; i < NbCU; i++)\r
{\r
NbVariables += PtrCU[i].NbVariables;\r
}\r
}\r
\r
\r
-// Get external variable type name based on his index (starting by 1)\r
+// Get global variable type name based on his index (starting from 1)\r
// Return NULL if not found\r
// May return NULL if there is not type linked to the variable's index\r
-char *DWARFManager_GetExternalVariableTypeName(size_t Index)\r
+char *DWARFManager_GetGlobalVariableTypeName(size_t Index)\r
{\r
- size_t i;\r
-\r
- for (i = 0; i < NbCU; i++)\r
+ for (size_t i = 0; i < NbCU; i++)\r
{\r
if (PtrCU[i].NbVariables)\r
{\r
}\r
\r
\r
-// Get external variable's type tag based on his index (starting by 1)\r
+// Get global variable's type tag based on his index (starting from 1)\r
// Return 0 if not found\r
-size_t DWARFManager_GetExternalVariableTypeTag(size_t Index)\r
+size_t DWARFManager_GetGlobalVariableTypeTag(size_t Index)\r
{\r
- size_t i;\r
-\r
- for (i = 0; i < NbCU; i++)\r
+ for (size_t i = 0; i < NbCU; i++)\r
{\r
if (PtrCU[i].NbVariables)\r
{\r
}\r
\r
\r
-// Get external variable byte size based on his index (starting by 1)\r
+// Get global variable byte size based on his index (starting from 1)\r
// Return 0 if not found\r
-size_t DWARFManager_GetExternalVariableTypeByteSize(size_t Index)\r
+size_t DWARFManager_GetGlobalVariableTypeByteSize(size_t Index)\r
{\r
- size_t i;\r
-\r
- for (i = 0; i < NbCU; i++)\r
+ for (size_t i = 0; i < NbCU; i++)\r
{\r
if (PtrCU[i].NbVariables)\r
{\r
}\r
\r
\r
-// Get external variable encoding based on his index (starting by 1)\r
+// Get global variable encoding based on his index (starting from 1)\r
// Return 0 if not found\r
-size_t DWARFManager_GetExternalVariableTypeEncoding(size_t Index)\r
+size_t DWARFManager_GetGlobalVariableTypeEncoding(size_t Index)\r
{\r
- size_t i;\r
-\r
- for (i = 0; i < NbCU; i++)\r
+ for (size_t i = 0; i < NbCU; i++)\r
{\r
if (PtrCU[i].NbVariables)\r
{\r
}\r
\r
\r
-// Get external variable address based on his index (starting by 1)\r
+// Get global variable memory address based on his index (starting from 1)\r
// Return 0 if not found\r
-size_t DWARFManager_GetExternalVariableAdr(size_t Index)\r
+size_t DWARFManager_GetGlobalVariableAdr(size_t Index)\r
{\r
- size_t i;\r
-\r
- for (i = 0; i < NbCU; i++)\r
+ for (size_t i = 0; i < NbCU; i++)\r
{\r
if (PtrCU[i].NbVariables)\r
{\r
}\r
\r
\r
-// Get external variable memory address based on his name\r
-// Return 0 if not found\r
-// Note: Return the first occurence found\r
-size_t DWARFManager_GetExternalVariableAdrFromName(char *VariableName)\r
+// Get global variable memory address based on his name\r
+// Return 0 if not found, or will return the first occurence found\r
+size_t DWARFManager_GetGlobalVariableAdrFromName(char *VariableName)\r
{\r
- size_t i, j;\r
-\r
- for (i = 0; i < NbCU; i++)\r
+ for (size_t i = 0; i < NbCU; i++)\r
{\r
if (PtrCU[i].NbVariables)\r
{\r
- for (j = 0; j < PtrCU[i].NbVariables; j++)\r
+ for (size_t j = 0; j < PtrCU[i].NbVariables; j++)\r
{\r
if (!strcmp(PtrCU[i].PtrVariables[j].PtrName,VariableName))\r
{\r
}\r
\r
\r
-// Get external variable name based on his index (starting by 1)\r
-// Return name's pointer text found\r
-// Return NULL if not found\r
-char *DWARFManager_GetExternalVariableName(size_t Index)\r
+// Get global variable name based on his index (starting from 1)\r
+// Return name's pointer text found, or will return NULL if no variable can be found\r
+char *DWARFManager_GetGlobalVariableName(size_t Index)\r
{\r
- size_t i;\r
-\r
- for (i = 0; i < NbCU; i++)\r
+ for (size_t i = 0; i < NbCU; i++)\r
{\r
if (PtrCU[i].NbVariables)\r
{\r
\r
\r
// Get text line from source based on address and his tag\r
+// A tag can be either 0 or a DW_TAG_subprogram\r
+// DW_TAG_subprogram will look for the line pointing to the function\r
// Return NULL if no text line has been found\r
char *DWARFManager_GetLineSrcFromAdr(size_t Adr, size_t Tag)\r
{\r
- size_t i, j, k;\r
-\r
- for (i = 0; i < NbCU; i++)\r
+ for (size_t i = 0; i < NbCU; i++)\r
{\r
if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
{\r
- for (j = 0; j < PtrCU[i].NbSubProgs; j++)\r
+ for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
{\r
if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
{\r
}\r
else\r
{\r
- for (k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++)\r
+ for (size_t k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++)\r
{\r
- if ((PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC == Adr) && (!Tag || (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].Tag == Tag)))\r
+ if (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC <= Adr)\r
{\r
- return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc;\r
+ if ((PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC == Adr) && (!Tag || (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].Tag == Tag)))\r
+ {\r
+ return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k - 1].PtrLineSrc;\r
}\r
}\r
}\r
}\r
\r
\r
-// Get line number based on the address and the tag\r
+// Get line number based on the address and a tag\r
+// A tag can be either 0 or a DW_TAG_subprogram\r
+// DW_TAG_subprogram will look for the line pointing to the function name as described in the source code\r
// Return 0 if no line number has been found\r
size_t DWARFManager_GetNumLineFromAdr(size_t Adr, size_t Tag)\r
{\r
- size_t i, j, k;\r
-\r
- for (i = 0; i < NbCU; i++)\r
+ for (size_t i = 0; i < NbCU; i++)\r
{\r
if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
{\r
- for (j = 0; (j < PtrCU[i].NbSubProgs); j++)\r
+ for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
{\r
if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
{\r
}\r
else\r
{\r
- for (k = 0; (k < PtrCU[i].PtrSubProgs[j].NbLinesSrc); k++)\r
+ for (size_t k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++)\r
{\r
- if ((PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC == Adr) && (!Tag || (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].Tag == Tag)))\r
+ if (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC <= Adr)\r
{\r
- return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc;\r
+ if ((PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC == Adr) && (!Tag || (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].Tag == Tag)))\r
+ {\r
+ return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k - 1].NumLineSrc;\r
}\r
}\r
}\r
#endif\r
}\r
}\r
+\r
+ // Check if a used line is found with the address\r
+ for (size_t j = 0; j < PtrCU[i].NbUsedLinesSrc; j++)\r
+ {\r
+ if (PtrCU[i].PtrUsedLinesSrc[j].StartPC == Adr)\r
+ {\r
+ return PtrCU[i].PtrUsedLinesSrc[j].NumLineSrc;\r
+ }\r
+ }\r
}\r
}\r
\r
}\r
\r
\r
-// Get text line from source based on address and num line (starting by 1)\r
+// Get function name based on an address\r
+// Return NULL if no function name has been found, otherwise will return the function name in the range of the provided address\r
+char *DWARFManager_GetFunctionName(size_t Adr)\r
+{\r
+ for (size_t i = 0; i < NbCU; i++)\r
+ {\r
+ if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
+ {\r
+ for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
+ {\r
+ if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
+ {\r
+ return PtrCU[i].PtrSubProgs[j].PtrSubprogramName;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+\r
+// Get number of lines of texts source list from source index\r
+size_t DWARFManager_GetSrcNbListPtrFromIndex(size_t Index, bool Used)\r
+{\r
+ if (!Used)\r
+ {\r
+ return PtrCU[Index].NbLinesLoadSrc;\r
+ }\r
+ else\r
+ {\r
+ return PtrCU[Index].NbUsedLinesSrc;\r
+ }\r
+}\r
+\r
+\r
+// Get text source line number list pointer from source index\r
+// Return NULL for the text source used list \r
+size_t *DWARFManager_GetSrcNumLinesPtrFromIndex(size_t Index, bool Used)\r
+{\r
+ if (Used)\r
+ {\r
+ return PtrCU[Index].PtrUsedNumLines;\r
+ }\r
+ else\r
+ {\r
+ return NULL;\r
+ }\r
+}\r
+\r
+\r
+// Get text source list pointers from source index\r
+// Return NULL for the text source used list \r
+char **DWARFManager_GetSrcListPtrFromIndex(size_t Index, bool Used)\r
+{\r
+ if (!Used)\r
+ {\r
+ return PtrCU[Index].PtrLinesLoadSrc;\r
+ }\r
+ else\r
+ {\r
+ return PtrCU[Index].PtrUsedLinesLoadSrc;\r
+ }\r
+}\r
+\r
+\r
+// Get source language\r
+size_t DWARFManager_GetSrcLanguageFromIndex(size_t Index)\r
+{\r
+ return PtrCU[Index].Language;\r
+}\r
+\r
+\r
+// Get text line from source based on address and num line (starting from 1)\r
// Return NULL if no text line has been found\r
char *DWARFManager_GetLineSrcFromAdrNumLine(size_t Adr, size_t NumLine)\r
{\r
- size_t i, j, k;\r
-\r
- for (i = 0; i < NbCU; i++)\r
+ for (size_t i = 0; i < NbCU; i++)\r
{\r
if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
{\r
- for (j = 0; j < PtrCU[i].NbSubProgs; j++)\r
+ for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
{\r
if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
{\r
}\r
else\r
{\r
- for (k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++)\r
+ for (size_t k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++)\r
{\r
if (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc == NumLine)\r
{\r
}\r
\r
\r
-// Get text line from source based on address and num line (starting by 1)\r
-// Return NULL if no text line has been found\r
+// Get text line pointer from source, based on address and line number (starting from 1)\r
+// Return NULL if no text line has been found, or if requested number line is above the source total number of lines\r
char *DWARFManager_GetLineSrcFromNumLineBaseAdr(size_t Adr, size_t NumLine)\r
{\r
- size_t i;\r
-\r
- for (i = 0; i < NbCU; i++)\r
+ for (size_t i = 0; i < NbCU; i++)\r
{\r
if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
{\r
return NULL;\r
}\r
\r
+\r
+// Get number of source code filenames\r
+size_t DWARFManager_GetNbSources(void)\r
+{\r
+ return NbCU;\r
+}\r
+\r
+\r
+// Get source code filename, including his directory, based on index (starting from 0)\r
+char *DWARFManager_GetNumFullSourceFilename(size_t Index)\r
+{\r
+ return (PtrCU[Index].PtrFullFilename);\r
+}\r
+\r
+\r
+// Get source code filename based on index (starting from 0)\r
+char *DWARFManager_GetNumSourceFilename(size_t Index)\r
+{\r
+ return (PtrCU[Index].PtrSourceFilename);\r
+}\r
+\r