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