dfc2ffc32db61eac206ab89b32a079907f31be3f
[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 0x42 // 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 }
668 else
669 {
670 // Set each source lines pointer to NULL
671 if (PtrCU[NbCU].NbSubProgs)
672 {
673 i = PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs - 1].PtrLinesSrc[PtrCU[NbCU].PtrSubProgs[PtrCU[NbCU].NbSubProgs - 1].NbLinesSrc - 1].NumLineSrc;
674 if (PtrCU[NbCU].PtrLinesLoadSrc = (char **)calloc(i, sizeof(char *)))
675 {
676 for (j = 0; j < i; j++)
677 {
678 PtrCU[NbCU].PtrLinesLoadSrc[j] = NULL;
679 }
680 }
681 }
682 }
683
684 // Init lines source information based on each source code line numbers
685 for (j = 0; j < PtrCU[NbCU].NbSubProgs; j++)
686 {
687 // Check if the subprog / function's line exists in the source code
688 if (PtrCU[NbCU].PtrSubProgs[j].NumLineSrc <= PtrCU[NbCU].NbLinesLoadSrc)
689 {
690 PtrCU[NbCU].PtrSubProgs[j].PtrLineSrc = PtrCU[NbCU].PtrLinesLoadSrc[PtrCU[NbCU].PtrSubProgs[j].NumLineSrc - 1];
691 }
692
693 for (k = 0; k < PtrCU[NbCU].PtrSubProgs[j].NbLinesSrc; k++)
694 {
695 PtrCU[NbCU].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc = PtrCU[NbCU].PtrLinesLoadSrc[PtrCU[NbCU].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc - 1];
696 }
697 }
698
699 // Init variables information based on types information
700 for (i = 0; i < PtrCU[NbCU].NbVariables; i++)
701 {
702 PtrCU[NbCU].PtrVariables[i].PtrTypeName = (char *)calloc(1000, 1);
703 TypeOffset = PtrCU[NbCU].PtrVariables[i].TypeOffset;
704
705 for (j = 0; j < PtrCU[NbCU].NbTypes; j++)
706 {
707 if (TypeOffset == PtrCU[NbCU].PtrTypes[j].Offset)
708 {
709 switch (PtrCU[NbCU].PtrTypes[j].Tag)
710 {
711 case DW_TAG_structure_type:
712 PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x1;
713 if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))
714 {
715 j = -1;
716 }
717 else
718 {
719 if ((PtrCU[NbCU].PtrVariables[i].TypeTag & 0x2))
720 {
721 strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, " *");
722 }
723 }
724 break;
725
726 case DW_TAG_pointer_type:
727 PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x2;
728 PtrCU[NbCU].PtrVariables[i].TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;
729 PtrCU[NbCU].PtrVariables[i].TypeEncoding = 0x10;
730 if (!(TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))
731 {
732 strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, "void *");
733 }
734 else
735 {
736 j = -1;
737 }
738 break;
739
740 case DW_TAG_typedef:
741 PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x20;
742 strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);
743 if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))
744 {
745 j = -1;
746 }
747 break;
748
749 case DW_TAG_subrange_type:
750 PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x4;
751 break;
752
753 case DW_TAG_array_type:
754 PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x8;
755 if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))
756 {
757 j = -1;
758 }
759 break;
760
761 case DW_TAG_const_type:
762 PtrCU[NbCU].PtrVariables[i].TypeTag |= 0x10;
763 strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, "const ");
764 if ((TypeOffset = PtrCU[NbCU].PtrTypes[j].TypeOffset))
765 {
766 j = -1;
767 }
768 break;
769
770 case DW_TAG_base_type:
771 strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, PtrCU[NbCU].PtrTypes[j].PtrName);
772 if ((PtrCU[NbCU].PtrVariables[i].TypeTag & 0x2))
773 {
774 strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, " *");
775 }
776 else
777 {
778 PtrCU[NbCU].PtrVariables[i].TypeByteSize = PtrCU[NbCU].PtrTypes[j].ByteSize;
779 PtrCU[NbCU].PtrVariables[i].TypeEncoding = PtrCU[NbCU].PtrTypes[j].Encoding;
780 }
781 if ((PtrCU[NbCU].PtrVariables[i].TypeTag & 0x8))
782 {
783 strcat(PtrCU[NbCU].PtrVariables[i].PtrTypeName, "[]");
784 }
785 break;
786
787 default:
788 break;
789 }
790 }
791 }
792 }
793 }
794
795 ++NbCU;
796 }
797 }
798
799 free(SourceFilename);
800 free(SourceFileDirectory);
801 free(SourceFullFilename);
802 }
803
804
805 // Get symbol name based from address
806 // Return NULL if no symbol name exists
807 char *DWARFManager_GetSymbolnameFromAdr(size_t Adr)
808 {
809 size_t i, j;
810
811 for (i = 0; i < NbCU; i++)
812 {
813 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
814 {
815 for (j = 0; (j < PtrCU[i].NbSubProgs); j++)
816 {
817 if ((PtrCU[i].PtrSubProgs[j].StartPC == Adr))
818 {
819 return PtrCU[i].PtrSubProgs[j].PtrSubprogramName;
820 }
821 }
822 }
823 }
824
825 return NULL;
826 }
827
828
829 // Get complete source filename based from address
830 // Return NULL if no source filename exists
831 // Return the existence status (true or false) in Error
832 char *DWARFManager_GetFullSourceFilenameFromAdr(size_t Adr, bool *Error)
833 {
834 size_t i;
835
836 for (i = 0; i < NbCU; i++)
837 {
838 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
839 {
840 *Error = PtrCU[i].PtrLoadSrc ? true : false;
841 return PtrCU[i].PtrFullFilename;
842 }
843 }
844
845 return NULL;
846 }
847
848
849 // Get text line source based on line number (starting by 1)
850 // Return NULL if no text line exists or if line number is 0
851 char *DWARFManager_GetLineSrcFromNumLine(char *PtrSrcFile, size_t NumLine)
852 {
853 size_t i = 0;
854 char *PtrLineSrc = NULL;
855
856 if (PtrSrcFile)
857 {
858 while (i != NumLine)
859 {
860 PtrLineSrc = PtrSrcFile;
861 while (*PtrSrcFile++);
862 i++;
863 }
864 }
865
866 return PtrLineSrc;
867 }
868
869
870 // Get Compilation Unit / External variables numbers
871 // Return variables number
872 size_t DWARFManager_GetNbExternalVariables(void)
873 {
874 size_t NbVariables = 0, i;
875
876 for (i = 0; i < NbCU; i++)
877 {
878 NbVariables += PtrCU[i].NbVariables;
879 }
880
881 return NbVariables;
882 }
883
884
885 // Get external variable type name based on his index (starting by 1)
886 // Return NULL if not found
887 // May return NULL if there is not type linked to the variable's index
888 char *DWARFManager_GetExternalVariableTypeName(size_t Index)
889 {
890 size_t i;
891
892 for (i = 0; i < NbCU; i++)
893 {
894 if (PtrCU[i].NbVariables)
895 {
896 if (Index <= PtrCU[i].NbVariables)
897 {
898 return PtrCU[i].PtrVariables[Index - 1].PtrTypeName;
899 }
900 else
901 {
902 Index -= PtrCU[i].NbVariables;
903 }
904 }
905 }
906
907 return NULL;
908 }
909
910
911 // Get external variable's type tag based on his index (starting by 1)
912 // Return 0 if not found
913 size_t DWARFManager_GetExternalVariableTypeTag(size_t Index)
914 {
915 size_t i;
916
917 for (i = 0; i < NbCU; i++)
918 {
919 if (PtrCU[i].NbVariables)
920 {
921 if (Index <= PtrCU[i].NbVariables)
922 {
923 return PtrCU[i].PtrVariables[Index - 1].TypeTag;
924 }
925 else
926 {
927 Index -= PtrCU[i].NbVariables;
928 }
929 }
930 }
931
932 return 0;
933 }
934
935
936 // Get external variable byte size based on his index (starting by 1)
937 // Return 0 if not found
938 size_t DWARFManager_GetExternalVariableTypeByteSize(size_t Index)
939 {
940 size_t i;
941
942 for (i = 0; i < NbCU; i++)
943 {
944 if (PtrCU[i].NbVariables)
945 {
946 if (Index <= PtrCU[i].NbVariables)
947 {
948 return PtrCU[i].PtrVariables[Index - 1].TypeByteSize;
949 }
950 else
951 {
952 Index -= PtrCU[i].NbVariables;
953 }
954 }
955 }
956
957 return 0;
958 }
959
960
961 // Get external variable encoding based on his index (starting by 1)
962 // Return 0 if not found
963 size_t DWARFManager_GetExternalVariableTypeEncoding(size_t Index)
964 {
965 size_t i;
966
967 for (i = 0; i < NbCU; i++)
968 {
969 if (PtrCU[i].NbVariables)
970 {
971 if (Index <= PtrCU[i].NbVariables)
972 {
973 return PtrCU[i].PtrVariables[Index - 1].TypeEncoding;
974 }
975 else
976 {
977 Index -= PtrCU[i].NbVariables;
978 }
979 }
980 }
981
982 return 0;
983 }
984
985
986 // Get external variable address based on his index (starting by 1)
987 // Return 0 if not found
988 size_t DWARFManager_GetExternalVariableAdr(size_t Index)
989 {
990 size_t i;
991
992 for (i = 0; i < NbCU; i++)
993 {
994 if (PtrCU[i].NbVariables)
995 {
996 if (Index <= PtrCU[i].NbVariables)
997 {
998 return PtrCU[i].PtrVariables[Index - 1].Addr;
999 }
1000 else
1001 {
1002 Index -= PtrCU[i].NbVariables;
1003 }
1004 }
1005 }
1006
1007 return 0;
1008 }
1009
1010
1011 // Get external variable memory address based on his name
1012 // Return 0 if not found
1013 // Note: Return the first occurence found
1014 size_t DWARFManager_GetExternalVariableAdrFromName(char *VariableName)
1015 {
1016 size_t i, j;
1017
1018 for (i = 0; i < NbCU; i++)
1019 {
1020 if (PtrCU[i].NbVariables)
1021 {
1022 for (j = 0; j < PtrCU[i].NbVariables; j++)
1023 {
1024 if (!strcmp(PtrCU[i].PtrVariables[j].PtrName,VariableName))
1025 {
1026 return PtrCU[i].PtrVariables[j].Addr;
1027 }
1028 }
1029 }
1030 }
1031
1032 return 0;
1033 }
1034
1035
1036 // Get external variable name based on his index (starting by 1)
1037 // Return name's pointer text found
1038 // Return NULL if not found
1039 char *DWARFManager_GetExternalVariableName(size_t Index)
1040 {
1041 size_t i;
1042
1043 for (i = 0; i < NbCU; i++)
1044 {
1045 if (PtrCU[i].NbVariables)
1046 {
1047 if (Index <= PtrCU[i].NbVariables)
1048 {
1049 return PtrCU[i].PtrVariables[Index - 1].PtrName;
1050 }
1051 else
1052 {
1053 Index -= PtrCU[i].NbVariables;
1054 }
1055 }
1056 }
1057
1058 return NULL;
1059 }
1060
1061
1062 // Get text line from source based on address and his tag
1063 // Return NULL if no text line has been found
1064 char *DWARFManager_GetLineSrcFromAdr(size_t Adr, size_t Tag)
1065 {
1066 size_t i, j, k;
1067
1068 for (i = 0; i < NbCU; i++)
1069 {
1070 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1071 {
1072 for (j = 0; j < PtrCU[i].NbSubProgs; j++)
1073 {
1074 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1075 {
1076 if ((PtrCU[i].PtrSubProgs[j].StartPC == Adr) && (!Tag || (Tag == DW_TAG_subprogram)))
1077 {
1078 return PtrCU[i].PtrSubProgs[j].PtrLineSrc;
1079 }
1080 else
1081 {
1082 for (k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++)
1083 {
1084 if ((PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC == Adr) && (!Tag || (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].Tag == Tag)))
1085 {
1086 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc;
1087 }
1088 }
1089 }
1090 }
1091 }
1092 }
1093 }
1094
1095 return NULL;
1096 }
1097
1098
1099 // Get line number based on the address and the tag
1100 // Return 0 if no line number has been found
1101 size_t DWARFManager_GetNumLineFromAdr(size_t Adr, size_t Tag)
1102 {
1103 size_t i, j, k;
1104
1105 for (i = 0; i < NbCU; i++)
1106 {
1107 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1108 {
1109 for (j = 0; (j < PtrCU[i].NbSubProgs); j++)
1110 {
1111 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1112 {
1113 if ((PtrCU[i].PtrSubProgs[j].StartPC == Adr) && (!Tag || (Tag == DW_TAG_subprogram)))
1114 {
1115 return PtrCU[i].PtrSubProgs[j].NumLineSrc;
1116 }
1117 else
1118 {
1119 for (k = 0; (k < PtrCU[i].PtrSubProgs[j].NbLinesSrc); k++)
1120 {
1121 if ((PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].StartPC == Adr) && (!Tag || (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].Tag == Tag)))
1122 {
1123 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc;
1124 }
1125 }
1126 }
1127 #if 0
1128 if (!Tag || (Tag == DW_TAG_subprogram))
1129 {
1130 return PtrCU[i].PtrSubProgs[j].NumLineSrc;
1131 }
1132 #endif
1133 }
1134 }
1135 }
1136 }
1137
1138 return 0;
1139 }
1140
1141
1142 // Get text line from source based on address and num line (starting by 1)
1143 // Return NULL if no text line has been found
1144 char *DWARFManager_GetLineSrcFromAdrNumLine(size_t Adr, size_t NumLine)
1145 {
1146 size_t i, j, k;
1147
1148 for (i = 0; i < NbCU; i++)
1149 {
1150 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1151 {
1152 for (j = 0; j < PtrCU[i].NbSubProgs; j++)
1153 {
1154 if ((Adr >= PtrCU[i].PtrSubProgs[j].LowPC) && (Adr < PtrCU[i].PtrSubProgs[j].HighPC))
1155 {
1156 if (PtrCU[i].PtrSubProgs[j].NumLineSrc == NumLine)
1157 {
1158 return PtrCU[i].PtrSubProgs[j].PtrLineSrc;
1159 }
1160 else
1161 {
1162 for (k = 0; k < PtrCU[i].PtrSubProgs[j].NbLinesSrc; k++)
1163 {
1164 if (PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].NumLineSrc == NumLine)
1165 {
1166 return PtrCU[i].PtrSubProgs[j].PtrLinesSrc[k].PtrLineSrc;
1167 }
1168 }
1169 }
1170 }
1171 }
1172 }
1173 }
1174
1175 return NULL;
1176 }
1177
1178
1179 // Get text line from source based on address and num line (starting by 1)
1180 // Return NULL if no text line has been found
1181 char *DWARFManager_GetLineSrcFromNumLineBaseAdr(size_t Adr, size_t NumLine)
1182 {
1183 size_t i;
1184
1185 for (i = 0; i < NbCU; i++)
1186 {
1187 if ((Adr >= PtrCU[i].LowPC) && (Adr < PtrCU[i].HighPC))
1188 {
1189 if (NumLine <= PtrCU[i].NbLinesLoadSrc)
1190 {
1191 return PtrCU[i].PtrLinesLoadSrc[NumLine - 1];
1192 }
1193 else
1194 {
1195 return NULL;
1196 }
1197 }
1198 }
1199
1200 return NULL;
1201 }
1202