2 // DWARFManager.cpp: DWARF format manager
6 // JPM = Jean-Paul Mari <djipi.mari@gmail.com>
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
19 // To use pointers instead of arrays usage
28 #include <sys/types.h>
33 #include "DWARFManager.h"
36 // Definitions for debugging
37 //#define DEBUG_NumCU 0x3 // CU number to debug or undefine it
38 //#define DEBUG_VariableName "sound_death" // Variable name to look for or undefine it
39 //#define DEBUG_TypeName "Cbuf_Execute" // Type name to look for or undefine it
40 //#define DEBUG_TypeDef DW_TAG_typedef // Type def to look for or undefine it (not supported)
41 //#define DEBUG_Filename "crt0" // Filename to look for or undefine it
43 // Definitions for handling data
44 //#define CONVERT_QT_HML // Text will be converted as HTML
46 // Definitions for the variables's typetag
47 #define TypeTag_structure 0x01 // structure
48 #define TypeTag_pointer 0x02 // pointer
49 #define TypeTag_subrange 0x04 // (subrange_type?)
50 #define TypeTag_arraytype 0x08 // array type
51 #define TypeTag_consttype 0x10 // const type
52 #define TypeTag_typedef 0x20 // typedef
53 #define TypeTag_enumeration_type 0x40 // enumeration
54 #define TypeTag_subroutine_type 0x80 // subroutine
57 // Source line CU structure
58 typedef struct CUStruct_LineSrc
65 // Source line internal structure
66 typedef struct DMIStruct_LineSrc
74 // Enumeration structure
75 typedef struct EnumerationStruct
77 char *PtrName
; // Enumeration's name
78 size_t value
; // Enumeration's value
81 // Structure members structure
82 //typedef struct StructureMembersStruct
84 //}S_StructureMembersStruct;
86 // Base type internal structure
87 typedef struct BaseTypeStruct
89 size_t Tag
; // Type's Tag
90 size_t Offset
; // Type's offset
91 size_t TypeOffset
; // Type's offset on another type
92 size_t ByteSize
; // Type's Byte Size
93 size_t Encoding
; // Type's encoding
94 char *PtrName
; // Type's name
95 size_t NbEnumeration
; // Type's enumeration numbers
96 EnumerationStruct
*PtrEnumeration
; // Type's enumeration
97 // StructureMembersStruct *PtrStructureMembers; // Type's structure members
100 // Variables internal structure
101 typedef struct VariablesStruct
103 size_t Op
; // Variable's DW_OP
106 size_t Addr
; // Variable memory address
107 int Offset
; // Variable stack offset (signed)
109 char *PtrName
; // Variable's name
110 size_t TypeOffset
; // Offset pointing on the Variable's Type
111 size_t TypeByteSize
; // Variable's Type byte size
112 size_t TypeTag
; // Variable's Type Tag
113 size_t TypeEncoding
; // Variable's Type encoding
114 char *PtrTypeName
; // Variable's Type name
117 // Sub program internal structure
118 typedef struct SubProgStruct
123 size_t LowPC
, HighPC
;
126 char *PtrSubprogramName
; // Sub program name
127 size_t NbLinesSrc
; // Number of lines source used by the sub program
128 DMIStruct_LineSrc
*PtrLinesSrc
; // Pointer of the lines source for the sub program
129 size_t NbVariables
; // Variables number
130 VariablesStruct
*PtrVariables
; // Pointer to the local variables list information structure
133 // Compilation Unit internal structure
134 typedef struct CUStruct
137 size_t Language
; // Language (C, etc.) used by the source code
138 size_t LowPC
, HighPC
; // Memory range for the code
139 char *PtrProducer
; // "Producer" text information (mostly compiler and compilation options used)
140 char *PtrSourceFilename
; // Source file name
141 char *PtrSourceFileDirectory
; // Directory of the source file
142 char *PtrFullFilename
; // Pointer to full namefile (directory & filename)
143 size_t SizeLoadSrc
; // Source code text size
144 char *PtrLoadSrc
; // Pointer to the source code text
145 size_t NbLinesLoadSrc
; // Total number of lines in the source code text
146 char **PtrLinesLoadSrc
; // Pointer lists to each source line put in QT html/text conformity
147 size_t NbSubProgs
; // Number of sub programs / routines
148 SubProgStruct
*PtrSubProgs
; // Pointer to the sub programs / routines structure
149 size_t NbTypes
; // Number of types
150 BaseTypeStruct
*PtrTypes
; // Pointer to types
151 size_t NbVariables
; // Variables number
152 VariablesStruct
*PtrVariables
; // Pointer to the global variables list structure
153 size_t NbFrames
; // Frames number
154 size_t NbUsedLinesSrc
; // Number of used source lines
155 size_t LastNumUsedLinesSrc
; // Last number line used
156 CUStruct_LineSrc
*PtrUsedLinesSrc
; // Pointer to the used source lines list structure
157 char **PtrUsedLinesLoadSrc
; // Pointer lists to each used source line referenced by the CUStruct_LineSrc structure
158 size_t *PtrUsedNumLines
; // List of the number lines used
159 struct _stat _statbuf
; // File information
160 DWARFstatus Status
; // File status
171 char **ListSearchPaths
;
172 size_t NbSearchPaths
;
173 struct _stat FileElfExeInfo
;
177 Dwarf_Handler
DWARFManager_ErrorHandler(Dwarf_Ptr perrarg
);
178 void DWARFManager_InitDMI(void);
179 void DWARFManager_CloseDMI(void);
180 bool DWARFManager_ElfClose(void);
181 char *DWARFManager_GetLineSrcFromNumLine(char *PtrSrcFile
, size_t NumLine
);
182 void DWARFManager_InitInfosVariable(VariablesStruct
*PtrVariables
);
183 void DWARFManager_SourceFileSearchPathsInit(void);
184 void DWARFManager_SourceFileSearchPathsReset(void);
185 void DWARFManager_SourceFileSearchPathsClose(void);
186 void DWARFManager_ConformSlachesBackslashes(char *Ptr
);
190 Dwarf_Handler
DWARFManager_ErrorHandler(Dwarf_Ptr perrarg
)
196 // Dwarf manager list search paths init
197 void DWARFManager_SourceFileSearchPathsInit(void)
199 ListSearchPaths
= NULL
;
204 // Dwarf manager list search paths reset
205 void DWARFManager_SourceFileSearchPathsReset(void)
207 ListSearchPaths
= NULL
;
212 // Dwarf manager list search paths close
213 void DWARFManager_SourceFileSearchPathsClose(void)
215 DWARFManager_SourceFileSearchPathsReset();
219 // Dwarf manager init
220 void DWARFManager_Init(void)
222 DWARFManager_SourceFileSearchPathsInit();
223 LibDwarf
= DW_DLV_NO_ENTRY
;
227 // Dwarf manager settings
228 void DWARFManager_Set(size_t NbPathsInList
, char **PtrListPaths
)
231 ListSearchPaths
= PtrListPaths
;
232 NbSearchPaths
= NbPathsInList
;
236 // Dwarf manager Reset
237 bool DWARFManager_Reset(void)
239 DWARFManager_SourceFileSearchPathsReset();
240 return DWARFManager_ElfClose();
244 // Dwarf manager Close
245 bool DWARFManager_Close(void)
247 DWARFManager_SourceFileSearchPathsClose();
248 return(DWARFManager_Reset());
252 // Dwarf manager Elf init
253 int DWARFManager_ElfInit(Elf
*ElfPtr
, struct _stat FileElfInfo
)
255 if ((LibDwarf
= dwarf_elf_init(ElfPtr
, DW_DLC_READ
, (Dwarf_Handler
)DWARFManager_ErrorHandler
, errarg
, &dbg
, &error
)) == DW_DLV_OK
)
257 FileElfExeInfo
= FileElfInfo
;
258 DWARFManager_InitDMI();
265 // Dwarf manager Elf close
266 bool DWARFManager_ElfClose(void)
268 if (LibDwarf
== DW_DLV_OK
)
270 DWARFManager_CloseDMI();
272 if (dwarf_finish(dbg
, &error
) == DW_DLV_OK
)
274 LibDwarf
= DW_DLV_NO_ENTRY
;
289 // Dwarf manager Compilation Units close
290 void DWARFManager_CloseDMI(void)
294 free(PtrCU
[NbCU
].PtrFullFilename
);
295 free(PtrCU
[NbCU
].PtrLoadSrc
);
296 free(PtrCU
[NbCU
].PtrProducer
);
297 free(PtrCU
[NbCU
].PtrSourceFilename
);
298 free(PtrCU
[NbCU
].PtrSourceFileDirectory
);
299 free(PtrCU
[NbCU
].PtrUsedLinesSrc
);
300 free(PtrCU
[NbCU
].PtrUsedLinesLoadSrc
);
301 free(PtrCU
[NbCU
].PtrUsedNumLines
);
303 while (PtrCU
[NbCU
].NbLinesLoadSrc
--)
305 free(PtrCU
[NbCU
].PtrLinesLoadSrc
[PtrCU
[NbCU
].NbLinesLoadSrc
]);
307 free(PtrCU
[NbCU
].PtrLinesLoadSrc
);
309 while (PtrCU
[NbCU
].NbSubProgs
--)
311 while (PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].NbVariables
--)
313 free(PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].PtrVariables
[PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].NbVariables
].PtrName
);
314 free(PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].PtrVariables
[PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].NbVariables
].PtrTypeName
);
316 free(PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].PtrVariables
);
318 free(PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].PtrLinesSrc
);
319 free(PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].PtrSubprogramName
);
321 free(PtrCU
[NbCU
].PtrSubProgs
);
323 while (PtrCU
[NbCU
].NbTypes
--)
325 free(PtrCU
[NbCU
].PtrTypes
[PtrCU
[NbCU
].NbTypes
].PtrName
);
327 free(PtrCU
[NbCU
].PtrTypes
);
329 while (PtrCU
[NbCU
].NbVariables
--)
331 free(PtrCU
[NbCU
].PtrVariables
[PtrCU
[NbCU
].NbVariables
].PtrName
);
332 free(PtrCU
[NbCU
].PtrVariables
[PtrCU
[NbCU
].NbVariables
].PtrTypeName
);
334 free(PtrCU
[NbCU
].PtrVariables
);
341 // Dwarf manager Compilation Units initialisations
342 void DWARFManager_InitDMI(void)
344 Dwarf_Unsigned next_cu_header
, return_uvalue
;
346 Dwarf_Attribute
*atlist
;
347 Dwarf_Attribute return_attr1
;
348 Dwarf_Half return_tagval
, return_attr
;
349 Dwarf_Addr return_lowpc
, return_highpc
, return_lineaddr
;
350 Dwarf_Block
*return_block
;
351 Dwarf_Signed atcnt
, cnt
;
352 Dwarf_Die return_sib
, return_die
, return_sub
, return_subdie
;
353 Dwarf_Off return_offset
;
359 // Initialisation for the Compilation Units table
363 // loop on the available Compilation Unit
364 while (dwarf_next_cu_header(dbg
, NULL
, NULL
, NULL
, NULL
, &next_cu_header
, &error
) == DW_DLV_OK
)
366 // Allocation of an additional Compilation Unit structure in the table
367 if (Ptr
= (char *)realloc(PtrCU
, ((NbCU
+ 1) * sizeof(CUStruct
))))
369 // Compilation Unit RAZ
370 PtrCU
= (CUStruct
*)Ptr
;
371 memset(PtrCU
+ NbCU
, 0, sizeof(CUStruct
));
375 if (NbCU
== DEBUG_NumCU
)
378 // Get 1st Die from the Compilation Unit
379 if (dwarf_siblingof(dbg
, NULL
, &return_sib
, &error
) == DW_DLV_OK
)
382 if ((dwarf_tag(return_sib
, &return_tagval
, &error
) == DW_DLV_OK
))
384 PtrCU
[NbCU
].Tag
= return_tagval
;
386 // Die type detection
387 switch (return_tagval
)
389 case DW_TAG_compile_unit
:
390 if (dwarf_attrlist(return_sib
, &atlist
, &atcnt
, &error
) == DW_DLV_OK
)
392 for (Dwarf_Signed i
= 0; i
< atcnt
; ++i
)
394 if (dwarf_whatattr(atlist
[i
], &return_attr
, &error
) == DW_DLV_OK
)
400 if (dwarf_lowpc(return_sib
, &return_lowpc
, &error
) == DW_DLV_OK
)
402 PtrCU
[NbCU
].LowPC
= return_lowpc
;
408 if (dwarf_highpc(return_sib
, &return_highpc
, &error
) == DW_DLV_OK
)
410 PtrCU
[NbCU
].HighPC
= return_highpc
;
414 // compilation information
416 if (dwarf_formstring(atlist
[i
], &return_string
, &error
) == DW_DLV_OK
)
418 PtrCU
[NbCU
].PtrProducer
= (char *)calloc(strlen(return_string
) + 1, 1);
419 strcpy(PtrCU
[NbCU
].PtrProducer
, return_string
);
420 dwarf_dealloc(dbg
, return_string
, DW_DLA_STRING
);
426 if (dwarf_formstring(atlist
[i
], &return_string
, &error
) == DW_DLV_OK
)
428 #ifdef DEBUG_Filename
429 if (strstr(return_string
, DEBUG_Filename
))
432 PtrCU
[NbCU
].PtrSourceFilename
= (char *)calloc((strlen(return_string
) + 1), 1);
433 strcpy(PtrCU
[NbCU
].PtrSourceFilename
, return_string
);
435 dwarf_dealloc(dbg
, return_string
, DW_DLA_STRING
);
441 if (dwarf_formstring(atlist
[i
], &return_string
, &error
) == DW_DLV_OK
)
443 PtrCU
[NbCU
].PtrSourceFileDirectory
= (char *)calloc((strlen(return_string
) + 1), 1);
444 strcpy(PtrCU
[NbCU
].PtrSourceFileDirectory
, return_string
);
445 dwarf_dealloc(dbg
, return_string
, DW_DLA_STRING
);
451 if (dwarf_formudata(atlist
[i
], &return_uvalue
, &error
) == DW_DLV_OK
)
453 PtrCU
[NbCU
].Language
= return_uvalue
;
461 dwarf_dealloc(dbg
, atlist
[i
], DW_DLA_ATTR
);
463 dwarf_dealloc(dbg
, atlist
, DW_DLA_LIST
);
466 // Check filename presence
467 if (!PtrCU
[NbCU
].PtrSourceFilename
)
469 PtrCU
[NbCU
].PtrSourceFilename
= (char *)calloc(1, 1);
472 // Check directory presence
473 if (!PtrCU
[NbCU
].PtrSourceFileDirectory
)
475 // Check if file exists in the search paths
476 for (size_t i
= 0; i
< NbSearchPaths
; i
++)
478 PtrCU
[NbCU
].PtrFullFilename
= (char *)realloc(PtrCU
[NbCU
].PtrFullFilename
, strlen(PtrCU
[NbCU
].PtrSourceFilename
) + strlen((const char *)ListSearchPaths
[i
]) + 2);
480 sprintf(PtrCU
[NbCU
].PtrFullFilename
, "%s\\%s", ListSearchPaths
[i
], PtrCU
[NbCU
].PtrSourceFilename
);
482 sprintf(PtrCU
[NbCU
].PtrFullFilename
, "%s/%s", ListSearchPaths
[i
], PtrCU
[NbCU
].PtrSourceFilename
);
484 if (!fopen_s(&SrcFile
, PtrCU
[NbCU
].PtrFullFilename
, "rb"))
486 PtrCU
[NbCU
].PtrSourceFileDirectory
= (char *)realloc(PtrCU
[NbCU
].PtrSourceFileDirectory
, strlen(ListSearchPaths
[i
]) + 1);
487 strcpy(PtrCU
[NbCU
].PtrSourceFileDirectory
, ListSearchPaths
[i
]);
491 // File directory doesn't exits
492 if (!PtrCU
[NbCU
].PtrSourceFileDirectory
)
494 PtrCU
[NbCU
].PtrSourceFileDirectory
= (char *)realloc(PtrCU
[NbCU
].PtrSourceFileDirectory
, 2);
495 strcpy(PtrCU
[NbCU
].PtrSourceFileDirectory
, ".");
499 // Conform slashes / backslashes for the filename
500 DWARFManager_ConformSlachesBackslashes(PtrCU
[NbCU
].PtrSourceFilename
);
502 // Check if filename contains already the complete directory
503 if (PtrCU
[NbCU
].PtrSourceFilename
[1] == ':')
505 // Copy the filename as the full filename
506 PtrCU
[NbCU
].PtrFullFilename
= (char *)realloc(PtrCU
[NbCU
].PtrFullFilename
, strlen(PtrCU
[NbCU
].PtrSourceFilename
) + 1);
507 strcpy(PtrCU
[NbCU
].PtrFullFilename
, PtrCU
[NbCU
].PtrSourceFilename
);
511 // Create full filename and Conform slashes / backslashes
512 PtrCU
[NbCU
].PtrFullFilename
= (char *)realloc(PtrCU
[NbCU
].PtrFullFilename
, strlen(PtrCU
[NbCU
].PtrSourceFilename
) + strlen(PtrCU
[NbCU
].PtrSourceFileDirectory
) + 2);
514 sprintf(PtrCU
[NbCU
].PtrFullFilename
, "%s\\%s", PtrCU
[NbCU
].PtrSourceFileDirectory
, PtrCU
[NbCU
].PtrSourceFilename
);
516 sprintf(PtrCU
[NbCU
].PtrFullFilename
, "%s/%s", PtrCU
[NbCU
].PtrSourceFileDirectory
, PtrCU
[NbCU
].PtrSourceFilename
);
520 DWARFManager_ConformSlachesBackslashes(PtrCU
[NbCU
].PtrFullFilename
);
522 // Directory path clean-up
524 while ((Ptr1
= Ptr
= strstr(PtrCU
[NbCU
].PtrFullFilename
, "\\..\\")))
526 while ((Ptr1
= Ptr
= strstr(PtrCU
[NbCU
].PtrFullFilename
, "/../")))
530 while (*--Ptr1
!= '\\');
532 while (*--Ptr1
!= '/');
534 strcpy((Ptr1
+ 1), (Ptr
+ 4));
537 // Get the source file information
538 if (!_stat(PtrCU
[NbCU
].PtrFullFilename
, &PtrCU
[NbCU
]._statbuf
))
540 // check the time stamp with the executable
541 if (PtrCU
[NbCU
]._statbuf
.st_mtime
<= FileElfExeInfo
.st_mtime
)
543 // Open the source file as a binary file
544 if (!fopen_s(&SrcFile
, PtrCU
[NbCU
].PtrFullFilename
, "rb"))
546 if (!fseek(SrcFile
, 0, SEEK_END
))
548 if ((PtrCU
[NbCU
].SizeLoadSrc
= ftell(SrcFile
)) > 0)
550 if (!fseek(SrcFile
, 0, SEEK_SET
))
552 if (PtrCU
[NbCU
].PtrLoadSrc
= Ptr
= Ptr1
= (char *)calloc(1, (PtrCU
[NbCU
].SizeLoadSrc
+ 2)))
555 if (fread_s(PtrCU
[NbCU
].PtrLoadSrc
, PtrCU
[NbCU
].SizeLoadSrc
, PtrCU
[NbCU
].SizeLoadSrc
, 1, SrcFile
) != 1)
557 free(PtrCU
[NbCU
].PtrLoadSrc
);
558 PtrCU
[NbCU
].PtrLoadSrc
= NULL
;
559 PtrCU
[NbCU
].SizeLoadSrc
= 0;
563 // Eliminate all carriage return code '\r' (oxd)
566 if ((*Ptr
= *Ptr1
) != '\r')
572 // Get back the new text file size
573 PtrCU
[NbCU
].SizeLoadSrc
= strlen(Ptr
= PtrCU
[NbCU
].PtrLoadSrc
);
575 // Make sure the text file finish with a new line code '\n' (0xa)
576 if (PtrCU
[NbCU
].PtrLoadSrc
[PtrCU
[NbCU
].SizeLoadSrc
- 1] != '\n')
578 PtrCU
[NbCU
].PtrLoadSrc
[PtrCU
[NbCU
].SizeLoadSrc
++] = '\n';
579 PtrCU
[NbCU
].PtrLoadSrc
[PtrCU
[NbCU
].SizeLoadSrc
] = 0;
582 // Reallocate text file
583 if (PtrCU
[NbCU
].PtrLoadSrc
= Ptr
= (char *)realloc(PtrCU
[NbCU
].PtrLoadSrc
, (PtrCU
[NbCU
].SizeLoadSrc
+ 1)))
585 // Count line numbers, based on the new line code '\n' (0xa), and finish each line with 0
590 PtrCU
[NbCU
].NbLinesLoadSrc
++;
605 // Source file doesn't exist
606 PtrCU
[NbCU
].Status
= DWARFSTATUS_NOFILE
;
611 // Source file is outdated
612 PtrCU
[NbCU
].Status
= DWARFSTATUS_OUTDATEDFILE
;
617 // Source file doesn't have information
618 PtrCU
[NbCU
].Status
= DWARFSTATUS_NOFILEINFO
;
627 // Get the source lines table located in the CU
628 if ((dwarf_srclines(return_sib
, &linebuf
, &cnt
, &error
) == DW_DLV_OK
) && (PtrCU
[NbCU
].Status
== DWARFSTATUS_OK
))
632 PtrCU
[NbCU
].NbUsedLinesSrc
= cnt
;
633 PtrCU
[NbCU
].PtrUsedLinesSrc
= (CUStruct_LineSrc
*)calloc(cnt
, sizeof(CUStruct_LineSrc
));
634 PtrCU
[NbCU
].PtrUsedLinesLoadSrc
= (char **)calloc(cnt
, sizeof(char *));
635 PtrCU
[NbCU
].PtrUsedNumLines
= (size_t *)calloc(cnt
, sizeof(size_t));
637 // Get the addresses and their source line numbers
638 for (Dwarf_Signed i
= 0; i
< cnt
; i
++)
640 if (dwarf_lineaddr(linebuf
[i
], &return_lineaddr
, &error
) == DW_DLV_OK
)
642 // Get the source line number
643 if (dwarf_lineno(linebuf
[i
], &return_uvalue
, &error
) == DW_DLV_OK
)
645 PtrCU
[NbCU
].PtrUsedLinesSrc
[i
].StartPC
= return_lineaddr
;
646 PtrCU
[NbCU
].PtrUsedLinesSrc
[i
].NumLineSrc
= return_uvalue
;
652 // Release the memory used by the source lines table located in the CU
653 dwarf_srclines_dealloc(dbg
, linebuf
, cnt
);
656 // Check if the CU has child
657 if (dwarf_child(return_sib
, &return_die
, &error
) == DW_DLV_OK
)
661 return_sib
= return_die
;
662 if ((dwarf_tag(return_die
, &return_tagval
, &error
) == DW_DLV_OK
))
664 switch (return_tagval
)
666 case DW_TAG_lexical_block
:
669 case DW_TAG_variable
:
670 if (dwarf_attrlist(return_die
, &atlist
, &atcnt
, &error
) == DW_DLV_OK
)
672 PtrCU
[NbCU
].PtrVariables
= (VariablesStruct
*)realloc(PtrCU
[NbCU
].PtrVariables
, ((PtrCU
[NbCU
].NbVariables
+ 1) * sizeof(VariablesStruct
)));
673 memset(PtrCU
[NbCU
].PtrVariables
+ PtrCU
[NbCU
].NbVariables
, 0, sizeof(VariablesStruct
));
675 for (Dwarf_Signed i
= 0; i
< atcnt
; ++i
)
677 if (dwarf_whatattr(atlist
[i
], &return_attr
, &error
) == DW_DLV_OK
)
679 if (dwarf_attr(return_die
, return_attr
, &return_attr1
, &error
) == DW_DLV_OK
)
684 if (dwarf_formblock(return_attr1
, &return_block
, &error
) == DW_DLV_OK
)
686 PtrCU
[NbCU
].PtrVariables
[PtrCU
[NbCU
].NbVariables
].Op
= (*((unsigned char *)(return_block
->bl_data
)));
688 switch (return_block
->bl_len
)
691 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));
697 dwarf_dealloc(dbg
, return_block
, DW_DLA_BLOCK
);
702 if (dwarf_global_formref(return_attr1
, &return_offset
, &error
) == DW_DLV_OK
)
704 PtrCU
[NbCU
].PtrVariables
[PtrCU
[NbCU
].NbVariables
].TypeOffset
= return_offset
;
710 if (dwarf_formstring(return_attr1
, &return_string
, &error
) == DW_DLV_OK
)
712 #ifdef DEBUG_VariableName
713 if (!strcmp(return_string
, DEBUG_VariableName
))
716 PtrCU
[NbCU
].PtrVariables
[PtrCU
[NbCU
].NbVariables
].PtrName
= (char *)calloc(strlen(return_string
) + 1, 1);
717 strcpy(PtrCU
[NbCU
].PtrVariables
[PtrCU
[NbCU
].NbVariables
].PtrName
, return_string
);
719 dwarf_dealloc(dbg
, return_string
, DW_DLA_STRING
);
729 dwarf_dealloc(dbg
, atlist
[i
], DW_DLA_ATTR
);
732 // Check variable's name validity
733 if (PtrCU
[NbCU
].PtrVariables
[PtrCU
[NbCU
].NbVariables
].PtrName
)
735 // Check variable's memory address validity
736 if (PtrCU
[NbCU
].PtrVariables
[PtrCU
[NbCU
].NbVariables
].Addr
)
739 PtrCU
[NbCU
].NbVariables
++;
744 free(PtrCU
[NbCU
].PtrVariables
[PtrCU
[NbCU
].NbVariables
].PtrName
);
745 PtrCU
[NbCU
].PtrVariables
[PtrCU
[NbCU
].NbVariables
].PtrName
= NULL
;
749 dwarf_dealloc(dbg
, atlist
, DW_DLA_LIST
);
753 case DW_TAG_base_type
:
755 case DW_TAG_structure_type
:
756 case DW_TAG_pointer_type
:
757 case DW_TAG_const_type
:
758 case DW_TAG_array_type
:
759 case DW_TAG_subrange_type
:
760 case DW_TAG_subroutine_type
:
761 case DW_TAG_enumeration_type
:
762 if (dwarf_attrlist(return_die
, &atlist
, &atcnt
, &error
) == DW_DLV_OK
)
764 // Allocate memory for this type
765 PtrCU
[NbCU
].PtrTypes
= (BaseTypeStruct
*)realloc(PtrCU
[NbCU
].PtrTypes
, ((PtrCU
[NbCU
].NbTypes
+ 1) * sizeof(BaseTypeStruct
)));
766 memset(PtrCU
[NbCU
].PtrTypes
+ PtrCU
[NbCU
].NbTypes
, 0, sizeof(BaseTypeStruct
));
767 PtrCU
[NbCU
].PtrTypes
[PtrCU
[NbCU
].NbTypes
].Tag
= return_tagval
;
769 if (dwarf_dieoffset(return_die
, &return_offset
, &error
) == DW_DLV_OK
)
771 PtrCU
[NbCU
].PtrTypes
[PtrCU
[NbCU
].NbTypes
].Offset
= return_offset
;
774 for (Dwarf_Signed i
= 0; i
< atcnt
; ++i
)
776 if (dwarf_whatattr(atlist
[i
], &return_attr
, &error
) == DW_DLV_OK
)
778 if (dwarf_attr(return_die
, return_attr
, &return_attr1
, &error
) == DW_DLV_OK
)
786 // Type's type offset
788 if (dwarf_global_formref(return_attr1
, &return_offset
, &error
) == DW_DLV_OK
)
790 PtrCU
[NbCU
].PtrTypes
[PtrCU
[NbCU
].NbTypes
].TypeOffset
= return_offset
;
795 case DW_AT_byte_size
:
796 if (dwarf_formudata(return_attr1
, &return_uvalue
, &error
) == DW_DLV_OK
)
798 PtrCU
[NbCU
].PtrTypes
[PtrCU
[NbCU
].NbTypes
].ByteSize
= return_uvalue
;
804 if (dwarf_formudata(return_attr1
, &return_uvalue
, &error
) == DW_DLV_OK
)
806 PtrCU
[NbCU
].PtrTypes
[PtrCU
[NbCU
].NbTypes
].Encoding
= return_uvalue
;
812 if (dwarf_formstring(return_attr1
, &return_string
, &error
) == DW_DLV_OK
)
814 #ifdef DEBUG_TypeName
815 if (!strcmp(return_string
, DEBUG_TypeName
))
818 PtrCU
[NbCU
].PtrTypes
[PtrCU
[NbCU
].NbTypes
].PtrName
= (char *)calloc(strlen(return_string
) + 1, 1);
819 strcpy(PtrCU
[NbCU
].PtrTypes
[PtrCU
[NbCU
].NbTypes
].PtrName
, return_string
);
821 dwarf_dealloc(dbg
, return_string
, DW_DLA_STRING
);
825 // Type's file number
826 case DW_AT_decl_file
:
829 // Type's line number
830 case DW_AT_decl_line
:
839 dwarf_dealloc(dbg
, atlist
[i
], DW_DLA_ATTR
);
842 PtrCU
[NbCU
].NbTypes
++;
844 dwarf_dealloc(dbg
, atlist
, DW_DLA_LIST
);
848 case DW_TAG_subprogram
:
849 if (dwarf_attrlist(return_die
, &atlist
, &atcnt
, &error
) == DW_DLV_OK
)
851 PtrCU
[NbCU
].PtrSubProgs
= (SubProgStruct
*)realloc(PtrCU
[NbCU
].PtrSubProgs
, ((PtrCU
[NbCU
].NbSubProgs
+ 1) * sizeof(SubProgStruct
)));
852 memset((void *)(PtrCU
[NbCU
].PtrSubProgs
+ PtrCU
[NbCU
].NbSubProgs
), 0, sizeof(SubProgStruct
));
853 PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].Tag
= return_tagval
;
855 for (Dwarf_Signed i
= 0; i
< atcnt
; ++i
)
857 if (dwarf_whatattr(atlist
[i
], &return_attr
, &error
) == DW_DLV_OK
)
859 if (dwarf_attr(return_die
, return_attr
, &return_attr1
, &error
) == DW_DLV_OK
)
865 if (dwarf_lowpc(return_die
, &return_lowpc
, &error
) == DW_DLV_OK
)
867 PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].StartPC
= return_lowpc
;
868 PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].LowPC
= return_lowpc
;
874 if (dwarf_highpc(return_die
, &return_highpc
, &error
) == DW_DLV_OK
)
876 PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].HighPC
= return_highpc
;
881 case DW_AT_decl_line
:
882 if (dwarf_formudata(return_attr1
, &return_uvalue
, &error
) == DW_DLV_OK
)
884 PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].NumLineSrc
= return_uvalue
;
889 case DW_AT_frame_base
:
890 if (dwarf_formudata(return_attr1
, &return_uvalue
, &error
) == DW_DLV_OK
)
892 PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].FrameBase
= return_uvalue
;
893 PtrCU
[NbCU
].NbFrames
++;
899 if (dwarf_formstring(return_attr1
, &return_string
, &error
) == DW_DLV_OK
)
901 PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].PtrSubprogramName
= (char *)calloc(strlen(return_string
) + 1, 1);
902 strcpy(PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].PtrSubprogramName
, return_string
);
903 dwarf_dealloc(dbg
, return_string
, DW_DLA_STRING
);
910 case DW_AT_GNU_all_tail_call_sites
:
916 case DW_AT_prototyped
:
920 case DW_AT_decl_file
:
931 dwarf_dealloc(dbg
, atlist
[i
], DW_DLA_ATTR
);
933 dwarf_dealloc(dbg
, atlist
, DW_DLA_LIST
);
935 // Get source line number and associated block of address
936 for (Dwarf_Signed i
= 0; i
< cnt
; ++i
)
938 // Check the presence of the line in the memory frame
939 if (PtrCU
[NbCU
].PtrUsedLinesSrc
&& (PtrCU
[NbCU
].PtrUsedLinesSrc
[i
].StartPC
>= return_lowpc
) && (PtrCU
[NbCU
].PtrUsedLinesSrc
[i
].StartPC
<= return_highpc
))
941 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
));
942 memset((void *)(PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].PtrLinesSrc
+ PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].NbLinesSrc
), 0, sizeof(DMIStruct_LineSrc
));
943 PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].PtrLinesSrc
[PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].NbLinesSrc
].StartPC
= PtrCU
[NbCU
].PtrUsedLinesSrc
[i
].StartPC
;
944 PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].PtrLinesSrc
[PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].NbLinesSrc
].NumLineSrc
= PtrCU
[NbCU
].PtrUsedLinesSrc
[i
].NumLineSrc
;
945 PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].NbLinesSrc
++;
949 if (dwarf_child(return_die
, &return_subdie
, &error
) == DW_DLV_OK
)
953 return_sub
= return_subdie
;
954 if ((dwarf_tag(return_subdie
, &return_tagval
, &error
) == DW_DLV_OK
))
956 switch (return_tagval
)
958 case DW_TAG_formal_parameter
:
959 case DW_TAG_variable
:
960 if (dwarf_attrlist(return_subdie
, &atlist
, &atcnt
, &error
) == DW_DLV_OK
)
962 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
)));
963 memset(PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].PtrVariables
+ PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].NbVariables
, 0, sizeof(VariablesStruct
));
965 for (Dwarf_Signed i
= 0; i
< atcnt
; ++i
)
967 if (dwarf_whatattr(atlist
[i
], &return_attr
, &error
) == DW_DLV_OK
)
969 if (dwarf_attr(return_subdie
, return_attr
, &return_attr1
, &error
) == DW_DLV_OK
)
974 if (dwarf_formblock(return_attr1
, &return_block
, &error
) == DW_DLV_OK
)
976 PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].PtrVariables
[PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].NbVariables
].Op
= *((unsigned char *)(return_block
->bl_data
));
978 switch (return_block
->bl_len
)
985 switch (return_tagval
)
987 case DW_TAG_variable
:
988 PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].PtrVariables
[PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].NbVariables
].Offset
= ReadLEB128((char *)return_block
->bl_data
+ 1);
991 case DW_TAG_formal_parameter
:
992 PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].PtrVariables
[PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].NbVariables
].Offset
= ReadULEB128((char *)return_block
->bl_data
+ 1);
1003 dwarf_dealloc(dbg
, return_block
, DW_DLA_BLOCK
);
1008 if (dwarf_global_formref(return_attr1
, &return_offset
, &error
) == DW_DLV_OK
)
1010 PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].PtrVariables
[PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].NbVariables
].TypeOffset
= return_offset
;
1015 if (dwarf_formstring(return_attr1
, &return_string
, &error
) == DW_DLV_OK
)
1017 #ifdef DEBUG_VariableName
1018 if (!strcmp(return_string
, DEBUG_VariableName
))
1021 PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].PtrVariables
[PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].NbVariables
].PtrName
= (char *)calloc(strlen(return_string
) + 1, 1);
1022 strcpy(PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].PtrVariables
[PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].NbVariables
].PtrName
, return_string
);
1024 dwarf_dealloc(dbg
, return_string
, DW_DLA_STRING
);
1028 case DW_AT_decl_file
:
1031 case DW_AT_decl_line
:
1040 dwarf_dealloc(dbg
, atlist
[i
], DW_DLA_ATTR
);
1043 PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
].NbVariables
++;
1045 dwarf_dealloc(dbg
, atlist
, DW_DLA_LIST
);
1057 while (dwarf_siblingof(dbg
, return_sub
, &return_subdie
, &error
) == DW_DLV_OK
);
1060 PtrCU
[NbCU
].NbSubProgs
++;
1069 while (dwarf_siblingof(dbg
, return_sib
, &return_die
, &error
) == DW_DLV_OK
);
1073 // Set the source code lines
1074 if (PtrCU
[NbCU
].NbLinesLoadSrc
)
1076 if (PtrCU
[NbCU
].PtrLinesLoadSrc
= (char **)calloc(PtrCU
[NbCU
].NbLinesLoadSrc
, sizeof(char *)))
1078 for (size_t j
= 0; j
< PtrCU
[NbCU
].NbLinesLoadSrc
; j
++)
1080 if (PtrCU
[NbCU
].PtrLinesLoadSrc
[j
] = (char *)calloc(10000, sizeof(char)))
1082 if (Ptr
= DWARFManager_GetLineSrcFromNumLine(PtrCU
[NbCU
].PtrLoadSrc
, (j
+ 1)))
1090 #ifdef CONVERT_QT_HML
1092 strcat(PtrCU
[NbCU
].PtrLinesLoadSrc
[j
], " ");
1097 strcat(PtrCU
[NbCU
].PtrLinesLoadSrc
[j
], "<");
1102 strcat(PtrCU
[NbCU
].PtrLinesLoadSrc
[j
], ">");
1107 strcpy(PtrCU
[NbCU
].PtrLinesLoadSrc
[j
], "&");
1108 i
+= strlen("&");
1113 strcpy(PtrCU
[NbCU
].PtrLinesLoadSrc
[j
], """);
1114 i
+= strlen(""");
1119 PtrCU
[NbCU
].PtrLinesLoadSrc
[j
][i
++] = *Ptr
;
1125 PtrCU
[NbCU
].PtrLinesLoadSrc
[j
] = (char *)realloc(PtrCU
[NbCU
].PtrLinesLoadSrc
[j
], strlen(PtrCU
[NbCU
].PtrLinesLoadSrc
[j
]) + 1);
1129 // Init lines source information for each source code line numbers and for each subprogs
1130 for (size_t j
= 0; j
< PtrCU
[NbCU
].NbSubProgs
; j
++)
1132 // Check if the subprog / function's line exists in the source code
1133 if (PtrCU
[NbCU
].PtrSubProgs
[j
].NumLineSrc
<= PtrCU
[NbCU
].NbLinesLoadSrc
)
1135 PtrCU
[NbCU
].PtrSubProgs
[j
].PtrLineSrc
= PtrCU
[NbCU
].PtrLinesLoadSrc
[PtrCU
[NbCU
].PtrSubProgs
[j
].NumLineSrc
- 1];
1138 for (size_t k
= 0; k
< PtrCU
[NbCU
].PtrSubProgs
[j
].NbLinesSrc
; k
++)
1140 if (PtrCU
[NbCU
].PtrSubProgs
[j
].PtrLinesSrc
[k
].NumLineSrc
<= PtrCU
[NbCU
].NbLinesLoadSrc
)
1142 PtrCU
[NbCU
].PtrSubProgs
[j
].PtrLinesSrc
[k
].PtrLineSrc
= PtrCU
[NbCU
].PtrLinesLoadSrc
[PtrCU
[NbCU
].PtrSubProgs
[j
].PtrLinesSrc
[k
].NumLineSrc
- 1];
1150 // Set each source lines pointer to NULL
1151 if (PtrCU
[NbCU
].NbSubProgs
)
1153 // Check the presence of source lines dedicated to the sub progs
1154 if (PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
- 1].NbLinesSrc
)
1156 size_t i
= PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
- 1].PtrLinesSrc
[PtrCU
[NbCU
].PtrSubProgs
[PtrCU
[NbCU
].NbSubProgs
- 1].NbLinesSrc
- 1].NumLineSrc
;
1157 if (PtrCU
[NbCU
].PtrLinesLoadSrc
= (char **)calloc(i
, sizeof(char *)))
1159 for (size_t j
= 0; j
< i
; j
++)
1161 PtrCU
[NbCU
].PtrLinesLoadSrc
[j
] = NULL
;
1168 // Check validity between used number lines and number lines in the source file
1169 if (PtrCU
[NbCU
].LastNumUsedLinesSrc
<= PtrCU
[NbCU
].NbLinesLoadSrc
)
1171 // Set information based on used line numbers
1172 if (PtrCU
[NbCU
].PtrUsedLinesSrc
)
1174 // Set the line source pointers for each used line numbers
1175 if (PtrCU
[NbCU
].PtrLinesLoadSrc
)
1177 for (size_t i
= 0; i
< PtrCU
[NbCU
].NbUsedLinesSrc
; i
++)
1179 PtrCU
[NbCU
].PtrUsedNumLines
[i
] = PtrCU
[NbCU
].PtrUsedLinesSrc
[i
].NumLineSrc
- 1;
1180 PtrCU
[NbCU
].PtrUsedLinesLoadSrc
[i
] = PtrCU
[NbCU
].PtrUsedLinesSrc
[i
].PtrLineSrc
= PtrCU
[NbCU
].PtrLinesLoadSrc
[PtrCU
[NbCU
].PtrUsedLinesSrc
[i
].NumLineSrc
- 1];
1183 // Setup memory range for the code if CU doesn't have already this information
1184 // It is taken from the used lines structure
1185 if (!PtrCU
[NbCU
].LowPC
&& (!PtrCU
[NbCU
].HighPC
|| (PtrCU
[NbCU
].HighPC
== ~0)))
1187 PtrCU
[NbCU
].LowPC
= PtrCU
[NbCU
].PtrUsedLinesSrc
[0].StartPC
;
1188 PtrCU
[NbCU
].HighPC
= PtrCU
[NbCU
].PtrUsedLinesSrc
[PtrCU
[NbCU
].NbUsedLinesSrc
- 1].StartPC
;
1194 // Init global variables information based on types information
1195 for (size_t i
= 0; i
< PtrCU
[NbCU
].NbVariables
; i
++)
1197 DWARFManager_InitInfosVariable(PtrCU
[NbCU
].PtrVariables
+ i
);
1200 // Init local variables information based on types information
1201 for (size_t i
= 0; i
< PtrCU
[NbCU
].NbSubProgs
; i
++)
1203 for (size_t j
= 0; j
< PtrCU
[NbCU
].PtrSubProgs
[i
].NbVariables
; j
++)
1205 DWARFManager_InitInfosVariable(PtrCU
[NbCU
].PtrSubProgs
[i
].PtrVariables
+ j
);
1216 // Conform slashes and backslashes
1217 void DWARFManager_ConformSlachesBackslashes(char *Ptr
)
1237 // Variables information initialisation
1238 void DWARFManager_InitInfosVariable(VariablesStruct
*PtrVariables
)
1240 size_t j
, TypeOffset
;
1242 #ifdef DEBUG_VariableName
1243 if (PtrVariables
->PtrName
&& !strcmp(PtrVariables
->PtrName
, DEBUG_VariableName
))
1246 PtrVariables
->PtrTypeName
= (char *)calloc(1000, 1);
1247 TypeOffset
= PtrVariables
->TypeOffset
;
1249 for (j
= 0; j
< PtrCU
[NbCU
].NbTypes
; j
++)
1251 if (TypeOffset
== PtrCU
[NbCU
].PtrTypes
[j
].Offset
)
1253 switch (PtrCU
[NbCU
].PtrTypes
[j
].Tag
)
1255 case DW_TAG_subroutine_type
:
1256 PtrVariables
->TypeTag
|= TypeTag_subroutine_type
;
1257 strcat(PtrVariables
->PtrTypeName
, " (* ) ()");
1260 // Structure type tag
1261 case DW_TAG_structure_type
:
1262 PtrVariables
->TypeTag
|= TypeTag_structure
;
1263 if (!(PtrVariables
->TypeTag
& TypeTag_typedef
))
1265 if (PtrCU
[NbCU
].PtrTypes
[j
].PtrName
)
1267 strcat(PtrVariables
->PtrTypeName
, PtrCU
[NbCU
].PtrTypes
[j
].PtrName
);
1270 if ((TypeOffset
= PtrCU
[NbCU
].PtrTypes
[j
].TypeOffset
))
1276 if ((PtrVariables
->TypeTag
& TypeTag_pointer
))
1278 strcat(PtrVariables
->PtrTypeName
, " *");
1284 case DW_TAG_pointer_type
:
1285 PtrVariables
->TypeTag
|= TypeTag_pointer
;
1286 PtrVariables
->TypeByteSize
= PtrCU
[NbCU
].PtrTypes
[j
].ByteSize
;
1287 PtrVariables
->TypeEncoding
= 0x10;
1288 if (!(TypeOffset
= PtrCU
[NbCU
].PtrTypes
[j
].TypeOffset
))
1290 strcat(PtrVariables
->PtrTypeName
, "void *");
1298 case DW_TAG_enumeration_type
:
1299 PtrVariables
->TypeTag
|= TypeTag_enumeration_type
;
1300 PtrVariables
->TypeByteSize
= PtrCU
[NbCU
].PtrTypes
[j
].ByteSize
;
1301 if (!(PtrVariables
->TypeEncoding
= PtrCU
[NbCU
].PtrTypes
[j
].Encoding
))
1303 // Try to determine the possible size
1304 switch (PtrVariables
->TypeByteSize
)
1307 PtrVariables
->TypeEncoding
= 0x7;
1317 case DW_TAG_typedef
:
1318 if (!(PtrVariables
->TypeTag
& TypeTag_typedef
))
1320 PtrVariables
->TypeTag
|= TypeTag_typedef
;
1321 strcat(PtrVariables
->PtrTypeName
, PtrCU
[NbCU
].PtrTypes
[j
].PtrName
);
1323 if ((TypeOffset
= PtrCU
[NbCU
].PtrTypes
[j
].TypeOffset
))
1330 case DW_TAG_subrange_type
:
1331 PtrVariables
->TypeTag
|= TypeTag_subrange
;
1335 case DW_TAG_array_type
:
1336 PtrVariables
->TypeTag
|= TypeTag_arraytype
;
1337 if ((TypeOffset
= PtrCU
[NbCU
].PtrTypes
[j
].TypeOffset
))
1344 case DW_TAG_const_type
:
1345 PtrVariables
->TypeTag
|= TypeTag_consttype
;
1346 strcat(PtrVariables
->PtrTypeName
, "const ");
1347 if ((TypeOffset
= PtrCU
[NbCU
].PtrTypes
[j
].TypeOffset
))
1354 case DW_TAG_base_type
:
1355 if (!(PtrVariables
->TypeTag
& TypeTag_typedef
))
1357 strcat(PtrVariables
->PtrTypeName
, PtrCU
[NbCU
].PtrTypes
[j
].PtrName
);
1359 if ((PtrVariables
->TypeTag
& TypeTag_pointer
))
1361 strcat(PtrVariables
->PtrTypeName
, " *");
1365 PtrVariables
->TypeByteSize
= PtrCU
[NbCU
].PtrTypes
[j
].ByteSize
;
1366 PtrVariables
->TypeEncoding
= PtrCU
[NbCU
].PtrTypes
[j
].Encoding
;
1368 if ((PtrVariables
->TypeTag
& TypeTag_arraytype
))
1370 strcat(PtrVariables
->PtrTypeName
, "[]");
1383 // Get symbol name based from address
1384 // Return NULL if no symbol name exists
1385 char *DWARFManager_GetSymbolnameFromAdr(size_t Adr
)
1387 for (size_t i
= 0; i
< NbCU
; i
++)
1389 if ((Adr
>= PtrCU
[i
].LowPC
) && (Adr
< PtrCU
[i
].HighPC
))
1391 for (size_t j
= 0; j
< PtrCU
[i
].NbSubProgs
; j
++)
1393 if ((PtrCU
[i
].PtrSubProgs
[j
].StartPC
== Adr
))
1395 return PtrCU
[i
].PtrSubProgs
[j
].PtrSubprogramName
;
1405 // Get complete source filename based from address
1406 // Return NULL if no source filename exists
1407 // Return the existence status in Status if pointer not NULL
1408 char *DWARFManager_GetFullSourceFilenameFromAdr(size_t Adr
, DWARFstatus
*Status
)
1410 for (size_t i
= 0; i
< NbCU
; i
++)
1412 if ((Adr
>= PtrCU
[i
].LowPC
) && (Adr
< PtrCU
[i
].HighPC
))
1416 *Status
= PtrCU
[i
].Status
;
1419 return PtrCU
[i
].PtrFullFilename
;
1427 // Get text line source based on line number (starting from 1)
1428 // Return NULL if no text line exists or if line number is 0
1429 char *DWARFManager_GetLineSrcFromNumLine(char *PtrSrcFile
, size_t NumLine
)
1432 char *PtrLineSrc
= NULL
;
1436 while (i
!= NumLine
)
1438 PtrLineSrc
= PtrSrcFile
;
1439 while (*PtrSrcFile
++);
1448 // Get number of variables referenced by the function range address
1449 size_t DWARFManager_GetNbLocalVariables(size_t Adr
)
1451 for (size_t i
= 0; i
< NbCU
; i
++)
1453 if ((Adr
>= PtrCU
[i
].LowPC
) && (Adr
< PtrCU
[i
].HighPC
))
1455 for (size_t j
= 0; j
< PtrCU
[i
].NbSubProgs
; j
++)
1457 if ((Adr
>= PtrCU
[i
].PtrSubProgs
[j
].LowPC
) && (Adr
< PtrCU
[i
].PtrSubProgs
[j
].HighPC
))
1459 return PtrCU
[i
].PtrSubProgs
[j
].NbVariables
;
1469 // Get local variable name based on his index (starting from 1)
1470 // Return name's pointer text found
1471 // Return NULL if not found
1472 char *DWARFManager_GetLocalVariableName(size_t Adr
, size_t Index
)
1474 for (size_t i
= 0; i
< NbCU
; i
++)
1476 if ((Adr
>= PtrCU
[i
].LowPC
) && (Adr
< PtrCU
[i
].HighPC
))
1478 for (size_t j
= 0; j
< PtrCU
[i
].NbSubProgs
; j
++)
1480 if ((Adr
>= PtrCU
[i
].PtrSubProgs
[j
].LowPC
) && (Adr
< PtrCU
[i
].PtrSubProgs
[j
].HighPC
))
1482 return PtrCU
[i
].PtrSubProgs
[j
].PtrVariables
[Index
- 1].PtrName
;
1492 // Get local variable's type tag based on his index (starting from 1)
1493 // Return 0 if not found
1494 size_t DWARFManager_GetLocalVariableTypeTag(size_t Adr
, size_t Index
)
1496 for (size_t i
= 0; i
< NbCU
; i
++)
1498 if ((Adr
>= PtrCU
[i
].LowPC
) && (Adr
< PtrCU
[i
].HighPC
))
1500 for (size_t j
= 0; j
< PtrCU
[i
].NbSubProgs
; j
++)
1502 if ((Adr
>= PtrCU
[i
].PtrSubProgs
[j
].LowPC
) && (Adr
< PtrCU
[i
].PtrSubProgs
[j
].HighPC
))
1504 return PtrCU
[i
].PtrSubProgs
[j
].PtrVariables
[Index
- 1].TypeTag
;
1514 // Get the local variable's offset based on a index (starting from 1)
1515 // Return 0 if no offset has been found
1516 int DWARFManager_GetLocalVariableOffset(size_t Adr
, size_t Index
)
1518 for (size_t i
= 0; i
< NbCU
; i
++)
1520 if ((Adr
>= PtrCU
[i
].LowPC
) && (Adr
< PtrCU
[i
].HighPC
))
1522 for (size_t j
= 0; j
< PtrCU
[i
].NbSubProgs
; j
++)
1524 if ((Adr
>= PtrCU
[i
].PtrSubProgs
[j
].LowPC
) && (Adr
< PtrCU
[i
].PtrSubProgs
[j
].HighPC
))
1526 return PtrCU
[i
].PtrSubProgs
[j
].PtrVariables
[Index
- 1].Offset
;
1536 // Get local variable Type Byte Size based on his address and index (starting from 1)
1537 // Return 0 if not found
1538 // May return 0 if there is no Type Byte Size linked to the variable's address and index
1539 size_t DWARFManager_GetLocalVariableTypeByteSize(size_t Adr
, size_t Index
)
1541 for (size_t i
= 0; i
< NbCU
; i
++)
1543 if ((Adr
>= PtrCU
[i
].LowPC
) && (Adr
< PtrCU
[i
].HighPC
))
1545 for (size_t j
= 0; j
< PtrCU
[i
].NbSubProgs
; j
++)
1547 if ((Adr
>= PtrCU
[i
].PtrSubProgs
[j
].LowPC
) && (Adr
< PtrCU
[i
].PtrSubProgs
[j
].HighPC
))
1549 return PtrCU
[i
].PtrSubProgs
[j
].PtrVariables
[Index
- 1].TypeByteSize
;
1559 // Get local variable Type Encoding based on his address and index (starting from 1)
1560 // Return 0 if not found
1561 // May return 0 if there is no Type Encoding linked to the variable's address and index
1562 size_t DWARFManager_GetLocalVariableTypeEncoding(size_t Adr
, size_t Index
)
1564 for (size_t i
= 0; i
< NbCU
; i
++)
1566 if ((Adr
>= PtrCU
[i
].LowPC
) && (Adr
< PtrCU
[i
].HighPC
))
1568 for (size_t j
= 0; j
< PtrCU
[i
].NbSubProgs
; j
++)
1570 if ((Adr
>= PtrCU
[i
].PtrSubProgs
[j
].LowPC
) && (Adr
< PtrCU
[i
].PtrSubProgs
[j
].HighPC
))
1572 return PtrCU
[i
].PtrSubProgs
[j
].PtrVariables
[Index
- 1].TypeEncoding
;
1582 // Get local variable Op based on his address and index (starting from 1)
1583 // Return 0 if not found, may return 0 if there isn't Op linked to the variable's index
1584 size_t DWARFManager_GetLocalVariableOp(size_t Adr
, size_t Index
)
1586 for (size_t i
= 0; i
< NbCU
; i
++)
1588 if ((Adr
>= PtrCU
[i
].LowPC
) && (Adr
< PtrCU
[i
].HighPC
))
1590 for (size_t j
= 0; j
< PtrCU
[i
].NbSubProgs
; j
++)
1592 if ((Adr
>= PtrCU
[i
].PtrSubProgs
[j
].LowPC
) && (Adr
< PtrCU
[i
].PtrSubProgs
[j
].HighPC
))
1594 return PtrCU
[i
].PtrSubProgs
[j
].PtrVariables
[Index
- 1].Op
;
1604 // Get local variable type name based on his index (starting from 1) and an address
1605 // Return NULL if not found, may also return NULL if there is no type linked to the variable's index
1606 char *DWARFManager_GetLocalVariableTypeName(size_t Adr
, size_t Index
)
1608 for (size_t i
= 0; i
< NbCU
; i
++)
1610 if ((Adr
>= PtrCU
[i
].LowPC
) && (Adr
< PtrCU
[i
].HighPC
))
1612 for (size_t j
= 0; j
< PtrCU
[i
].NbSubProgs
; j
++)
1614 if ((Adr
>= PtrCU
[i
].PtrSubProgs
[j
].LowPC
) && (Adr
< PtrCU
[i
].PtrSubProgs
[j
].HighPC
))
1616 return PtrCU
[i
].PtrSubProgs
[j
].PtrVariables
[Index
- 1].PtrTypeName
;
1626 // Get Compilation Unit / global variables numbers
1627 // Return number of variables
1628 size_t DWARFManager_GetNbGlobalVariables(void)
1630 size_t NbVariables
= 0;
1632 for (size_t i
= 0; i
< NbCU
; i
++)
1634 NbVariables
+= PtrCU
[i
].NbVariables
;
1641 // Get global variable type name based on his index (starting from 1)
1642 // Return NULL if not found
1643 // May return NULL if there is not type linked to the variable's index
1644 char *DWARFManager_GetGlobalVariableTypeName(size_t Index
)
1646 for (size_t i
= 0; i
< NbCU
; i
++)
1648 if (PtrCU
[i
].NbVariables
)
1650 if (Index
<= PtrCU
[i
].NbVariables
)
1652 return PtrCU
[i
].PtrVariables
[Index
- 1].PtrTypeName
;
1656 Index
-= PtrCU
[i
].NbVariables
;
1665 // Get global variable's type tag based on his index (starting from 1)
1666 // Return 0 if not found
1667 size_t DWARFManager_GetGlobalVariableTypeTag(size_t Index
)
1669 for (size_t i
= 0; i
< NbCU
; i
++)
1671 if (PtrCU
[i
].NbVariables
)
1673 if (Index
<= PtrCU
[i
].NbVariables
)
1675 return PtrCU
[i
].PtrVariables
[Index
- 1].TypeTag
;
1679 Index
-= PtrCU
[i
].NbVariables
;
1688 // Get global variable byte size based on his index (starting from 1)
1689 // Return 0 if not found
1690 size_t DWARFManager_GetGlobalVariableTypeByteSize(size_t Index
)
1692 for (size_t i
= 0; i
< NbCU
; i
++)
1694 if (PtrCU
[i
].NbVariables
)
1696 if (Index
<= PtrCU
[i
].NbVariables
)
1698 return PtrCU
[i
].PtrVariables
[Index
- 1].TypeByteSize
;
1702 Index
-= PtrCU
[i
].NbVariables
;
1711 // Get global variable encoding based on his index (starting from 1)
1712 // Return 0 if not found
1713 size_t DWARFManager_GetGlobalVariableTypeEncoding(size_t Index
)
1715 for (size_t i
= 0; i
< NbCU
; i
++)
1717 if (PtrCU
[i
].NbVariables
)
1719 if (Index
<= PtrCU
[i
].NbVariables
)
1721 return PtrCU
[i
].PtrVariables
[Index
- 1].TypeEncoding
;
1725 Index
-= PtrCU
[i
].NbVariables
;
1734 // Get global variable memory address based on his index (starting from 1)
1735 // Return 0 if not found
1736 size_t DWARFManager_GetGlobalVariableAdr(size_t Index
)
1738 for (size_t i
= 0; i
< NbCU
; i
++)
1740 if (PtrCU
[i
].NbVariables
)
1742 if (Index
<= PtrCU
[i
].NbVariables
)
1744 return PtrCU
[i
].PtrVariables
[Index
- 1].Addr
;
1748 Index
-= PtrCU
[i
].NbVariables
;
1757 // Get global variable memory address based on his name
1758 // Return 0 if not found, or will return the first occurence found
1759 size_t DWARFManager_GetGlobalVariableAdrFromName(char *VariableName
)
1761 for (size_t i
= 0; i
< NbCU
; i
++)
1763 if (PtrCU
[i
].NbVariables
)
1765 for (size_t j
= 0; j
< PtrCU
[i
].NbVariables
; j
++)
1767 if (!strcmp(PtrCU
[i
].PtrVariables
[j
].PtrName
,VariableName
))
1769 return PtrCU
[i
].PtrVariables
[j
].Addr
;
1779 // Get global variable name based on his index (starting from 1)
1780 // Return name's pointer text found, or will return NULL if no variable can be found
1781 char *DWARFManager_GetGlobalVariableName(size_t Index
)
1783 for (size_t i
= 0; i
< NbCU
; i
++)
1785 if (PtrCU
[i
].NbVariables
)
1787 if (Index
<= PtrCU
[i
].NbVariables
)
1789 return PtrCU
[i
].PtrVariables
[Index
- 1].PtrName
;
1793 Index
-= PtrCU
[i
].NbVariables
;
1802 // Get text line from source based on address and his tag
1803 // A tag can be either 0 or a DW_TAG_subprogram
1804 // DW_TAG_subprogram will look for the line pointing to the function
1805 // Return NULL if no text line has been found
1806 char *DWARFManager_GetLineSrcFromAdr(size_t Adr
, size_t Tag
)
1808 for (size_t i
= 0; i
< NbCU
; i
++)
1810 if ((Adr
>= PtrCU
[i
].LowPC
) && (Adr
< PtrCU
[i
].HighPC
))
1812 for (size_t j
= 0; j
< PtrCU
[i
].NbSubProgs
; j
++)
1814 if ((Adr
>= PtrCU
[i
].PtrSubProgs
[j
].LowPC
) && (Adr
< PtrCU
[i
].PtrSubProgs
[j
].HighPC
))
1816 if ((PtrCU
[i
].PtrSubProgs
[j
].StartPC
== Adr
) && (!Tag
|| (Tag
== DW_TAG_subprogram
)))
1818 return PtrCU
[i
].PtrSubProgs
[j
].PtrLineSrc
;
1822 for (size_t k
= 0; k
< PtrCU
[i
].PtrSubProgs
[j
].NbLinesSrc
; k
++)
1824 if (PtrCU
[i
].PtrSubProgs
[j
].PtrLinesSrc
[k
].StartPC
<= Adr
)
1826 if ((PtrCU
[i
].PtrSubProgs
[j
].PtrLinesSrc
[k
].StartPC
== Adr
) && (!Tag
|| (PtrCU
[i
].PtrSubProgs
[j
].PtrLinesSrc
[k
].Tag
== Tag
)))
1828 return PtrCU
[i
].PtrSubProgs
[j
].PtrLinesSrc
[k
].PtrLineSrc
;
1833 return PtrCU
[i
].PtrSubProgs
[j
].PtrLinesSrc
[k
- 1].PtrLineSrc
;
1846 // Get line number based on the address and a tag
1847 // A tag can be either 0 or a DW_TAG_subprogram
1848 // DW_TAG_subprogram will look for the line pointing to the function name as described in the source code
1849 // Return 0 if no line number has been found
1850 size_t DWARFManager_GetNumLineFromAdr(size_t Adr
, size_t Tag
)
1852 for (size_t i
= 0; i
< NbCU
; i
++)
1854 if ((Adr
>= PtrCU
[i
].LowPC
) && (Adr
< PtrCU
[i
].HighPC
))
1856 for (size_t j
= 0; j
< PtrCU
[i
].NbSubProgs
; j
++)
1858 if ((Adr
>= PtrCU
[i
].PtrSubProgs
[j
].LowPC
) && (Adr
< PtrCU
[i
].PtrSubProgs
[j
].HighPC
))
1860 if ((PtrCU
[i
].PtrSubProgs
[j
].StartPC
== Adr
) && (!Tag
|| (Tag
== DW_TAG_subprogram
)))
1862 return PtrCU
[i
].PtrSubProgs
[j
].NumLineSrc
;
1866 for (size_t k
= 0; k
< PtrCU
[i
].PtrSubProgs
[j
].NbLinesSrc
; k
++)
1868 if ((PtrCU
[i
].PtrSubProgs
[j
].PtrLinesSrc
[k
].StartPC
== Adr
) && (!Tag
|| (PtrCU
[i
].PtrSubProgs
[j
].PtrLinesSrc
[k
].Tag
== Tag
)))
1870 return PtrCU
[i
].PtrSubProgs
[j
].PtrLinesSrc
[k
].NumLineSrc
;
1875 if (!Tag
|| (Tag
== DW_TAG_subprogram
))
1877 return PtrCU
[i
].PtrSubProgs
[j
].NumLineSrc
;
1883 // Check if a used line is found with the address
1884 for (size_t j
= 0; j
< PtrCU
[i
].NbUsedLinesSrc
; j
++)
1886 if (PtrCU
[i
].PtrUsedLinesSrc
[j
].StartPC
== Adr
)
1888 return PtrCU
[i
].PtrUsedLinesSrc
[j
].NumLineSrc
;
1898 // Get function name based on an address
1899 // Return NULL if no function name has been found, otherwise will return the function name in the range of the provided address
1900 char *DWARFManager_GetFunctionName(size_t Adr
)
1902 for (size_t i
= 0; i
< NbCU
; i
++)
1904 if ((Adr
>= PtrCU
[i
].LowPC
) && (Adr
< PtrCU
[i
].HighPC
))
1906 for (size_t j
= 0; j
< PtrCU
[i
].NbSubProgs
; j
++)
1908 if ((Adr
>= PtrCU
[i
].PtrSubProgs
[j
].LowPC
) && (Adr
< PtrCU
[i
].PtrSubProgs
[j
].HighPC
))
1910 return PtrCU
[i
].PtrSubProgs
[j
].PtrSubprogramName
;
1920 // Get number of lines of texts source list from source index
1921 size_t DWARFManager_GetSrcNbListPtrFromIndex(size_t Index
, bool Used
)
1925 return PtrCU
[Index
].NbLinesLoadSrc
;
1929 return PtrCU
[Index
].NbUsedLinesSrc
;
1934 // Get text source line number list pointer from source index
1935 // Return NULL for the text source used list
1936 size_t *DWARFManager_GetSrcNumLinesPtrFromIndex(size_t Index
, bool Used
)
1940 return PtrCU
[Index
].PtrUsedNumLines
;
1949 // Get text source list pointers from source index
1950 // Return NULL for the text source used list
1951 char **DWARFManager_GetSrcListPtrFromIndex(size_t Index
, bool Used
)
1955 return PtrCU
[Index
].PtrLinesLoadSrc
;
1959 return PtrCU
[Index
].PtrUsedLinesLoadSrc
;
1964 // Get source language
1965 size_t DWARFManager_GetSrcLanguageFromIndex(size_t Index
)
1967 return PtrCU
[Index
].Language
;
1971 // Get text line from source based on address and num line (starting from 1)
1972 // Return NULL if no text line has been found
1973 char *DWARFManager_GetLineSrcFromAdrNumLine(size_t Adr
, size_t NumLine
)
1975 for (size_t i
= 0; i
< NbCU
; i
++)
1977 if ((Adr
>= PtrCU
[i
].LowPC
) && (Adr
< PtrCU
[i
].HighPC
))
1979 for (size_t j
= 0; j
< PtrCU
[i
].NbSubProgs
; j
++)
1981 if ((Adr
>= PtrCU
[i
].PtrSubProgs
[j
].LowPC
) && (Adr
< PtrCU
[i
].PtrSubProgs
[j
].HighPC
))
1983 if (PtrCU
[i
].PtrSubProgs
[j
].NumLineSrc
== NumLine
)
1985 return PtrCU
[i
].PtrSubProgs
[j
].PtrLineSrc
;
1989 for (size_t k
= 0; k
< PtrCU
[i
].PtrSubProgs
[j
].NbLinesSrc
; k
++)
1991 if (PtrCU
[i
].PtrSubProgs
[j
].PtrLinesSrc
[k
].NumLineSrc
== NumLine
)
1993 return PtrCU
[i
].PtrSubProgs
[j
].PtrLinesSrc
[k
].PtrLineSrc
;
2006 // Get text line pointer from source, based on address and line number (starting from 1)
2007 // Return NULL if no text line has been found, or if requested number line is above the source total number of lines
2008 char *DWARFManager_GetLineSrcFromNumLineBaseAdr(size_t Adr
, size_t NumLine
)
2010 for (size_t i
= 0; i
< NbCU
; i
++)
2012 if ((Adr
>= PtrCU
[i
].LowPC
) && (Adr
< PtrCU
[i
].HighPC
))
2014 if (NumLine
<= PtrCU
[i
].NbLinesLoadSrc
)
2016 return PtrCU
[i
].PtrLinesLoadSrc
[NumLine
- 1];
2029 // Get number of source code filenames
2030 size_t DWARFManager_GetNbSources(void)
2036 // Get source code filename, including his directory, based on index (starting from 0)
2037 char *DWARFManager_GetNumFullSourceFilename(size_t Index
)
2039 return (PtrCU
[Index
].PtrFullFilename
);
2043 // Get source code filename based on index (starting from 0)
2044 char *DWARFManager_GetNumSourceFilename(size_t Index
)
2046 return (PtrCU
[Index
].PtrSourceFilename
);