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