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