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