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