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