Update the breakpoint feature
[clinton/Virtual-Jaguar-Rx.git] / src / debugger / DWARFManager.cpp
... / ...
CommitLineData
1//\r
2// DWARFManager.cpp: DWARF format manager\r
3//\r
4// by Jean-Paul Mari\r
5//\r
6// JPM = Jean-Paul Mari <djipi.mari@gmail.com>\r
7// RG = Richard Goedeken\r
8//\r
9// WHO WHEN WHAT\r
10// --- ---------- ------------------------------------------------------------\r
11// JPM Dec./2016 Created this file, and added the DWARF format support\r
12// JPM Sept./2018 Added LEB128 decoding features, and improve the DWARF parsing information\r
13// 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
14// JPM Aug./2019 Added new functions to handle DWARF information, full filename fix\r
15// JPM Mar./2020 Fix a random crash when reading the source lines information\r
16// JPM Aug./2020 Added a source code file date check when reading DWARF information\r
17// RG Jan./2021 Linux build fixes\r
18//\r
19\r
20// To Do\r
21// To use pointers instead of arrays usage\r
22// \r
23\r
24\r
25#include <stdlib.h>\r
26#include <stdio.h>\r
27#include <stdint.h>\r
28#include <string.h>\r
29#include <time.h>\r
30#include <sys/types.h>\r
31#include <sys/stat.h>\r
32#include "libdwarf.h"\r
33#include "dwarf.h"\r
34#include "LEB128.h"\r
35#include "DWARFManager.h"\r
36\r
37// Definitions for debugging\r
38//#define DEBUG_NumCU 0x3 // CU number to debug or undefine it\r
39//#define DEBUG_VariableName "sound_death" // Variable name to look for or undefine it\r
40//#define DEBUG_TypeName "Cbuf_Execute" // Type name to look for or undefine it\r
41//#define DEBUG_TypeDef DW_TAG_typedef // Type def to look for or undefine it (not supported)\r
42//#define DEBUG_Filename "crt0" // Filename to look for or undefine it\r
43\r
44// Definitions for handling data\r
45//#define CONVERT_QT_HML // Text will be converted as HTML\r
46\r
47// Definitions for the variables's typetag\r
48#define TypeTag_structure 0x01 // structure\r
49#define TypeTag_pointer 0x02 // pointer\r
50#define TypeTag_subrange 0x04 // (subrange_type?)\r
51#define TypeTag_arraytype 0x08 // array type\r
52#define TypeTag_consttype 0x10 // const type\r
53#define TypeTag_typedef 0x20 // typedef\r
54#define TypeTag_enumeration_type 0x40 // enumeration\r
55#define TypeTag_subroutine_type 0x80 // subroutine\r
56\r
57\r
58// Source line CU structure\r
59typedef struct CUStruct_LineSrc\r
60{\r
61 size_t StartPC;\r
62 size_t NumLineSrc;\r
63 char *PtrLineSrc;\r
64}S_CUStruct_LineSrc;\r
65\r
66// Source line internal structure\r
67typedef struct DMIStruct_LineSrc\r
68{\r
69 size_t Tag;\r
70 size_t StartPC;\r
71 size_t NumLineSrc;\r
72 char *PtrLineSrc;\r
73}S_DMIStruct_LineSrc;\r
74\r
75// Enumeration structure\r
76typedef struct EnumerationStruct\r
77{\r
78 char *PtrName; // Enumeration's name\r
79 size_t value; // Enumeration's value\r
80}S_EnumerationStruct;\r
81\r
82// Structure members structure\r
83//typedef struct StructureMembersStruct\r
84//{\r
85//}S_StructureMembersStruct;\r
86\r
87// Base type internal structure\r
88typedef struct BaseTypeStruct\r
89{\r
90 size_t Tag; // Type's Tag\r
91 size_t Offset; // Type's offset\r
92 size_t TypeOffset; // Type's offset on another type\r
93 size_t ByteSize; // Type's Byte Size\r
94 size_t Encoding; // Type's encoding\r
95 char *PtrName; // Type's name\r
96 size_t NbEnumeration; // Type's enumeration numbers\r
97 EnumerationStruct *PtrEnumeration; // Type's enumeration\r
98// StructureMembersStruct *PtrStructureMembers; // Type's structure members\r
99}S_BaseTypeStruct;\r
100\r
101// Variables internal structure\r
102typedef struct VariablesStruct\r
103{\r
104 size_t Op; // Variable's DW_OP\r
105 union\r
106 {\r
107 size_t Addr; // Variable memory address\r
108 int Offset; // Variable stack offset (signed)\r
109 };\r
110 char *PtrName; // Variable's name\r
111 size_t TypeOffset; // Offset pointing on the Variable's Type\r
112 size_t TypeByteSize; // Variable's Type byte size\r
113 size_t TypeTag; // Variable's Type Tag\r
114 size_t TypeEncoding; // Variable's Type encoding\r
115 char *PtrTypeName; // Variable's Type name\r
116}S_VariablesStruct;\r
117\r
118// Sub program internal structure\r
119typedef struct SubProgStruct\r
120{\r
121 size_t Tag;\r
122 size_t NumLineSrc;\r
123 size_t StartPC;\r
124 size_t LowPC, HighPC;\r
125 size_t FrameBase;\r
126 char *PtrLineSrc;\r
127 char *PtrSubprogramName; // Sub program name\r
128 size_t NbLinesSrc; // Number of lines source used by the sub program\r
129 DMIStruct_LineSrc *PtrLinesSrc; // Pointer of the lines source for the sub program\r
130 size_t NbVariables; // Variables number\r
131 VariablesStruct *PtrVariables; // Pointer to the local variables list information structure\r
132}S_SubProgStruct;\r
133\r
134// Compilation Unit internal structure\r
135typedef struct CUStruct\r
136{\r
137 size_t Tag;\r
138 size_t Language; // Language (C, etc.) used by the source code\r
139 size_t LowPC, HighPC; // Memory range for the code\r
140 char *PtrProducer; // "Producer" text information (mostly compiler and compilation options used)\r
141 char *PtrSourceFilename; // Source file name\r
142 char *PtrSourceFileDirectory; // Directory of the source file\r
143 char *PtrFullFilename; // Pointer to full namefile (directory & filename)\r
144 size_t SizeLoadSrc; // Source code text size\r
145 char *PtrLoadSrc; // Pointer to the source code text\r
146 size_t NbLinesLoadSrc; // Total number of lines in the source code text\r
147 char **PtrLinesLoadSrc; // Pointer lists to each source line put in QT html/text conformity\r
148 size_t NbSubProgs; // Number of sub programs / routines\r
149 SubProgStruct *PtrSubProgs; // Pointer to the sub programs / routines structure\r
150 size_t NbTypes; // Number of types\r
151 BaseTypeStruct *PtrTypes; // Pointer to types\r
152 size_t NbVariables; // Variables number\r
153 VariablesStruct *PtrVariables; // Pointer to the global variables list structure\r
154 size_t NbFrames; // Frames number\r
155 size_t NbUsedLinesSrc; // Number of used source lines\r
156 size_t LastNumUsedLinesSrc; // Last number line used\r
157 CUStruct_LineSrc *PtrUsedLinesSrc; // Pointer to the used source lines list structure\r
158 char **PtrUsedLinesLoadSrc; // Pointer lists to each used source line referenced by the CUStruct_LineSrc structure\r
159 size_t *PtrUsedNumLines; // List of the number lines used\r
160 struct stat _statbuf; // File information\r
161 DWARFstatus Status; // File status\r
162}S_CUStruct;\r
163\r
164\r
165// Dwarf management\r
166uint32_t LibDwarf;\r
167uint32_t NbCU;\r
168Dwarf_Ptr errarg;\r
169Dwarf_Error error;\r
170Dwarf_Debug dbg;\r
171CUStruct *PtrCU;\r
172char **ListSearchPaths;\r
173size_t NbSearchPaths;\r
174struct stat FileElfExeInfo;\r
175\r
176\r
177//\r
178Dwarf_Handler DWARFManager_ErrorHandler(Dwarf_Ptr perrarg);\r
179void DWARFManager_InitDMI(void);\r
180void DWARFManager_CloseDMI(void);\r
181bool DWARFManager_ElfClose(void);\r
182char *DWARFManager_GetLineSrcFromNumLine(char *PtrSrcFile, size_t NumLine);\r
183void DWARFManager_InitInfosVariable(VariablesStruct *PtrVariables);\r
184void DWARFManager_SourceFileSearchPathsInit(void);\r
185void DWARFManager_SourceFileSearchPathsReset(void);\r
186void DWARFManager_SourceFileSearchPathsClose(void);\r
187void DWARFManager_ConformSlachesBackslashes(char *Ptr);\r
188\r
189\r
190//\r
191Dwarf_Handler DWARFManager_ErrorHandler(Dwarf_Ptr perrarg)\r
192{\r
193 return 0;\r
194}\r
195\r
196\r
197// Dwarf manager list search paths init\r
198void DWARFManager_SourceFileSearchPathsInit(void)\r
199{\r
200 ListSearchPaths = NULL;\r
201 NbSearchPaths = 0;\r
202}\r
203\r
204\r
205// Dwarf manager list search paths reset\r
206void DWARFManager_SourceFileSearchPathsReset(void)\r
207{\r
208 ListSearchPaths = NULL;\r
209 NbSearchPaths = 0;\r
210}\r
211\r
212\r
213// Dwarf manager list search paths close\r
214void DWARFManager_SourceFileSearchPathsClose(void)\r
215{\r
216 DWARFManager_SourceFileSearchPathsReset();\r
217}\r
218\r
219\r
220// Dwarf manager init\r
221void DWARFManager_Init(void)\r
222{\r
223 DWARFManager_SourceFileSearchPathsInit();\r
224 LibDwarf = DW_DLV_NO_ENTRY;\r
225}\r
226\r
227\r
228// Dwarf manager settings\r
229void DWARFManager_Set(size_t NbPathsInList, char **PtrListPaths)\r
230{\r
231 // Search paths init\r
232 ListSearchPaths = PtrListPaths;\r
233 NbSearchPaths = NbPathsInList;\r
234}\r
235\r
236\r
237// Dwarf manager Reset\r
238bool DWARFManager_Reset(void)\r
239{\r
240 DWARFManager_SourceFileSearchPathsReset();\r
241 return DWARFManager_ElfClose();\r
242}\r
243\r
244\r
245// Dwarf manager Close\r
246bool DWARFManager_Close(void)\r
247{\r
248 DWARFManager_SourceFileSearchPathsClose();\r
249 return(DWARFManager_Reset());\r
250}\r
251\r
252\r
253// Dwarf manager Elf init\r
254int DWARFManager_ElfInit(Elf *ElfPtr, struct stat FileElfInfo)\r
255{\r
256 if ((LibDwarf = dwarf_elf_init(ElfPtr, DW_DLC_READ, (Dwarf_Handler)DWARFManager_ErrorHandler, errarg, &dbg, &error)) == DW_DLV_OK)\r
257 {\r
258 FileElfExeInfo = FileElfInfo;\r
259 DWARFManager_InitDMI();\r
260 }\r
261\r
262 return LibDwarf;\r
263}\r
264\r
265\r
266// Dwarf manager Elf close\r
267bool DWARFManager_ElfClose(void)\r
268{\r
269 if (LibDwarf == DW_DLV_OK)\r
270 {\r
271 DWARFManager_CloseDMI();\r
272\r
273 if (dwarf_finish(dbg, &error) == DW_DLV_OK)\r
274 {\r
275 LibDwarf = DW_DLV_NO_ENTRY;\r
276 return true;\r
277 }\r
278 else\r
279 {\r
280 return false;\r
281 }\r
282 }\r
283 else\r
284 {\r
285 return true;\r
286 }\r
287}\r
288\r
289\r
290// Dwarf manager Compilation Units close\r
291void DWARFManager_CloseDMI(void)\r
292{\r
293 while (NbCU--)\r
294 {\r
295 free(PtrCU[NbCU].PtrFullFilename);\r
296 free(PtrCU[NbCU].PtrLoadSrc);\r
297 free(PtrCU[NbCU].PtrProducer);\r
298 free(PtrCU[NbCU].PtrSourceFilename);\r
299 free(PtrCU[NbCU].PtrSourceFileDirectory);\r
300 free(PtrCU[NbCU].PtrUsedLinesSrc);\r
301 free(PtrCU[NbCU].PtrUsedLinesLoadSrc);\r
302 free(PtrCU[NbCU].PtrUsedNumLines);\r
303\r
304 while (PtrCU[NbCU].NbLinesLoadSrc--)\r
305 {\r
306 free(PtrCU[NbCU].PtrLinesLoadSrc[PtrCU[NbCU].NbLinesLoadSrc]);\r
307 }\r
308 free(PtrCU[NbCU].PtrLinesLoadSrc);\r
309\r
310 while (PtrCU[NbCU].NbSubProgs--)\r
311 {\r
312 while (PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables--)\r
313 {\r
314 free(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].PtrName);\r
315 free(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].PtrTypeName);\r
316 }\r
317 free(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables);\r
318\r
319 free(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc);\r
320 free(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrSubprogramName);\r
321 }\r
322 free(PtrCU[NbCU].PtrSubProgs);\r
323\r
324 while (PtrCU[NbCU].NbTypes--)\r
325 {\r
326 free(PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName);\r
327 }\r
328 free(PtrCU[NbCU].PtrTypes);\r
329\r
330 while (PtrCU[NbCU].NbVariables--)\r
331 {\r
332 free(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName);\r
333 free(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrTypeName);\r
334 }\r
335 free(PtrCU[NbCU].PtrVariables);\r
336 }\r
337\r
338 free(PtrCU);\r
339}\r
340\r
341\r
342// Dwarf manager Compilation Units initialisations\r
343void DWARFManager_InitDMI(void)\r
344{\r
345 Dwarf_Unsigned next_cu_header, return_uvalue;\r
346 Dwarf_Error error;\r
347 Dwarf_Attribute *atlist;\r
348 Dwarf_Attribute return_attr1;\r
349 Dwarf_Half return_tagval, return_attr;\r
350 Dwarf_Addr return_lowpc, return_highpc, return_lineaddr;\r
351 Dwarf_Block *return_block;\r
352 Dwarf_Signed atcnt, cnt;\r
353 Dwarf_Die return_sib, return_die, return_sub, return_subdie;\r
354 Dwarf_Off return_offset;\r
355 Dwarf_Line *linebuf;\r
356 FILE *SrcFile;\r
357 char *return_string;\r
358 char *Ptr, *Ptr1;\r
359\r
360 // Initialisation for the Compilation Units table\r
361 NbCU = 0;\r
362 PtrCU = NULL;\r
363\r
364 // loop on the available Compilation Unit\r
365 while (dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, &next_cu_header, &error) == DW_DLV_OK)\r
366 {\r
367 // Allocation of an additional Compilation Unit structure in the table\r
368 if (Ptr = (char *)realloc(PtrCU, ((NbCU + 1) * sizeof(CUStruct))))\r
369 {\r
370 // Compilation Unit RAZ\r
371 PtrCU = (CUStruct *)Ptr;\r
372 memset(PtrCU + NbCU, 0, sizeof(CUStruct));\r
373\r
374 // Debug specific CU\r
375#ifdef DEBUG_NumCU\r
376 if (NbCU == DEBUG_NumCU)\r
377#endif\r
378 {\r
379 // Get 1st Die from the Compilation Unit\r
380 if (dwarf_siblingof(dbg, NULL, &return_sib, &error) == DW_DLV_OK)\r
381 {\r
382 // Get Die's Tag\r
383 if ((dwarf_tag(return_sib, &return_tagval, &error) == DW_DLV_OK))\r
384 {\r
385 PtrCU[NbCU].Tag = return_tagval;\r
386\r
387 // Die type detection\r
388 switch (return_tagval)\r
389 {\r
390 case DW_TAG_compile_unit:\r
391 if (dwarf_attrlist(return_sib, &atlist, &atcnt, &error) == DW_DLV_OK)\r
392 {\r
393 for (Dwarf_Signed i = 0; i < atcnt; ++i)\r
394 {\r
395 if (dwarf_whatattr(atlist[i], &return_attr, &error) == DW_DLV_OK)\r
396 {\r
397 switch (return_attr)\r
398 {\r
399 // Start address\r
400 case DW_AT_low_pc:\r
401 if (dwarf_lowpc(return_sib, &return_lowpc, &error) == DW_DLV_OK)\r
402 {\r
403 PtrCU[NbCU].LowPC = return_lowpc;\r
404 }\r
405 break;\r
406\r
407 // End address\r
408 case DW_AT_high_pc:\r
409 if (dwarf_highpc(return_sib, &return_highpc, &error) == DW_DLV_OK)\r
410 {\r
411 PtrCU[NbCU].HighPC = return_highpc;\r
412 }\r
413 break;\r
414\r
415 // compilation information\r
416 case DW_AT_producer:\r
417 if (dwarf_formstring(atlist[i], &return_string, &error) == DW_DLV_OK)\r
418 {\r
419 PtrCU[NbCU].PtrProducer = (char *)calloc(strlen(return_string) + 1, 1);\r
420 strcpy(PtrCU[NbCU].PtrProducer, return_string);\r
421 dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
422 }\r
423 break;\r
424\r
425 // Filename\r
426 case DW_AT_name:\r
427 if (dwarf_formstring(atlist[i], &return_string, &error) == DW_DLV_OK)\r
428 {\r
429#ifdef DEBUG_Filename\r
430 if (strstr(return_string, DEBUG_Filename))\r
431#endif\r
432 {\r
433 PtrCU[NbCU].PtrSourceFilename = (char *)calloc((strlen(return_string) + 1), 1);\r
434 strcpy(PtrCU[NbCU].PtrSourceFilename, return_string);\r
435 }\r
436 dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
437 }\r
438 break;\r
439\r
440 // Directory name\r
441 case DW_AT_comp_dir:\r
442 if (dwarf_formstring(atlist[i], &return_string, &error) == DW_DLV_OK)\r
443 {\r
444 PtrCU[NbCU].PtrSourceFileDirectory = (char *)calloc((strlen(return_string) + 1), 1);\r
445 strcpy(PtrCU[NbCU].PtrSourceFileDirectory, return_string);\r
446 dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
447 }\r
448 break;\r
449\r
450 // Language\r
451 case DW_AT_language:\r
452 if (dwarf_formudata(atlist[i], &return_uvalue, &error) == DW_DLV_OK)\r
453 {\r
454 PtrCU[NbCU].Language = return_uvalue;\r
455 }\r
456 break;\r
457\r
458 default:\r
459 break;\r
460 }\r
461 }\r
462 dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);\r
463 }\r
464 dwarf_dealloc(dbg, atlist, DW_DLA_LIST);\r
465 }\r
466\r
467 // Check filename presence\r
468 if (!PtrCU[NbCU].PtrSourceFilename)\r
469 {\r
470 PtrCU[NbCU].PtrSourceFilename = (char *)calloc(1, 1);\r
471 }\r
472\r
473 // Check directory presence\r
474 if (!PtrCU[NbCU].PtrSourceFileDirectory)\r
475 {\r
476 // Check if file exists in the search paths\r
477 for (size_t i = 0; i < NbSearchPaths; i++)\r
478 {\r
479 PtrCU[NbCU].PtrFullFilename = (char *)realloc(PtrCU[NbCU].PtrFullFilename, strlen(PtrCU[NbCU].PtrSourceFilename) + strlen((const char *)ListSearchPaths[i]) + 2);\r
480#if defined(_WIN32)\r
481 sprintf(PtrCU[NbCU].PtrFullFilename, "%s\\%s", ListSearchPaths[i], PtrCU[NbCU].PtrSourceFilename);\r
482 if (!fopen_s(&SrcFile, PtrCU[NbCU].PtrFullFilename, "rb"))\r
483#else\r
484 sprintf(PtrCU[NbCU].PtrFullFilename, "%s/%s", ListSearchPaths[i], PtrCU[NbCU].PtrSourceFilename);\r
485 SrcFile = fopen(PtrCU[NbCU].PtrFullFilename, "rb");\r
486 if (SrcFile == NULL)\r
487#endif\r
488 {\r
489 PtrCU[NbCU].PtrSourceFileDirectory = (char *)realloc(PtrCU[NbCU].PtrSourceFileDirectory, strlen(ListSearchPaths[i]) + 1);\r
490 strcpy(PtrCU[NbCU].PtrSourceFileDirectory, ListSearchPaths[i]);\r
491 }\r
492 }\r
493\r
494 // File directory doesn't exits\r
495 if (!PtrCU[NbCU].PtrSourceFileDirectory)\r
496 {\r
497 PtrCU[NbCU].PtrSourceFileDirectory = (char *)realloc(PtrCU[NbCU].PtrSourceFileDirectory, 2);\r
498 strcpy(PtrCU[NbCU].PtrSourceFileDirectory, ".");\r
499 }\r
500 }\r
501\r
502 // Conform slashes / backslashes for the filename\r
503 DWARFManager_ConformSlachesBackslashes(PtrCU[NbCU].PtrSourceFilename);\r
504\r
505 // Check if filename contains already the complete directory\r
506 if (PtrCU[NbCU].PtrSourceFilename[1] == ':')\r
507 {\r
508 // Copy the filename as the full filename\r
509 PtrCU[NbCU].PtrFullFilename = (char *)realloc(PtrCU[NbCU].PtrFullFilename, strlen(PtrCU[NbCU].PtrSourceFilename) + 1);\r
510 strcpy(PtrCU[NbCU].PtrFullFilename, PtrCU[NbCU].PtrSourceFilename);\r
511 }\r
512 else\r
513 {\r
514 // Create full filename and Conform slashes / backslashes\r
515 PtrCU[NbCU].PtrFullFilename = (char *)realloc(PtrCU[NbCU].PtrFullFilename, strlen(PtrCU[NbCU].PtrSourceFilename) + strlen(PtrCU[NbCU].PtrSourceFileDirectory) + 2);\r
516#if defined(_WIN32)\r
517 sprintf(PtrCU[NbCU].PtrFullFilename, "%s\\%s", PtrCU[NbCU].PtrSourceFileDirectory, PtrCU[NbCU].PtrSourceFilename);\r
518#else\r
519 sprintf(PtrCU[NbCU].PtrFullFilename, "%s/%s", PtrCU[NbCU].PtrSourceFileDirectory, PtrCU[NbCU].PtrSourceFilename);\r
520#endif\r
521 }\r
522\r
523 DWARFManager_ConformSlachesBackslashes(PtrCU[NbCU].PtrFullFilename);\r
524\r
525 // Directory path clean-up\r
526#if defined(_WIN32)\r
527 while ((Ptr1 = Ptr = strstr(PtrCU[NbCU].PtrFullFilename, "\\..\\")))\r
528#else\r
529 while ((Ptr1 = Ptr = strstr(PtrCU[NbCU].PtrFullFilename, "/../")))\r
530#endif\r
531 {\r
532#if defined(_WIN32)\r
533 while (*--Ptr1 != '\\');\r
534#else\r
535 while (*--Ptr1 != '/');\r
536#endif\r
537 strcpy((Ptr1 + 1), (Ptr + 4));\r
538 }\r
539\r
540 // Get the source file information\r
541 if (!stat(PtrCU[NbCU].PtrFullFilename, &PtrCU[NbCU]._statbuf))\r
542 {\r
543 // check the time stamp with the executable\r
544 if (PtrCU[NbCU]._statbuf.st_mtime <= FileElfExeInfo.st_mtime)\r
545 {\r
546 // Open the source file as a binary file\r
547#if defined(_WIN32)\r
548 if (!fopen_s(&SrcFile, PtrCU[NbCU].PtrFullFilename, "rb"))\r
549#else\r
550 SrcFile = fopen(PtrCU[NbCU].PtrFullFilename, "rb");\r
551 if (SrcFile == NULL)\r
552#endif\r
553 {\r
554 if (!fseek(SrcFile, 0, SEEK_END))\r
555 {\r
556 if ((PtrCU[NbCU].SizeLoadSrc = ftell(SrcFile)) > 0)\r
557 {\r
558 if (!fseek(SrcFile, 0, SEEK_SET))\r
559 {\r
560 if (PtrCU[NbCU].PtrLoadSrc = Ptr = Ptr1 = (char *)calloc(1, (PtrCU[NbCU].SizeLoadSrc + 2)))\r
561 {\r
562 // Read whole file\r
563#if defined(_WIN32) \r
564 if (fread_s(PtrCU[NbCU].PtrLoadSrc, PtrCU[NbCU].SizeLoadSrc, PtrCU[NbCU].SizeLoadSrc, 1, SrcFile) != 1)\r
565#else\r
566 if (fread(PtrCU[NbCU].PtrLoadSrc, PtrCU[NbCU].SizeLoadSrc, 1, SrcFile) != 1)\r
567#endif\r
568 {\r
569 free(PtrCU[NbCU].PtrLoadSrc);\r
570 PtrCU[NbCU].PtrLoadSrc = NULL;\r
571 PtrCU[NbCU].SizeLoadSrc = 0;\r
572 }\r
573 else\r
574 {\r
575 // Eliminate all carriage return code '\r' (oxd)\r
576 do\r
577 {\r
578 if ((*Ptr = *Ptr1) != '\r')\r
579 {\r
580 Ptr++;\r
581 }\r
582 } while (*Ptr1++);\r
583\r
584 // Get back the new text file size\r
585 PtrCU[NbCU].SizeLoadSrc = strlen(Ptr = PtrCU[NbCU].PtrLoadSrc);\r
586\r
587 // Make sure the text file finish with a new line code '\n' (0xa)\r
588 if (PtrCU[NbCU].PtrLoadSrc[PtrCU[NbCU].SizeLoadSrc - 1] != '\n')\r
589 {\r
590 PtrCU[NbCU].PtrLoadSrc[PtrCU[NbCU].SizeLoadSrc++] = '\n';\r
591 PtrCU[NbCU].PtrLoadSrc[PtrCU[NbCU].SizeLoadSrc] = 0;\r
592 }\r
593\r
594 // Reallocate text file\r
595 if (PtrCU[NbCU].PtrLoadSrc = Ptr = (char *)realloc(PtrCU[NbCU].PtrLoadSrc, (PtrCU[NbCU].SizeLoadSrc + 1)))\r
596 {\r
597 // Count line numbers, based on the new line code '\n' (0xa), and finish each line with 0\r
598 do\r
599 {\r
600 if (*Ptr == '\n')\r
601 {\r
602 PtrCU[NbCU].NbLinesLoadSrc++;\r
603 *Ptr = 0;\r
604 }\r
605 } while (*++Ptr);\r
606 }\r
607 }\r
608 }\r
609 }\r
610 }\r
611 }\r
612\r
613 fclose(SrcFile);\r
614 }\r
615 else\r
616 {\r
617 // Source file doesn't exist\r
618 PtrCU[NbCU].Status = DWARFSTATUS_NOFILE;\r
619 }\r
620 }\r
621 else\r
622 {\r
623 // Source file is outdated\r
624 PtrCU[NbCU].Status = DWARFSTATUS_OUTDATEDFILE;\r
625 }\r
626 }\r
627 else\r
628 {\r
629 // Source file doesn't have information\r
630 PtrCU[NbCU].Status = DWARFSTATUS_NOFILEINFO;\r
631 }\r
632 break;\r
633\r
634 default:\r
635 break;\r
636 }\r
637 }\r
638\r
639 // Get the source lines table located in the CU\r
640 if ((dwarf_srclines(return_sib, &linebuf, &cnt, &error) == DW_DLV_OK) && (PtrCU[NbCU].Status == DWARFSTATUS_OK))\r
641 {\r
642 if (cnt)\r
643 {\r
644 PtrCU[NbCU].NbUsedLinesSrc = cnt;\r
645 PtrCU[NbCU].PtrUsedLinesSrc = (CUStruct_LineSrc *)calloc(cnt, sizeof(CUStruct_LineSrc));\r
646 PtrCU[NbCU].PtrUsedLinesLoadSrc = (char **)calloc(cnt, sizeof(char *));\r
647 PtrCU[NbCU].PtrUsedNumLines = (size_t *)calloc(cnt, sizeof(size_t));\r
648\r
649 // Get the addresses and their source line numbers\r
650 for (Dwarf_Signed i = 0; i < cnt; i++)\r
651 {\r
652 if (dwarf_lineaddr(linebuf[i], &return_lineaddr, &error) == DW_DLV_OK)\r
653 {\r
654 // Get the source line number\r
655 if (dwarf_lineno(linebuf[i], &return_uvalue, &error) == DW_DLV_OK)\r
656 {\r
657 PtrCU[NbCU].PtrUsedLinesSrc[i].StartPC = return_lineaddr;\r
658 PtrCU[NbCU].PtrUsedLinesSrc[i].NumLineSrc = return_uvalue;\r
659 }\r
660 }\r
661 }\r
662 }\r
663\r
664 // Release the memory used by the source lines table located in the CU\r
665 dwarf_srclines_dealloc(dbg, linebuf, cnt);\r
666 }\r
667\r
668 // Check if the CU has child\r
669 if (dwarf_child(return_sib, &return_die, &error) == DW_DLV_OK)\r
670 {\r
671 do\r
672 {\r
673 return_sib = return_die;\r
674 if ((dwarf_tag(return_die, &return_tagval, &error) == DW_DLV_OK))\r
675 {\r
676 switch (return_tagval)\r
677 {\r
678 case DW_TAG_lexical_block:\r
679 break;\r
680\r
681 case DW_TAG_variable:\r
682 if (dwarf_attrlist(return_die, &atlist, &atcnt, &error) == DW_DLV_OK)\r
683 {\r
684 PtrCU[NbCU].PtrVariables = (VariablesStruct *)realloc(PtrCU[NbCU].PtrVariables, ((PtrCU[NbCU].NbVariables + 1) * sizeof(VariablesStruct)));\r
685 memset(PtrCU[NbCU].PtrVariables + PtrCU[NbCU].NbVariables, 0, sizeof(VariablesStruct));\r
686\r
687 for (Dwarf_Signed i = 0; i < atcnt; ++i)\r
688 {\r
689 if (dwarf_whatattr(atlist[i], &return_attr, &error) == DW_DLV_OK)\r
690 {\r
691 if (dwarf_attr(return_die, return_attr, &return_attr1, &error) == DW_DLV_OK)\r
692 {\r
693 switch (return_attr)\r
694 {\r
695 case DW_AT_location:\r
696 if (dwarf_formblock(return_attr1, &return_block, &error) == DW_DLV_OK)\r
697 {\r
698 PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].Op = (*((unsigned char *)(return_block->bl_data)));\r
699\r
700 switch (return_block->bl_len)\r
701 {\r
702 case 5:\r
703 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
704 break;\r
705\r
706 default:\r
707 break;\r
708 }\r
709 dwarf_dealloc(dbg, return_block, DW_DLA_BLOCK);\r
710 }\r
711 break;\r
712\r
713 case DW_AT_type:\r
714 if (dwarf_global_formref(return_attr1, &return_offset, &error) == DW_DLV_OK)\r
715 {\r
716 PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].TypeOffset = return_offset;\r
717 }\r
718 break;\r
719\r
720 // Variable name\r
721 case DW_AT_name:\r
722 if (dwarf_formstring(return_attr1, &return_string, &error) == DW_DLV_OK)\r
723 {\r
724#ifdef DEBUG_VariableName\r
725 if (!strcmp(return_string, DEBUG_VariableName))\r
726#endif\r
727 {\r
728 PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName = (char *)calloc(strlen(return_string) + 1, 1);\r
729 strcpy(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName, return_string);\r
730 }\r
731 dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
732 }\r
733 break;\r
734\r
735 default:\r
736 break;\r
737 }\r
738 }\r
739 }\r
740\r
741 dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);\r
742 }\r
743\r
744 // Check variable's name validity\r
745 if (PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName)\r
746 {\r
747 // Check variable's memory address validity\r
748 if (PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].Addr)\r
749 {\r
750 // Valid variable\r
751 PtrCU[NbCU].NbVariables++;\r
752 }\r
753 else\r
754 {\r
755 // Invalid variable\r
756 free(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName);\r
757 PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName = NULL;\r
758 }\r
759 }\r
760\r
761 dwarf_dealloc(dbg, atlist, DW_DLA_LIST);\r
762 }\r
763 break;\r
764\r
765 case DW_TAG_base_type:\r
766 case DW_TAG_typedef:\r
767 case DW_TAG_structure_type:\r
768 case DW_TAG_pointer_type:\r
769 case DW_TAG_const_type:\r
770 case DW_TAG_array_type:\r
771 case DW_TAG_subrange_type:\r
772 case DW_TAG_subroutine_type:\r
773 case DW_TAG_enumeration_type:\r
774 if (dwarf_attrlist(return_die, &atlist, &atcnt, &error) == DW_DLV_OK)\r
775 {\r
776 // Allocate memory for this type\r
777 PtrCU[NbCU].PtrTypes = (BaseTypeStruct *)realloc(PtrCU[NbCU].PtrTypes, ((PtrCU[NbCU].NbTypes + 1) * sizeof(BaseTypeStruct)));\r
778 memset(PtrCU[NbCU].PtrTypes + PtrCU[NbCU].NbTypes, 0, sizeof(BaseTypeStruct));\r
779 PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].Tag = return_tagval;\r
780\r
781 if (dwarf_dieoffset(return_die, &return_offset, &error) == DW_DLV_OK)\r
782 {\r
783 PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].Offset = return_offset;\r
784 }\r
785\r
786 for (Dwarf_Signed i = 0; i < atcnt; ++i)\r
787 {\r
788 if (dwarf_whatattr(atlist[i], &return_attr, &error) == DW_DLV_OK)\r
789 {\r
790 if (dwarf_attr(return_die, return_attr, &return_attr1, &error) == DW_DLV_OK)\r
791 {\r
792 switch (return_attr)\r
793 {\r
794 // \r
795 case DW_AT_sibling:\r
796 break;\r
797\r
798 // Type's type offset\r
799 case DW_AT_type:\r
800 if (dwarf_global_formref(return_attr1, &return_offset, &error) == DW_DLV_OK)\r
801 {\r
802 PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].TypeOffset = return_offset;\r
803 }\r
804 break;\r
805\r
806 // Type's byte size\r
807 case DW_AT_byte_size:\r
808 if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK)\r
809 {\r
810 PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].ByteSize = return_uvalue;\r
811 }\r
812 break;\r
813\r
814 // Type's encoding\r
815 case DW_AT_encoding:\r
816 if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK)\r
817 {\r
818 PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].Encoding = return_uvalue;\r
819 }\r
820 break;\r
821\r
822 // Type's name\r
823 case DW_AT_name:\r
824 if (dwarf_formstring(return_attr1, &return_string, &error) == DW_DLV_OK)\r
825 {\r
826#ifdef DEBUG_TypeName\r
827 if (!strcmp(return_string, DEBUG_TypeName))\r
828#endif\r
829 {\r
830 PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName = (char *)calloc(strlen(return_string) + 1, 1);\r
831 strcpy(PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName, return_string);\r
832 }\r
833 dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
834 }\r
835 break;\r
836\r
837 // Type's file number\r
838 case DW_AT_decl_file:\r
839 break;\r
840\r
841 // Type's line number\r
842 case DW_AT_decl_line:\r
843 break;\r
844\r
845 default:\r
846 break;\r
847 }\r
848 }\r
849 }\r
850\r
851 dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);\r
852 }\r
853\r
854 PtrCU[NbCU].NbTypes++;\r
855\r
856 dwarf_dealloc(dbg, atlist, DW_DLA_LIST);\r
857 }\r
858 break;\r
859\r
860 case DW_TAG_subprogram:\r
861 if (dwarf_attrlist(return_die, &atlist, &atcnt, &error) == DW_DLV_OK)\r
862 {\r
863 PtrCU[NbCU].PtrSubProgs = (SubProgStruct *)realloc(PtrCU[NbCU].PtrSubProgs, ((PtrCU[NbCU].NbSubProgs + 1) * sizeof(SubProgStruct)));\r
864 memset((void *)(PtrCU[NbCU].PtrSubProgs + PtrCU[NbCU].NbSubProgs), 0, sizeof(SubProgStruct));\r
865 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].Tag = return_tagval;\r
866\r
867 for (Dwarf_Signed i = 0; i < atcnt; ++i)\r
868 {\r
869 if (dwarf_whatattr(atlist[i], &return_attr, &error) == DW_DLV_OK)\r
870 {\r
871 if (dwarf_attr(return_die, return_attr, &return_attr1, &error) == DW_DLV_OK)\r
872 {\r
873 switch (return_attr)\r
874 {\r
875 // start address\r
876 case DW_AT_low_pc:\r
877 if (dwarf_lowpc(return_die, &return_lowpc, &error) == DW_DLV_OK)\r
878 {\r
879 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].StartPC = return_lowpc;\r
880 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].LowPC = return_lowpc;\r
881 }\r
882 break;\r
883\r
884 // end address\r
885 case DW_AT_high_pc:\r
886 if (dwarf_highpc(return_die, &return_highpc, &error) == DW_DLV_OK)\r
887 {\r
888 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].HighPC = return_highpc;\r
889 }\r
890 break;\r
891\r
892 // Line number\r
893 case DW_AT_decl_line:\r
894 if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK)\r
895 {\r
896 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NumLineSrc = return_uvalue;\r
897 }\r
898 break;\r
899\r
900 // Frame\r
901 case DW_AT_frame_base:\r
902 if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK)\r
903 {\r
904 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].FrameBase = return_uvalue;\r
905 PtrCU[NbCU].NbFrames++;\r
906 }\r
907 break;\r
908\r
909 // function name\r
910 case DW_AT_name:\r
911 if (dwarf_formstring(return_attr1, &return_string, &error) == DW_DLV_OK)\r
912 {\r
913 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrSubprogramName = (char *)calloc(strlen(return_string) + 1, 1);\r
914 strcpy(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrSubprogramName, return_string);\r
915 dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
916 }\r
917 break;\r
918\r
919 case DW_AT_sibling:\r
920 break;\r
921\r
922 case DW_AT_GNU_all_tail_call_sites:\r
923 break;\r
924\r
925 case DW_AT_type:\r
926 break;\r
927\r
928 case DW_AT_prototyped:\r
929 break;\r
930\r
931 // File number\r
932 case DW_AT_decl_file:\r
933 break;\r
934\r
935 case DW_AT_external:\r
936 break;\r
937\r
938 default:\r
939 break;\r
940 }\r
941 }\r
942 }\r
943 dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);\r
944 }\r
945 dwarf_dealloc(dbg, atlist, DW_DLA_LIST);\r
946\r
947 // Get source line number and associated block of address\r
948 for (Dwarf_Signed i = 0; i < cnt; ++i)\r
949 {\r
950 // Check the presence of the line in the memory frame\r
951 if (PtrCU[NbCU].PtrUsedLinesSrc && (PtrCU[NbCU].PtrUsedLinesSrc[i].StartPC >= return_lowpc) && (PtrCU[NbCU].PtrUsedLinesSrc[i].StartPC <= return_highpc))\r
952 {\r
953 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
954 memset((void *)(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc + PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc), 0, sizeof(DMIStruct_LineSrc));\r
955 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc].StartPC = PtrCU[NbCU].PtrUsedLinesSrc[i].StartPC;\r
956 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc].NumLineSrc = PtrCU[NbCU].PtrUsedLinesSrc[i].NumLineSrc;\r
957 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc++;\r
958 }\r
959 }\r
960\r
961 if (dwarf_child(return_die, &return_subdie, &error) == DW_DLV_OK)\r
962 {\r
963 do\r
964 {\r
965 return_sub = return_subdie;\r
966 if ((dwarf_tag(return_subdie, &return_tagval, &error) == DW_DLV_OK))\r
967 {\r
968 switch (return_tagval)\r
969 {\r
970 case DW_TAG_formal_parameter:\r
971 case DW_TAG_variable:\r
972 if (dwarf_attrlist(return_subdie, &atlist, &atcnt, &error) == DW_DLV_OK)\r
973 {\r
974 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
975 memset(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables + PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables, 0, sizeof(VariablesStruct));\r
976\r
977 for (Dwarf_Signed i = 0; i < atcnt; ++i)\r
978 {\r
979 if (dwarf_whatattr(atlist[i], &return_attr, &error) == DW_DLV_OK)\r
980 {\r
981 if (dwarf_attr(return_subdie, return_attr, &return_attr1, &error) == DW_DLV_OK)\r
982 {\r
983 switch (return_attr)\r
984 {\r
985 case DW_AT_location:\r
986 if (dwarf_formblock(return_attr1, &return_block, &error) == DW_DLV_OK)\r
987 {\r
988 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].Op = *((unsigned char *)(return_block->bl_data));\r
989\r
990 switch (return_block->bl_len)\r
991 {\r
992 case 1:\r
993 break;\r
994\r
995 case 2:\r
996 case 3:\r
997 switch (return_tagval)\r
998 {\r
999 case DW_TAG_variable:\r
1000 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].Offset = ReadLEB128((char *)return_block->bl_data + 1);\r
1001 break;\r
1002\r
1003 case DW_TAG_formal_parameter:\r
1004 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].Offset = ReadULEB128((char *)return_block->bl_data + 1);\r
1005 break;\r
1006\r
1007 default:\r
1008 break;\r
1009 }\r
1010 break;\r
1011\r
1012 default:\r
1013 break;\r
1014 }\r
1015 dwarf_dealloc(dbg, return_block, DW_DLA_BLOCK);\r
1016 }\r
1017 break;\r
1018\r
1019 case DW_AT_type:\r
1020 if (dwarf_global_formref(return_attr1, &return_offset, &error) == DW_DLV_OK)\r
1021 {\r
1022 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].TypeOffset = return_offset;\r
1023 }\r
1024 break;\r
1025\r
1026 case DW_AT_name:\r
1027 if (dwarf_formstring(return_attr1, &return_string, &error) == DW_DLV_OK)\r
1028 {\r
1029#ifdef DEBUG_VariableName\r
1030 if (!strcmp(return_string, DEBUG_VariableName))\r
1031#endif\r
1032 {\r
1033 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].PtrName = (char *)calloc(strlen(return_string) + 1, 1);\r
1034 strcpy(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].PtrName, return_string);\r
1035 }\r
1036 dwarf_dealloc(dbg, return_string, DW_DLA_STRING);\r
1037 }\r
1038 break;\r
1039\r
1040 case DW_AT_decl_file:\r
1041 break;\r
1042\r
1043 case DW_AT_decl_line:\r
1044 break;\r
1045\r
1046 default:\r
1047 break;\r
1048 }\r
1049 }\r
1050 }\r
1051\r
1052 dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);\r
1053 }\r
1054\r
1055 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables++;\r
1056\r
1057 dwarf_dealloc(dbg, atlist, DW_DLA_LIST);\r
1058 }\r
1059 break;\r
1060\r
1061 case DW_TAG_label:\r
1062 break;\r
1063\r
1064 default:\r
1065 break;\r
1066 }\r
1067 }\r
1068 }\r
1069 while (dwarf_siblingof(dbg, return_sub, &return_subdie, &error) == DW_DLV_OK);\r
1070 }\r
1071\r
1072 PtrCU[NbCU].NbSubProgs++;\r
1073 }\r
1074 break;\r
1075\r
1076 default:\r
1077 break;\r
1078 }\r
1079 }\r
1080 }\r
1081 while (dwarf_siblingof(dbg, return_sib, &return_die, &error) == DW_DLV_OK);\r
1082 }\r
1083 }\r
1084\r
1085 // Set the source code lines\r
1086 if (PtrCU[NbCU].NbLinesLoadSrc)\r
1087 {\r
1088 if (PtrCU[NbCU].PtrLinesLoadSrc = (char **)calloc(PtrCU[NbCU].NbLinesLoadSrc, sizeof(char *)))\r
1089 {\r
1090 for (size_t j = 0; j < PtrCU[NbCU].NbLinesLoadSrc; j++)\r
1091 {\r
1092 if (PtrCU[NbCU].PtrLinesLoadSrc[j] = (char *)calloc(10000, sizeof(char)))\r
1093 {\r
1094 if (Ptr = DWARFManager_GetLineSrcFromNumLine(PtrCU[NbCU].PtrLoadSrc, (j + 1)))\r
1095 {\r
1096#ifndef CONVERT_QT_HML\r
1097 strcpy(PtrCU[NbCU].PtrLinesLoadSrc[j], Ptr);\r
1098#else\r
1099 size_t i = 0;\r
1100\r
1101 while (*Ptr)\r
1102 {\r
1103 switch (*Ptr)\r
1104 {\r
1105 case 9:\r
1106 strcat(PtrCU[NbCU].PtrLinesLoadSrc[j], "&nbsp;");\r
1107 i += 6;\r
1108 break;\r
1109\r
1110 case '<':\r
1111 strcat(PtrCU[NbCU].PtrLinesLoadSrc[j], "&lt;");\r
1112 i += 4;\r
1113 break;\r
1114\r
1115 case '>':\r
1116 strcat(PtrCU[NbCU].PtrLinesLoadSrc[j], "&gt;");\r
1117 i += 4;\r
1118 break;\r
1119#if 0\r
1120 case '&':\r
1121 strcpy(PtrCU[NbCU].PtrLinesLoadSrc[j], "&amp;");\r
1122 i += strlen("&amp;");\r
1123 break;\r
1124#endif\r
1125#if 0\r
1126 case '"':\r
1127 strcpy(PtrCU[NbCU].PtrLinesLoadSrc[j], "&quot;");\r
1128 i += strlen("&quot;");\r
1129 break;\r
1130#endif\r
1131 default:\r
1132 PtrCU[NbCU].PtrLinesLoadSrc[j][i++] = *Ptr;\r
1133 break;\r
1134 }\r
1135 Ptr++;\r
1136 }\r
1137#endif\r
1138 }\r
1139 PtrCU[NbCU].PtrLinesLoadSrc[j] = (char *)realloc(PtrCU[NbCU].PtrLinesLoadSrc[j], strlen(PtrCU[NbCU].PtrLinesLoadSrc[j]) + 1);\r
1140 }\r
1141 }\r
1142\r
1143 // Init lines source information for each source code line numbers and for each subprogs\r
1144 for (size_t j = 0; j < PtrCU[NbCU].NbSubProgs; j++)\r
1145 {\r
1146 // Check if the subprog / function's line exists in the source code\r
1147 if (PtrCU[NbCU].PtrSubProgs[j].NumLineSrc <= PtrCU[NbCU].NbLinesLoadSrc)\r
1148 {\r
1149 PtrCU[NbCU].PtrSubProgs[j].PtrLineSrc = PtrCU[NbCU].PtrLinesLoadSrc[PtrCU[NbCU].PtrSubProgs[j].NumLineSrc - 1];\r
1150 }\r
1151\r
1152 for (size_t k = 0; k < PtrCU[NbCU].PtrSubProgs[j].NbLinesSrc; k++)\r
1153 {\r
1154 if (PtrCU[NbCU].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc <= PtrCU[NbCU].NbLinesLoadSrc)\r
1155 {\r
1156 PtrCU[NbCU].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc = PtrCU[NbCU].PtrLinesLoadSrc[PtrCU[NbCU].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc - 1];\r
1157 }\r
1158 }\r
1159 }\r
1160 }\r
1161 }\r
1162 else\r
1163 {\r
1164 // Set each source lines pointer to NULL\r
1165 if (PtrCU[NbCU].NbSubProgs)\r
1166 {\r
1167 // Check the presence of source lines dedicated to the sub progs\r
1168 if (PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs - 1].NbLinesSrc)\r
1169 {\r
1170 size_t i = PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs - 1].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs - 1].NbLinesSrc - 1].NumLineSrc;\r
1171 if (PtrCU[NbCU].PtrLinesLoadSrc = (char **)calloc(i, sizeof(char *)))\r
1172 {\r
1173 for (size_t j = 0; j < i; j++)\r
1174 {\r
1175 PtrCU[NbCU].PtrLinesLoadSrc[j] = NULL;\r
1176 }\r
1177 }\r
1178 }\r
1179 }\r
1180 }\r
1181\r
1182 // Check validity between used number lines and number lines in the source file\r
1183 if (PtrCU[NbCU].LastNumUsedLinesSrc <= PtrCU[NbCU].NbLinesLoadSrc)\r
1184 {\r
1185 // Set information based on used line numbers\r
1186 if (PtrCU[NbCU].PtrUsedLinesSrc)\r
1187 {\r
1188 // Set the line source pointers for each used line numbers\r
1189 if (PtrCU[NbCU].PtrLinesLoadSrc)\r
1190 {\r
1191 for (size_t i = 0; i < PtrCU[NbCU].NbUsedLinesSrc; i++)\r
1192 {\r
1193 PtrCU[NbCU].PtrUsedNumLines[i] = PtrCU[NbCU].PtrUsedLinesSrc[i].NumLineSrc - 1;\r
1194 PtrCU[NbCU].PtrUsedLinesLoadSrc[i] = PtrCU[NbCU].PtrUsedLinesSrc[i].PtrLineSrc = PtrCU[NbCU].PtrLinesLoadSrc[PtrCU[NbCU].PtrUsedLinesSrc[i].NumLineSrc - 1];\r
1195 }\r
1196\r
1197 // Setup memory range for the code if CU doesn't have already this information\r
1198 // It is taken from the used lines structure\r
1199 if (!PtrCU[NbCU].LowPC && (!PtrCU[NbCU].HighPC || (PtrCU[NbCU].HighPC == ~0)))\r
1200 {\r
1201 PtrCU[NbCU].LowPC = PtrCU[NbCU].PtrUsedLinesSrc[0].StartPC;\r
1202 PtrCU[NbCU].HighPC = PtrCU[NbCU].PtrUsedLinesSrc[PtrCU[NbCU].NbUsedLinesSrc - 1].StartPC;\r
1203 }\r
1204 }\r
1205 }\r
1206 }\r
1207\r
1208 // Init global variables information based on types information\r
1209 for (size_t i = 0; i < PtrCU[NbCU].NbVariables; i++)\r
1210 {\r
1211 DWARFManager_InitInfosVariable(PtrCU[NbCU].PtrVariables + i);\r
1212 }\r
1213\r
1214 // Init local variables information based on types information\r
1215 for (size_t i = 0; i < PtrCU[NbCU].NbSubProgs; i++)\r
1216 {\r
1217 for (size_t j = 0; j < PtrCU[NbCU].PtrSubProgs[i].NbVariables; j++)\r
1218 {\r
1219 DWARFManager_InitInfosVariable(PtrCU[NbCU].PtrSubProgs[i].PtrVariables + j);\r
1220 }\r
1221 }\r
1222 }\r
1223\r
1224 ++NbCU;\r
1225 }\r
1226 } \r
1227}\r
1228\r
1229\r
1230// Conform slashes and backslashes\r
1231void DWARFManager_ConformSlachesBackslashes(char *Ptr)\r
1232{\r
1233 while (*Ptr)\r
1234 {\r
1235#if defined(_WIN32)\r
1236 if (*Ptr == '/')\r
1237 {\r
1238 *Ptr = '\\';\r
1239 }\r
1240#else\r
1241 if (*Ptr == '\\')\r
1242 {\r
1243 *Ptr = '/';\r
1244 }\r
1245#endif\r
1246 Ptr++;\r
1247 }\r
1248}\r
1249\r
1250\r
1251// Variables information initialisation\r
1252void DWARFManager_InitInfosVariable(VariablesStruct *PtrVariables)\r
1253{\r
1254 size_t j, TypeOffset;\r
1255\r
1256#ifdef DEBUG_VariableName\r
1257 if (PtrVariables->PtrName && !strcmp(PtrVariables->PtrName, DEBUG_VariableName))\r
1258#endif\r
1259 {\r
1260 PtrVariables->PtrTypeName = (char *)calloc(1000, 1);\r
1261 TypeOffset = PtrVariables->TypeOffset;\r
1262\r
1263 for (j = 0; j < PtrCU[NbCU].NbTypes; j++)\r
1264 {\r
1265 if (TypeOffset == PtrCU[NbCU].PtrTypes[j].Offset)\r
1266 {\r
1267 switch (PtrCU[NbCU].PtrTypes[j].Tag)\r
1268 {\r
1269 case DW_TAG_subroutine_type:\r
1270 PtrVariables->TypeTag |= TypeTag_subroutine_type;\r
1271 strcat(PtrVariables->PtrTypeName, " (* ) ()");\r
1272 break;\r
1273\r
1274 // Structure type tag\r
1275 case DW_TAG_structure_type:\r
1276 PtrVariables->TypeTag |= TypeTag_structure;\r
1277 if (!(PtrVariables->TypeTag & TypeTag_typedef))\r
1278 {\r
1279 if (PtrCU[NbCU].PtrTypes[j].PtrName)\r
1280 {\r
1281 strcat(PtrVariables->PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);\r
1282 }\r
1283 }\r
1284 if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
1285 {\r
1286 j = -1;\r
1287 }\r
1288 else\r
1289 {\r
1290 if ((PtrVariables->TypeTag & TypeTag_pointer))\r
1291 {\r
1292 strcat(PtrVariables->PtrTypeName, " *");\r
1293 }\r
1294 }\r
1295 break;\r
1296\r
1297 // Pointer type tag\r
1298 case DW_TAG_pointer_type:\r
1299 PtrVariables->TypeTag |= TypeTag_pointer;\r
1300 PtrVariables->TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;\r
1301 PtrVariables->TypeEncoding = 0x10;\r
1302 if (!(TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
1303 {\r
1304 strcat(PtrVariables->PtrTypeName, "void *");\r
1305 }\r
1306 else\r
1307 {\r
1308 j = -1;\r
1309 }\r
1310 break;\r
1311\r
1312 case DW_TAG_enumeration_type:\r
1313 PtrVariables->TypeTag |= TypeTag_enumeration_type;\r
1314 PtrVariables->TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;\r
1315 if (!(PtrVariables->TypeEncoding = PtrCU[NbCU].PtrTypes[j].Encoding))\r
1316 {\r
1317 // Try to determine the possible size\r
1318 switch (PtrVariables->TypeByteSize)\r
1319 {\r
1320 case 4:\r
1321 PtrVariables->TypeEncoding = 0x7;\r
1322 break;\r
1323\r
1324 default:\r
1325 break;\r
1326 }\r
1327 }\r
1328 break;\r
1329\r
1330 // Typedef type tag\r
1331 case DW_TAG_typedef:\r
1332 if (!(PtrVariables->TypeTag & TypeTag_typedef))\r
1333 {\r
1334 PtrVariables->TypeTag |= TypeTag_typedef;\r
1335 strcat(PtrVariables->PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);\r
1336 }\r
1337 if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
1338 {\r
1339 j = -1;\r
1340 }\r
1341 break;\r
1342\r
1343 // ? type tag\r
1344 case DW_TAG_subrange_type:\r
1345 PtrVariables->TypeTag |= TypeTag_subrange;\r
1346 break;\r
1347\r
1348 // Array type tag\r
1349 case DW_TAG_array_type:\r
1350 PtrVariables->TypeTag |= TypeTag_arraytype;\r
1351 if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
1352 {\r
1353 j = -1;\r
1354 }\r
1355 break;\r
1356\r
1357 // Const type tag\r
1358 case DW_TAG_const_type:\r
1359 PtrVariables->TypeTag |= TypeTag_consttype;\r
1360 strcat(PtrVariables->PtrTypeName, "const ");\r
1361 if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))\r
1362 {\r
1363 j = -1;\r
1364 }\r
1365 break;\r
1366\r
1367 // Base type tag\r
1368 case DW_TAG_base_type:\r
1369 if (!(PtrVariables->TypeTag & TypeTag_typedef))\r
1370 {\r
1371 strcat(PtrVariables->PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);\r
1372 }\r
1373 if ((PtrVariables->TypeTag & TypeTag_pointer))\r
1374 {\r
1375 strcat(PtrVariables->PtrTypeName, " *");\r
1376 }\r
1377 else\r
1378 {\r
1379 PtrVariables->TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;\r
1380 PtrVariables->TypeEncoding = PtrCU[NbCU].PtrTypes[j].Encoding;\r
1381 }\r
1382 if ((PtrVariables->TypeTag & TypeTag_arraytype))\r
1383 {\r
1384 strcat(PtrVariables->PtrTypeName, "[]");\r
1385 }\r
1386 break;\r
1387\r
1388 default:\r
1389 break;\r
1390 }\r
1391 }\r
1392 }\r
1393 }\r
1394}\r
1395\r
1396\r
1397// Get symbol name based from address\r
1398// Return NULL if no symbol name exists\r
1399char *DWARFManager_GetSymbolnameFromAdr(size_t Adr)\r
1400{\r
1401 for (size_t i = 0; i < NbCU; i++)\r
1402 {\r
1403 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
1404 {\r
1405 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
1406 {\r
1407 if ((PtrCU[i].PtrSubProgs[j].StartPC == Adr))\r
1408 {\r
1409 return PtrCU[i].PtrSubProgs[j].PtrSubprogramName;\r
1410 }\r
1411 }\r
1412 }\r
1413 }\r
1414\r
1415 return NULL;\r
1416}\r
1417\r
1418\r
1419// Get complete source filename based from address\r
1420// Return NULL if no source filename exists\r
1421// Return the existence status in Status if pointer not NULL\r
1422char *DWARFManager_GetFullSourceFilenameFromAdr(size_t Adr, DWARFstatus *Status)\r
1423{\r
1424 for (size_t i = 0; i < NbCU; i++)\r
1425 {\r
1426 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
1427 {\r
1428 if (Status)\r
1429 {\r
1430 *Status = PtrCU[i].Status;\r
1431 }\r
1432\r
1433 return PtrCU[i].PtrFullFilename;\r
1434 }\r
1435 }\r
1436\r
1437 return NULL;\r
1438}\r
1439\r
1440\r
1441// Get text line source based on line number (starting from 1)\r
1442// Return NULL if no text line exists or if line number is 0\r
1443char *DWARFManager_GetLineSrcFromNumLine(char *PtrSrcFile, size_t NumLine)\r
1444{\r
1445 size_t i = 0;\r
1446 char *PtrLineSrc = NULL;\r
1447\r
1448 if (PtrSrcFile)\r
1449 {\r
1450 while (i != NumLine)\r
1451 {\r
1452 PtrLineSrc = PtrSrcFile;\r
1453 while (*PtrSrcFile++);\r
1454 i++;\r
1455 }\r
1456 }\r
1457\r
1458 return PtrLineSrc;\r
1459}\r
1460\r
1461\r
1462// Get number of variables referenced by the function range address\r
1463size_t DWARFManager_GetNbLocalVariables(size_t Adr)\r
1464{\r
1465 for (size_t i = 0; i < NbCU; i++)\r
1466 {\r
1467 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
1468 {\r
1469 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
1470 {\r
1471 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
1472 {\r
1473 return PtrCU[i].PtrSubProgs[j].NbVariables;\r
1474 }\r
1475 }\r
1476 }\r
1477 }\r
1478\r
1479 return 0;\r
1480}\r
1481\r
1482\r
1483// Get local variable name based on his index (starting from 1)\r
1484// Return name's pointer text found\r
1485// Return NULL if not found\r
1486char *DWARFManager_GetLocalVariableName(size_t Adr, size_t Index)\r
1487{\r
1488 for (size_t i = 0; i < NbCU; i++)\r
1489 {\r
1490 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
1491 {\r
1492 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
1493 {\r
1494 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
1495 {\r
1496 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].PtrName;\r
1497 }\r
1498 }\r
1499 }\r
1500 }\r
1501\r
1502 return NULL;\r
1503}\r
1504\r
1505\r
1506// Get local variable's type tag based on his index (starting from 1)\r
1507// Return 0 if not found\r
1508size_t DWARFManager_GetLocalVariableTypeTag(size_t Adr, size_t Index)\r
1509{\r
1510 for (size_t i = 0; i < NbCU; i++)\r
1511 {\r
1512 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
1513 {\r
1514 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
1515 {\r
1516 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
1517 {\r
1518 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].TypeTag;\r
1519 }\r
1520 }\r
1521 }\r
1522 }\r
1523\r
1524 return 0;\r
1525}\r
1526\r
1527\r
1528// Get the local variable's offset based on a index (starting from 1)\r
1529// Return 0 if no offset has been found\r
1530int DWARFManager_GetLocalVariableOffset(size_t Adr, size_t Index)\r
1531{\r
1532 for (size_t i = 0; i < NbCU; i++)\r
1533 {\r
1534 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
1535 {\r
1536 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
1537 {\r
1538 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
1539 {\r
1540 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].Offset;\r
1541 }\r
1542 }\r
1543 }\r
1544 }\r
1545\r
1546 return 0;\r
1547}\r
1548\r
1549\r
1550// Get local variable Type Byte Size based on his address and index (starting from 1)\r
1551// Return 0 if not found\r
1552// May return 0 if there is no Type Byte Size linked to the variable's address and index\r
1553size_t DWARFManager_GetLocalVariableTypeByteSize(size_t Adr, size_t Index)\r
1554{\r
1555 for (size_t i = 0; i < NbCU; i++)\r
1556 {\r
1557 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
1558 {\r
1559 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
1560 {\r
1561 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
1562 {\r
1563 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].TypeByteSize;\r
1564 }\r
1565 }\r
1566 }\r
1567 }\r
1568\r
1569 return 0;\r
1570}\r
1571\r
1572\r
1573// Get local variable Type Encoding based on his address and index (starting from 1)\r
1574// Return 0 if not found\r
1575// May return 0 if there is no Type Encoding linked to the variable's address and index\r
1576size_t DWARFManager_GetLocalVariableTypeEncoding(size_t Adr, size_t Index)\r
1577{\r
1578 for (size_t i = 0; i < NbCU; i++)\r
1579 {\r
1580 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
1581 {\r
1582 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
1583 {\r
1584 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
1585 {\r
1586 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].TypeEncoding;\r
1587 }\r
1588 }\r
1589 }\r
1590 }\r
1591\r
1592 return 0;\r
1593}\r
1594\r
1595\r
1596// Get local variable Op based on his address and index (starting from 1)\r
1597// Return 0 if not found, may return 0 if there isn't Op linked to the variable's index\r
1598size_t DWARFManager_GetLocalVariableOp(size_t Adr, size_t Index)\r
1599{\r
1600 for (size_t i = 0; i < NbCU; i++)\r
1601 {\r
1602 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
1603 {\r
1604 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
1605 {\r
1606 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
1607 {\r
1608 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].Op;\r
1609 }\r
1610 }\r
1611 }\r
1612 }\r
1613\r
1614 return 0;\r
1615}\r
1616\r
1617\r
1618// Get local variable type name based on his index (starting from 1) and an address\r
1619// Return NULL if not found, may also return NULL if there is no type linked to the variable's index\r
1620char *DWARFManager_GetLocalVariableTypeName(size_t Adr, size_t Index)\r
1621{\r
1622 for (size_t i = 0; i < NbCU; i++)\r
1623 {\r
1624 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
1625 {\r
1626 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
1627 {\r
1628 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
1629 {\r
1630 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].PtrTypeName;\r
1631 }\r
1632 }\r
1633 }\r
1634 }\r
1635\r
1636 return NULL;\r
1637}\r
1638\r
1639\r
1640// Get Compilation Unit / global variables numbers\r
1641// Return number of variables\r
1642size_t DWARFManager_GetNbGlobalVariables(void)\r
1643{\r
1644 size_t NbVariables = 0;\r
1645\r
1646 for (size_t i = 0; i < NbCU; i++)\r
1647 {\r
1648 NbVariables += PtrCU[i].NbVariables;\r
1649 }\r
1650\r
1651 return NbVariables;\r
1652}\r
1653\r
1654\r
1655// Get global variable type name based on his index (starting from 1)\r
1656// Return NULL if not found\r
1657// May return NULL if there is not type linked to the variable's index\r
1658char *DWARFManager_GetGlobalVariableTypeName(size_t Index)\r
1659{\r
1660 for (size_t i = 0; i < NbCU; i++)\r
1661 {\r
1662 if (PtrCU[i].NbVariables)\r
1663 {\r
1664 if (Index <= PtrCU[i].NbVariables)\r
1665 {\r
1666 return PtrCU[i].PtrVariables[Index - 1].PtrTypeName;\r
1667 }\r
1668 else\r
1669 {\r
1670 Index -= PtrCU[i].NbVariables;\r
1671 }\r
1672 }\r
1673 }\r
1674\r
1675 return NULL;\r
1676}\r
1677\r
1678\r
1679// Get global variable's type tag based on his index (starting from 1)\r
1680// Return 0 if not found\r
1681size_t DWARFManager_GetGlobalVariableTypeTag(size_t Index)\r
1682{\r
1683 for (size_t i = 0; i < NbCU; i++)\r
1684 {\r
1685 if (PtrCU[i].NbVariables)\r
1686 {\r
1687 if (Index <= PtrCU[i].NbVariables)\r
1688 {\r
1689 return PtrCU[i].PtrVariables[Index - 1].TypeTag;\r
1690 }\r
1691 else\r
1692 {\r
1693 Index -= PtrCU[i].NbVariables;\r
1694 }\r
1695 }\r
1696 }\r
1697\r
1698 return 0;\r
1699}\r
1700\r
1701\r
1702// Get global variable byte size based on his index (starting from 1)\r
1703// Return 0 if not found\r
1704size_t DWARFManager_GetGlobalVariableTypeByteSize(size_t Index)\r
1705{\r
1706 for (size_t i = 0; i < NbCU; i++)\r
1707 {\r
1708 if (PtrCU[i].NbVariables)\r
1709 {\r
1710 if (Index <= PtrCU[i].NbVariables)\r
1711 {\r
1712 return PtrCU[i].PtrVariables[Index - 1].TypeByteSize;\r
1713 }\r
1714 else\r
1715 {\r
1716 Index -= PtrCU[i].NbVariables;\r
1717 }\r
1718 }\r
1719 }\r
1720\r
1721 return 0;\r
1722}\r
1723\r
1724\r
1725// Get global variable encoding based on his index (starting from 1)\r
1726// Return 0 if not found\r
1727size_t DWARFManager_GetGlobalVariableTypeEncoding(size_t Index)\r
1728{\r
1729 for (size_t i = 0; i < NbCU; i++)\r
1730 {\r
1731 if (PtrCU[i].NbVariables)\r
1732 {\r
1733 if (Index <= PtrCU[i].NbVariables)\r
1734 {\r
1735 return PtrCU[i].PtrVariables[Index - 1].TypeEncoding;\r
1736 }\r
1737 else\r
1738 {\r
1739 Index -= PtrCU[i].NbVariables;\r
1740 }\r
1741 }\r
1742 }\r
1743\r
1744 return 0;\r
1745}\r
1746\r
1747\r
1748// Get global variable memory address based on his index (starting from 1)\r
1749// Return 0 if not found\r
1750size_t DWARFManager_GetGlobalVariableAdr(size_t Index)\r
1751{\r
1752 for (size_t i = 0; i < NbCU; i++)\r
1753 {\r
1754 if (PtrCU[i].NbVariables)\r
1755 {\r
1756 if (Index <= PtrCU[i].NbVariables)\r
1757 {\r
1758 return PtrCU[i].PtrVariables[Index - 1].Addr;\r
1759 }\r
1760 else\r
1761 {\r
1762 Index -= PtrCU[i].NbVariables;\r
1763 }\r
1764 }\r
1765 }\r
1766\r
1767 return 0;\r
1768}\r
1769\r
1770\r
1771// Get global variable memory address based on his name\r
1772// Return 0 if not found, or will return the first occurence found\r
1773size_t DWARFManager_GetGlobalVariableAdrFromName(char *VariableName)\r
1774{\r
1775 for (size_t i = 0; i < NbCU; i++)\r
1776 {\r
1777 if (PtrCU[i].NbVariables)\r
1778 {\r
1779 for (size_t j = 0; j < PtrCU[i].NbVariables; j++)\r
1780 {\r
1781 if (!strcmp(PtrCU[i].PtrVariables[j].PtrName,VariableName))\r
1782 {\r
1783 return PtrCU[i].PtrVariables[j].Addr;\r
1784 }\r
1785 }\r
1786 }\r
1787 }\r
1788\r
1789 return 0;\r
1790}\r
1791\r
1792\r
1793// Get global variable name based on his index (starting from 1)\r
1794// Return name's pointer text found, or will return NULL if no variable can be found\r
1795char *DWARFManager_GetGlobalVariableName(size_t Index)\r
1796{\r
1797 for (size_t i = 0; i < NbCU; i++)\r
1798 {\r
1799 if (PtrCU[i].NbVariables)\r
1800 {\r
1801 if (Index <= PtrCU[i].NbVariables)\r
1802 {\r
1803 return PtrCU[i].PtrVariables[Index - 1].PtrName;\r
1804 }\r
1805 else\r
1806 {\r
1807 Index -= PtrCU[i].NbVariables;\r
1808 }\r
1809 }\r
1810 }\r
1811\r
1812 return NULL;\r
1813}\r
1814\r
1815\r
1816// Get text line from source based on address and his tag\r
1817// A tag can be either 0 or a DW_TAG_subprogram\r
1818// DW_TAG_subprogram will look for the line pointing to the function\r
1819// Return NULL if no text line has been found\r
1820char *DWARFManager_GetLineSrcFromAdr(size_t Adr, size_t Tag)\r
1821{\r
1822 for (size_t i = 0; i < NbCU; i++)\r
1823 {\r
1824 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
1825 {\r
1826 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
1827 {\r
1828 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
1829 {\r
1830 if ((PtrCU[i].PtrSubProgs[j].StartPC == Adr) && (!Tag || (Tag == DW_TAG_subprogram)))\r
1831 {\r
1832 return PtrCU[i].PtrSubProgs[j].PtrLineSrc;\r
1833 }\r
1834 else\r
1835 {\r
1836 for (size_t k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++)\r
1837 {\r
1838 if (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC <= Adr)\r
1839 {\r
1840 if ((PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC == Adr) && (!Tag || (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].Tag == Tag)))\r
1841 {\r
1842 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc;\r
1843 }\r
1844 }\r
1845 else\r
1846 {\r
1847 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k - 1].PtrLineSrc;\r
1848 }\r
1849 }\r
1850 }\r
1851 }\r
1852 }\r
1853 }\r
1854 }\r
1855\r
1856 return NULL;\r
1857}\r
1858\r
1859\r
1860// Get line number based on the address and a tag\r
1861// A tag can be either 0 or a DW_TAG_subprogram\r
1862// DW_TAG_subprogram will look for the line pointing to the function name as described in the source code\r
1863// Return 0 if no line number has been found\r
1864size_t DWARFManager_GetNumLineFromAdr(size_t Adr, size_t Tag)\r
1865{\r
1866 for (size_t i = 0; i < NbCU; i++)\r
1867 {\r
1868 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
1869 {\r
1870 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
1871 {\r
1872 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
1873 {\r
1874 if ((PtrCU[i].PtrSubProgs[j].StartPC == Adr) && (!Tag || (Tag == DW_TAG_subprogram)))\r
1875 {\r
1876 return PtrCU[i].PtrSubProgs[j].NumLineSrc;\r
1877 }\r
1878 else\r
1879 {\r
1880 for (size_t k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++)\r
1881 {\r
1882 if ((PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC == Adr) && (!Tag || (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].Tag == Tag)))\r
1883 {\r
1884 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc;\r
1885 }\r
1886 }\r
1887 }\r
1888#if 0\r
1889 if (!Tag || (Tag == DW_TAG_subprogram))\r
1890 {\r
1891 return PtrCU[i].PtrSubProgs[j].NumLineSrc;\r
1892 }\r
1893#endif\r
1894 }\r
1895 }\r
1896\r
1897 // Check if a used line is found with the address\r
1898 for (size_t j = 0; j < PtrCU[i].NbUsedLinesSrc; j++)\r
1899 {\r
1900 if (PtrCU[i].PtrUsedLinesSrc[j].StartPC == Adr)\r
1901 {\r
1902 return PtrCU[i].PtrUsedLinesSrc[j].NumLineSrc;\r
1903 }\r
1904 }\r
1905 }\r
1906 }\r
1907\r
1908 return 0;\r
1909}\r
1910\r
1911\r
1912// Get function name based on an address\r
1913// Return NULL if no function name has been found, otherwise will return the function name in the range of the provided address\r
1914char *DWARFManager_GetFunctionName(size_t Adr)\r
1915{\r
1916 for (size_t i = 0; i < NbCU; i++)\r
1917 {\r
1918 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
1919 {\r
1920 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
1921 {\r
1922 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
1923 {\r
1924 return PtrCU[i].PtrSubProgs[j].PtrSubprogramName;\r
1925 }\r
1926 }\r
1927 }\r
1928 }\r
1929\r
1930 return NULL;\r
1931}\r
1932\r
1933\r
1934// Get number of lines of texts source list from source index\r
1935size_t DWARFManager_GetSrcNbListPtrFromIndex(size_t Index, bool Used)\r
1936{\r
1937 if (!Used)\r
1938 {\r
1939 return PtrCU[Index].NbLinesLoadSrc;\r
1940 }\r
1941 else\r
1942 {\r
1943 return PtrCU[Index].NbUsedLinesSrc;\r
1944 }\r
1945}\r
1946\r
1947\r
1948// Get text source line number list pointer from source index\r
1949// Return NULL for the text source used list \r
1950size_t *DWARFManager_GetSrcNumLinesPtrFromIndex(size_t Index, bool Used)\r
1951{\r
1952 if (Used)\r
1953 {\r
1954 return PtrCU[Index].PtrUsedNumLines;\r
1955 }\r
1956 else\r
1957 {\r
1958 return NULL;\r
1959 }\r
1960}\r
1961\r
1962\r
1963// Get text source list pointers from source index\r
1964// Return NULL for the text source used list \r
1965char **DWARFManager_GetSrcListPtrFromIndex(size_t Index, bool Used)\r
1966{\r
1967 if (!Used)\r
1968 {\r
1969 return PtrCU[Index].PtrLinesLoadSrc;\r
1970 }\r
1971 else\r
1972 {\r
1973 return PtrCU[Index].PtrUsedLinesLoadSrc;\r
1974 }\r
1975}\r
1976\r
1977\r
1978// Get source language\r
1979size_t DWARFManager_GetSrcLanguageFromIndex(size_t Index)\r
1980{\r
1981 return PtrCU[Index].Language;\r
1982}\r
1983\r
1984\r
1985// Get text line from source based on address and num line (starting from 1)\r
1986// Return NULL if no text line has been found\r
1987char *DWARFManager_GetLineSrcFromAdrNumLine(size_t Adr, size_t NumLine)\r
1988{\r
1989 for (size_t i = 0; i < NbCU; i++)\r
1990 {\r
1991 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
1992 {\r
1993 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)\r
1994 {\r
1995 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))\r
1996 {\r
1997 if (PtrCU[i].PtrSubProgs[j].NumLineSrc == NumLine)\r
1998 {\r
1999 return PtrCU[i].PtrSubProgs[j].PtrLineSrc;\r
2000 }\r
2001 else\r
2002 {\r
2003 for (size_t k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++)\r
2004 {\r
2005 if (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc == NumLine)\r
2006 {\r
2007 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc;\r
2008 }\r
2009 }\r
2010 }\r
2011 }\r
2012 }\r
2013 }\r
2014 }\r
2015\r
2016 return NULL;\r
2017}\r
2018\r
2019\r
2020// Get text line pointer from source, based on address and line number (starting from 1)\r
2021// Return NULL if no text line has been found, or if requested number line is above the source total number of lines\r
2022char *DWARFManager_GetLineSrcFromNumLineBaseAdr(size_t Adr, size_t NumLine)\r
2023{\r
2024 for (size_t i = 0; i < NbCU; i++)\r
2025 {\r
2026 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))\r
2027 {\r
2028 if (NumLine <= PtrCU[i].NbLinesLoadSrc)\r
2029 {\r
2030 return PtrCU[i].PtrLinesLoadSrc[NumLine - 1];\r
2031 }\r
2032 else\r
2033 {\r
2034 return NULL;\r
2035 }\r
2036 }\r
2037 }\r
2038\r
2039 return NULL;\r
2040}\r
2041\r
2042\r
2043// Get number of source code filenames\r
2044size_t DWARFManager_GetNbSources(void)\r
2045{\r
2046 return NbCU;\r
2047}\r
2048\r
2049\r
2050// Get source code filename, including his directory, based on index (starting from 0)\r
2051char *DWARFManager_GetNumFullSourceFilename(size_t Index)\r
2052{\r
2053 return (PtrCU[Index].PtrFullFilename);\r
2054}\r
2055\r
2056\r
2057// Get source code filename based on index (starting from 0)\r
2058char *DWARFManager_GetNumSourceFilename(size_t Index)\r
2059{\r
2060 return (PtrCU[Index].PtrSourceFilename);\r
2061}\r
2062\r