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