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