Fix a random crash when reading the source lines information
[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
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 *Error = PtrCU[i].PtrLoadSrc ? true : false;
1333 return PtrCU[i].PtrFullFilename;
1334 }
1335 }
1336
1337 return NULL;
1338 }
1339
1340
1341 // Get text line source based on line number (starting from 1)
1342 // Return NULL if no text line exists or if line number is 0
1343 char *DWARFManager_GetLineSrcFromNumLine(char *PtrSrcFile, size_t NumLine)
1344 {
1345 size_t i = 0;
1346 char *PtrLineSrc = NULL;
1347
1348 if (PtrSrcFile)
1349 {
1350 while (i != NumLine)
1351 {
1352 PtrLineSrc = PtrSrcFile;
1353 while (*PtrSrcFile++);
1354 i++;
1355 }
1356 }
1357
1358 return PtrLineSrc;
1359 }
1360
1361
1362 // Get number of variables referenced by the function range address
1363 size_t DWARFManager_GetNbLocalVariables(size_t Adr)
1364 {
1365 for (size_t i = 0; i < NbCU; i++)
1366 {
1367 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1368 {
1369 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1370 {
1371 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1372 {
1373 return PtrCU[i].PtrSubProgs[j].NbVariables;
1374 }
1375 }
1376 }
1377 }
1378
1379 return 0;
1380 }
1381
1382
1383 // Get local variable name based on his index (starting from 1)
1384 // Return name's pointer text found
1385 // Return NULL if not found
1386 char *DWARFManager_GetLocalVariableName(size_t Adr, size_t Index)
1387 {
1388 for (size_t i = 0; i < NbCU; i++)
1389 {
1390 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1391 {
1392 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1393 {
1394 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1395 {
1396 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].PtrName;
1397 }
1398 }
1399 }
1400 }
1401
1402 return NULL;
1403 }
1404
1405
1406 // Get local variable's type tag based on his index (starting from 1)
1407 // Return 0 if not found
1408 size_t DWARFManager_GetLocalVariableTypeTag(size_t Adr, size_t Index)
1409 {
1410 for (size_t i = 0; i < NbCU; i++)
1411 {
1412 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1413 {
1414 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1415 {
1416 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1417 {
1418 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].TypeTag;
1419 }
1420 }
1421 }
1422 }
1423
1424 return 0;
1425 }
1426
1427
1428 // Get the local variable's offset based on a index (starting from 1)
1429 // Return 0 if no offset has been found
1430 int DWARFManager_GetLocalVariableOffset(size_t Adr, size_t Index)
1431 {
1432 for (size_t i = 0; i < NbCU; i++)
1433 {
1434 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1435 {
1436 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1437 {
1438 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1439 {
1440 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].Offset;
1441 }
1442 }
1443 }
1444 }
1445
1446 return 0;
1447 }
1448
1449
1450 // Get local variable Type Byte Size based on his address and index (starting from 1)
1451 // Return 0 if not found
1452 // May return 0 if there is no Type Byte Size linked to the variable's address and index
1453 size_t DWARFManager_GetLocalVariableTypeByteSize(size_t Adr, size_t Index)
1454 {
1455 for (size_t i = 0; i < NbCU; i++)
1456 {
1457 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1458 {
1459 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1460 {
1461 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1462 {
1463 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].TypeByteSize;
1464 }
1465 }
1466 }
1467 }
1468
1469 return 0;
1470 }
1471
1472
1473 // Get local variable Type Encoding based on his address and index (starting from 1)
1474 // Return 0 if not found
1475 // May return 0 if there is no Type Encoding linked to the variable's address and index
1476 size_t DWARFManager_GetLocalVariableTypeEncoding(size_t Adr, size_t Index)
1477 {
1478 for (size_t i = 0; i < NbCU; i++)
1479 {
1480 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1481 {
1482 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1483 {
1484 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1485 {
1486 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].TypeEncoding;
1487 }
1488 }
1489 }
1490 }
1491
1492 return 0;
1493 }
1494
1495
1496 // Get local variable Op based on his address and index (starting from 1)
1497 // Return 0 if not found, may return 0 if there isn't Op linked to the variable's index
1498 size_t DWARFManager_GetLocalVariableOp(size_t Adr, size_t Index)
1499 {
1500 for (size_t i = 0; i < NbCU; i++)
1501 {
1502 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1503 {
1504 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1505 {
1506 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1507 {
1508 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].Op;
1509 }
1510 }
1511 }
1512 }
1513
1514 return 0;
1515 }
1516
1517
1518 // Get local variable type name based on his index (starting from 1) and an address
1519 // Return NULL if not found, may also return NULL if there is no type linked to the variable's index
1520 char *DWARFManager_GetLocalVariableTypeName(size_t Adr, size_t Index)
1521 {
1522 for (size_t i = 0; i < NbCU; i++)
1523 {
1524 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1525 {
1526 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1527 {
1528 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1529 {
1530 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].PtrTypeName;
1531 }
1532 }
1533 }
1534 }
1535
1536 return NULL;
1537 }
1538
1539
1540 // Get Compilation Unit / global variables numbers
1541 // Return number of variables
1542 size_t DWARFManager_GetNbGlobalVariables(void)
1543 {
1544 size_t NbVariables = 0;
1545
1546 for (size_t i = 0; i < NbCU; i++)
1547 {
1548 NbVariables += PtrCU[i].NbVariables;
1549 }
1550
1551 return NbVariables;
1552 }
1553
1554
1555 // Get global variable type name based on his index (starting from 1)
1556 // Return NULL if not found
1557 // May return NULL if there is not type linked to the variable's index
1558 char *DWARFManager_GetGlobalVariableTypeName(size_t Index)
1559 {
1560 for (size_t i = 0; i < NbCU; i++)
1561 {
1562 if (PtrCU[i].NbVariables)
1563 {
1564 if (Index <= PtrCU[i].NbVariables)
1565 {
1566 return PtrCU[i].PtrVariables[Index - 1].PtrTypeName;
1567 }
1568 else
1569 {
1570 Index -= PtrCU[i].NbVariables;
1571 }
1572 }
1573 }
1574
1575 return NULL;
1576 }
1577
1578
1579 // Get global variable's type tag based on his index (starting from 1)
1580 // Return 0 if not found
1581 size_t DWARFManager_GetGlobalVariableTypeTag(size_t Index)
1582 {
1583 for (size_t i = 0; i < NbCU; i++)
1584 {
1585 if (PtrCU[i].NbVariables)
1586 {
1587 if (Index <= PtrCU[i].NbVariables)
1588 {
1589 return PtrCU[i].PtrVariables[Index - 1].TypeTag;
1590 }
1591 else
1592 {
1593 Index -= PtrCU[i].NbVariables;
1594 }
1595 }
1596 }
1597
1598 return 0;
1599 }
1600
1601
1602 // Get global variable byte size based on his index (starting from 1)
1603 // Return 0 if not found
1604 size_t DWARFManager_GetGlobalVariableTypeByteSize(size_t Index)
1605 {
1606 for (size_t i = 0; i < NbCU; i++)
1607 {
1608 if (PtrCU[i].NbVariables)
1609 {
1610 if (Index <= PtrCU[i].NbVariables)
1611 {
1612 return PtrCU[i].PtrVariables[Index - 1].TypeByteSize;
1613 }
1614 else
1615 {
1616 Index -= PtrCU[i].NbVariables;
1617 }
1618 }
1619 }
1620
1621 return 0;
1622 }
1623
1624
1625 // Get global variable encoding based on his index (starting from 1)
1626 // Return 0 if not found
1627 size_t DWARFManager_GetGlobalVariableTypeEncoding(size_t Index)
1628 {
1629 for (size_t i = 0; i < NbCU; i++)
1630 {
1631 if (PtrCU[i].NbVariables)
1632 {
1633 if (Index <= PtrCU[i].NbVariables)
1634 {
1635 return PtrCU[i].PtrVariables[Index - 1].TypeEncoding;
1636 }
1637 else
1638 {
1639 Index -= PtrCU[i].NbVariables;
1640 }
1641 }
1642 }
1643
1644 return 0;
1645 }
1646
1647
1648 // Get global variable memory address based on his index (starting from 1)
1649 // Return 0 if not found
1650 size_t DWARFManager_GetGlobalVariableAdr(size_t Index)
1651 {
1652 for (size_t i = 0; i < NbCU; i++)
1653 {
1654 if (PtrCU[i].NbVariables)
1655 {
1656 if (Index <= PtrCU[i].NbVariables)
1657 {
1658 return PtrCU[i].PtrVariables[Index - 1].Addr;
1659 }
1660 else
1661 {
1662 Index -= PtrCU[i].NbVariables;
1663 }
1664 }
1665 }
1666
1667 return 0;
1668 }
1669
1670
1671 // Get global variable memory address based on his name
1672 // Return 0 if not found, or will return the first occurence found
1673 size_t DWARFManager_GetGlobalVariableAdrFromName(char *VariableName)
1674 {
1675 for (size_t i = 0; i < NbCU; i++)
1676 {
1677 if (PtrCU[i].NbVariables)
1678 {
1679 for (size_t j = 0; j < PtrCU[i].NbVariables; j++)
1680 {
1681 if (!strcmp(PtrCU[i].PtrVariables[j].PtrName,VariableName))
1682 {
1683 return PtrCU[i].PtrVariables[j].Addr;
1684 }
1685 }
1686 }
1687 }
1688
1689 return 0;
1690 }
1691
1692
1693 // Get global variable name based on his index (starting from 1)
1694 // Return name's pointer text found, or will return NULL if no variable can be found
1695 char *DWARFManager_GetGlobalVariableName(size_t Index)
1696 {
1697 for (size_t i = 0; i < NbCU; i++)
1698 {
1699 if (PtrCU[i].NbVariables)
1700 {
1701 if (Index <= PtrCU[i].NbVariables)
1702 {
1703 return PtrCU[i].PtrVariables[Index - 1].PtrName;
1704 }
1705 else
1706 {
1707 Index -= PtrCU[i].NbVariables;
1708 }
1709 }
1710 }
1711
1712 return NULL;
1713 }
1714
1715
1716 // Get text line from source based on address and his tag
1717 // A tag can be either 0 or a DW_TAG_subprogram
1718 // DW_TAG_subprogram will look for the line pointing to the function
1719 // Return NULL if no text line has been found
1720 char *DWARFManager_GetLineSrcFromAdr(size_t Adr, size_t Tag)
1721 {
1722 for (size_t i = 0; i < NbCU; i++)
1723 {
1724 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1725 {
1726 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1727 {
1728 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1729 {
1730 if ((PtrCU[i].PtrSubProgs[j].StartPC == Adr) && (!Tag || (Tag == DW_TAG_subprogram)))
1731 {
1732 return PtrCU[i].PtrSubProgs[j].PtrLineSrc;
1733 }
1734 else
1735 {
1736 for (size_t k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++)
1737 {
1738 if (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC <= Adr)
1739 {
1740 if ((PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC == Adr) && (!Tag || (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].Tag == Tag)))
1741 {
1742 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc;
1743 }
1744 }
1745 else
1746 {
1747 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k - 1].PtrLineSrc;
1748 }
1749 }
1750 }
1751 }
1752 }
1753 }
1754 }
1755
1756 return NULL;
1757 }
1758
1759
1760 // Get line number based on the address and a tag
1761 // A tag can be either 0 or a DW_TAG_subprogram
1762 // DW_TAG_subprogram will look for the line pointing to the function name as described in the source code
1763 // Return 0 if no line number has been found
1764 size_t DWARFManager_GetNumLineFromAdr(size_t Adr, size_t Tag)
1765 {
1766 for (size_t i = 0; i < NbCU; i++)
1767 {
1768 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1769 {
1770 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1771 {
1772 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1773 {
1774 if ((PtrCU[i].PtrSubProgs[j].StartPC == Adr) && (!Tag || (Tag == DW_TAG_subprogram)))
1775 {
1776 return PtrCU[i].PtrSubProgs[j].NumLineSrc;
1777 }
1778 else
1779 {
1780 for (size_t k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++)
1781 {
1782 if ((PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC == Adr) && (!Tag || (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].Tag == Tag)))
1783 {
1784 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc;
1785 }
1786 }
1787 }
1788 #if 0
1789 if (!Tag || (Tag == DW_TAG_subprogram))
1790 {
1791 return PtrCU[i].PtrSubProgs[j].NumLineSrc;
1792 }
1793 #endif
1794 }
1795 }
1796
1797 // Check if a used line is found with the address
1798 for (size_t j = 0; j < PtrCU[i].NbLinesSrc; j++)
1799 {
1800 if (PtrCU[i].PtrLinesSrc[j].StartPC == Adr)
1801 {
1802 return PtrCU[i].PtrLinesSrc[j].NumLineSrc;
1803 }
1804 }
1805 }
1806 }
1807
1808 return 0;
1809 }
1810
1811
1812 // Get function name based on an address
1813 // Return NULL if no function name has been found, otherwise will return the function name in the range of the provided address
1814 char *DWARFManager_GetFunctionName(size_t Adr)
1815 {
1816 for (size_t i = 0; i < NbCU; i++)
1817 {
1818 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1819 {
1820 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1821 {
1822 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1823 {
1824 return PtrCU[i].PtrSubProgs[j].PtrSubprogramName;
1825 }
1826 }
1827 }
1828 }
1829
1830 return NULL;
1831 }
1832
1833
1834 // Get text line from source based on address and num line (starting from 1)
1835 // Return NULL if no text line has been found
1836 char *DWARFManager_GetLineSrcFromAdrNumLine(size_t Adr, size_t NumLine)
1837 {
1838 for (size_t i = 0; i < NbCU; i++)
1839 {
1840 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1841 {
1842 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1843 {
1844 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1845 {
1846 if (PtrCU[i].PtrSubProgs[j].NumLineSrc == NumLine)
1847 {
1848 return PtrCU[i].PtrSubProgs[j].PtrLineSrc;
1849 }
1850 else
1851 {
1852 for (size_t k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++)
1853 {
1854 if (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc == NumLine)
1855 {
1856 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc;
1857 }
1858 }
1859 }
1860 }
1861 }
1862 }
1863 }
1864
1865 return NULL;
1866 }
1867
1868
1869 // Get text line pointer from source, based on address and line number (starting from 1)
1870 // Return NULL if no text line has been found, or if requested number line is above the source total number of lines
1871 char *DWARFManager_GetLineSrcFromNumLineBaseAdr(size_t Adr, size_t NumLine)
1872 {
1873 for (size_t i = 0; i < NbCU; i++)
1874 {
1875 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1876 {
1877 if (NumLine <= PtrCU[i].NbLinesLoadSrc)
1878 {
1879 return PtrCU[i].PtrLinesLoadSrc[NumLine - 1];
1880 }
1881 else
1882 {
1883 return NULL;
1884 }
1885 }
1886 }
1887
1888 return NULL;
1889 }
1890
1891
1892 // Get number of source code filenames
1893 size_t DWARFManager_GetNbFullSourceFilename(void)
1894 {
1895 return NbCU;
1896 }
1897
1898
1899 // Get source code filename based on index (starting from 0)
1900 char *DWARFManager_GetNumFullSourceFilename(size_t Index)
1901 {
1902 return (PtrCU[Index].PtrFullFilename);
1903 }
1904