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