4ff8abbbd963d9865f695b4faaa17e63092af11d
[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 0x9 // 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 strcat(PtrVariables->PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);
1192 }
1193 if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))
1194 {
1195 j = -1;
1196 }
1197 else
1198 {
1199 if ((PtrVariables->TypeTag & TypeTag_pointer))
1200 {
1201 strcat(PtrVariables->PtrTypeName, " *");
1202 }
1203 }
1204 break;
1205
1206 // Pointer type tag
1207 case DW_TAG_pointer_type:
1208 PtrVariables->TypeTag |= TypeTag_pointer;
1209 PtrVariables->TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;
1210 PtrVariables->TypeEncoding = 0x10;
1211 if (!(TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))
1212 {
1213 strcat(PtrVariables->PtrTypeName, "void *");
1214 }
1215 else
1216 {
1217 j = -1;
1218 }
1219 break;
1220
1221 case DW_TAG_enumeration_type:
1222 PtrVariables->TypeTag |= TypeTag_enumeration_type;
1223 PtrVariables->TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;
1224 if (!(PtrVariables->TypeEncoding = PtrCU[NbCU].PtrTypes[j].Encoding))
1225 {
1226 // Try to determine the possible size
1227 switch (PtrVariables->TypeByteSize)
1228 {
1229 case 4:
1230 PtrVariables->TypeEncoding = 0x7;
1231 break;
1232
1233 default:
1234 break;
1235 }
1236 }
1237 break;
1238
1239 // Typedef type tag
1240 case DW_TAG_typedef:
1241 if (!(PtrVariables->TypeTag & TypeTag_typedef))
1242 {
1243 PtrVariables->TypeTag |= TypeTag_typedef;
1244 strcat(PtrVariables->PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);
1245 }
1246 if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))
1247 {
1248 j = -1;
1249 }
1250 break;
1251
1252 // ? type tag
1253 case DW_TAG_subrange_type:
1254 PtrVariables->TypeTag |= TypeTag_subrange;
1255 break;
1256
1257 // Array type tag
1258 case DW_TAG_array_type:
1259 PtrVariables->TypeTag |= TypeTag_arraytype;
1260 if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))
1261 {
1262 j = -1;
1263 }
1264 break;
1265
1266 // Const type tag
1267 case DW_TAG_const_type:
1268 PtrVariables->TypeTag |= TypeTag_consttype;
1269 strcat(PtrVariables->PtrTypeName, "const ");
1270 if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))
1271 {
1272 j = -1;
1273 }
1274 break;
1275
1276 // Base type tag
1277 case DW_TAG_base_type:
1278 if (!(PtrVariables->TypeTag & TypeTag_typedef))
1279 {
1280 strcat(PtrVariables->PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);
1281 }
1282 if ((PtrVariables->TypeTag & TypeTag_pointer))
1283 {
1284 strcat(PtrVariables->PtrTypeName, " *");
1285 }
1286 else
1287 {
1288 PtrVariables->TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;
1289 PtrVariables->TypeEncoding = PtrCU[NbCU].PtrTypes[j].Encoding;
1290 }
1291 if ((PtrVariables->TypeTag & TypeTag_arraytype))
1292 {
1293 strcat(PtrVariables->PtrTypeName, "[]");
1294 }
1295 break;
1296
1297 default:
1298 break;
1299 }
1300 }
1301 }
1302 }
1303 }
1304
1305
1306 // Get symbol name based from address
1307 // Return NULL if no symbol name exists
1308 char *DWARFManager_GetSymbolnameFromAdr(size_t Adr)
1309 {
1310 for (size_t i = 0; i < NbCU; i++)
1311 {
1312 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1313 {
1314 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1315 {
1316 if ((PtrCU[i].PtrSubProgs[j].StartPC == Adr))
1317 {
1318 return PtrCU[i].PtrSubProgs[j].PtrSubprogramName;
1319 }
1320 }
1321 }
1322 }
1323
1324 return NULL;
1325 }
1326
1327
1328 // Get complete source filename based from address
1329 // Return NULL if no source filename exists
1330 // Return the existence status (true or false) in Error
1331 char *DWARFManager_GetFullSourceFilenameFromAdr(size_t Adr, bool *Error)
1332 {
1333 for (size_t i = 0; i < NbCU; i++)
1334 {
1335 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1336 {
1337 *Error = PtrCU[i].PtrLoadSrc ? true : false;
1338 return PtrCU[i].PtrFullFilename;
1339 }
1340 }
1341
1342 return NULL;
1343 }
1344
1345
1346 // Get text line source based on line number (starting from 1)
1347 // Return NULL if no text line exists or if line number is 0
1348 char *DWARFManager_GetLineSrcFromNumLine(char *PtrSrcFile, size_t NumLine)
1349 {
1350 size_t i = 0;
1351 char *PtrLineSrc = NULL;
1352
1353 if (PtrSrcFile)
1354 {
1355 while (i != NumLine)
1356 {
1357 PtrLineSrc = PtrSrcFile;
1358 while (*PtrSrcFile++);
1359 i++;
1360 }
1361 }
1362
1363 return PtrLineSrc;
1364 }
1365
1366
1367 // Get number of variables referenced by the function range address
1368 size_t DWARFManager_GetNbLocalVariables(size_t Adr)
1369 {
1370 for (size_t i = 0; i < NbCU; i++)
1371 {
1372 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1373 {
1374 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1375 {
1376 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1377 {
1378 return PtrCU[i].PtrSubProgs[j].NbVariables;
1379 }
1380 }
1381 }
1382 }
1383
1384 return 0;
1385 }
1386
1387
1388 // Get local variable name based on his index (starting from 1)
1389 // Return name's pointer text found
1390 // Return NULL if not found
1391 char *DWARFManager_GetLocalVariableName(size_t Adr, size_t Index)
1392 {
1393 for (size_t i = 0; i < NbCU; i++)
1394 {
1395 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1396 {
1397 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1398 {
1399 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1400 {
1401 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].PtrName;
1402 }
1403 }
1404 }
1405 }
1406
1407 return NULL;
1408 }
1409
1410
1411 // Get local variable's type tag based on his index (starting from 1)
1412 // Return 0 if not found
1413 size_t DWARFManager_GetLocalVariableTypeTag(size_t Adr, size_t Index)
1414 {
1415 for (size_t i = 0; i < NbCU; i++)
1416 {
1417 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1418 {
1419 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1420 {
1421 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1422 {
1423 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].TypeTag;
1424 }
1425 }
1426 }
1427 }
1428
1429 return 0;
1430 }
1431
1432
1433 // Get the local variable's offset based on a index (starting from 1)
1434 // Return 0 if no offset has been found
1435 int DWARFManager_GetLocalVariableOffset(size_t Adr, size_t Index)
1436 {
1437 for (size_t i = 0; i < NbCU; i++)
1438 {
1439 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1440 {
1441 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1442 {
1443 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1444 {
1445 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].Offset;
1446 }
1447 }
1448 }
1449 }
1450
1451 return 0;
1452 }
1453
1454
1455 // Get local variable Type Byte Size based on his address and index (starting from 1)
1456 // Return 0 if not found
1457 // May return 0 if there is no Type Byte Size linked to the variable's address and index
1458 size_t DWARFManager_GetLocalVariableTypeByteSize(size_t Adr, size_t Index)
1459 {
1460 for (size_t i = 0; i < NbCU; i++)
1461 {
1462 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1463 {
1464 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1465 {
1466 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1467 {
1468 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].TypeByteSize;
1469 }
1470 }
1471 }
1472 }
1473
1474 return 0;
1475 }
1476
1477
1478 // Get local variable Type Encoding based on his address and index (starting from 1)
1479 // Return 0 if not found
1480 // May return 0 if there is no Type Encoding linked to the variable's address and index
1481 size_t DWARFManager_GetLocalVariableTypeEncoding(size_t Adr, size_t Index)
1482 {
1483 for (size_t i = 0; i < NbCU; i++)
1484 {
1485 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1486 {
1487 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1488 {
1489 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1490 {
1491 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].TypeEncoding;
1492 }
1493 }
1494 }
1495 }
1496
1497 return 0;
1498 }
1499
1500
1501 // Get local variable Op based on his address and index (starting from 1)
1502 // Return 0 if not found, may return 0 if there isn't Op linked to the variable's index
1503 size_t DWARFManager_GetLocalVariableOp(size_t Adr, size_t Index)
1504 {
1505 for (size_t i = 0; i < NbCU; i++)
1506 {
1507 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1508 {
1509 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1510 {
1511 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1512 {
1513 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].Op;
1514 }
1515 }
1516 }
1517 }
1518
1519 return 0;
1520 }
1521
1522
1523 // Get local variable type name based on his index (starting from 1) and an address
1524 // Return NULL if not found, may also return NULL if there is no type linked to the variable's index
1525 char *DWARFManager_GetLocalVariableTypeName(size_t Adr, size_t Index)
1526 {
1527 for (size_t i = 0; i < NbCU; i++)
1528 {
1529 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1530 {
1531 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1532 {
1533 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1534 {
1535 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].PtrTypeName;
1536 }
1537 }
1538 }
1539 }
1540
1541 return NULL;
1542 }
1543
1544
1545 // Get Compilation Unit / global variables numbers
1546 // Return number of variables
1547 size_t DWARFManager_GetNbGlobalVariables(void)
1548 {
1549 size_t NbVariables = 0;
1550
1551 for (size_t i = 0; i < NbCU; i++)
1552 {
1553 NbVariables += PtrCU[i].NbVariables;
1554 }
1555
1556 return NbVariables;
1557 }
1558
1559
1560 // Get global variable type name based on his index (starting from 1)
1561 // Return NULL if not found
1562 // May return NULL if there is not type linked to the variable's index
1563 char *DWARFManager_GetGlobalVariableTypeName(size_t Index)
1564 {
1565 for (size_t i = 0; i < NbCU; i++)
1566 {
1567 if (PtrCU[i].NbVariables)
1568 {
1569 if (Index <= PtrCU[i].NbVariables)
1570 {
1571 return PtrCU[i].PtrVariables[Index - 1].PtrTypeName;
1572 }
1573 else
1574 {
1575 Index -= PtrCU[i].NbVariables;
1576 }
1577 }
1578 }
1579
1580 return NULL;
1581 }
1582
1583
1584 // Get global variable's type tag based on his index (starting from 1)
1585 // Return 0 if not found
1586 size_t DWARFManager_GetGlobalVariableTypeTag(size_t Index)
1587 {
1588 for (size_t i = 0; i < NbCU; i++)
1589 {
1590 if (PtrCU[i].NbVariables)
1591 {
1592 if (Index <= PtrCU[i].NbVariables)
1593 {
1594 return PtrCU[i].PtrVariables[Index - 1].TypeTag;
1595 }
1596 else
1597 {
1598 Index -= PtrCU[i].NbVariables;
1599 }
1600 }
1601 }
1602
1603 return 0;
1604 }
1605
1606
1607 // Get global variable byte size based on his index (starting from 1)
1608 // Return 0 if not found
1609 size_t DWARFManager_GetGlobalVariableTypeByteSize(size_t Index)
1610 {
1611 for (size_t i = 0; i < NbCU; i++)
1612 {
1613 if (PtrCU[i].NbVariables)
1614 {
1615 if (Index <= PtrCU[i].NbVariables)
1616 {
1617 return PtrCU[i].PtrVariables[Index - 1].TypeByteSize;
1618 }
1619 else
1620 {
1621 Index -= PtrCU[i].NbVariables;
1622 }
1623 }
1624 }
1625
1626 return 0;
1627 }
1628
1629
1630 // Get global variable encoding based on his index (starting from 1)
1631 // Return 0 if not found
1632 size_t DWARFManager_GetGlobalVariableTypeEncoding(size_t Index)
1633 {
1634 for (size_t i = 0; i < NbCU; i++)
1635 {
1636 if (PtrCU[i].NbVariables)
1637 {
1638 if (Index <= PtrCU[i].NbVariables)
1639 {
1640 return PtrCU[i].PtrVariables[Index - 1].TypeEncoding;
1641 }
1642 else
1643 {
1644 Index -= PtrCU[i].NbVariables;
1645 }
1646 }
1647 }
1648
1649 return 0;
1650 }
1651
1652
1653 // Get global variable memory address based on his index (starting from 1)
1654 // Return 0 if not found
1655 size_t DWARFManager_GetGlobalVariableAdr(size_t Index)
1656 {
1657 for (size_t i = 0; i < NbCU; i++)
1658 {
1659 if (PtrCU[i].NbVariables)
1660 {
1661 if (Index <= PtrCU[i].NbVariables)
1662 {
1663 return PtrCU[i].PtrVariables[Index - 1].Addr;
1664 }
1665 else
1666 {
1667 Index -= PtrCU[i].NbVariables;
1668 }
1669 }
1670 }
1671
1672 return 0;
1673 }
1674
1675
1676 // Get global variable memory address based on his name
1677 // Return 0 if not found, or will return the first occurence found
1678 size_t DWARFManager_GetGlobalVariableAdrFromName(char *VariableName)
1679 {
1680 for (size_t i = 0; i < NbCU; i++)
1681 {
1682 if (PtrCU[i].NbVariables)
1683 {
1684 for (size_t j = 0; j < PtrCU[i].NbVariables; j++)
1685 {
1686 if (!strcmp(PtrCU[i].PtrVariables[j].PtrName,VariableName))
1687 {
1688 return PtrCU[i].PtrVariables[j].Addr;
1689 }
1690 }
1691 }
1692 }
1693
1694 return 0;
1695 }
1696
1697
1698 // Get global variable name based on his index (starting from 1)
1699 // Return name's pointer text found, or will return NULL if no variable can be found
1700 char *DWARFManager_GetGlobalVariableName(size_t Index)
1701 {
1702 for (size_t i = 0; i < NbCU; i++)
1703 {
1704 if (PtrCU[i].NbVariables)
1705 {
1706 if (Index <= PtrCU[i].NbVariables)
1707 {
1708 return PtrCU[i].PtrVariables[Index - 1].PtrName;
1709 }
1710 else
1711 {
1712 Index -= PtrCU[i].NbVariables;
1713 }
1714 }
1715 }
1716
1717 return NULL;
1718 }
1719
1720
1721 // Get text line from source based on address and his tag
1722 // A tag can be either 0 or a DW_TAG_subprogram
1723 // DW_TAG_subprogram will look for the line pointing to the function
1724 // Return NULL if no text line has been found
1725 char *DWARFManager_GetLineSrcFromAdr(size_t Adr, size_t Tag)
1726 {
1727 for (size_t i = 0; i < NbCU; i++)
1728 {
1729 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1730 {
1731 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1732 {
1733 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1734 {
1735 if ((PtrCU[i].PtrSubProgs[j].StartPC == Adr) && (!Tag || (Tag == DW_TAG_subprogram)))
1736 {
1737 return PtrCU[i].PtrSubProgs[j].PtrLineSrc;
1738 }
1739 else
1740 {
1741 for (size_t k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++)
1742 {
1743 if (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC <= Adr)
1744 {
1745 if ((PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC == Adr) && (!Tag || (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].Tag == Tag)))
1746 {
1747 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc;
1748 }
1749 }
1750 else
1751 {
1752 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k - 1].PtrLineSrc;
1753 }
1754 }
1755 }
1756 }
1757 }
1758 }
1759 }
1760
1761 return NULL;
1762 }
1763
1764
1765 // Get line number based on the address and a tag
1766 // A tag can be either 0 or a DW_TAG_subprogram
1767 // DW_TAG_subprogram will look for the line pointing to the function name as described in the source code
1768 // Return 0 if no line number has been found
1769 size_t DWARFManager_GetNumLineFromAdr(size_t Adr, size_t Tag)
1770 {
1771 for (size_t i = 0; i < NbCU; i++)
1772 {
1773 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1774 {
1775 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1776 {
1777 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1778 {
1779 if ((PtrCU[i].PtrSubProgs[j].StartPC == Adr) && (!Tag || (Tag == DW_TAG_subprogram)))
1780 {
1781 return PtrCU[i].PtrSubProgs[j].NumLineSrc;
1782 }
1783 else
1784 {
1785 for (size_t k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++)
1786 {
1787 if ((PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC == Adr) && (!Tag || (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].Tag == Tag)))
1788 {
1789 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc;
1790 }
1791 }
1792 }
1793 #if 0
1794 if (!Tag || (Tag == DW_TAG_subprogram))
1795 {
1796 return PtrCU[i].PtrSubProgs[j].NumLineSrc;
1797 }
1798 #endif
1799 }
1800 }
1801
1802 // Check if a used line is found with the address
1803 for (size_t j = 0; j < PtrCU[i].NbLinesSrc; j++)
1804 {
1805 if (PtrCU[i].PtrLinesSrc[j].StartPC == Adr)
1806 {
1807 return PtrCU[i].PtrLinesSrc[j].NumLineSrc;
1808 }
1809 }
1810 }
1811 }
1812
1813 return 0;
1814 }
1815
1816
1817 // Get function name based on an address
1818 // Return NULL if no function name has been found, otherwise will return the function name in the range of the provided address
1819 char *DWARFManager_GetFunctionName(size_t Adr)
1820 {
1821 for (size_t i = 0; i < NbCU; i++)
1822 {
1823 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1824 {
1825 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1826 {
1827 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1828 {
1829 return PtrCU[i].PtrSubProgs[j].PtrSubprogramName;
1830 }
1831 }
1832 }
1833 }
1834
1835 return NULL;
1836 }
1837
1838
1839 // Get text line from source based on address and num line (starting from 1)
1840 // Return NULL if no text line has been found
1841 char *DWARFManager_GetLineSrcFromAdrNumLine(size_t Adr, size_t NumLine)
1842 {
1843 for (size_t i = 0; i < NbCU; i++)
1844 {
1845 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1846 {
1847 for (size_t j = 0; j < PtrCU[i].NbSubProgs; j++)
1848 {
1849 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1850 {
1851 if (PtrCU[i].PtrSubProgs[j].NumLineSrc == NumLine)
1852 {
1853 return PtrCU[i].PtrSubProgs[j].PtrLineSrc;
1854 }
1855 else
1856 {
1857 for (size_t k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++)
1858 {
1859 if (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc == NumLine)
1860 {
1861 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc;
1862 }
1863 }
1864 }
1865 }
1866 }
1867 }
1868 }
1869
1870 return NULL;
1871 }
1872
1873
1874 // Get text line pointer from source, based on address and line number (starting from 1)
1875 // Return NULL if no text line has been found, or if requested number line is above the source total number of lines
1876 char *DWARFManager_GetLineSrcFromNumLineBaseAdr(size_t Adr, size_t NumLine)
1877 {
1878 for (size_t i = 0; i < NbCU; i++)
1879 {
1880 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1881 {
1882 if (NumLine <= PtrCU[i].NbLinesLoadSrc)
1883 {
1884 return PtrCU[i].PtrLinesLoadSrc[NumLine - 1];
1885 }
1886 else
1887 {
1888 return NULL;
1889 }
1890 }
1891 }
1892
1893 return NULL;
1894 }
1895
1896
1897 // Get number of source code filenames
1898 size_t DWARFManager_GetNbFullSourceFilename(void)
1899 {
1900 return NbCU;
1901 }
1902
1903
1904 // Get source code filename based on index (starting from 0)
1905 char *DWARFManager_GetNumFullSourceFilename(size_t Index)
1906 {
1907 return (PtrCU[Index].PtrFullFilename);
1908 }
1909