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