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