edbc76630e37201f1b03f04a69ba06a2823cd732
[clinton/Virtual-Jaguar-Rx.git] / src / debugger / DBGManager.cpp
1 //
2 // DBGManager.cpp: Debugger information manager
3 //
4 // by Jean-Paul Mari
5 //
6 // JPM = Jean-Paul Mari <djipi.mari@gmail.com>
7 // RG = Richard Goedeken
8 //
9 // WHO WHEN WHAT
10 // --- ---------- ------------------------------------------------------------
11 // JPM 12/21/2016 Created this file
12 // JPM Various efforts to set the ELF format support
13 // JPM Various efforts to set the DWARF format support
14 // JPM 09/15/2018 Support the unsigned char
15 // JPM Oct./2018 Cosmetic changes, added source file search paths, and ELF function name
16 // JPM Aug./2019 Added new functions mainly for source text lines
17 // JPM Sept./2019 Support the unsigned/signed short type
18 // RG Jan./2021 Linux build fixes
19 // JPM May/2021 Code refactoring for the variables
20 //
21
22 // To Do
23 // To think about unique format to handle variations from ELF, DWARF, etc.
24 //
25
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdint.h>
30 #include "libelf.h"
31 #include "gelf.h"
32 #include "log.h"
33 #include "ELFManager.h"
34 #include "DWARFManager.h"
35 #include "DBGManager.h"
36 #include "HWLABELManager.h"
37 #include "settings.h"
38 #include "memory.h"
39
40
41 //
42 struct Value
43 {
44 union
45 {
46 char Ct[10];
47 char C;
48 bool B;
49 double D;
50 float F;
51 int16_t SS;
52 int32_t SI;
53 int64_t SL;
54 uint16_t US;
55 uint32_t UI;
56 uint64_t UL;
57 };
58 }S_Value;
59
60
61 //
62 void DBGManager_SourceFileSearchPathsInit(void);
63 void DBGManager_SourceFileSearchPathsReset(void);
64 void DBGManager_SourceFileSearchPathsClose(void);
65
66
67 // Common debugger variables
68 size_t DBGType;
69 char value[1000];
70 size_t NbSFSearchPaths;
71 char **SourceFileSearchPaths;
72
73
74 // Init the source file search paths
75 void DBGManager_SourceFileSearchPathsInit(void)
76 {
77 NbSFSearchPaths = 0;
78 SourceFileSearchPaths = NULL;
79 }
80
81
82 // Set the source file search paths
83 // Create individual path for each one provided in the list (separate with ';')
84 void DBGManager_SourceFileSearchPathsSet(char *ListPaths)
85 {
86 // Check presence of a previous list
87 if (NbSFSearchPaths)
88 {
89 // Reset previous list
90 DBGManager_SourceFileSearchPathsReset();
91 }
92
93 // Check if there is a paths list
94 if (strlen(ListPaths))
95 {
96 // Get number of paths
97 char *Ptr = ListPaths;
98 while(*Ptr)
99 {
100 while (*Ptr && (*Ptr++ != ';'));
101 {
102 NbSFSearchPaths++;
103 }
104 }
105
106 // Isolate each search path
107 SourceFileSearchPaths = (char **)calloc(NbSFSearchPaths, sizeof(char *));
108 size_t i = 0;
109 Ptr = ListPaths;
110
111 while (*Ptr)
112 {
113 // Search the path separator (';')
114 char *Ptr1 = Ptr;
115 while (*Ptr && (*Ptr++ != ';'));
116
117 // Copy the inidividual search path
118 SourceFileSearchPaths[i] = (char *)calloc(1, (Ptr - Ptr1) + 1);
119 strncpy(SourceFileSearchPaths[i], Ptr1, (Ptr - Ptr1));
120 if (SourceFileSearchPaths[i][strlen(SourceFileSearchPaths[i]) - 1] == ';')
121 {
122 SourceFileSearchPaths[i][strlen(SourceFileSearchPaths[i]) - 1] = 0;
123 }
124 i++;
125 }
126 }
127
128 DWARFManager_Set(NbSFSearchPaths, SourceFileSearchPaths);
129 }
130
131
132 // Reset the source file search paths
133 void DBGManager_SourceFileSearchPathsReset(void)
134 {
135 // Free each path
136 while (NbSFSearchPaths)
137 {
138 free(SourceFileSearchPaths[--NbSFSearchPaths]);
139 }
140
141 // Free the pointers list
142 free(SourceFileSearchPaths);
143 SourceFileSearchPaths = NULL;
144 }
145
146
147 // Close the source file search paths
148 void DBGManager_SourceFileSearchPathsClose(void)
149 {
150 DBGManager_SourceFileSearchPathsReset();
151 }
152
153
154 // Common debugger initialisation
155 void DBGManager_Init(void)
156 {
157 // DBG initialisations
158 DBGType = DBG_NO_TYPE;
159 DBGManager_SourceFileSearchPathsInit();
160
161 // ELF initialisation
162 ELFManager_Init();
163 // DWARF initialisation
164 DWARFManager_Init();
165 }
166
167
168 // Common debugger reset
169 void DBGManager_Reset(void)
170 {
171 if ((DBGType & DBG_DWARF))
172 {
173 DWARFManager_Reset();
174 }
175
176 if ((DBGType & DBG_ELF))
177 {
178 ELFManager_Reset();
179 }
180
181 //DBGType = vjs.displayHWlabels ? DBG_HWLABEL : DBG_NO_TYPE;
182 DBGType = DBG_NO_TYPE;
183 }
184
185
186 // Common debugger close
187 void DBGManager_Close(void)
188 {
189 if ((DBGType & DBG_DWARF))
190 {
191 DWARFManager_Close();
192 }
193
194 if ((DBGType & DBG_ELF))
195 {
196 ELFManager_Close();
197 }
198
199 DBGManager_SourceFileSearchPathsClose();
200 DBGType = DBG_NO_TYPE;
201 }
202
203
204 // Common debugger set
205 void DBGManager_SetType(size_t DBGTypeSet)
206 {
207 DBGType |= DBGTypeSet;
208 }
209
210
211 // Get debugger type
212 size_t DBGManager_GetType(void)
213 {
214 return DBGType;
215 }
216
217
218 // Get source filename based on the memeory address
219 // return NULL if no source filename
220 char *DBGManager_GetFullSourceFilenameFromAdr(size_t Adr, DBGstatus *Status)
221 {
222 if ((DBGType & DBG_ELFDWARF))
223 {
224 return DWARFManager_GetFullSourceFilenameFromAdr(Adr, (DWARFstatus *)Status);
225 }
226 else
227 {
228 return NULL;
229 }
230 }
231
232
233 // Get number of variables
234 // A NULL address will return the numbre of global variables, otherwise it will return the number of local variables
235 size_t DBGManager_GetNbVariables(size_t Adr)
236 {
237 if ((DBGType & DBG_ELFDWARF))
238 {
239 return DWARFManager_GetNbVariables(Adr);
240 }
241 else
242 {
243 return 0;
244 }
245 }
246
247
248 // Get variable's information
249 // A NULL address will return the pointer to the global variable structure, otherwise it will return the local's one
250 S_VariablesStruct* DBGManager_GetInfosVariable(size_t Adr, size_t Index)
251 {
252 if ((DBGType & DBG_ELFDWARF))
253 {
254 return (S_VariablesStruct*)DWARFManager_GetInfosVariable(Adr, Index);
255 }
256 else
257 {
258 return NULL;
259 }
260 }
261
262
263 // Get global variable's Address based on his Name
264 // Return found Address
265 // Return NULL if no Address has been found
266 size_t DBGManager_GetGlobalVariableAdrFromName(char *VariableName)
267 {
268 if ((DBGType & DBG_ELFDWARF))
269 {
270 return DWARFManager_GetGlobalVariableAdrFromName(VariableName);
271 }
272 else
273 {
274 return 0;
275 }
276 }
277
278
279 #if 0
280 // Get number of local variables
281 // Return 0 if none has been found
282 size_t DBGManager_GetNbLocalVariables(size_t Adr)
283 {
284 if ((DBGType & DBG_ELFDWARF))
285 {
286 return DWARFManager_GetNbLocalVariables(Adr);
287 }
288 else
289 {
290 return 0;
291 }
292 }
293
294
295 // Get number of global variables
296 // Return 0 if none has been found
297 size_t DBGManager_GetNbGlobalVariables(void)
298 {
299 if ((DBGType & DBG_ELFDWARF))
300 {
301 return DWARFManager_GetNbGlobalVariables();
302 }
303 else
304 {
305 return 0;
306 }
307 }
308 #endif
309
310
311 // Get address from symbol name
312 // Return found address
313 // Return NULL if no symbol has been found
314 size_t DBGManager_GetAdrFromSymbolName(char *SymbolName)
315 {
316 if (SymbolName)
317 {
318 if ((DBGType & DBG_ELF))
319 {
320 return ELFManager_GetAdrFromSymbolName(SymbolName);
321 }
322 }
323
324 return 0;
325 }
326
327
328 #if 0
329 // Get local variable's type encoding based on his address and Index
330 // Return the type encoding found
331 // Return 0 if no type encoding has been found
332 size_t DBGManager_GetLocalVariableTypeEncoding(size_t Adr, size_t Index)
333 {
334 if ((DBGType & DBG_ELFDWARF))
335 {
336 return DWARFManager_GetLocalVariableTypeEncoding(Adr, Index);
337 }
338 else
339 {
340 return 0;
341 }
342 }
343
344
345 //
346 int DBGManager_GetLocalVariableOffset(size_t Adr, size_t Index)
347 {
348 if ((DBGType & DBG_ELFDWARF))
349 {
350 return DWARFManager_GetLocalVariableOffset(Adr, Index);
351 }
352 else
353 {
354 return 0;
355 }
356 }
357
358
359 // Get local variable's type byte size based on his address and Index
360 // Return the type's byte size found
361 // Return 0 if no type's byte size has been found
362 size_t DBGManager_GetLocalVariableTypeByteSize(size_t Adr, size_t Index)
363 {
364 if ((DBGType & DBG_ELFDWARF))
365 {
366 return DWARFManager_GetLocalVariableTypeByteSize(Adr, Index);
367 }
368 else
369 {
370 return 0;
371 }
372 }
373
374
375 //
376 size_t DBGManager_GetLocalVariableTypeTag(size_t Adr, size_t Index)
377 {
378 if ((DBGType & DBG_ELFDWARF))
379 {
380 return DWARFManager_GetLocalVariableTypeTag(Adr, Index);
381 }
382 else
383 {
384 return 0;
385 }
386 }
387
388
389 //
390 size_t DBGManager_GetGlobalVariableTypeTag(size_t Index)
391 {
392 if ((DBGType & DBG_ELFDWARF))
393 {
394 return DWARFManager_GetGlobalVariableTypeTag(Index);
395 }
396 else
397 {
398 return 0;
399 }
400 }
401
402
403 // Get global variable's type name based on his Index
404 // Return type name's text pointer found
405 // Return NULL if no type name has been found
406 char *DBGManager_GetGlobalVariableTypeName(size_t Index)
407 {
408 if ((DBGType & DBG_ELFDWARF))
409 {
410 return DWARFManager_GetGlobalVariableTypeName(Index);
411 }
412 else
413 {
414 return NULL;
415 }
416 }
417
418
419 // Get global variable's Address based on his Index
420 // Return the Address found
421 // Return 0 if no Address has been found
422 size_t DBGManager_GetGlobalVariableAdr(size_t Index)
423 {
424 if ((DBGType & DBG_ELFDWARF))
425 {
426 return DWARFManager_GetGlobalVariableAdr(Index);
427 }
428 else
429 {
430 return 0;
431 }
432 }
433
434
435 // Get global variable's type byte size based on his Index
436 // Return the type's byte size found
437 // Return 0 if no type's byte size has been found
438 size_t DBGManager_GetGlobalVariableTypeByteSize(size_t Index)
439 {
440 if ((DBGType & DBG_ELFDWARF))
441 {
442 return DWARFManager_GetGlobalVariableTypeByteSize(Index);
443 }
444 else
445 {
446 return 0;
447 }
448 }
449
450
451 // Get global variable's type encoding based on his Index
452 // Return the type encoding found
453 // Return 0 if no type encoding has been found
454 size_t DBGManager_GetGlobalVariableTypeEncoding(size_t Index)
455 {
456 if ((DBGType & DBG_ELFDWARF))
457 {
458 return DWARFManager_GetGlobalVariableTypeEncoding(Index);
459 }
460 else
461 {
462 return 0;
463 }
464 }
465
466
467 // Get global variable value based on his Index
468 // Return value as a text pointer
469 // Note: Pointer may point on a 0 lenght text
470 char *DBGManager_GetGlobalVariableValue(size_t Index)
471 {
472 size_t Adr = 0;
473 size_t TypeEncoding = DBG_NO_TYPEENCODING;
474 size_t TypeByteSize = 0;
475
476 if ((DBGType & DBG_ELFDWARF))
477 {
478 Adr = DWARFManager_GetGlobalVariableAdr(Index);
479 TypeEncoding = DWARFManager_GetGlobalVariableTypeEncoding(Index);
480 TypeByteSize = DWARFManager_GetGlobalVariableTypeByteSize(Index);
481 }
482
483 return DBGManager_GetVariableValueFromAdr(Adr, TypeEncoding, TypeByteSize);
484 }
485
486
487 // Get local variable's type name based on his Index
488 // Return type name's text pointer found
489 // Return NULL if no type name has been found
490 char *DBGManager_GetLocalVariableTypeName(size_t Adr, size_t Index)
491 {
492 if ((DBGType & DBG_ELFDWARF))
493 {
494 return DWARFManager_GetLocalVariableTypeName(Adr, Index);
495 }
496 else
497 {
498 return NULL;
499 }
500 }
501
502
503 // Get local variable Op based on his Index
504 // Return variable Op's found
505 // Return 0 if no variable Op has been found
506 size_t DBGManager_GetLocalVariableOp(size_t Adr, size_t Index)
507 {
508 if ((DBGType & DBG_ELFDWARF))
509 {
510 return DWARFManager_GetLocalVariableOp(Adr, Index);
511 }
512 else
513 {
514 return 0;
515 }
516 }
517
518
519 // Get local variable name based on his Index
520 // Return variable name's text pointer found
521 // Return NULL if no variable name has been found
522 char *DBGManager_GetLocalVariableName(size_t Adr, size_t Index)
523 {
524 if ((DBGType & DBG_ELFDWARF))
525 {
526 return DWARFManager_GetLocalVariableName(Adr, Index);
527 }
528 else
529 {
530 return NULL;
531 }
532 }
533
534
535 // Get global variable name based on his Index
536 // Return variable name's text pointer found
537 // Return NULL if no variable name has been found
538 char *DBGManager_GetGlobalVariableName(size_t Index)
539 {
540 if ((DBGType & DBG_ELFDWARF))
541 {
542 return DWARFManager_GetGlobalVariableName(Index);
543 }
544 else
545 {
546 return NULL;
547 }
548 }
549 #endif
550
551
552 // Get variable value based on his Adresse, Encoding Type and Size
553 // Return value as a text pointer
554 // Note: Pointer may point on a 0 length text
555 char *DBGManager_GetVariableValueFromAdr(size_t Adr, size_t TypeEncoding, size_t TypeByteSize)
556 {
557 Value V;
558 char *Ptrvalue = value;
559
560 value[0] = 0;
561
562 #if 0
563 if (Adr)
564 #endif
565 {
566 memset(&V, 0, sizeof(Value));
567 #if 0
568 for (uint32_t i = 0; i < TypeByteSize; i++)
569 jaguarMainRAM[Adr + i] = 0;
570 //jaguarMainRAM[Adr + i] = rand();
571 jaguarMainRAM[Adr + TypeByteSize - 1] = 0x10;
572 #else
573 for (size_t i = 0, j = TypeByteSize; i < TypeByteSize; i++, j--)
574 {
575 V.Ct[i] = jaguarMainRAM[Adr + j - 1];
576 }
577 #endif
578 switch (TypeEncoding)
579 {
580 case DBG_ATE_address:
581 break;
582
583 case DBG_ATE_boolean:
584 sprintf(value, "%s", V.B ? "true" : "false");
585 break;
586
587 case DBG_ATE_complex_float:
588 break;
589
590 case DBG_ATE_float:
591 switch (TypeByteSize)
592 {
593 case 4:
594 sprintf(value, "%F", V.F);
595 break;
596
597 case 8:
598 //V.D = (double)jaguarMainRAM[Adr];
599 //sprintf(value, "%10.10F", V.D);
600 sprintf(value, "%F", V.D);
601 break;
602
603 default:
604 break;
605 }
606 break;
607
608 case DBG_ATE_signed:
609 switch (TypeByteSize)
610 {
611 case 2:
612 sprintf(value, "%i", V.SS);
613 break;
614
615 case 4:
616 sprintf(value, "%i", V.SI);
617 break;
618
619 case 8:
620 sprintf(value, "%i", V.SL);
621 break;
622
623 default:
624 break;
625 }
626 break;
627
628 case DBG_ATE_signed_char:
629 break;
630
631 case DBG_ATE_unsigned:
632 switch (TypeByteSize)
633 {
634 case 2:
635 sprintf(value, "%u", V.US);
636 break;
637
638 case 4:
639 sprintf(value, "%u", V.UI);
640 break;
641
642 case 8:
643 sprintf(value, "%u", V.UL);
644 break;
645
646 default:
647 break;
648 }
649 break;
650
651 case DBG_ATE_unsigned_char:
652 sprintf(value, "%u", (unsigned int) V.C);
653 break;
654
655 case DBG_ATE_ptr:
656 switch (TypeByteSize)
657 {
658 case 4:
659 sprintf(value, "0x%06x", V.UI);
660 break;
661
662 default:
663 break;
664 }
665
666 default:
667 break;
668 }
669 }
670
671 return Ptrvalue;
672 }
673
674
675 // Get function name from address
676 // Return function name found
677 // Return NULL if no function name has been found
678 char *DBGManager_GetFunctionName(size_t Adr)
679 {
680 char *Symbolname = NULL;
681
682 if ((DBGType & DBG_ELFDWARF))
683 {
684 Symbolname = DWARFManager_GetFunctionName(Adr);
685 }
686
687 if ((DBGType & DBG_ELF) && (Symbolname == NULL))
688 {
689 Symbolname = ELFManager_GetFunctionName(Adr);
690 }
691
692 return Symbolname;
693 }
694
695
696 // Get line number from address and his tag
697 // Return line number on the symbol name found
698 // Return 0 if no symbol name has been found
699 size_t DBGManager_GetNumLineFromAdr(size_t Adr, size_t Tag)
700 {
701 if ((DBGType & DBG_ELFDWARF))
702 {
703 return DWARFManager_GetNumLineFromAdr(Adr, Tag);
704 }
705 else
706 {
707 return 0;
708 }
709 }
710
711
712 // Get symbol name from address
713 // Return text pointer on the symbol name found
714 // Return NULL if no symbol name has been found
715 char *DBGManager_GetSymbolNameFromAdr(size_t Adr)
716 {
717 char *Symbolname;
718
719 //if ((DBGType & DBG_HWLABEL) || vjs.displayHWlabels)
720 if (vjs.displayHWlabels)
721 {
722 Symbolname = HWLABELManager_GetSymbolnameFromAdr(Adr);
723 }
724 else
725 {
726 Symbolname = NULL;
727 }
728 #ifdef _MSC_VER
729 #pragma message("Warning: !!! Need to set the DBG_HWLABEL in DBGType instead to use the setting value !!!")
730 #else
731 #warning "!!! Need to set the DBG_HWLABEL in DBGType instead to use the setting value !!!"
732 #endif // _MSC_VER
733
734 if (Symbolname == NULL)
735 {
736 if ((DBGType & DBG_ELFDWARF))
737 {
738 Symbolname = DWARFManager_GetSymbolnameFromAdr(Adr);
739 }
740
741 if ((DBGType & DBG_ELF) && (Symbolname == NULL))
742 {
743 Symbolname = ELFManager_GetSymbolnameFromAdr(Adr);
744 }
745 }
746
747 return Symbolname;
748 }
749
750
751 // Get source line based on the Address and his Tag
752 // Return text pointer on the source line found
753 // Return NULL if no source line has been found
754 char *DBGManager_GetLineSrcFromAdr(size_t Adr, size_t Tag)
755 {
756 char *TextLine = NULL;
757
758 if ((DBGType & DBG_ELFDWARF))
759 {
760 TextLine = DWARFManager_GetLineSrcFromAdr(Adr, Tag);
761 }
762
763 return TextLine;
764 }
765
766
767 // Get text line from source based on address and num line (starting from 1)
768 // Return NULL if no text line has been found
769 char *DBGManager_GetLineSrcFromAdrNumLine(size_t Adr, size_t NumLine)
770 {
771 char *TextLine = NULL;
772
773 if ((DBGType & DBG_ELFDWARF))
774 {
775 TextLine = DWARFManager_GetLineSrcFromAdrNumLine(Adr, NumLine);
776 }
777
778 return TextLine;
779 }
780
781
782 // Get text line from source based on address and num line (starting from 1)
783 // Return NULL if no text line has been found
784 char *DBGManager_GetLineSrcFromNumLineBaseAdr(size_t Adr, size_t NumLine)
785 {
786 char *TextLine = NULL;
787
788 if ((DBGType & DBG_ELFDWARF))
789 {
790 TextLine = DWARFManager_GetLineSrcFromNumLineBaseAdr(Adr, NumLine);
791 }
792
793 return TextLine;
794 }
795
796
797 // Get number of source code filenames
798 size_t DBGManager_GetNbSources(void)
799 {
800 size_t Nbr = 0;
801
802 if ((DBGType & DBG_ELFDWARF))
803 {
804 Nbr = DWARFManager_GetNbSources();
805 }
806
807 return Nbr;
808 }
809
810
811 // Get source code filename based on index
812 char *DBGManager_GetNumSourceFilename(size_t Index)
813 {
814 char *SourceFilename = NULL;
815
816 if ((DBGType & DBG_ELFDWARF))
817 {
818 SourceFilename = DWARFManager_GetNumSourceFilename(Index);
819 }
820
821 return SourceFilename;
822 }
823
824
825 // Get source code filename based on index
826 char *DBGManager_GetNumFullSourceFilename(size_t Index)
827 {
828 char *FullSourceFilename = NULL;
829
830 if ((DBGType & DBG_ELFDWARF))
831 {
832 FullSourceFilename = DWARFManager_GetNumFullSourceFilename(Index);
833 }
834
835 return FullSourceFilename;
836 }
837
838
839 // Get number of lines of texts source list from source index
840 size_t DBGManager_GetSrcNbListPtrFromIndex(size_t Index, bool Used)
841 {
842 size_t NbListPtr = 0;
843
844 if ((DBGType & DBG_ELFDWARF))
845 {
846 NbListPtr = DWARFManager_GetSrcNbListPtrFromIndex(Index, Used);
847 }
848
849 return NbListPtr;
850 }
851
852
853 // Get pointer to the lines number list from source index
854 size_t *DBGManager_GetSrcNumLinesPtrFromIndex(size_t Index, bool Used)
855 {
856 size_t *PtrNumLines = NULL;
857
858 if ((DBGType & DBG_ELFDWARF))
859 {
860 PtrNumLines = DWARFManager_GetSrcNumLinesPtrFromIndex(Index, Used);
861 }
862
863 return PtrNumLines;
864 }
865
866
867 // Get text source list pointers from source index
868 char **DBGManager_GetSrcListPtrFromIndex(size_t Index, bool Used)
869 {
870 char **PtrSource = NULL;
871
872 if ((DBGType & DBG_ELFDWARF))
873 {
874 PtrSource = DWARFManager_GetSrcListPtrFromIndex(Index, Used);
875 }
876
877 return PtrSource;
878 }
879
880
881 // Get source language
882 size_t DBGManager_GetSrcLanguageFromIndex(size_t Index)
883 {
884 size_t Language = 0;
885
886 if ((DBGType & DBG_ELFDWARF))
887 {
888 Language = DWARFManager_GetSrcLanguageFromIndex(Index);
889 }
890
891 return Language;
892 }
893