Linux build fixes
[clinton/Virtual-Jaguar-Rx.git] / src / debugger / DWARFManager.cpp
index b65227f..028b1e4 100644 (file)
 // 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
 //\r
 \r
 // To Do\r
 // To use pointers instead of arrays usage\r
-// To keep sources text file intact wihtout QT/HTML transformation\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                  0x44                            // CU number to debug or undefine it\r
+//#define DEBUG_NumCU                  0x                            // 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
@@ -131,7 +135,7 @@ typedef struct CUStruct
        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
@@ -147,10 +151,12 @@ typedef struct CUStruct
        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 used source number line\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;                                                // Pointer list to the number lines used\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
@@ -163,6 +169,7 @@ Dwarf_Debug dbg;
 CUStruct *PtrCU;\r
 char **ListSearchPaths;\r
 size_t NbSearchPaths;\r
+struct stat FileElfExeInfo;\r
 \r
 \r
 //\r
@@ -242,10 +249,11 @@ bool DWARFManager_Close(void)
 \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
@@ -469,10 +477,12 @@ void DWARFManager_InitDMI(void)
                                                                        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
@@ -525,65 +535,97 @@ void DWARFManager_InitDMI(void)
                                                                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
+                                                               else\r
+                                                               {\r
+                                                                       // Source file is outdated\r
+                                                                       PtrCU[NbCU].Status = DWARFSTATUS_OUTDATEDFILE;\r
                                                                }\r
-                                                               fclose(SrcFile);\r
+                                                       }\r
+                                                       else\r
+                                                       {\r
+                                                               // Source file doesn't have information\r
+                                                               PtrCU[NbCU].Status = DWARFSTATUS_NOFILEINFO;\r
                                                        }\r
                                                        break;\r
 \r
@@ -593,7 +635,7 @@ void DWARFManager_InitDMI(void)
                                        }\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
@@ -607,20 +649,18 @@ void DWARFManager_InitDMI(void)
                                                        {\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
@@ -905,19 +945,14 @@ void DWARFManager_InitDMI(void)
                                                                                // 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
@@ -1043,16 +1078,9 @@ void DWARFManager_InitDMI(void)
                                                }\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 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
@@ -1386,14 +1414,18 @@ char *DWARFManager_GetSymbolnameFromAdr(size_t Adr)
 \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