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