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