573292c1c4ed4113b3c6bea5091c8adfe9d08ad4
[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
13
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <stdint.h>
17 #include <string.h>
18 #include <libdwarf.h>
19 #include <dwarf.h>
20
21
22 //
23 //#define DEBUG_NumCU 0x6 // CU number to debug or undefine it
24
25
26 // Source line internal structure
27 struct DMIStruct_LineSrc
28 {
29 size_t Tag;
30 size_t StartPC;
31 size_t NumLineSrc;
32 char *PtrLineSrc;
33 }S_DMIStruct_LineSrc;
34
35 // Base type internal structure
36 struct BaseTypeStruct
37 {
38 size_t Tag; // Type's Tag
39 size_t Offset; // Type's offset
40 size_t TypeOffset; // Type's offset on another type
41 size_t ByteSize; // Type's Byte Size
42 size_t Encoding; // Type's encoding
43 char *PtrName; // Type's name
44 }S_BaseTypeStruct;
45
46 // Variables internal structure
47 struct VariablesStruct
48 {
49 size_t Addr; // Variable memory address
50 char *PtrName; // Variable's name
51 size_t TypeOffset; // Offset pointing on the Variable's Type
52 size_t TypeByteSize; // Variable's Type byte size
53 size_t TypeTag; // Variable's Type Tag
54 size_t TypeEncoding; // Variable's Type encoding
55 char *PtrTypeName; // Variable's Type name
56 }S_VariablesStruct;
57
58 // Sub program internal structure
59 struct SubProgStruct
60 {
61 size_t Tag;
62 size_t NumLineSrc;
63 size_t StartPC;
64 size_t LowPC, HighPC;
65 char *PtrLineSrc;
66 char *PtrSubprogramName;
67 size_t NbLinesSrc;
68 DMIStruct_LineSrc *PtrLinesSrc;
69 }S_SubProgStruct;
70
71 // Compilation Unit internal structure
72 struct CUStruct
73 {
74 size_t Tag;
75 size_t LowPC, HighPC;
76 char *PtrProducer; // Pointer to the "Producer" information (compiler and compilation options used)
77 char *PtrFullFilename; // Pointer to full namefile (directory & filename)
78 size_t SizeLoadSrc; // Source code size
79 char *PtrLoadSrc; // Pointer to loaded source code
80 size_t NbLinesLoadSrc; // Lines source number
81 char **PtrLinesLoadSrc; // Pointer lists to each source line put in QT html/text conformity
82 size_t NbSubProgs; // Number of sub programs / routines
83 SubProgStruct *PtrSubProgs; // Pointer to the sub programs / routines information structure
84 size_t NbTypes;
85 BaseTypeStruct *PtrTypes;
86 size_t NbVariables; // Variables number
87 VariablesStruct *PtrVariables; // Pointer to the variables list information structure
88 }S_CUStruct;
89
90
91 // Dwarf management
92 uint32_t LibDwarf;
93 uint32_t NbCU;
94 Dwarf_Ptr errarg;
95 Dwarf_Error error;
96 Dwarf_Debug dbg;
97 CUStruct *PtrCU;
98
99
100 //
101 Dwarf_Handler DWARFManager_ErrorHandler(Dwarf_Ptr perrarg);
102 void DWARFManager_InitDMI(void);
103 void DWARFManager_CloseDMI(void);
104 bool DWARFManager_ElfClose(void);
105 char *DWARFManager_GetLineSrcFromNumLine(char *PtrSrcFile, size_t NumLine);
106
107
108 //
109 Dwarf_Handler DWARFManager_ErrorHandler(Dwarf_Ptr perrarg)
110 {
111 return 0;
112 }
113
114
115 // Dwarf manager init
116 void DWARFManager_Init(void)
117 {
118 LibDwarf = DW_DLV_NO_ENTRY;
119 }
120
121
122 // Dwarf manager Reset
123 bool DWARFManager_Reset(void)
124 {
125 return DWARFManager_ElfClose();
126 }
127
128
129 // Dwarf manager Close
130 bool DWARFManager_Close(void)
131 {
132 return(DWARFManager_Reset());
133 }
134
135
136 // Dwarf manager Elf init
137 int DWARFManager_ElfInit(Elf *ElfPtr)
138 {
139 if ((LibDwarf = dwarf_elf_init(ElfPtr, DW_DLC_READ, (Dwarf_Handler)DWARFManager_ErrorHandler, errarg, &dbg, &error)) == DW_DLV_OK)
140 {
141 DWARFManager_InitDMI();
142 }
143
144 return LibDwarf;
145 }
146
147
148 // Dwarf manager Elf close
149 bool DWARFManager_ElfClose(void)
150 {
151 if (LibDwarf == DW_DLV_OK)
152 {
153 DWARFManager_CloseDMI();
154
155 if (dwarf_finish(dbg, &error) == DW_DLV_OK)
156 {
157 LibDwarf = DW_DLV_NO_ENTRY;
158 return true;
159 }
160 else
161 {
162 return false;
163 }
164 }
165 else
166 {
167 return true;
168 }
169 }
170
171
172 // Dwarf manager Compilation Units close
173 void DWARFManager_CloseDMI(void)
174 {
175 while (NbCU--)
176 {
177 free(PtrCU[NbCU].PtrFullFilename);
178 free(PtrCU[NbCU].PtrLoadSrc);
179 free(PtrCU[NbCU].PtrProducer);
180
181 while (PtrCU[NbCU].NbLinesLoadSrc--)
182 {
183 free(PtrCU[NbCU].PtrLinesLoadSrc[PtrCU[NbCU].NbLinesLoadSrc]);
184 }
185 free(PtrCU[NbCU].PtrLinesLoadSrc);
186
187 while (PtrCU[NbCU].NbSubProgs--)
188 {
189 free(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc);
190 free(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrSubprogramName);
191 }
192 free(PtrCU[NbCU].PtrSubProgs);
193
194 while (PtrCU[NbCU].NbTypes--)
195 {
196 free(PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName);
197 }
198 free(PtrCU[NbCU].PtrTypes);
199
200 while (PtrCU[NbCU].NbVariables--)
201 {
202 free(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName);
203 free(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrTypeName);
204 }
205 free(PtrCU[NbCU].PtrVariables);
206 }
207
208 free(PtrCU);
209 }
210
211
212 // Dwarf manager Compilation Units initialisations
213 void DWARFManager_InitDMI(void)
214 {
215 Dwarf_Unsigned next_cu_header, return_uvalue;
216 Dwarf_Error error;
217 Dwarf_Attribute *atlist;
218 Dwarf_Attribute return_attr1;
219 Dwarf_Half return_tagval, return_attr;
220 Dwarf_Addr return_lowpc, return_highpc, return_lineaddr;
221 Dwarf_Block *return_block;
222 Dwarf_Signed atcnt, cnt;
223 Dwarf_Die return_sib, return_die;
224 Dwarf_Off return_offset;
225 Dwarf_Line *linebuf;
226 FILE *SrcFile;
227 size_t i, j, k, TypeOffset;
228 char *return_string;
229 char *Ptr;
230 char *SourceFilename = NULL;
231 char *SourceFileDirectory = NULL;
232 char *SourceFullFilename = NULL;
233
234 // Initialisation for the Compilation Units table
235 NbCU = 0;
236 PtrCU = NULL;
237
238 // loop on the available Compilation Unit
239 while (dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, &next_cu_header, &error) == DW_DLV_OK)
240 {
241 // Allocation of an additional Compilation Unit structure in the table
242 if (Ptr = (char *)realloc(PtrCU, ((NbCU + 1) * sizeof(CUStruct))))
243 {
244 // Compilation Unit RAZ
245 PtrCU = (CUStruct *)Ptr;
246 memset(PtrCU + NbCU, 0, sizeof(CUStruct));
247
248 // Debug specific CU
249 #ifdef DEBUG_NumCU
250 if (NbCU == DEBUG_NumCU)
251 #endif
252 {
253 // Get 1st Die from the Compilation Unit
254 if (dwarf_siblingof(dbg, NULL, &return_sib, &error) == DW_DLV_OK)
255 {
256 // Get Die's Tag
257 if ((dwarf_tag(return_sib, &return_tagval, &error) == DW_DLV_OK))
258 {
259 PtrCU[NbCU].Tag = return_tagval;
260
261 // Die type detection
262 switch (return_tagval)
263 {
264 case DW_TAG_compile_unit:
265 if (dwarf_attrlist(return_sib, &atlist, &atcnt, &error) == DW_DLV_OK)
266 {
267 for (Dwarf_Signed i = 0; i < atcnt; ++i)
268 {
269 if (dwarf_whatattr(atlist[i], &return_attr, &error) == DW_DLV_OK)
270 {
271 switch (return_attr)
272 {
273 case DW_AT_low_pc:
274 if (dwarf_lowpc(return_sib, &return_lowpc, &error) == DW_DLV_OK)
275 {
276 PtrCU[NbCU].LowPC = return_lowpc;
277 }
278 break;
279
280 case DW_AT_high_pc:
281 if (dwarf_highpc(return_sib, &return_highpc, &error) == DW_DLV_OK)
282 {
283 PtrCU[NbCU].HighPC = return_highpc;
284 }
285 break;
286
287 case DW_AT_producer:
288 if (dwarf_formstring(atlist[i], &return_string, &error) == DW_DLV_OK)
289 {
290 PtrCU[NbCU].PtrProducer = (char *)calloc(strlen(return_string) + 1, 1);
291 strcpy(PtrCU[NbCU].PtrProducer, return_string);
292 dwarf_dealloc(dbg, return_string, DW_DLA_STRING);
293 }
294 break;
295
296 case DW_AT_name:
297 if (dwarf_formstring(atlist[i], &return_string, &error) == DW_DLV_OK)
298 {
299 SourceFilename = (char *)realloc(SourceFilename, strlen(return_string) + 1);
300 strcpy(SourceFilename, return_string);
301 dwarf_dealloc(dbg, return_string, DW_DLA_STRING);
302 }
303 break;
304
305 case DW_AT_comp_dir:
306 if (dwarf_formstring(atlist[i], &return_string, &error) == DW_DLV_OK)
307 {
308 SourceFileDirectory = (char *)realloc(SourceFileDirectory, strlen(return_string) + 1);
309 strcpy(SourceFileDirectory, return_string);
310 dwarf_dealloc(dbg, return_string, DW_DLA_STRING);
311 }
312 break;
313
314 default:
315 break;
316 }
317 }
318 dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);
319 }
320 dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
321 }
322
323 Ptr = SourceFullFilename = (char *)realloc(SourceFullFilename, strlen(SourceFilename) + strlen(SourceFileDirectory) + 2);
324 sprintf(SourceFullFilename, "%s\\%s", SourceFileDirectory, SourceFilename);
325 while (*Ptr)
326 {
327 if (*Ptr == '/')
328 {
329 *Ptr = '\\';
330 }
331 Ptr++;
332 }
333 PtrCU[NbCU].PtrFullFilename = (char *)calloc(strlen(SourceFullFilename) + 1, 1);
334 strcpy((char *)PtrCU[NbCU].PtrFullFilename, SourceFullFilename);
335
336 #ifndef __CYGWIN__
337 if (!fopen_s(&SrcFile, SourceFullFilename, "rt"))
338 #else
339 if (!(SrcFile = fopen(SourceFullFilename, "rt")))
340 #endif
341 {
342 if (!fseek(SrcFile, 0, SEEK_END))
343 {
344 if ((PtrCU[NbCU].SizeLoadSrc = ftell(SrcFile)) > 0)
345 {
346 if (PtrCU[NbCU].PtrLoadSrc = Ptr = (char *)calloc((PtrCU[NbCU].SizeLoadSrc + 1), 1))
347 {
348 rewind(SrcFile);
349 if (PtrCU[NbCU].SizeLoadSrc < fread(Ptr, 1, PtrCU[NbCU].SizeLoadSrc, SrcFile))
350 {
351 free(PtrCU[NbCU].PtrLoadSrc);
352 PtrCU[NbCU].PtrLoadSrc = NULL;
353 PtrCU[NbCU].SizeLoadSrc = 0;
354 }
355 else
356 {
357 do
358 {
359 if (*Ptr == 0xa)
360 {
361 PtrCU[NbCU].NbLinesLoadSrc++;
362 *Ptr = 0;
363 }
364 } while (*++Ptr);
365 }
366 }
367 }
368 }
369 fclose(SrcFile);
370 }
371 break;
372
373 default:
374 break;
375 }
376 }
377
378 // Get the source lines table located in the Compilation Unit
379 if (dwarf_srclines(return_sib, &linebuf, &cnt, &error) == DW_DLV_OK)
380 {
381 }
382
383 if (dwarf_child(return_sib, &return_die, &error) == DW_DLV_OK)
384 {
385 do
386 {
387 return_sib = return_die;
388 if ((dwarf_tag(return_die, &return_tagval, &error) == DW_DLV_OK))
389 {
390 switch (return_tagval)
391 {
392 case DW_TAG_lexical_block:
393 break;
394
395 case DW_TAG_variable:
396 if (dwarf_attrlist(return_die, &atlist, &atcnt, &error) == DW_DLV_OK)
397 {
398 PtrCU[NbCU].PtrVariables = (VariablesStruct *)realloc(PtrCU[NbCU].PtrVariables, ((PtrCU[NbCU].NbVariables + 1) * sizeof(VariablesStruct)));
399 memset(PtrCU[NbCU].PtrVariables + PtrCU[NbCU].NbVariables, 0, sizeof(VariablesStruct));
400
401 for (Dwarf_Signed i = 0; i < atcnt; ++i)
402 {
403 if (dwarf_whatattr(atlist[i], &return_attr, &error) == DW_DLV_OK)
404 {
405 if (dwarf_attr(return_die, return_attr, &return_attr1, &error) == DW_DLV_OK)
406 {
407 switch (return_attr)
408 {
409 case DW_AT_location:
410 if (dwarf_formblock(return_attr1, &return_block, &error) == DW_DLV_OK)
411 {
412 if (return_block->bl_len == 5)
413 {
414 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));
415 }
416 dwarf_dealloc(dbg, return_block, DW_DLA_BLOCK);
417 }
418 break;
419
420 case DW_AT_type:
421 if (dwarf_global_formref(return_attr1, &return_offset, &error) == DW_DLV_OK)
422 {
423 PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].TypeOffset = return_offset;
424 }
425 break;
426
427 case DW_AT_name:
428 if (dwarf_formstring(return_attr1, &return_string, &error) == DW_DLV_OK)
429 {
430 PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName = (char *)calloc(strlen(return_string) + 1, 1);
431 strcpy(PtrCU[NbCU].PtrVariables[PtrCU[NbCU].NbVariables].PtrName, return_string);
432 dwarf_dealloc(dbg, return_string, DW_DLA_STRING);
433 }
434 break;
435
436 default:
437 break;
438 }
439 }
440 }
441
442 dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);
443 }
444
445 PtrCU[NbCU].NbVariables++;
446
447 dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
448 }
449 break;
450
451 case DW_TAG_base_type:
452 case DW_TAG_typedef:
453 case DW_TAG_structure_type:
454 case DW_TAG_pointer_type:
455 case DW_TAG_const_type:
456 case DW_TAG_array_type:
457 case DW_TAG_subrange_type:
458 case DW_TAG_subroutine_type:
459 if (dwarf_attrlist(return_die, &atlist, &atcnt, &error) == DW_DLV_OK)
460 {
461 PtrCU[NbCU].PtrTypes = (BaseTypeStruct *)realloc(PtrCU[NbCU].PtrTypes, ((PtrCU[NbCU].NbTypes + 1) * sizeof(BaseTypeStruct)));
462 memset(PtrCU[NbCU].PtrTypes + PtrCU[NbCU].NbTypes, 0, sizeof(BaseTypeStruct));
463 PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].Tag = return_tagval;
464
465 if (dwarf_dieoffset(return_die, &return_offset, &error) == DW_DLV_OK)
466 {
467 PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].Offset = return_offset;
468 }
469
470 for (Dwarf_Signed i = 0; i < atcnt; ++i)
471 {
472 if (dwarf_whatattr(atlist[i], &return_attr, &error) == DW_DLV_OK)
473 {
474 if (dwarf_attr(return_die, return_attr, &return_attr1, &error) == DW_DLV_OK)
475 {
476 switch (return_attr)
477 {
478 case DW_AT_type:
479 if (dwarf_global_formref(return_attr1, &return_offset, &error) == DW_DLV_OK)
480 {
481 PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].TypeOffset = return_offset;
482 }
483 break;
484
485 case DW_AT_byte_size:
486 if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK)
487 {
488 PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].ByteSize = return_uvalue;
489 }
490 break;
491
492 case DW_AT_encoding:
493 if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK)
494 {
495 PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].Encoding = return_uvalue;
496 }
497 break;
498
499 case DW_AT_name:
500 if (dwarf_formstring(return_attr1, &return_string, &error) == DW_DLV_OK)
501 {
502 PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName = (char *)calloc(strlen(return_string) + 1, 1);
503 strcpy(PtrCU[NbCU].PtrTypes[PtrCU[NbCU].NbTypes].PtrName, return_string);
504 dwarf_dealloc(dbg, return_string, DW_DLA_STRING);
505 }
506 break;
507
508 default:
509 break;
510 }
511 }
512 }
513
514 dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);
515 }
516
517 PtrCU[NbCU].NbTypes++;
518
519 dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
520 }
521 break;
522
523 case DW_TAG_subprogram:
524 if (dwarf_attrlist(return_die, &atlist, &atcnt, &error) == DW_DLV_OK)
525 {
526 PtrCU[NbCU].PtrSubProgs = (SubProgStruct *)realloc(PtrCU[NbCU].PtrSubProgs, ((PtrCU[NbCU].NbSubProgs + 1) * sizeof(SubProgStruct)));
527 memset((void *)(PtrCU[NbCU].PtrSubProgs + PtrCU[NbCU].NbSubProgs), 0, sizeof(SubProgStruct));
528 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].Tag = return_tagval;
529
530 for (Dwarf_Signed i = 0; i < atcnt; ++i)
531 {
532 if (dwarf_whatattr(atlist[i], &return_attr, &error) == DW_DLV_OK)
533 {
534 if (dwarf_attr(return_die, return_attr, &return_attr1, &error) == DW_DLV_OK)
535 {
536 switch (return_attr)
537 {
538 case DW_AT_low_pc:
539 if (dwarf_lowpc(return_die, &return_lowpc, &error) == DW_DLV_OK)
540 {
541 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].StartPC = return_lowpc;
542 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].LowPC = return_lowpc;
543 }
544 break;
545
546 case DW_AT_high_pc:
547 if (dwarf_highpc(return_die, &return_highpc, &error) == DW_DLV_OK)
548 {
549 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].HighPC = return_highpc;
550 }
551 break;
552
553 case DW_AT_decl_line:
554 if (dwarf_formudata(return_attr1, &return_uvalue, &error) == DW_DLV_OK)
555 {
556 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NumLineSrc = return_uvalue;
557 }
558 break;
559
560 case DW_AT_name:
561 if (dwarf_formstring(return_attr1, &return_string, &error) == DW_DLV_OK)
562 {
563 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrSubprogramName = (char *)calloc(strlen(return_string) + 1, 1);
564 strcpy(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrSubprogramName, return_string);
565 dwarf_dealloc(dbg, return_string, DW_DLA_STRING);
566 }
567 break;
568
569 default:
570 break;
571 }
572 }
573 }
574 dwarf_dealloc(dbg, atlist[i], DW_DLA_ATTR);
575 }
576 dwarf_dealloc(dbg, atlist, DW_DLA_LIST);
577
578 for (i = 0; i < (size_t)cnt; ++i)
579 {
580 if (dwarf_lineaddr(linebuf[i], &return_lineaddr, &error) == DW_DLV_OK)
581 {
582 if (dwarf_lineno(linebuf[i], &return_uvalue, &error) == DW_DLV_OK)
583 {
584 if ((return_lineaddr >= return_lowpc) && (return_lineaddr <= return_highpc))
585 {
586 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));
587 memset((void *)(PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc + PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc), 0, sizeof(DMIStruct_LineSrc));
588 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc].StartPC = return_lineaddr;
589 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc].NumLineSrc = return_uvalue;
590 PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs].NbLinesSrc++;
591 }
592 }
593 }
594 }
595
596 PtrCU[NbCU].NbSubProgs++;
597 }
598 break;
599
600 default:
601 break;
602 }
603 }
604 } while (dwarf_siblingof(dbg, return_sib, &return_die, &error) == DW_DLV_OK);
605 }
606
607 // Release the memory used by the source lines
608 for (i = 0; i < (size_t)cnt; ++i)
609 dwarf_dealloc(dbg, linebuf[i], DW_DLA_LINE);
610 dwarf_dealloc(dbg, linebuf, DW_DLA_LIST);
611 }
612
613 // Set the source code lines for QT html/text conformity
614 if (PtrCU[NbCU].NbLinesLoadSrc)
615 {
616 if (PtrCU[NbCU].PtrLinesLoadSrc = (char **)calloc(PtrCU[NbCU].NbLinesLoadSrc, sizeof(char *)))
617 {
618 for (j = 0; j < PtrCU[NbCU].NbLinesLoadSrc; j++)
619 {
620 if (PtrCU[NbCU].PtrLinesLoadSrc[j] = (char *)calloc(10000, sizeof(char)))
621 {
622 if (Ptr = DWARFManager_GetLineSrcFromNumLine(PtrCU[NbCU].PtrLoadSrc, (j + 1)))
623 {
624 i = 0;
625
626 while (*Ptr)
627 {
628 switch (*Ptr)
629 {
630 case 9:
631 strcat(PtrCU[NbCU].PtrLinesLoadSrc[j], "&nbsp;");
632 i += strlen("&nbsp;");
633 break;
634
635 case '<':
636 strcat(PtrCU[NbCU].PtrLinesLoadSrc[j], "&lt;");
637 i += strlen("&lt;");
638 break;
639
640 case '>':
641 strcat(PtrCU[NbCU].PtrLinesLoadSrc[j], "&gt;");
642 i += strlen("&gt;");
643 break;
644 #if 0
645 case '&':
646 strcpy(PtrCU[NbCU].PtrLinesLoadSrc[j], "&amp;");
647 i += strlen("&amp;");
648 break;
649 #endif
650 #if 0
651 case '"':
652 strcpy(PtrCU[NbCU].PtrLinesLoadSrc[j], "&quot;");
653 i += strlen("&quot;");
654 break;
655 #endif
656 default:
657 PtrCU[NbCU].PtrLinesLoadSrc[j][i++] = *Ptr;
658 break;
659 }
660 Ptr++;
661 }
662 }
663 PtrCU[NbCU].PtrLinesLoadSrc[j] = (char *)realloc(PtrCU[NbCU].PtrLinesLoadSrc[j], i + 1);
664 }
665 }
666
667 // Init lines source information based on each source code line numbers
668 for (j = 0; j < PtrCU[NbCU].NbSubProgs; j++)
669 {
670 // Check if the subprog / function's line exists in the source code
671 if (PtrCU[NbCU].PtrSubProgs[j].NumLineSrc <= PtrCU[NbCU].NbLinesLoadSrc)
672 {
673 PtrCU[NbCU].PtrSubProgs[j].PtrLineSrc = PtrCU[NbCU].PtrLinesLoadSrc[PtrCU[NbCU].PtrSubProgs[j].NumLineSrc - 1];
674 }
675
676 for (k = 0; k < PtrCU[NbCU].PtrSubProgs[j].NbLinesSrc; k++)
677 {
678 if (PtrCU[NbCU].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc <= PtrCU[NbCU].NbLinesLoadSrc)
679 {
680 PtrCU[NbCU].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc = PtrCU[NbCU].PtrLinesLoadSrc[PtrCU[NbCU].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc - 1];
681 }
682 }
683 }
684 }
685 }
686 else
687 {
688 // Set each source lines pointer to NULL
689 if (PtrCU[NbCU].NbSubProgs)
690 {
691 // Check the presence of source lines dedicated to the sub progs
692 if (PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs - 1].NbLinesSrc)
693 {
694 i = PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs - 1].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs - 1].NbLinesSrc - 1].NumLineSrc;
695 if (PtrCU[NbCU].PtrLinesLoadSrc = (char **)calloc(i, sizeof(char *)))
696 {
697 for (j = 0; j < i; j++)
698 {
699 PtrCU[NbCU].PtrLinesLoadSrc[j] = NULL;
700 }
701 }
702 }
703 }
704 }
705
706 // Init variables information based on types information
707 for (i = 0; i < PtrCU[NbCU].NbVariables; i++)
708 {
709 PtrCU[NbCU].PtrVariables[i].PtrTypeName = (char *)calloc(1000, 1);
710 TypeOffset = PtrCU[NbCU].PtrVariables[i].TypeOffset;
711
712 for (j = 0; j < PtrCU[NbCU].NbTypes; j++)
713 {
714 if (TypeOffset == PtrCU[NbCU].PtrTypes[j].Offset)
715 {
716 switch (PtrCU[NbCU].PtrTypes[j].Tag)
717 {
718 case DW_TAG_structure_type:
719 PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x1;
720 if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))
721 {
722 j = -1;
723 }
724 else
725 {
726 if ((PtrCU[NbCU].PtrVariables[i].TypeTag & 0x2))
727 {
728 strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, " *");
729 }
730 }
731 break;
732
733 case DW_TAG_pointer_type:
734 PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x2;
735 PtrCU[NbCU].PtrVariables[i].TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;
736 PtrCU[NbCU].PtrVariables[i].TypeEncoding = 0x10;
737 if (!(TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))
738 {
739 strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, "void *");
740 }
741 else
742 {
743 j = -1;
744 }
745 break;
746
747 case DW_TAG_typedef:
748 PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x20;
749 strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);
750 if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))
751 {
752 j = -1;
753 }
754 break;
755
756 case DW_TAG_subrange_type:
757 PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x4;
758 break;
759
760 case DW_TAG_array_type:
761 PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x8;
762 if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))
763 {
764 j = -1;
765 }
766 break;
767
768 case DW_TAG_const_type:
769 PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x10;
770 strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, "const ");
771 if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))
772 {
773 j = -1;
774 }
775 break;
776
777 case DW_TAG_base_type:
778 strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);
779 if ((PtrCU[NbCU].PtrVariables[i].TypeTag & 0x2))
780 {
781 strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, " *");
782 }
783 else
784 {
785 PtrCU[NbCU].PtrVariables[i].TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;
786 PtrCU[NbCU].PtrVariables[i].TypeEncoding = PtrCU[NbCU].PtrTypes[j].Encoding;
787 }
788 if ((PtrCU[NbCU].PtrVariables[i].TypeTag & 0x8))
789 {
790 strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, "[]");
791 }
792 break;
793
794 default:
795 break;
796 }
797 }
798 }
799 }
800 }
801
802 ++NbCU;
803 }
804 }
805
806 free(SourceFilename);
807 free(SourceFileDirectory);
808 free(SourceFullFilename);
809 }
810
811
812 // Get symbol name based from address
813 // Return NULL if no symbol name exists
814 char *DWARFManager_GetSymbolnameFromAdr(size_t Adr)
815 {
816 size_t i, j;
817
818 for (i = 0; i < NbCU; i++)
819 {
820 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
821 {
822 for (j = 0; (j < PtrCU[i].NbSubProgs); j++)
823 {
824 if ((PtrCU[i].PtrSubProgs[j].StartPC == Adr))
825 {
826 return PtrCU[i].PtrSubProgs[j].PtrSubprogramName;
827 }
828 }
829 }
830 }
831
832 return NULL;
833 }
834
835
836 // Get complete source filename based from address
837 // Return NULL if no source filename exists
838 // Return the existence status (true or false) in Error
839 char *DWARFManager_GetFullSourceFilenameFromAdr(size_t Adr, bool *Error)
840 {
841 size_t i;
842
843 for (i = 0; i < NbCU; i++)
844 {
845 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
846 {
847 *Error = PtrCU[i].PtrLoadSrc ? true : false;
848 return PtrCU[i].PtrFullFilename;
849 }
850 }
851
852 return NULL;
853 }
854
855
856 // Get text line source based on line number (starting by 1)
857 // Return NULL if no text line exists or if line number is 0
858 char *DWARFManager_GetLineSrcFromNumLine(char *PtrSrcFile, size_t NumLine)
859 {
860 size_t i = 0;
861 char *PtrLineSrc = NULL;
862
863 if (PtrSrcFile)
864 {
865 while (i != NumLine)
866 {
867 PtrLineSrc = PtrSrcFile;
868 while (*PtrSrcFile++);
869 i++;
870 }
871 }
872
873 return PtrLineSrc;
874 }
875
876
877 // Get Compilation Unit / External variables numbers
878 // Return variables number
879 size_t DWARFManager_GetNbExternalVariables(void)
880 {
881 size_t NbVariables = 0, i;
882
883 for (i = 0; i < NbCU; i++)
884 {
885 NbVariables += PtrCU[i].NbVariables;
886 }
887
888 return NbVariables;
889 }
890
891
892 // Get external variable type name based on his index (starting by 1)
893 // Return NULL if not found
894 // May return NULL if there is not type linked to the variable's index
895 char *DWARFManager_GetExternalVariableTypeName(size_t Index)
896 {
897 size_t i;
898
899 for (i = 0; i < NbCU; i++)
900 {
901 if (PtrCU[i].NbVariables)
902 {
903 if (Index <= PtrCU[i].NbVariables)
904 {
905 return PtrCU[i].PtrVariables[Index - 1].PtrTypeName;
906 }
907 else
908 {
909 Index -= PtrCU[i].NbVariables;
910 }
911 }
912 }
913
914 return NULL;
915 }
916
917
918 // Get external variable's type tag based on his index (starting by 1)
919 // Return 0 if not found
920 size_t DWARFManager_GetExternalVariableTypeTag(size_t Index)
921 {
922 size_t i;
923
924 for (i = 0; i < NbCU; i++)
925 {
926 if (PtrCU[i].NbVariables)
927 {
928 if (Index <= PtrCU[i].NbVariables)
929 {
930 return PtrCU[i].PtrVariables[Index - 1].TypeTag;
931 }
932 else
933 {
934 Index -= PtrCU[i].NbVariables;
935 }
936 }
937 }
938
939 return 0;
940 }
941
942
943 // Get external variable byte size based on his index (starting by 1)
944 // Return 0 if not found
945 size_t DWARFManager_GetExternalVariableTypeByteSize(size_t Index)
946 {
947 size_t i;
948
949 for (i = 0; i < NbCU; i++)
950 {
951 if (PtrCU[i].NbVariables)
952 {
953 if (Index <= PtrCU[i].NbVariables)
954 {
955 return PtrCU[i].PtrVariables[Index - 1].TypeByteSize;
956 }
957 else
958 {
959 Index -= PtrCU[i].NbVariables;
960 }
961 }
962 }
963
964 return 0;
965 }
966
967
968 // Get external variable encoding based on his index (starting by 1)
969 // Return 0 if not found
970 size_t DWARFManager_GetExternalVariableTypeEncoding(size_t Index)
971 {
972 size_t i;
973
974 for (i = 0; i < NbCU; i++)
975 {
976 if (PtrCU[i].NbVariables)
977 {
978 if (Index <= PtrCU[i].NbVariables)
979 {
980 return PtrCU[i].PtrVariables[Index - 1].TypeEncoding;
981 }
982 else
983 {
984 Index -= PtrCU[i].NbVariables;
985 }
986 }
987 }
988
989 return 0;
990 }
991
992
993 // Get external variable address based on his index (starting by 1)
994 // Return 0 if not found
995 size_t DWARFManager_GetExternalVariableAdr(size_t Index)
996 {
997 size_t i;
998
999 for (i = 0; i < NbCU; i++)
1000 {
1001 if (PtrCU[i].NbVariables)
1002 {
1003 if (Index <= PtrCU[i].NbVariables)
1004 {
1005 return PtrCU[i].PtrVariables[Index - 1].Addr;
1006 }
1007 else
1008 {
1009 Index -= PtrCU[i].NbVariables;
1010 }
1011 }
1012 }
1013
1014 return 0;
1015 }
1016
1017
1018 // Get external variable memory address based on his name
1019 // Return 0 if not found
1020 // Note: Return the first occurence found
1021 size_t DWARFManager_GetExternalVariableAdrFromName(char *VariableName)
1022 {
1023 size_t i, j;
1024
1025 for (i = 0; i < NbCU; i++)
1026 {
1027 if (PtrCU[i].NbVariables)
1028 {
1029 for (j = 0; j < PtrCU[i].NbVariables; j++)
1030 {
1031 if (!strcmp(PtrCU[i].PtrVariables[j].PtrName,VariableName))
1032 {
1033 return PtrCU[i].PtrVariables[j].Addr;
1034 }
1035 }
1036 }
1037 }
1038
1039 return 0;
1040 }
1041
1042
1043 // Get external variable name based on his index (starting by 1)
1044 // Return name's pointer text found
1045 // Return NULL if not found
1046 char *DWARFManager_GetExternalVariableName(size_t Index)
1047 {
1048 size_t i;
1049
1050 for (i = 0; i < NbCU; i++)
1051 {
1052 if (PtrCU[i].NbVariables)
1053 {
1054 if (Index <= PtrCU[i].NbVariables)
1055 {
1056 return PtrCU[i].PtrVariables[Index - 1].PtrName;
1057 }
1058 else
1059 {
1060 Index -= PtrCU[i].NbVariables;
1061 }
1062 }
1063 }
1064
1065 return NULL;
1066 }
1067
1068
1069 // Get text line from source based on address and his tag
1070 // Return NULL if no text line has been found
1071 char *DWARFManager_GetLineSrcFromAdr(size_t Adr, size_t Tag)
1072 {
1073 size_t i, j, k;
1074
1075 for (i = 0; i < NbCU; i++)
1076 {
1077 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1078 {
1079 for (j = 0; j < PtrCU[i].NbSubProgs; j++)
1080 {
1081 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1082 {
1083 if ((PtrCU[i].PtrSubProgs[j].StartPC == Adr) && (!Tag || (Tag == DW_TAG_subprogram)))
1084 {
1085 return PtrCU[i].PtrSubProgs[j].PtrLineSrc;
1086 }
1087 else
1088 {
1089 for (k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++)
1090 {
1091 if ((PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC == Adr) && (!Tag || (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].Tag == Tag)))
1092 {
1093 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc;
1094 }
1095 }
1096 }
1097 }
1098 }
1099 }
1100 }
1101
1102 return NULL;
1103 }
1104
1105
1106 // Get line number based on the address and the tag
1107 // Return 0 if no line number has been found
1108 size_t DWARFManager_GetNumLineFromAdr(size_t Adr, size_t Tag)
1109 {
1110 size_t i, j, k;
1111
1112 for (i = 0; i < NbCU; i++)
1113 {
1114 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1115 {
1116 for (j = 0; (j < PtrCU[i].NbSubProgs); j++)
1117 {
1118 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1119 {
1120 if ((PtrCU[i].PtrSubProgs[j].StartPC == Adr) && (!Tag || (Tag == DW_TAG_subprogram)))
1121 {
1122 return PtrCU[i].PtrSubProgs[j].NumLineSrc;
1123 }
1124 else
1125 {
1126 for (k = 0; (k < PtrCU[i].PtrSubProgs[j].NbLinesSrc); k++)
1127 {
1128 if ((PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC == Adr) && (!Tag || (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].Tag == Tag)))
1129 {
1130 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc;
1131 }
1132 }
1133 }
1134 #if 0
1135 if (!Tag || (Tag == DW_TAG_subprogram))
1136 {
1137 return PtrCU[i].PtrSubProgs[j].NumLineSrc;
1138 }
1139 #endif
1140 }
1141 }
1142 }
1143 }
1144
1145 return 0;
1146 }
1147
1148
1149 // Get text line from source based on address and num line (starting by 1)
1150 // Return NULL if no text line has been found
1151 char *DWARFManager_GetLineSrcFromAdrNumLine(size_t Adr, size_t NumLine)
1152 {
1153 size_t i, j, k;
1154
1155 for (i = 0; i < NbCU; i++)
1156 {
1157 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1158 {
1159 for (j = 0; j < PtrCU[i].NbSubProgs; j++)
1160 {
1161 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1162 {
1163 if (PtrCU[i].PtrSubProgs[j].NumLineSrc == NumLine)
1164 {
1165 return PtrCU[i].PtrSubProgs[j].PtrLineSrc;
1166 }
1167 else
1168 {
1169 for (k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++)
1170 {
1171 if (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc == NumLine)
1172 {
1173 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc;
1174 }
1175 }
1176 }
1177 }
1178 }
1179 }
1180 }
1181
1182 return NULL;
1183 }
1184
1185
1186 // Get text line from source based on address and num line (starting by 1)
1187 // Return NULL if no text line has been found
1188 char *DWARFManager_GetLineSrcFromNumLineBaseAdr(size_t Adr, size_t NumLine)
1189 {
1190 size_t i;
1191
1192 for (i = 0; i < NbCU; i++)
1193 {
1194 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1195 {
1196 if (NumLine <= PtrCU[i].NbLinesLoadSrc)
1197 {
1198 return PtrCU[i].PtrLinesLoadSrc[NumLine - 1];
1199 }
1200 else
1201 {
1202 return NULL;
1203 }
1204 }
1205 }
1206
1207 return NULL;
1208 }
1209