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