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