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