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