// 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 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\r
+// RG Jan./2021 Linux build fixes\r
+// JPM Apr./2021 Support the structure and union members\r
//\r
\r
// To Do\r
-// To use pointers instead of arrays usage\r
+// To use pointers instead of arrays usage (originally done to check if values are set at the right places)\r
// \r
\r
\r
#include <stdio.h>\r
#include <stdint.h>\r
#include <string.h>\r
-#include <libdwarf.h>\r
-#include <dwarf.h>\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
-\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_NumCU 0x2 // CU number to debug or undefine it\r
+//#define DEBUG_VariableName "cvar_vars" // Variable name to look for or undefine it\r
+//#define DEBUG_TypeName "edict_t" // Type name to look for or undefine it\r
+//#define DEBUG_TypeDef DW_TAG_typedef // Type def to look for or undefine it (not used / not supported)\r
//#define DEBUG_Filename "crt0" // Filename to look for or undefine it\r
\r
// Definitions for handling data\r
#define TypeTag_typedef 0x20 // typedef\r
#define TypeTag_enumeration_type 0x40 // enumeration\r
#define TypeTag_subroutine_type 0x80 // subroutine\r
+#define TypeTag_union 0x100 // union\r
\r
\r
// Source line CU structure\r
// Enumeration structure\r
typedef struct EnumerationStruct\r
{\r
- char *PtrName; // Enumeration's name\r
- size_t value; // Enumeration's value\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
+typedef struct StructureMembersStruct\r
+{\r
+ char *PtrName; // Structure member's name\r
+ size_t TypeOffset; // Structure member's offset on another type\r
+ size_t DataMemberLocation; // Structure member's data member\r
+}S_StructureMembersStruct;\r
\r
// Base type internal structure\r
typedef struct BaseTypeStruct\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
+ size_t NbEnumerations; // Type's enumeration numbers\r
+ EnumerationStruct *PtrEnumerations; // Type's enumeration\r
+ size_t NbStructureMembers; // Type's numbers of structure members\r
+ StructureMembersStruct *PtrStructureMembers; // Type's structure members\r
}S_BaseTypeStruct;\r
\r
// Variables internal structure\r
typedef struct VariablesStruct\r
{\r
- size_t Op; // Variable's DW_OP\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
+ 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
- size_t TypeTag; // Variable's Type Tag\r
- size_t TypeEncoding; // Variable's Type encoding\r
- char *PtrTypeName; // Variable's Type name\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
+ size_t TypeTag; // Variable's Type Tag\r
+ size_t TypeEncoding; // Variable's Type encoding\r
+ char *PtrTypeName; // Variable's Type name\r
+ size_t NbTabVariables; // Number of Variable's members\r
+ VariablesStruct **TabVariables; // Variable's Members (used for structures at the moment)\r
}S_VariablesStruct;\r
\r
// Sub program internal structure\r
size_t Tag;\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; // Pointer to the "Producer" text information (mostly compiler and compilation options used)\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
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
CUStruct *PtrCU;\r
char **ListSearchPaths;\r
size_t NbSearchPaths;\r
+struct stat FileElfExeInfo;\r
\r
\r
-//\r
+// Function declarations\r
Dwarf_Handler DWARFManager_ErrorHandler(Dwarf_Ptr perrarg);\r
void DWARFManager_InitDMI(void);\r
void DWARFManager_CloseDMI(void);\r
void DWARFManager_SourceFileSearchPathsReset(void);\r
void DWARFManager_SourceFileSearchPathsClose(void);\r
void DWARFManager_ConformSlachesBackslashes(char *Ptr);\r
+#if 0\r
+size_t DWARFManager_GetNbGlobalVariables(void);\r
+size_t DWARFManager_GetNbLocalVariables(size_t Adr);\r
+#endif\r
\r
\r
//\r
-Dwarf_Handler DWARFManager_ErrorHandler(Dwarf_Ptr perrarg)\r
+Dwarf_Handler DWARFManager_ErrorHandler(Dwarf_Ptr /* perrarg */)\r
{\r
return 0;\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
// Dwarf manager Compilation Units close\r
void DWARFManager_CloseDMI(void)\r
{\r
+ // loop on all CU\r
while (NbCU--)\r
{\r
+ // free pointers\r
free(PtrCU[NbCU].PtrFullFilename);\r
free(PtrCU[NbCU].PtrLoadSrc);\r
free(PtrCU[NbCU].PtrProducer);\r
free(PtrCU[NbCU].PtrUsedLinesLoadSrc);\r
free(PtrCU[NbCU].PtrUsedNumLines);\r
\r
+ // free lines from the source code\r
while (PtrCU[NbCU].NbLinesLoadSrc--)\r
{\r
free(PtrCU[NbCU].PtrLinesLoadSrc[PtrCU[NbCU].NbLinesLoadSrc]);\r
}\r
free(PtrCU[NbCU].PtrLinesLoadSrc);\r
\r
+ // free the functions information\r
while (PtrCU[NbCU].NbSubProgs--)\r
{\r
while (PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables--)\r
}\r
free(PtrCU[NbCU].PtrSubProgs);\r
\r
+ // free the types\r
while (PtrCU[NbCU].NbTypes--)\r
{\r
free(PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName);\r
+\r
+ // free the structure's members\r
+ while (PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].NbStructureMembers--)\r
+ {\r
+ free(PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrStructureMembers[PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].NbStructureMembers].PtrName);\r
+ }\r
+ free(PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrStructureMembers);\r
}\r
free(PtrCU[NbCU].PtrTypes);\r
\r
+ // free variables\r
while (PtrCU[NbCU].NbVariables--)\r
{\r
free(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName);\r
free(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrTypeName);\r
+\r
+ // free the variable's members\r
+ while (PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].NbTabVariables--)\r
+ {\r
+ free(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].TabVariables[PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].NbTabVariables]);\r
+ }\r
}\r
free(PtrCU[NbCU].PtrVariables);\r
}\r
\r
+ // free the CU\r
free(PtrCU);\r
}\r
\r
Dwarf_Attribute *atlist;\r
Dwarf_Attribute return_attr1;\r
Dwarf_Half return_tagval, return_attr;\r
+ Dwarf_Half version, offset_size;\r
Dwarf_Addr return_lowpc, return_highpc, return_lineaddr;\r
Dwarf_Block *return_block;\r
- Dwarf_Signed atcnt, cnt;\r
+ Dwarf_Signed atcnt, cnt, return_value;\r
Dwarf_Die return_sib, return_die, return_sub, return_subdie;\r
Dwarf_Off return_offset;\r
Dwarf_Line *linebuf;\r
+ Dwarf_Half form;\r
FILE *SrcFile;\r
char *return_string;\r
char *Ptr, *Ptr1;\r
PtrCU = NULL;\r
\r
// loop on the available Compilation Unit\r
- while (dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, &next_cu_header, &error) == DW_DLV_OK)\r
+ while (dwarf_next_cu_header_b(dbg, NULL, &version, NULL, NULL, &offset_size, NULL, &next_cu_header, &error) == DW_DLV_OK)\r
{\r
// Allocation of an additional Compilation Unit structure in the table\r
if (Ptr = (char *)realloc(PtrCU, ((NbCU + 1) * sizeof(CUStruct))))\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
- if (!fopen_s(&SrcFile, PtrCU[NbCU].PtrFullFilename, "rb"))\r
{\r
PtrCU[NbCU].PtrSourceFileDirectory = (char *)realloc(PtrCU[NbCU].PtrSourceFileDirectory, strlen(ListSearchPaths[i]) + 1);\r
strcpy(PtrCU[NbCU].PtrSourceFileDirectory, ListSearchPaths[i]);\r
strcpy((Ptr1 + 1), (Ptr + 4));\r
}\r
\r
- // Open the source file as a binary file\r
- if (!fopen_s(&SrcFile, PtrCU[NbCU].PtrFullFilename, "rb"))\r
+ // Get the source file information\r
+ if (!stat(PtrCU[NbCU].PtrFullFilename, &PtrCU[NbCU]._statbuf))\r
{\r
- if (!fseek(SrcFile, 0, SEEK_END))\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 (!fseek(SrcFile, 0, SEEK_SET))\r
+ if (!fseek(SrcFile, 0, SEEK_END))\r
{\r
- if (PtrCU[NbCU].PtrLoadSrc = Ptr = Ptr1 = (char *)calloc(1, (PtrCU[NbCU].SizeLoadSrc + 2)))\r
+ if ((PtrCU[NbCU].SizeLoadSrc = ftell(SrcFile)) > 0)\r
{\r
- // Read whole file\r
- if (fread_s(PtrCU[NbCU].PtrLoadSrc, PtrCU[NbCU].SizeLoadSrc, PtrCU[NbCU].SizeLoadSrc, 1, SrcFile) != 1)\r
- {\r
- free(PtrCU[NbCU].PtrLoadSrc);\r
- PtrCU[NbCU].PtrLoadSrc = NULL;\r
- PtrCU[NbCU].SizeLoadSrc = 0;\r
- }\r
- else\r
+ if (!fseek(SrcFile, 0, SEEK_SET))\r
{\r
- // Eliminate all carriage return code '\r' (oxd)\r
- do\r
+ if (PtrCU[NbCU].PtrLoadSrc = Ptr = Ptr1 = (char *)calloc(1, (PtrCU[NbCU].SizeLoadSrc + 2)))\r
{\r
- if ((*Ptr = *Ptr1) != '\r')\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
- Ptr++;\r
+ free(PtrCU[NbCU].PtrLoadSrc);\r
+ PtrCU[NbCU].PtrLoadSrc = NULL;\r
+ PtrCU[NbCU].SizeLoadSrc = 0;\r
}\r
- }\r
- while (*Ptr1++);\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
+ // 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
+ // 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
+ // Reallocate text file\r
+ if (PtrCU[NbCU].PtrLoadSrc = Ptr = (char *)realloc(PtrCU[NbCU].PtrLoadSrc, (PtrCU[NbCU].SizeLoadSrc + 1)))\r
{\r
- PtrCU[NbCU].NbLinesLoadSrc++;\r
- *Ptr = 0;\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
- } while (*++Ptr);\r
+ }\r
}\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
// Get the source lines table located in the CU\r
- if (dwarf_srclines(return_sib, &linebuf, &cnt, &error) == DW_DLV_OK)\r
+ if ((dwarf_srclines(return_sib, &linebuf, &cnt, &error) == DW_DLV_OK) && (PtrCU[NbCU].Status == DWARFSTATUS_OK))\r
{\r
if (cnt)\r
{\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
- // Get the last used line number in the source file\r
- if (PtrCU[NbCU].LastNumUsedLinesSrc < PtrCU[NbCU].PtrUsedLinesSrc[i].NumLineSrc)\r
- {\r
- PtrCU[NbCU].LastNumUsedLinesSrc = PtrCU[NbCU].PtrUsedLinesSrc[i].NumLineSrc;\r
- }\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
\r
case DW_TAG_base_type:\r
case DW_TAG_typedef:\r
+ case DW_TAG_union_type:\r
case DW_TAG_structure_type:\r
case DW_TAG_pointer_type:\r
case DW_TAG_const_type:\r
dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);\r
}\r
\r
- PtrCU[NbCU].NbTypes++;\r
-\r
dwarf_dealloc(dbg, atlist, DW_DLA_LIST);\r
+\r
+ switch (return_tagval)\r
+ {\r
+ case DW_TAG_structure_type:\r
+ case DW_TAG_union_type:\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
+ switch (return_tagval)\r
+ {\r
+ case DW_TAG_member:\r
+ if (dwarf_attrlist(return_subdie, &atlist, &atcnt, &error) == DW_DLV_OK)\r
+ {\r
+ // Allocate memory for this member\r
+ 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)));\r
+ memset(PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrStructureMembers + PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].NbStructureMembers, 0, sizeof(StructureMembersStruct));\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_data_member_location:\r
+ if (dwarf_whatform(return_attr1, &form, &error) == DW_DLV_OK)\r
+ {\r
+ 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))\r
+ {\r
+ if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK)\r
+ {\r
+ PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrStructureMembers[PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].NbStructureMembers].DataMemberLocation = return_uvalue;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if (form == DW_FORM_sdata)\r
+ {\r
+ if (dwarf_formsdata(return_attr1, &return_value, &error) == DW_DLV_OK)\r
+ {\r
+ PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrStructureMembers[PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].NbStructureMembers].DataMemberLocation = return_value;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if (dwarf_formblock(return_attr1, &return_block, &error) == DW_DLV_OK)\r
+ {\r
+ switch (return_block->bl_len)\r
+ {\r
+ case 2:\r
+ case 3:\r
+ case 4:\r
+ PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrStructureMembers[PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].NbStructureMembers].DataMemberLocation = ReadULEB128((char *)return_block->bl_data + 1);\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ dwarf_dealloc(dbg, return_block, DW_DLA_BLOCK);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ break;\r
+\r
+ case DW_AT_type:\r
+ //dwarf_whatform(return_attr1, &form, &error);\r
+ if (dwarf_global_formref(return_attr1, &return_uvalue, &error) == DW_DLV_OK)\r
+ {\r
+ PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrStructureMembers[PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].NbStructureMembers].TypeOffset = return_uvalue;\r
+ }\r
+ break;\r
+\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].PtrStructureMembers[PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].NbStructureMembers].PtrName = (char *)calloc(strlen(return_string) + 1, 1);\r
+ strcpy(PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrStructureMembers[PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].NbStructureMembers].PtrName, return_string);\r
+\r
+ dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
+ }\r
+ break;\r
+\r
+ // Member's file number\r
+ case DW_AT_decl_file:\r
+ break;\r
+\r
+ // Member's line number\r
+ case DW_AT_decl_line:\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ dwarf_dealloc(dbg, atlist, DW_DLA_LIST);\r
+\r
+ PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].NbStructureMembers++;\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ } while (dwarf_siblingof(dbg, return_sub, &return_subdie, &error) == DW_DLV_OK);\r
+ }\r
+ break;\r
+ }\r
+\r
+ PtrCU[NbCU].NbTypes++;\r
}\r
break;\r
\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
- {\r
- if ((return_lineaddr >= return_lowpc) && (return_lineaddr <= return_highpc))\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
- }\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 = 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
}\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 (Dwarf_Signed i = 0; i < cnt; ++i)\r
- {\r
- dwarf_dealloc(dbg, linebuf[i], DW_DLA_LINE);\r
- }\r
- dwarf_dealloc(dbg, linebuf, DW_DLA_LIST);\r
}\r
\r
// Set the source code lines\r
{\r
if (Ptr = DWARFManager_GetLineSrcFromNumLine(PtrCU[NbCU].PtrLoadSrc, (j + 1)))\r
{\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
switch (*Ptr)\r
{\r
-#ifdef CONVERT_QT_HML\r
case 9:\r
strcat(PtrCU[NbCU].PtrLinesLoadSrc[j], " ");\r
i += 6;\r
strcpy(PtrCU[NbCU].PtrLinesLoadSrc[j], """);\r
i += strlen(""");\r
break;\r
-#endif\r
#endif\r
default:\r
PtrCU[NbCU].PtrLinesLoadSrc[j][i++] = *Ptr;\r
}\r
Ptr++;\r
}\r
+#endif\r
}\r
PtrCU[NbCU].PtrLinesLoadSrc[j] = (char *)realloc(PtrCU[NbCU].PtrLinesLoadSrc[j], strlen(PtrCU[NbCU].PtrLinesLoadSrc[j]) + 1);\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
+ size_t TypeOffset = PtrVariables->TypeOffset;\r
\r
- for (j = 0; j < PtrCU[NbCU].NbTypes; j++)\r
+ for (size_t 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
+ // subroutine / function pointer\r
case DW_TAG_subroutine_type:\r
PtrVariables->TypeTag |= TypeTag_subroutine_type;\r
strcat(PtrVariables->PtrTypeName, " (* ) ()");\r
break;\r
\r
- // Structure type tag\r
+ // structure & union type tag\r
case DW_TAG_structure_type:\r
- PtrVariables->TypeTag |= TypeTag_structure;\r
+ case DW_TAG_union_type:\r
+ PtrVariables->TypeTag |= (PtrCU[NbCU].PtrTypes[j].Tag == DW_TAG_structure_type) ? TypeTag_structure : TypeTag_union;\r
if (!(PtrVariables->TypeTag & TypeTag_typedef))\r
{\r
if (PtrCU[NbCU].PtrTypes[j].PtrName)\r
{\r
if ((PtrVariables->TypeTag & TypeTag_pointer))\r
{\r
- strcat(PtrVariables->PtrTypeName, " *");\r
+ strcat(PtrVariables->PtrTypeName, "* ");\r
+ }\r
+\r
+ if (PtrVariables->Op)\r
+ {\r
+ // fill the structure members\r
+ PtrVariables->TabVariables = (VariablesStruct**)calloc(PtrCU[NbCU].PtrTypes[j].NbStructureMembers, sizeof(VariablesStruct*));\r
+ for (size_t i = 0; i < PtrCU[NbCU].PtrTypes[j].NbStructureMembers; i++)\r
+ {\r
+ //if (PtrVariables->PtrName != PtrCU[NbCU].PtrTypes[j].PtrStructureMembers[i].PtrName)\r
+ {\r
+ PtrVariables->TabVariables[PtrVariables->NbTabVariables] = (VariablesStruct*)calloc(1, sizeof(VariablesStruct));\r
+ PtrVariables->TabVariables[PtrVariables->NbTabVariables]->PtrName = PtrCU[NbCU].PtrTypes[j].PtrStructureMembers[i].PtrName;\r
+ PtrVariables->TabVariables[PtrVariables->NbTabVariables]->TypeOffset = PtrCU[NbCU].PtrTypes[j].PtrStructureMembers[i].TypeOffset;\r
+ PtrVariables->TabVariables[PtrVariables->NbTabVariables]->Offset = (int)PtrCU[NbCU].PtrTypes[j].PtrStructureMembers[i].DataMemberLocation;\r
+ DWARFManager_InitInfosVariable(PtrVariables->TabVariables[PtrVariables->NbTabVariables++]);\r
+ }\r
+ }\r
}\r
}\r
break;\r
\r
- // Pointer type tag\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
+ strcat(PtrVariables->PtrTypeName, "void* ");\r
}\r
else\r
{\r
}\r
if ((PtrVariables->TypeTag & TypeTag_pointer))\r
{\r
- strcat(PtrVariables->PtrTypeName, " *");\r
+ strcat(PtrVariables->PtrTypeName, "* ");\r
}\r
else\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
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 number of variables\r
+// A NULL address will return the numbre of global variables, otherwise it will return the number of local variables\r
+size_t DWARFManager_GetNbVariables(size_t Adr)\r
+{\r
+ // check the address\r
+ if (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].NbVariables;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ else\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
+ return NbVariables;\r
+ }\r
+\r
+ return 0;\r
+#if 0\r
+ return Adr ? DWARFManager_GetNbLocalVariables(Adr) : DWARFManager_GetNbGlobalVariables();\r
+#endif\r
+}\r
+\r
+\r
+// Get variable's information\r
+// A NULL address will return the pointer to the global variable structure, otherwise it will return the local's one\r
+void* DWARFManager_GetInfosVariable(size_t Adr, size_t Index)\r
+{\r
+ // check the address\r
+ if (Adr)\r
+ {\r
+ // get the pointer's information from a local variable\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];\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // get the pointer's information from a global variable\r
+ for (size_t i = 0; i < NbCU; i++)\r
+ {\r
+ if (PtrCU[i].NbVariables)\r
+ {\r
+ if (Index <= PtrCU[i].NbVariables)\r
+ {\r
+ return &PtrCU[i].PtrVariables[Index - 1];\r
+ }\r
+ else\r
+ {\r
+ Index -= PtrCU[i].NbVariables;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+\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
+ for (size_t i = 0; i < NbCU; i++)\r
+ {\r
+ if (PtrCU[i].NbVariables)\r
+ {\r
+ for (size_t j = 0; j < PtrCU[i].NbVariables; j++)\r
+ {\r
+ if (!strcmp(PtrCU[i].PtrVariables[j].PtrName, VariableName))\r
+ {\r
+ return PtrCU[i].PtrVariables[j].Addr;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+#if 0\r
// Get number of variables referenced by the function range address\r
size_t DWARFManager_GetNbLocalVariables(size_t Adr)\r
{\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
+ return NbVariables;\r
+}\r
+\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
}\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
- return NbVariables;\r
-}\r
-\r
-\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
}\r
\r
\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
- for (size_t i = 0; i < NbCU; i++)\r
- {\r
- if (PtrCU[i].NbVariables)\r
- {\r
- for (size_t j = 0; j < PtrCU[i].NbVariables; j++)\r
- {\r
- if (!strcmp(PtrCU[i].PtrVariables[j].PtrName,VariableName))\r
- {\r
- return PtrCU[i].PtrVariables[j].Addr;\r
- }\r
- }\r
- }\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-\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
return NULL;\r
}\r
+#endif\r
\r
\r
// Get text line from source based on address and his tag\r
{\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
+ 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].NumLineSrc;\r
+ return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k - 1].NumLineSrc;\r
}\r
}\r
}\r