df4f67180209f06b456bc14c7cf75097b99fb1c3
[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 Oct./2018 Improve the DWARF parsing information
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 "cmd.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 // Read the file as text
437 #ifndef __CYGWIN__
438 if (!fopen_s(&SrcFile, PtrCU[NbCU].PtrFullFilename, "rt"))
439 #else
440 if (!(SrcFile = fopen(SourceFullFilename, "rt")))
441 #endif
442 {
443 if (!fseek(SrcFile, 0, SEEK_END))
444 {
445 if ((PtrCU[NbCU].SizeLoadSrc = ftell(SrcFile)) > 0)
446 {
447 if (PtrCU[NbCU].PtrLoadSrc = Ptr = (char *)calloc((PtrCU[NbCU].SizeLoadSrc + 1), 1))
448 {
449 rewind(SrcFile);
450 if (PtrCU[NbCU].SizeLoadSrc < fread(Ptr, 1, PtrCU[NbCU].SizeLoadSrc, SrcFile))
451 {
452 free(PtrCU[NbCU].PtrLoadSrc);
453 PtrCU[NbCU].PtrLoadSrc = NULL;
454 PtrCU[NbCU].SizeLoadSrc = 0;
455 }
456 else
457 {
458 do
459 {
460 if (*Ptr == 0xa)
461 {
462 PtrCU[NbCU].NbLinesLoadSrc++;
463 *Ptr = 0;
464 }
465 } while (*++Ptr);
466 }
467 }
468 }
469 }
470 fclose(SrcFile);
471 }
472 break;
473
474 default:
475 break;
476 }
477 }
478
479 // Get the source lines table located in the Compilation Unit
480 if (dwarf_srclines(return_sib, &linebuf, &cnt, &error) == DW_DLV_OK)
481 {
482 }
483
484 // Check if the CU has child
485 if (dwarf_child(return_sib, &return_die, &error) == DW_DLV_OK)
486 {
487 do
488 {
489 return_sib = return_die;
490 if ((dwarf_tag(return_die, &return_tagval, &error) == DW_DLV_OK))
491 {
492 switch (return_tagval)
493 {
494 case DW_TAG_lexical_block:
495 break;
496
497 case DW_TAG_variable:
498 if (dwarf_attrlist(return_die, &atlist, &atcnt, &error) == DW_DLV_OK)
499 {
500 PtrCU[NbCU].PtrVariables = (VariablesStruct *)realloc(PtrCU[NbCU].PtrVariables, ((PtrCU[NbCU].NbVariables + 1) * sizeof(VariablesStruct)));
501 memset(PtrCU[NbCU].PtrVariables + PtrCU[NbCU].NbVariables, 0, sizeof(VariablesStruct));
502
503 for (Dwarf_Signed i = 0; i < atcnt; ++i)
504 {
505 if (dwarf_whatattr(atlist[i], &return_attr, &error) == DW_DLV_OK)
506 {
507 if (dwarf_attr(return_die, return_attr, &return_attr1, &error) == DW_DLV_OK)
508 {
509 switch (return_attr)
510 {
511 case DW_AT_location:
512 if (dwarf_formblock(return_attr1, &return_block, &error) == DW_DLV_OK)
513 {
514 PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].Op = (*((unsigned char *)(return_block->bl_data)));
515
516 switch (return_block->bl_len)
517 {
518 case 5:
519 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));
520 break;
521
522 default:
523 break;
524 }
525 dwarf_dealloc(dbg, return_block, DW_DLA_BLOCK);
526 }
527 break;
528
529 case DW_AT_type:
530 if (dwarf_global_formref(return_attr1, &return_offset, &error) == DW_DLV_OK)
531 {
532 PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].TypeOffset = return_offset;
533 }
534 break;
535
536 // Variable name
537 case DW_AT_name:
538 if (dwarf_formstring(return_attr1, &return_string, &error) == DW_DLV_OK)
539 {
540 #ifdef DEBUG_VariableName
541 if (!strcmp(return_string, DEBUG_VariableName))
542 #endif
543 {
544 PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName = (char *)calloc(strlen(return_string) + 1, 1);
545 strcpy(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName, return_string);
546 }
547 dwarf_dealloc(dbg, return_string, DW_DLA_STRING);
548 }
549 break;
550
551 default:
552 break;
553 }
554 }
555 }
556
557 dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);
558 }
559
560 // Check variable's name validity
561 if (PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName)
562 {
563 // Check variable's memory address validity
564 if (PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].Addr)
565 {
566 // Valid variable
567 PtrCU[NbCU].NbVariables++;
568 }
569 else
570 {
571 // Invalid variable
572 free(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName);
573 PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName = NULL;
574 }
575 }
576
577 dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
578 }
579 break;
580
581 case DW_TAG_base_type:
582 case DW_TAG_typedef:
583 case DW_TAG_structure_type:
584 case DW_TAG_pointer_type:
585 case DW_TAG_const_type:
586 case DW_TAG_array_type:
587 case DW_TAG_subrange_type:
588 case DW_TAG_subroutine_type:
589 case DW_TAG_enumeration_type:
590 if (dwarf_attrlist(return_die, &atlist, &atcnt, &error) == DW_DLV_OK)
591 {
592 // Allocate memory for this type
593 PtrCU[NbCU].PtrTypes = (BaseTypeStruct *)realloc(PtrCU[NbCU].PtrTypes, ((PtrCU[NbCU].NbTypes + 1) * sizeof(BaseTypeStruct)));
594 memset(PtrCU[NbCU].PtrTypes + PtrCU[NbCU].NbTypes, 0, sizeof(BaseTypeStruct));
595 PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].Tag = return_tagval;
596
597 if (dwarf_dieoffset(return_die, &return_offset, &error) == DW_DLV_OK)
598 {
599 PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].Offset = return_offset;
600 }
601
602 for (Dwarf_Signed i = 0; i < atcnt; ++i)
603 {
604 if (dwarf_whatattr(atlist[i], &return_attr, &error) == DW_DLV_OK)
605 {
606 if (dwarf_attr(return_die, return_attr, &return_attr1, &error) == DW_DLV_OK)
607 {
608 switch (return_attr)
609 {
610 //
611 case DW_AT_sibling:
612 break;
613
614 // Type's type offset
615 case DW_AT_type:
616 if (dwarf_global_formref(return_attr1, &return_offset, &error) == DW_DLV_OK)
617 {
618 PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].TypeOffset = return_offset;
619 }
620 break;
621
622 // Type's byte size
623 case DW_AT_byte_size:
624 if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK)
625 {
626 PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].ByteSize = return_uvalue;
627 }
628 break;
629
630 // Type's encoding
631 case DW_AT_encoding:
632 if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK)
633 {
634 PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].Encoding = return_uvalue;
635 }
636 break;
637
638 // Type's name
639 case DW_AT_name:
640 if (dwarf_formstring(return_attr1, &return_string, &error) == DW_DLV_OK)
641 {
642 #ifdef DEBUG_TypeName
643 if (!strcmp(return_string, DEBUG_TypeName))
644 #endif
645 {
646 PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName = (char *)calloc(strlen(return_string) + 1, 1);
647 strcpy(PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName, return_string);
648 }
649 dwarf_dealloc(dbg, return_string, DW_DLA_STRING);
650 }
651 break;
652
653 // Type's file number
654 case DW_AT_decl_file:
655 break;
656
657 // Type's line number
658 case DW_AT_decl_line:
659 break;
660
661 default:
662 break;
663 }
664 }
665 }
666
667 dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);
668 }
669
670 PtrCU[NbCU].NbTypes++;
671
672 dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
673 }
674 break;
675
676 case DW_TAG_subprogram:
677 if (dwarf_attrlist(return_die, &atlist, &atcnt, &error) == DW_DLV_OK)
678 {
679 PtrCU[NbCU].PtrSubProgs = (SubProgStruct *)realloc(PtrCU[NbCU].PtrSubProgs, ((PtrCU[NbCU].NbSubProgs + 1) * sizeof(SubProgStruct)));
680 memset((void *)(PtrCU[NbCU].PtrSubProgs + PtrCU[NbCU].NbSubProgs), 0, sizeof(SubProgStruct));
681 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].Tag = return_tagval;
682
683 for (Dwarf_Signed i = 0; i < atcnt; ++i)
684 {
685 if (dwarf_whatattr(atlist[i], &return_attr, &error) == DW_DLV_OK)
686 {
687 if (dwarf_attr(return_die, return_attr, &return_attr1, &error) == DW_DLV_OK)
688 {
689 switch (return_attr)
690 {
691 // start address
692 case DW_AT_low_pc:
693 if (dwarf_lowpc(return_die, &return_lowpc, &error) == DW_DLV_OK)
694 {
695 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].StartPC = return_lowpc;
696 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].LowPC = return_lowpc;
697 }
698 break;
699
700 // end address
701 case DW_AT_high_pc:
702 if (dwarf_highpc(return_die, &return_highpc, &error) == DW_DLV_OK)
703 {
704 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].HighPC = return_highpc;
705 }
706 break;
707
708 // Line number
709 case DW_AT_decl_line:
710 if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK)
711 {
712 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NumLineSrc = return_uvalue;
713 }
714 break;
715
716 // Frame
717 case DW_AT_frame_base:
718 if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK)
719 {
720 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].FrameBase = return_uvalue;
721 PtrCU[NbCU].NbFrames++;
722 }
723 break;
724
725 // function name
726 case DW_AT_name:
727 if (dwarf_formstring(return_attr1, &return_string, &error) == DW_DLV_OK)
728 {
729 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrSubprogramName = (char *)calloc(strlen(return_string) + 1, 1);
730 strcpy(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrSubprogramName, return_string);
731 dwarf_dealloc(dbg, return_string, DW_DLA_STRING);
732 }
733 break;
734
735 case DW_AT_sibling:
736 break;
737
738 case DW_AT_GNU_all_tail_call_sites:
739 break;
740
741 case DW_AT_type:
742 break;
743
744 case DW_AT_prototyped:
745 break;
746
747 // File number
748 case DW_AT_decl_file:
749 break;
750
751 case DW_AT_external:
752 break;
753
754 default:
755 break;
756 }
757 }
758 }
759 dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);
760 }
761 dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
762
763 // Get source line number and associated block of address
764 for (Dwarf_Signed i = 0; i < cnt; ++i)
765 {
766 if (dwarf_lineaddr(linebuf[i], &return_lineaddr, &error) == DW_DLV_OK)
767 {
768 if (dwarf_lineno(linebuf[i], &return_uvalue, &error) == DW_DLV_OK)
769 {
770 if ((return_lineaddr >= return_lowpc) && (return_lineaddr <= return_highpc))
771 {
772 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));
773 memset((void *)(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc + PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc), 0, sizeof(DMIStruct_LineSrc));
774 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc].StartPC = return_lineaddr;
775 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc].NumLineSrc = return_uvalue;
776 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc++;
777 }
778 }
779 }
780 }
781
782 if (dwarf_child(return_die, &return_subdie, &error) == DW_DLV_OK)
783 {
784 do
785 {
786 return_sub = return_subdie;
787 if ((dwarf_tag(return_subdie, &return_tagval, &error) == DW_DLV_OK))
788 {
789 switch (return_tagval)
790 {
791 case DW_TAG_formal_parameter:
792 case DW_TAG_variable:
793 if (dwarf_attrlist(return_subdie, &atlist, &atcnt, &error) == DW_DLV_OK)
794 {
795 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)));
796 memset(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables + PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables, 0, sizeof(VariablesStruct));
797
798 for (Dwarf_Signed i = 0; i < atcnt; ++i)
799 {
800 if (dwarf_whatattr(atlist[i], &return_attr, &error) == DW_DLV_OK)
801 {
802 if (dwarf_attr(return_subdie, return_attr, &return_attr1, &error) == DW_DLV_OK)
803 {
804 switch (return_attr)
805 {
806 case DW_AT_location:
807 if (dwarf_formblock(return_attr1, &return_block, &error) == DW_DLV_OK)
808 {
809 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].Op = *((unsigned char *)(return_block->bl_data));
810
811 switch (return_block->bl_len)
812 {
813 case 1:
814 break;
815
816 case 2:
817 case 3:
818 switch (return_tagval)
819 {
820 case DW_TAG_variable:
821 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].Offset = ReadLEB128((char *)return_block->bl_data + 1);
822 break;
823
824 case DW_TAG_formal_parameter:
825 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].Offset = ReadULEB128((char *)return_block->bl_data + 1);
826 break;
827
828 default:
829 break;
830 }
831 break;
832
833 default:
834 break;
835 }
836 dwarf_dealloc(dbg, return_block, DW_DLA_BLOCK);
837 }
838 break;
839
840 case DW_AT_type:
841 if (dwarf_global_formref(return_attr1, &return_offset, &error) == DW_DLV_OK)
842 {
843 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].TypeOffset = return_offset;
844 }
845 break;
846
847 case DW_AT_name:
848 if (dwarf_formstring(return_attr1, &return_string, &error) == DW_DLV_OK)
849 {
850 #ifdef DEBUG_VariableName
851 if (!strcmp(return_string, DEBUG_VariableName))
852 #endif
853 {
854 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].PtrName = (char *)calloc(strlen(return_string) + 1, 1);
855 strcpy(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrVariables[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables].PtrName, return_string);
856 }
857 dwarf_dealloc(dbg, return_string, DW_DLA_STRING);
858 }
859 break;
860
861 case DW_AT_decl_file:
862 break;
863
864 case DW_AT_decl_line:
865 break;
866
867 default:
868 break;
869 }
870 }
871 }
872
873 dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);
874 }
875
876 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbVariables++;
877
878 dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
879 }
880 break;
881
882 case DW_TAG_label:
883 break;
884
885 default:
886 break;
887 }
888 }
889 }
890 while (dwarf_siblingof(dbg, return_sub, &return_subdie, &error) == DW_DLV_OK);
891 }
892
893 PtrCU[NbCU].NbSubProgs++;
894 }
895 break;
896
897 default:
898 break;
899 }
900 }
901 }
902 while (dwarf_siblingof(dbg, return_sib, &return_die, &error) == DW_DLV_OK);
903 }
904
905 // Release the memory used by the source lines
906 for (Dwarf_Signed i = 0; i < cnt; ++i)
907 {
908 dwarf_dealloc(dbg, linebuf[i], DW_DLA_LINE);
909 }
910 dwarf_dealloc(dbg, linebuf, DW_DLA_LIST);
911 }
912
913 // Set the source code lines for QT html/text conformity
914 if (PtrCU[NbCU].NbLinesLoadSrc)
915 {
916 if (PtrCU[NbCU].PtrLinesLoadSrc = (char **)calloc(PtrCU[NbCU].NbLinesLoadSrc, sizeof(char *)))
917 {
918 for (size_t j = 0; j < PtrCU[NbCU].NbLinesLoadSrc; j++)
919 {
920 if (PtrCU[NbCU].PtrLinesLoadSrc[j] = (char *)calloc(10000, sizeof(char)))
921 {
922 if (Ptr = DWARFManager_GetLineSrcFromNumLine(PtrCU[NbCU].PtrLoadSrc, (j + 1)))
923 {
924 size_t i = 0;
925
926 while (*Ptr)
927 {
928 switch (*Ptr)
929 {
930 case 9:
931 strcat(PtrCU[NbCU].PtrLinesLoadSrc[j], "&nbsp;");
932 i += 6;
933 break;
934
935 case '<':
936 strcat(PtrCU[NbCU].PtrLinesLoadSrc[j], "&lt;");
937 i += 4;
938 break;
939
940 case '>':
941 strcat(PtrCU[NbCU].PtrLinesLoadSrc[j], "&gt;");
942 i += 4;
943 break;
944 #if 0
945 case '&':
946 strcpy(PtrCU[NbCU].PtrLinesLoadSrc[j], "&amp;");
947 i += strlen("&amp;");
948 break;
949 #endif
950 #if 0
951 case '"':
952 strcpy(PtrCU[NbCU].PtrLinesLoadSrc[j], "&quot;");
953 i += strlen("&quot;");
954 break;
955 #endif
956 default:
957 PtrCU[NbCU].PtrLinesLoadSrc[j][i++] = *Ptr;
958 break;
959 }
960 Ptr++;
961 }
962 }
963 PtrCU[NbCU].PtrLinesLoadSrc[j] = (char *)realloc(PtrCU[NbCU].PtrLinesLoadSrc[j], strlen(PtrCU[NbCU].PtrLinesLoadSrc[j]) + 1);
964 }
965 }
966
967 // Init lines source information based on each source code line numbers
968 for (size_t j = 0; j < PtrCU[NbCU].NbSubProgs; j++)
969 {
970 // Check if the subprog / function's line exists in the source code
971 if (PtrCU[NbCU].PtrSubProgs[j].NumLineSrc <= PtrCU[NbCU].NbLinesLoadSrc)
972 {
973 PtrCU[NbCU].PtrSubProgs[j].PtrLineSrc = PtrCU[NbCU].PtrLinesLoadSrc[PtrCU[NbCU].PtrSubProgs[j].NumLineSrc - 1];
974 }
975
976 for (size_t k = 0; k < PtrCU[NbCU].PtrSubProgs[j].NbLinesSrc; k++)
977 {
978 if (PtrCU[NbCU].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc <= PtrCU[NbCU].NbLinesLoadSrc)
979 {
980 PtrCU[NbCU].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc = PtrCU[NbCU].PtrLinesLoadSrc[PtrCU[NbCU].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc - 1];
981 }
982 }
983 }
984 }
985 }
986 else
987 {
988 // Set each source lines pointer to NULL
989 if (PtrCU[NbCU].NbSubProgs)
990 {
991 // Check the presence of source lines dedicated to the sub progs
992 if (PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs - 1].NbLinesSrc)
993 {
994 size_t i = PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs - 1].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs - 1].NbLinesSrc - 1].NumLineSrc;
995 if (PtrCU[NbCU].PtrLinesLoadSrc = (char **)calloc(i, sizeof(char *)))
996 {
997 for (size_t j = 0; j < i; j++)
998 {
999 PtrCU[NbCU].PtrLinesLoadSrc[j] = NULL;
1000 }
1001 }
1002 }
1003 }
1004 }
1005
1006 // Init global variables information based on types information
1007 for (size_t i = 0; i < PtrCU[NbCU].NbVariables; i++)
1008 {
1009 DWARFManager_InitInfosVariable(PtrCU[NbCU].PtrVariables + i);
1010 }
1011
1012 // Init local variables information based on types information
1013 for (size_t i = 0; i < PtrCU[NbCU].NbSubProgs; i++)
1014 {
1015 for (size_t j = 0; j < PtrCU[NbCU].PtrSubProgs[i].NbVariables; j++)
1016 {
1017 DWARFManager_InitInfosVariable(PtrCU[NbCU].PtrSubProgs[i].PtrVariables + j);
1018 }
1019 }
1020 }
1021
1022 ++NbCU;
1023 }
1024 }
1025 }
1026
1027
1028 // Variables information initialisation
1029 void DWARFManager_InitInfosVariable(VariablesStruct *PtrVariables)
1030 {
1031 size_t j, TypeOffset;
1032
1033 #ifdef DEBUG_VariableName
1034 if (PtrVariables->PtrName && !strcmp(PtrVariables->PtrName, DEBUG_VariableName))
1035 #endif
1036 {
1037 PtrVariables->PtrTypeName = (char *)calloc(1000, 1);
1038 TypeOffset = PtrVariables->TypeOffset;
1039
1040 for (j = 0; j < PtrCU[NbCU].NbTypes; j++)
1041 {
1042 if (TypeOffset == PtrCU[NbCU].PtrTypes[j].Offset)
1043 {
1044 switch (PtrCU[NbCU].PtrTypes[j].Tag)
1045 {
1046 case DW_TAG_subroutine_type:
1047 PtrVariables->TypeTag |= TypeTag_subroutine_type;
1048 strcat(PtrVariables->PtrTypeName, " (* ) ()");
1049 break;
1050
1051 // Structure type tag
1052 case DW_TAG_structure_type:
1053 PtrVariables->TypeTag |= TypeTag_structure;
1054 if (!(PtrVariables->TypeTag & TypeTag_typedef))
1055 {
1056 strcat(PtrVariables->PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);
1057 }
1058 if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))
1059 {
1060 j = -1;
1061 }
1062 else
1063 {
1064 if ((PtrVariables->TypeTag & TypeTag_pointer))
1065 {
1066 strcat(PtrVariables->PtrTypeName, " *");
1067 }
1068 }
1069 break;
1070
1071 // Pointer type tag
1072 case DW_TAG_pointer_type:
1073 PtrVariables->TypeTag |= TypeTag_pointer;
1074 PtrVariables->TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;
1075 PtrVariables->TypeEncoding = 0x10;
1076 if (!(TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))
1077 {
1078 strcat(PtrVariables->PtrTypeName, "void *");
1079 }
1080 else
1081 {
1082 j = -1;
1083 }
1084 break;
1085
1086 case DW_TAG_enumeration_type:
1087 PtrVariables->TypeTag |= TypeTag_enumeration_type;
1088 PtrVariables->TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;
1089 if (!(PtrVariables->TypeEncoding = PtrCU[NbCU].PtrTypes[j].Encoding))
1090 {
1091 // Try to determine the possible size
1092 switch (PtrVariables->TypeByteSize)
1093 {
1094 case 4:
1095 PtrVariables->TypeEncoding = 0x7;
1096 break;
1097
1098 default:
1099 break;
1100 }
1101 }
1102 break;
1103
1104 // Typedef type tag
1105 case DW_TAG_typedef:
1106 if (!(PtrVariables->TypeTag & TypeTag_typedef))
1107 {
1108 PtrVariables->TypeTag |= TypeTag_typedef;
1109 strcat(PtrVariables->PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);
1110 }
1111 if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))
1112 {
1113 j = -1;
1114 }
1115 break;
1116
1117 // ? type tag
1118 case DW_TAG_subrange_type:
1119 PtrVariables->TypeTag |= TypeTag_subrange;
1120 break;
1121
1122 // Array type tag
1123 case DW_TAG_array_type:
1124 PtrVariables->TypeTag |= TypeTag_arraytype;
1125 if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))
1126 {
1127 j = -1;
1128 }
1129 break;
1130
1131 // Const type tag
1132 case DW_TAG_const_type:
1133 PtrVariables->TypeTag |= TypeTag_consttype;
1134 strcat(PtrVariables->PtrTypeName, "const ");
1135 if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))
1136 {
1137 j = -1;
1138 }
1139 break;
1140
1141 // Base type tag
1142 case DW_TAG_base_type:
1143 if (!(PtrVariables->TypeTag & TypeTag_typedef))
1144 {
1145 strcat(PtrVariables->PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);
1146 }
1147 if ((PtrVariables->TypeTag & TypeTag_pointer))
1148 {
1149 strcat(PtrVariables->PtrTypeName, " *");
1150 }
1151 else
1152 {
1153 PtrVariables->TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;
1154 PtrVariables->TypeEncoding = PtrCU[NbCU].PtrTypes[j].Encoding;
1155 }
1156 if ((PtrVariables->TypeTag & TypeTag_arraytype))
1157 {
1158 strcat(PtrVariables->PtrTypeName, "[]");
1159 }
1160 break;
1161
1162 default:
1163 break;
1164 }
1165 }
1166 }
1167 }
1168 }
1169
1170
1171 // Get symbol name based from address
1172 // Return NULL if no symbol name exists
1173 char *DWARFManager_GetSymbolnameFromAdr(size_t Adr)
1174 {
1175 size_t i, j;
1176
1177 for (i = 0; i < NbCU; i++)
1178 {
1179 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1180 {
1181 for (j = 0; (j < PtrCU[i].NbSubProgs); j++)
1182 {
1183 if ((PtrCU[i].PtrSubProgs[j].StartPC == Adr))
1184 {
1185 return PtrCU[i].PtrSubProgs[j].PtrSubprogramName;
1186 }
1187 }
1188 }
1189 }
1190
1191 return NULL;
1192 }
1193
1194
1195 // Get complete source filename based from address
1196 // Return NULL if no source filename exists
1197 // Return the existence status (true or false) in Error
1198 char *DWARFManager_GetFullSourceFilenameFromAdr(size_t Adr, bool *Error)
1199 {
1200 size_t i;
1201
1202 for (i = 0; i < NbCU; i++)
1203 {
1204 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1205 {
1206 *Error = PtrCU[i].PtrLoadSrc ? true : false;
1207 return PtrCU[i].PtrFullFilename;
1208 }
1209 }
1210
1211 return NULL;
1212 }
1213
1214
1215 // Get text line source based on line number (starting by 1)
1216 // Return NULL if no text line exists or if line number is 0
1217 char *DWARFManager_GetLineSrcFromNumLine(char *PtrSrcFile, size_t NumLine)
1218 {
1219 size_t i = 0;
1220 char *PtrLineSrc = NULL;
1221
1222 if (PtrSrcFile)
1223 {
1224 while (i != NumLine)
1225 {
1226 PtrLineSrc = PtrSrcFile;
1227 while (*PtrSrcFile++);
1228 i++;
1229 }
1230 }
1231
1232 return PtrLineSrc;
1233 }
1234
1235
1236 // Get number of variables referenced by the function range address
1237 size_t DWARFManager_GetNbLocalVariables(size_t Adr)
1238 {
1239 size_t i, j;
1240
1241 for (i = 0; i < NbCU; i++)
1242 {
1243 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1244 {
1245 for (j = 0; j < PtrCU[i].NbSubProgs; j++)
1246 {
1247 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1248 {
1249 return PtrCU[i].PtrSubProgs[j].NbVariables;
1250 }
1251 }
1252 }
1253 }
1254
1255 return 0;
1256 }
1257
1258
1259 // Get local variable name based on his index (starting by 1)
1260 // Return name's pointer text found
1261 // Return NULL if not found
1262 char *DWARFManager_GetLocalVariableName(size_t Adr, size_t Index)
1263 {
1264 size_t i, j;
1265
1266 for (i = 0; i < NbCU; i++)
1267 {
1268 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1269 {
1270 for (j = 0; j < PtrCU[i].NbSubProgs; j++)
1271 {
1272 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1273 {
1274 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].PtrName;
1275 }
1276 }
1277 }
1278 }
1279
1280 return NULL;
1281 }
1282
1283
1284 // Get local variable's type tag based on his index (starting by 1)
1285 // Return 0 if not found
1286 size_t DWARFManager_GetLocalVariableTypeTag(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].TypeTag;
1299 }
1300 }
1301 }
1302 }
1303
1304 return 0;
1305 }
1306
1307
1308 //
1309 int DWARFManager_GetLocalVariableOffset(size_t Adr, size_t Index)
1310 {
1311 size_t i, j;
1312
1313 for (i = 0; i < NbCU; i++)
1314 {
1315 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1316 {
1317 for (j = 0; j < PtrCU[i].NbSubProgs; j++)
1318 {
1319 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1320 {
1321 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].Offset;
1322 }
1323 }
1324 }
1325 }
1326
1327 return 0;
1328 }
1329
1330
1331 // Get local variable Type Byte Size based on his address and index (starting by 1)
1332 // Return 0 if not found
1333 // May return 0 if there is no Type Byte Size linked to the variable's address and index
1334 size_t DWARFManager_GetLocalVariableTypeByteSize(size_t Adr, size_t Index)
1335 {
1336 size_t i, j;
1337
1338 for (i = 0; i < NbCU; i++)
1339 {
1340 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1341 {
1342 for (j = 0; j < PtrCU[i].NbSubProgs; j++)
1343 {
1344 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1345 {
1346 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].TypeByteSize;
1347 }
1348 }
1349 }
1350 }
1351
1352 return 0;
1353 }
1354
1355
1356 // Get local variable Type Encoding based on his address and index (starting by 1)
1357 // Return 0 if not found
1358 // May return 0 if there is no Type Encoding linked to the variable's address and index
1359 size_t DWARFManager_GetLocalVariableTypeEncoding(size_t Adr, size_t Index)
1360 {
1361 size_t i, j;
1362
1363 for (i = 0; i < NbCU; i++)
1364 {
1365 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1366 {
1367 for (j = 0; j < PtrCU[i].NbSubProgs; j++)
1368 {
1369 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1370 {
1371 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].TypeEncoding;
1372 }
1373 }
1374 }
1375 }
1376
1377 return 0;
1378 }
1379
1380
1381 // Get local variable Op based on his address and index (starting by 1)
1382 // Return 0 if not found
1383 // May return 0 if there isn't Op linked to the variable's index
1384 size_t DWARFManager_GetLocalVariableOp(size_t Adr, size_t Index)
1385 {
1386 size_t i, j;
1387
1388 for (i = 0; i < NbCU; i++)
1389 {
1390 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1391 {
1392 for (j = 0; j < PtrCU[i].NbSubProgs; j++)
1393 {
1394 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1395 {
1396 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].Op;
1397 }
1398 }
1399 }
1400 }
1401
1402 return 0;
1403 }
1404
1405
1406 // Get local variable type name based on his index (starting by 1)
1407 // Return NULL if not found
1408 // May return NULL if there is not type linked to the variable's index
1409 char *DWARFManager_GetLocalVariableTypeName(size_t Adr, size_t Index)
1410 {
1411 size_t i, j;
1412
1413 for (i = 0; i < NbCU; i++)
1414 {
1415 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1416 {
1417 for (j = 0; j < PtrCU[i].NbSubProgs; j++)
1418 {
1419 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1420 {
1421 return PtrCU[i].PtrSubProgs[j].PtrVariables[Index - 1].PtrTypeName;
1422 }
1423 }
1424 }
1425 }
1426
1427 return NULL;
1428 }
1429
1430
1431 // Get Compilation Unit / global variables numbers
1432 // Return variables number
1433 size_t DWARFManager_GetNbGlobalVariables(void)
1434 {
1435 size_t NbVariables = 0, i;
1436
1437 for (i = 0; i < NbCU; i++)
1438 {
1439 NbVariables += PtrCU[i].NbVariables;
1440 }
1441
1442 return NbVariables;
1443 }
1444
1445
1446 // Get global variable type name based on his index (starting by 1)
1447 // Return NULL if not found
1448 // May return NULL if there is not type linked to the variable's index
1449 char *DWARFManager_GetGlobalVariableTypeName(size_t Index)
1450 {
1451 size_t i;
1452
1453 for (i = 0; i < NbCU; i++)
1454 {
1455 if (PtrCU[i].NbVariables)
1456 {
1457 if (Index <= PtrCU[i].NbVariables)
1458 {
1459 return PtrCU[i].PtrVariables[Index - 1].PtrTypeName;
1460 }
1461 else
1462 {
1463 Index -= PtrCU[i].NbVariables;
1464 }
1465 }
1466 }
1467
1468 return NULL;
1469 }
1470
1471
1472 // Get global variable's type tag based on his index (starting by 1)
1473 // Return 0 if not found
1474 size_t DWARFManager_GetGlobalVariableTypeTag(size_t Index)
1475 {
1476 size_t i;
1477
1478 for (i = 0; i < NbCU; i++)
1479 {
1480 if (PtrCU[i].NbVariables)
1481 {
1482 if (Index <= PtrCU[i].NbVariables)
1483 {
1484 return PtrCU[i].PtrVariables[Index - 1].TypeTag;
1485 }
1486 else
1487 {
1488 Index -= PtrCU[i].NbVariables;
1489 }
1490 }
1491 }
1492
1493 return 0;
1494 }
1495
1496
1497 // Get global variable byte size based on his index (starting by 1)
1498 // Return 0 if not found
1499 size_t DWARFManager_GetGlobalVariableTypeByteSize(size_t Index)
1500 {
1501 size_t i;
1502
1503 for (i = 0; i < NbCU; i++)
1504 {
1505 if (PtrCU[i].NbVariables)
1506 {
1507 if (Index <= PtrCU[i].NbVariables)
1508 {
1509 return PtrCU[i].PtrVariables[Index - 1].TypeByteSize;
1510 }
1511 else
1512 {
1513 Index -= PtrCU[i].NbVariables;
1514 }
1515 }
1516 }
1517
1518 return 0;
1519 }
1520
1521
1522 // Get global variable encoding based on his index (starting by 1)
1523 // Return 0 if not found
1524 size_t DWARFManager_GetGlobalVariableTypeEncoding(size_t Index)
1525 {
1526 size_t i;
1527
1528 for (i = 0; i < NbCU; i++)
1529 {
1530 if (PtrCU[i].NbVariables)
1531 {
1532 if (Index <= PtrCU[i].NbVariables)
1533 {
1534 return PtrCU[i].PtrVariables[Index - 1].TypeEncoding;
1535 }
1536 else
1537 {
1538 Index -= PtrCU[i].NbVariables;
1539 }
1540 }
1541 }
1542
1543 return 0;
1544 }
1545
1546
1547 // Get global variable address based on his index (starting by 1)
1548 // Return 0 if not found
1549 size_t DWARFManager_GetGlobalVariableAdr(size_t Index)
1550 {
1551 size_t i;
1552
1553 for (i = 0; i < NbCU; i++)
1554 {
1555 if (PtrCU[i].NbVariables)
1556 {
1557 if (Index <= PtrCU[i].NbVariables)
1558 {
1559 return PtrCU[i].PtrVariables[Index - 1].Addr;
1560 }
1561 else
1562 {
1563 Index -= PtrCU[i].NbVariables;
1564 }
1565 }
1566 }
1567
1568 return 0;
1569 }
1570
1571
1572 // Get global variable memory address based on his name
1573 // Return 0 if not found
1574 // Note: Return the first occurence found
1575 size_t DWARFManager_GetGlobalVariableAdrFromName(char *VariableName)
1576 {
1577 size_t i, j;
1578
1579 for (i = 0; i < NbCU; i++)
1580 {
1581 if (PtrCU[i].NbVariables)
1582 {
1583 for (j = 0; j < PtrCU[i].NbVariables; j++)
1584 {
1585 if (!strcmp(PtrCU[i].PtrVariables[j].PtrName,VariableName))
1586 {
1587 return PtrCU[i].PtrVariables[j].Addr;
1588 }
1589 }
1590 }
1591 }
1592
1593 return 0;
1594 }
1595
1596
1597 // Get global variable name based on his index (starting by 1)
1598 // Return name's pointer text found
1599 // Return NULL if not found
1600 char *DWARFManager_GetGlobalVariableName(size_t Index)
1601 {
1602 size_t i;
1603
1604 for (i = 0; i < NbCU; i++)
1605 {
1606 if (PtrCU[i].NbVariables)
1607 {
1608 if (Index <= PtrCU[i].NbVariables)
1609 {
1610 return PtrCU[i].PtrVariables[Index - 1].PtrName;
1611 }
1612 else
1613 {
1614 Index -= PtrCU[i].NbVariables;
1615 }
1616 }
1617 }
1618
1619 return NULL;
1620 }
1621
1622
1623 // Get text line from source based on address and his tag
1624 // Return NULL if no text line has been found
1625 char *DWARFManager_GetLineSrcFromAdr(size_t Adr, size_t Tag)
1626 {
1627 size_t i, j, k;
1628
1629 for (i = 0; i < NbCU; i++)
1630 {
1631 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1632 {
1633 for (j = 0; j < PtrCU[i].NbSubProgs; j++)
1634 {
1635 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1636 {
1637 if ((PtrCU[i].PtrSubProgs[j].StartPC == Adr) && (!Tag || (Tag == DW_TAG_subprogram)))
1638 {
1639 return PtrCU[i].PtrSubProgs[j].PtrLineSrc;
1640 }
1641 else
1642 {
1643 for (k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++)
1644 {
1645 if (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC <= Adr)
1646 {
1647 if ((PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC == Adr) && (!Tag || (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].Tag == Tag)))
1648 {
1649 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc;
1650 }
1651 }
1652 else
1653 {
1654 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k - 1].PtrLineSrc;
1655 }
1656 }
1657 }
1658 }
1659 }
1660 }
1661 }
1662
1663 return NULL;
1664 }
1665
1666
1667 // Get line number based on the address and the tag
1668 // Return 0 if no line number has been found
1669 size_t DWARFManager_GetNumLineFromAdr(size_t Adr, size_t Tag)
1670 {
1671 size_t i, j, k;
1672
1673 for (i = 0; i < NbCU; i++)
1674 {
1675 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1676 {
1677 for (j = 0; (j < PtrCU[i].NbSubProgs); j++)
1678 {
1679 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1680 {
1681 if ((PtrCU[i].PtrSubProgs[j].StartPC == Adr) && (!Tag || (Tag == DW_TAG_subprogram)))
1682 {
1683 return PtrCU[i].PtrSubProgs[j].NumLineSrc;
1684 }
1685 else
1686 {
1687 for (k = 0; (k < PtrCU[i].PtrSubProgs[j].NbLinesSrc); k++)
1688 {
1689 if ((PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC == Adr) && (!Tag || (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].Tag == Tag)))
1690 {
1691 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc;
1692 }
1693 }
1694 }
1695 #if 0
1696 if (!Tag || (Tag == DW_TAG_subprogram))
1697 {
1698 return PtrCU[i].PtrSubProgs[j].NumLineSrc;
1699 }
1700 #endif
1701 }
1702 }
1703 }
1704 }
1705
1706 return 0;
1707 }
1708
1709
1710 // Get function name based on address and his range
1711 // Return NULL if no function name has been found
1712 char *DWARFManager_GetFunctionName(size_t Adr)
1713 {
1714 size_t i, j;
1715
1716 for (i = 0; i < NbCU; i++)
1717 {
1718 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1719 {
1720 for (j = 0; j < PtrCU[i].NbSubProgs; j++)
1721 {
1722 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1723 {
1724 return PtrCU[i].PtrSubProgs[j].PtrSubprogramName;
1725 }
1726 }
1727 }
1728 }
1729
1730 return NULL;
1731 }
1732
1733
1734 // Get text line from source based on address and num line (starting by 1)
1735 // Return NULL if no text line has been found
1736 char *DWARFManager_GetLineSrcFromAdrNumLine(size_t Adr, size_t NumLine)
1737 {
1738 size_t i, j, k;
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 if (PtrCU[i].PtrSubProgs[j].NumLineSrc == NumLine)
1749 {
1750 return PtrCU[i].PtrSubProgs[j].PtrLineSrc;
1751 }
1752 else
1753 {
1754 for (k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++)
1755 {
1756 if (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc == NumLine)
1757 {
1758 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc;
1759 }
1760 }
1761 }
1762 }
1763 }
1764 }
1765 }
1766
1767 return NULL;
1768 }
1769
1770
1771 // Get text line from source based on address and num line (starting by 1)
1772 // Return NULL if no text line has been found
1773 char *DWARFManager_GetLineSrcFromNumLineBaseAdr(size_t Adr, size_t NumLine)
1774 {
1775 size_t i;
1776
1777 for (i = 0; i < NbCU; i++)
1778 {
1779 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1780 {
1781 if (NumLine <= PtrCU[i].NbLinesLoadSrc)
1782 {
1783 return PtrCU[i].PtrLinesLoadSrc[NumLine - 1];
1784 }
1785 else
1786 {
1787 return NULL;
1788 }
1789 }
1790 }
1791
1792 return NULL;
1793 }
1794
1795
1796 // Get number of source code filenames
1797 size_t DWARFManager_GetNbFullSourceFilename(void)
1798 {
1799 return NbCU;
1800 }
1801
1802
1803 // Get source code filename based on index
1804 char *DWARFManager_GetNumFullSourceFilename(size_t Index)
1805 {
1806 return (PtrCU[Index].PtrFullFilename);
1807 }
1808