https://github.com/virtualagc/virtualagc
Revision 66d8e606a8d996ded60bc81d5edf319142a5fad9 authored by Ron Burkey on 04 October 2021, 11:49:55 UTC, committed by Ron Burkey on 04 October 2021, 11:49:55 UTC
Tip revision: 66d8e606a8d996ded60bc81d5edf319142a5fad9 authored by Ron Burkey on 04 October 2021, 11:49:55 UTC
Merge branch 'master' of https://github.com/virtualagc/virtualagc
Merge branch 'master' of https://github.com/virtualagc/virtualagc
Tip revision: 66d8e60
agc_gdbmi.c
/*
* Copyright 2008,2016 Onno Hommes:1
*
* This file is part of yaAGC.
*
* yaAGC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* yaAGC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with yaAGC; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* In addition, as a special exception, permission is granted to
* link the code of this program with the Orbiter SDK library (or with
* modified versions of the Orbiter SDK library that use the same license as
* the Orbiter SDK library), and distribute linked combinations including
* the two. You must obey the GNU General Public License in all respects for
* all of the code used other than the Orbiter SDK library. If you modify
* this file, you may extend this exception to your version of the file,
* but you are not obligated to do so. If you do not wish to do so, delete
* this exception statement from your version.
*
* Filename: agc_gdbmi.c
* Purpose: This is module covers the gdb/mi subsystem of yaAGC and enables
* yaAGC to be debugged in a Graphical Debugger front-end to gdb.
* Compiler: GNU gcc.
* Contact: Onno Hommes
* Reference: http://virtualagc.googlecode.com
* Mods: 01/01/08 OH Began work.
* 06/08/09 OH Added info variables,functions and fixed
* Showing source line when not using -fullname.
* 06/14/09 OH Add the gdb style disassemble command
* 07/01/09 OH Convert to command tables to prepare for machine
* independence and change to GNU formating
* 08/01/09 RSB Adjusted to use NormalizeSourceName().
* 07/17/16 RSB gdbmi_format was commented out everywhere
* it appeared, since it wasn't being used
* and was generating compiler warnings.
* 09/12/16 OH Add /fmt capabilities to print and output
* 09/20/16 OH Support floating point with scalar types.
* 11/24/16 RSB Changed a printf with a %#u format to %u ...
* it causes compiler warnings that have become
* increasingly troublesome to deal with on different
* platforms, and has no meaning whatever that I've
* been able to determine from googling.
*/
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include "yaAGC.h"
#include "agc_engine.h"
#include "agc_symtab.h"
#include "agc_debug.h"
#include "agc_debugger.h"
#include "agc_disassembler.h"
#include "agc_gdbmi.h"
#include <string.h>
#include <unistd.h>
#ifdef WIN32
#include <windows.h>
#include <sys/time.h>
#include "regex.h"
#define LB "\r\n"
#else
#include <time.h>
#include <sys/times.h>
#include <regex.h>
#define LB ""
#endif
//#define VERSION(x) #x
extern char agcPrompt[16];
extern int HaveSymbols;
extern int FullNameMode;
extern int Break;
extern int DebuggerInterruptMasks[11];
extern char* CurrentSourceFile;
extern int SymbolTableSize;
extern Symbol_t *SymbolTable;
extern char SourceFiles[MAX_NUM_FILES][MAX_FILE_LENGTH];
extern int NumberFiles;
extern SymbolLine_t*
FindLastLineMain (void);
extern void
CheckDec (char *s);
extern char*
DbgGetFrameNameByAddr (unsigned LinearAddress);
static int gdbmi_break_id = 0;
static int gdbmi_status;
//static int cli_argc;
static char* cli_arg;
static char FileName[MAX_FILE_LENGTH + 1];
static agc_t* State;
static char* s;
static char* sraw;
static CustomCommand_t gdbmiCustomCmds[32];
const char disp_keep[5] = "keep";
const char disp_delete[4] = "del";
#define SP (unsigned)1
#define DP (unsigned)2
#define PI 3.14159265358979
typedef int GdbmiComplement_t;
typedef struct {
char type[3];
unsigned precision;
double scalar;
} GdmiScalar_t;
const GdmiScalar_t GdbmiScalarMap[] = {
{"FF",SP, 85.41}, // TRIM DEGREES: seconds of arc
{"GG",SP, 1.0/16384}, // INERTIA: Frac. of 1,048,576 kg m²
{"II",SP, 1.0/16384}, // THRUST MOMENT: Frac. of 1,048,576 Nm
{"JJ",DP, 2.0}, // POSITION5: m
{"KK",SP, 1.0/16384}, // WEIGHT2: kg
{"LL",DP, 0.00008055}, // POSITION6: Nautical Miles.
{"MM",DP, 25.0/268435456}, // DRAG ACCELERATION: G
{"PP",DP, 1.0}, // 2 INTEGERS
{"UU",DP, 1.0/268435456}, // VELOCITY/2VS: Frac. of 51,532.3946 feet/sec
{"VV",DP, 0.00005128}, // POSITION8: Nautical miles
{"XX",DP, 1.0/512}, // POSITION9: Meters
{"YY",DP, 1.0/268435456}, // VELOCITY4: Meters/Centisec
{"SP",SP, 1.0/16384}, // GENERIC: Single Precision Fraction.
{"DP",DP, 1.0/268435456}, // GENERIC: Double Precision Fraction.
/* {"TP",DP, 1.0/4398046511104}// GENERIC: Triple Precision Fraction. */
{ "A",SP, 1.0}, // OCTAL: Octal
{ "B",SP, 1.0/16384}, // FRACTIONAL: Fraction (Default)
{ "C",SP, 1.0}, // WHOLE: 1 Unit
{ "D",SP,360.0/32768}, // CDU DEGREES: Degrees (15 Bit 2s Complement)
{ "E",SP, 90.0/16384}, // ELEVATION DEGREES: Degrees
{ "F",SP,180.0/16384}, // DEGREES : Degrees
{ "G",DP,360.0/268435456}, // DEGREES (90): Degrees
{ "H",DP,360.0/268435456}, // DEGREES (360): Degrees
{ "J",SP, 90.0/32768}, // DEGREES: Degrees (15 bit 2s Complement)
{ "K",DP, 1.0/100}, // TIME (HR, MIN, SEC): seconds
{ "L",DP, 1.0/100}, // TIME (MIN SEC): minutes | seconds
{ "M",SP, 1.0/100}, // TIME (SEC): seconds
{ "N",DP, 1.0/100}, // TIME (SEC): seconds
{ "P",DP, 1.0/2097152}, // VELOCITY 2: meters/centi-sec
{ "Q",DP, 2.0}, // POSITION 4: meters
{ "S",DP, 1.0/2097152}, // VELOCITY 3: meters/centi-sec
{ "T",SP, 1.0/100}, // G
};
#define SCALARS sizeof(GdbmiScalarMap)/sizeof(GdmiScalar_t)
char*
GdbmiStringToUpper (char* str)
{
char* ss;
/* Ensure command s is in uppercase */
for (ss = str; *ss; *ss = toupper (*ss), ss++)
;
return (str);
}
/**
Adjust the command string pointer with the value given.
*/
static inline void
GdbmiAdjustCmdPtr (int i)
{
s += i;
sraw += i;
}
/**
Adjust the command string pointer with the value given.
*/
static inline void
GdbmiSkipSpace ()
{
while (*sraw == ' ') GdbmiAdjustCmdPtr(1);
}
/**
Skip to the next token.
*/
static inline void
GdbmiNextToken()
{
while (*sraw != ' ' && *sraw != '\0' ) {
GdbmiAdjustCmdPtr(1);
}
}
static inline void
GdbmiGet(char* token)
{
}
static int GdbmiScalar = 12;
/**
* Set the FMT specifier if provided in the command string
*/
static inline void GdbmiParseFmt(GdbmiFmt_t* fmt)
{
*fmt = 'o';
int i;
/* Get basic Format specified if provided */
if (*sraw == '/') {
*fmt = *(sraw + 1);
GdbmiAdjustCmdPtr(2);
}
/* Get extended type scalar if speficied */
if (*sraw == ':') {
GdbmiAdjustCmdPtr(1);
/* Find Scalar Type */
for (i=0; i< SCALARS; i++)
{
const char* type = GdbmiScalarMap[i].type;
if (strncmp(s,type, strlen(type)) == 0 ){
GdbmiScalar = i;
break;
}
}
/* Adjust string pointers */
GdbmiNextToken();
}
}
GdbmiResult
GdbmiParseConsoleCommands (GdbmiCommands_t* CmdTable)
{
int i = -1;
int CmdLength;
GdbmiResult GdbmiStat = GdbmiCmdUnhandled;
while (CmdTable[++i].Command)
{
CmdLength = strlen (CmdTable[i].Command);
if (!strncmp (s, CmdTable[i].Command, CmdLength))
{
GdbmiStat = CmdTable[i].Handler (CmdLength);
break;
}
}
return (GdbmiStat);
}
static char *
GdbmiBasename (const char *name)
{
const char *base;
#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
/* Skip over the disk name in MSDOS pathnames. */
if (ISALPHA (name[0]) && name[1] == ':')
name += 2;
#endif
for (base = name; *name; name++)
{
if (*name == '/' || *name == '\\')
{
base = name + 1;
}
}
return (char *) base;
}
void
GdbmiDisassemble (agc_t *State, unsigned start_linear, unsigned end_linear)
{
}
void
GdbmiDisplayBreakpointForLine (SymbolLine_t* Line, int BreakpointId)
{
unsigned LinearAddress = DbgLinearAddr (&Line->CodeAddress);
printf ("Breakpoint %d, %s () at %s:%d\n", BreakpointId,
DbgGetFrameNameByAddr (LinearAddress), Line->FileName,
Line->LineNumber);
}
/* Handle the break GDB/CLI command */
static GdbmiResult
GdbmiHandleAllBreak (int j, char disp)
{
int i, vRegBB, LineNumber;
Symbol_t *Symbol = NULL;
SymbolLine_t *Line = NULL;
char SymbolName[MAX_LABEL_LENGTH + 1], *cli_char;
unsigned gdbmiAddress = 0;
Address_t agc_addr;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (j);
if (strlen (s) > 0) /* Do we have an argument */
{
s++;
sraw++; /* Skip space */
/* Remove Enclosing Double Quotes */
if (sraw[0] == '\"')
{
++sraw;
++s;
if (sraw[strlen (sraw) - 1] == '\"')
{
sraw[strlen (sraw) - 1] = 0;
s[strlen (s) - 1] = 0;
}
}
sraw = GdbmiBasename (sraw);
s = GdbmiBasename (s);
/* First replace ":" with space !!FIX to prevent DOS disk separator!! */
cli_char = strstr (sraw, ":");
if (cli_char)
*cli_char = ' '; /* replace colon with space */
if (HaveSymbols && (2 == sscanf (sraw, "%s %d", FileName, &LineNumber))
&& (Line = (SymbolLine_t*) ResolveFileLineNumber (FileName,
LineNumber)))
{
gdbmiAddress = DbgLinearAddr (&Line->CodeAddress);
}
else if (HaveSymbols && (1 == sscanf (s, "%d", &LineNumber)) && (Line =
ResolveLineNumber (LineNumber)))
{
gdbmiAddress = DbgLinearAddr (&Line->CodeAddress);
}
else if (HaveSymbols && (1 == sscanf (s, "%s", SymbolName)) && (Symbol =
ResolveSymbol (SymbolName, SYMBOL_LABEL)))
{
gdbmiAddress = DbgLinearAddr (&Symbol->Value);
}
else if (1 == sscanf (s, "*0X%x", &gdbmiAddress))
;
else
{
/* Insert error message not help */
printf ("Illegal syntax for break.\n");
return (GdbmiCmdDone);
}
}
else /* Default Break point is current address */
{
gdbmiAddress = DbgLinearFixedAddr (
State->Erasable[0][RegZ] & 07777,
037 & (State->Erasable[0][RegBB] >> 10),
(State->OutputChannel7 & 0100) ? 1 : 0);
}
if (gdbmiAddress < 04000)
{
printf ("Line number points to erasable memory.\n");
return (GdbmiCmdDone);
}
agc_addr = DbgNativeAddr (gdbmiAddress);
vRegBB = ((agc_addr.FB << 10) | (agc_addr.Super << 7));
if (Line == NULL)
Line = ResolveLineAGC (agc_addr.SReg, agc_addr.FB, agc_addr.Super);
for (i = 0; i < NumBreakpoints; i++)
if (Breakpoints[i].Address12 == agc_addr.SReg
&& Breakpoints[i].vRegBB == vRegBB && Breakpoints[i].WatchBreak == 0)
{
printf ("This breakpoint already exists.\n");
return (GdbmiCmdDone);
}
if (NumBreakpoints < MAX_BREAKPOINTS)
{
Breakpoints[NumBreakpoints].Id = ++gdbmi_break_id;
Breakpoints[NumBreakpoints].Hits = 0;
Breakpoints[NumBreakpoints].Enable = 'y';
Breakpoints[NumBreakpoints].Disposition = disp;
Breakpoints[NumBreakpoints].Address12 = agc_addr.SReg;
Breakpoints[NumBreakpoints].vRegBB = vRegBB;
Breakpoints[NumBreakpoints].WatchBreak = 0;
Breakpoints[NumBreakpoints].Symbol = Symbol;
Breakpoints[NumBreakpoints].Line = Line;
NumBreakpoints++;
if (Line)
printf ("Breakpoint %d at 0x%04x: file %s, line %d.\n", NumBreakpoints,
gdbmiAddress, Line->FileName, Line->LineNumber);
}
else
printf ("The maximum number of breakpoints is already defined.\n");
// FIX ME
return (GdbmiCmdDone);
}
/* Handle the temporary break GDB/CLI command */
static GdbmiResult
GdbmiHandleTmpBrk (int i)
{
return (GdbmiHandleAllBreak (i, BP_DELETE));
}
/* Handle the normal break GDB/CLI command */
static GdbmiResult
GdbmiHandleNormBrk (int i)
{
return (GdbmiHandleAllBreak (i, BP_KEEP));
}
static GdbmiResult
GdbmiHandleWatch (int j)
{
int k, i, vRegBB, WatchType, WatchValue = 0777777;
Symbol_t *Symbol = NULL;
unsigned gdbmi_address;
Address_t agc_addr;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (j);
if (strlen (sraw))
Symbol = ResolveSymbol (
sraw, SYMBOL_VARIABLE | SYMBOL_REGISTER | SYMBOL_CONSTANT);
if (Symbol != NULL && !Symbol->Value.Erasable)
Symbol = NULL;
if (Symbol != NULL)
{
/* Get linear address for display */
gdbmi_address = DbgLinearAddr (&Symbol->Value);
/* Watch Type 3 = for value, Watch type 1 for any change */
agc_addr = DbgNativeAddr (gdbmi_address);
WatchType = 1;
vRegBB = agc_addr.EB;
k = agc_addr.SReg;
WatchValue = State->Erasable[vRegBB][k];
}
for (i = 0; i < NumBreakpoints; i++)
if (Breakpoints[i].Address12 == k && Breakpoints[i].vRegBB == vRegBB
&& Breakpoints[i].WatchBreak == WatchType)
{
printf ("This watchpoint already exists.\n");
return (GdbmiCmdDone);
}
if (NumBreakpoints < MAX_BREAKPOINTS)
{
Breakpoints[NumBreakpoints].Id = ++gdbmi_break_id;
Breakpoints[NumBreakpoints].Hits = 0;
Breakpoints[NumBreakpoints].Enable = 'y';
Breakpoints[NumBreakpoints].Disposition = BP_KEEP;
Breakpoints[NumBreakpoints].Address12 = k;
Breakpoints[NumBreakpoints].vRegBB = vRegBB;
Breakpoints[NumBreakpoints].WatchBreak = WatchType;
Breakpoints[NumBreakpoints].Symbol = Symbol;
Breakpoints[NumBreakpoints].Line = NULL;
if (WatchType == 1)
Breakpoints[NumBreakpoints].WatchValue = DbgGetWatch (
State, &Breakpoints[NumBreakpoints]);
else
Breakpoints[NumBreakpoints].WatchValue = WatchValue;
NumBreakpoints++;
if (Symbol)
printf ("Hardware watchpoint %d: %s\n", gdbmi_break_id, Symbol->Name);
}
else
printf ("The maximum number of watchpoints is already defined.\n");
return (GdbmiCmdDone);
}
void
GdbmiHandleShowVersion (void)
{
DbgDisplayVersion ();
}
static GdbmiResult
GdbmiHandleInfoRegisters (int i)
{
int cli_argc = 0;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (i);
if (strlen (s) > 1)
{
cli_argc++;
cli_arg = s + 1;
}
/* Print the requested register contents */
if (!cli_argc || !strcmp (cli_arg, "A"))
printf ("A\t\t0x%04x\t%d\n", 0177777 & State->Erasable[0][RegA],
0177777 & State->Erasable[0][RegA]);
if (!cli_argc || !strcmp (cli_arg, "L"))
printf ("L\t\t0x%04x\t%d\n", 0177777 & State->Erasable[0][RegL],
0177777 & State->Erasable[0][RegL]);
if (!cli_argc || !strcmp (cli_arg, "Q"))
printf ("Q\t\t0x%04x\t%d\n", 0177777 & State->Erasable[0][RegQ],
0177777 & State->Erasable[0][RegQ]);
if (!cli_argc || !strcmp (cli_arg, "EB"))
printf ("EB\t\t0x%04x\t%d\n", 0177777 & State->Erasable[0][RegEB],
0177777 & State->Erasable[0][RegEB]);
if (!cli_argc || !strcmp (cli_arg, "FB"))
printf ("FB\t\t0x%04x\t%d\n", 0177777 & State->Erasable[0][RegFB],
0177777 & State->Erasable[0][RegFB]);
if (!cli_argc || !strcmp (cli_arg, "Z"))
printf ("Z\t\t0x%04x\t%d\n", 0177777 & State->Erasable[0][RegZ],
0177777 & State->Erasable[0][RegZ]);
if (!cli_argc || !strcmp (cli_arg, "BB"))
printf ("BB\t\t0x%04x\t%d\n", 0177777 & State->Erasable[0][RegBB],
0177777 & State->Erasable[0][RegBB]);
if (!cli_argc || !strcmp (cli_arg, "ARUPT"))
printf ("ARUPT\t\t0x%04x\t%d\n", 0177777 & State->Erasable[0][RegARUPT],
0177777 & State->Erasable[0][RegARUPT]);
if (!cli_argc || !strcmp (cli_arg, "LRUPT"))
printf ("LRUPT\t\t0x%04x\t%d\n", 0177777 & State->Erasable[0][RegLRUPT],
0177777 & State->Erasable[0][RegLRUPT]);
if (!cli_argc || !strcmp (cli_arg, "QRUPT"))
printf ("QRUPT\t\t0x%04x\t%d\n", 0177777 & State->Erasable[0][RegQRUPT],
0177777 & State->Erasable[0][RegQRUPT]);
if (!cli_argc || !strcmp (cli_arg, "ZRUPT"))
printf ("ZRUPT\t\t0x%04x\t%d\n", 0177777 & State->Erasable[0][RegZRUPT],
0177777 & State->Erasable[0][RegZRUPT]);
if (!cli_argc || !strcmp (cli_arg, "BBRUPT"))
printf ("BBRUPT\t\t0x%04x\t%d\n", 0177777 & State->Erasable[0][RegBBRUPT],
0177777 & State->Erasable[0][RegBBRUPT]);
if (!cli_argc || !strcmp (cli_arg, "BRUPT"))
printf ("BRUPT\t\t0x%04x\t%d\n", 0177777 & State->Erasable[0][RegBRUPT],
0177777 & State->Erasable[0][RegBRUPT]);
if (!cli_argc || !strcmp (cli_arg, "CHAN07"))
printf ("CHAN07\t\t0x%04x\t%d\n", 0177777 & State->InputChannel[7],
0177777 & State->InputChannel[7]);
if (!cli_argc || !strcmp (cli_arg, "CYR"))
printf ("CYR\t\t0x%04x\t%d\n", 0177777 & State->Erasable[0][RegCYR],
0177777 & State->Erasable[0][RegCYR]);
if (!cli_argc || !strcmp (cli_arg, "SR"))
printf ("SR\t\t0x%04x\t%d\n", 0177777 & State->Erasable[0][RegSR],
0177777 & State->Erasable[0][RegSR]);
if (!cli_argc || !strcmp (cli_arg, "CYL"))
printf ("CYL\t\t0x%04x\t%d\n", 0177777 & State->Erasable[0][RegCYL],
0177777 & State->Erasable[0][RegCYL]);
if (!cli_argc || !strcmp (cli_arg, "EDOP"))
printf ("EDOP\t\t0x%04x\t%d\n", 0177777 & State->Erasable[0][RegEDOP],
0177777 & State->Erasable[0][RegEDOP]);
if (!cli_argc || !strcmp (cli_arg, "INDEX"))
printf ("INDEX\t\t0x%04x\t%d\n", 0177777 & State->IndexValue,
0177777 & State->IndexValue);
if (!cli_argc || !strcmp (cli_arg, "EXTEND"))
printf ("EXTEND\t\t0x%04x\t%d\n", 0177777 & State->ExtraCode,
0177777 & State->ExtraCode);
if (!cli_argc || !strcmp (cli_arg, "IRQMSK"))
printf ("IRQMSK\t\t0x%04x\t%d\n", 0177777 & State->AllowInterrupt,
0177777 & State->AllowInterrupt);
if (!cli_argc || !strcmp (cli_arg, "ISR"))
printf ("ISR\t\t0x%04x\t%d\n", 0177777 & State->InIsr,
0177777 & State->InIsr);
return (GdbmiCmdDone);
}
GdbmiResult
GdbmiHandleInfoBreakpoints (int j)
{
int i;
char* disposition;
/* No CmdPtr adjust ment necessary so ignore input */
if (NumBreakpoints == 0)
printf ("No breakpoints or watchpoints.\n");
else
printf ("Num\tType\t\tDisp\tEnb\tAddress\tWhat\n");
for (i = 0; i < NumBreakpoints; i++)
{
int Address12, vRegBB;
if (Breakpoints[i].Disposition == BP_KEEP)
disposition = (char*) disp_keep;
else
disposition = (char*) disp_delete;
if (Breakpoints[i].WatchBreak > 0)
{
if (Breakpoints[i].Symbol != NULL)
{
printf ("%d\thw watchpoint\t%s\t%c\t %s",
Breakpoints[i].Id, disposition, Breakpoints[i].Enable,
Breakpoints[i].Symbol->Name);
}
}
else
{
printf ("%d\tbreakpoint\t%s\t%c\t", Breakpoints[i].Id, disposition,
Breakpoints[i].Enable);
}
Address12 = Breakpoints[i].Address12;
vRegBB = Breakpoints[i].vRegBB;
if (Address12 < 01400 || Address12 >= 04000)
printf ("0x%04x", DbgLinearFixedAddr (Address12, 0, 0));
else if (Address12 >= 02000 && Address12 < 04000)
{
int Bank;
Bank = (vRegBB >> 10) & 037;
if (0 != (vRegBB & 0100) && Bank >= 030)
Bank += 010;
printf ("0x%04x", DbgLinearFixedAddr (Address12, Bank, 0));
}
// Print out the file,line if set for the breakpoint
if (HaveSymbols)
{
if (Breakpoints[i].Symbol != NULL && !Breakpoints[i].WatchBreak)
printf (" in file %s:%d", Breakpoints[i].Symbol->FileName,
Breakpoints[i].Symbol->LineNumber);
else if (Breakpoints[i].Line != NULL && !Breakpoints[i].WatchBreak)
printf (" in file %s:%d", Breakpoints[i].Line->FileName,
Breakpoints[i].Line->LineNumber);
}
printf ("\n");
if (Breakpoints[i].Hits == 1)
printf ("\tbreakpoint already hit %d time\n", Breakpoints[i].Hits);
else if (Breakpoints[i].Hits > 1)
printf ("\tbreakpoint already hit %d times\n", Breakpoints[i].Hits);
}
return (GdbmiCmdDone);
}
void
GdbmiPrintFullNameFrame (SymbolLine_t *Line)
{
printf (
"\032\032%s:%d:%d:beg:0x%04x\n",
NormalizeSourceName (SourcePathName, Line->FileName),
Line->LineNumber,
Line->LineNumber,
DbgLinearFixedAddr (Line->CodeAddress.SReg, Line->CodeAddress.FB,
Line->CodeAddress.Super));
}
static char* CurrentFileName = 0;
void
GdbmiPrintSourceFrame (SymbolLine_t *Line)
{
if (CurrentFileName == 0 || strcmp (CurrentFileName, Line->FileName))
{
/* Looks like a source file switch print the file info */
unsigned Address = DbgLinearAddr (&Line->CodeAddress);
printf ("%s () at %s:%d\n", DbgGetFrameNameByAddr (Address),
Line->FileName, Line->LineNumber);
CurrentFileName = Line->FileName;
}
ListSourceLine (Line->FileName, Line->LineNumber, 0);
}
GdbmiResult
GdbmiHandleInfoLine (int i)
{
int LineNumber;
SymbolLine_t *Line = NULL;
char *cli_char = NULL;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (i);
if (*s == ' ')
{
cli_char = strstr (sraw, ":");
*cli_char = ' ';
if (2 == sscanf (sraw + 1, "%s %d", FileName, &LineNumber))
{
Line = (SymbolLine_t*) ResolveFileLineNumber (FileName, LineNumber);
}
}
else
{
int CurrentZ = State->Erasable[0][RegZ] & 07777;
int FB = 037 & (State->Erasable[0][RegBB] >> 10);
int SBB = (State->OutputChannel7 & 0100) ? 1 : 0;
Line = ResolveLineAGC (CurrentZ, FB, SBB);
}
if (Line)
{
unsigned Addr = DbgLinearAddr (&Line->CodeAddress);
char* FrameName = DbgGetFrameNameByAddr (Addr);
printf ("Line %d of \"%s\" starts at address 0x%04x <%s>\n",
Line->LineNumber, Line->FileName, Addr, FrameName);
printf (" and ends at 0x%04x <%s>.\n", Addr, FrameName);
if (FullNameMode)
GdbmiPrintFullNameFrame (Line);
}
return (GdbmiCmdDone);
}
GdbmiResult
GdbmiHandleInfoTarget (int i)
{
printf ("Symbols from \"%s\".\n", SymbolFile);
printf ("Local exec file:\n");
printf ("\tfile type ropes-agc.\n");
printf ("\tEntry point: 0x0800\n");
printf ("\t0x0000 - 0x02ff is .unswitched_eraseable\n");
printf ("\t0x0300 - 0x07ff is .switched_eraseable\n");
printf ("\t0x0800 - 0x0fff is .fixed_fixed\n");
printf ("\t0x1000 - 0x17ff is .common_fixed\n");
printf ("\t0x1800 - 0x1fff is .fixed_fixed\n");
printf ("\t0x2000 - 0x6fff is .common_fixed\n");
printf ("\t0x7000 - 0x9fff is .super_bank\n");
return (GdbmiCmdDone);
}
GdbmiResult
GdbmiHandleInfoChannels (int i)
{
int chx;
unsigned value;
int select = -1;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (i);
/* Check for a channel argument */
if (strlen (s) > 0)
{
select = strtol (s, 0, 0);
}
for (chx = 0; chx < NUM_CHANNELS; chx++)
{
value = ReadIO (State, chx);
if (select < 0 || select == chx)
{
printf ("CHAN%o\t0x%04x %5d\n", chx, value, value);
}
}
return (GdbmiCmdDone);
}
typedef struct io_regs_tag
{
char name[8];
int offset;
} t_io_regs;
#define NUM_IO_REGS 23
const t_io_regs io_registers[NUM_IO_REGS] =
{
{ "CDUX", 032 },
{ "CDUY", 033 },
{ "CDUZ", 034 },
{ "OPTY", 035 },
{ "OPTX", 036 },
{ "PIPAX", 037 },
{ "PIPAY", 040 },
{ "PIPAZ", 041 },
{ "RHCP", 042 },
{ "RHCY", 043 },
{ "RHCR", 044 },
{ "INLINK", 045 },
{ "RNRAD", 046 },
{ "GYROCMD", 047 },
{ "CDUXCMD", 050 },
{ "CDUYCMD", 051 },
{ "CDUZCMD", 052 },
{ "OPTYCMD", 053 },
{ "OPTXCMD", 054 },
{ "THRUST", 055 },
{ "LEMONM", 056 },
{ "OUTLINK", 057 },
{ "ALTM", 060 } };
static GdbmiResult
GdbmiHandleInfoIoRegisters (int j)
{
int io_select = 0;
int i;
unsigned value;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (j);
if (strlen (s++) > 1)
io_select = 1;
for (i = 0; i < NUM_IO_REGS; i++)
{
if (io_select == 0 || !strcmp (s, io_registers[i].name))
{
value = 0177777 & State->Erasable[0][io_registers[i].offset];
printf ("%s\t\t0x%04x\t%u\n", io_registers[i].name, value, value);
}
}
return (GdbmiCmdDone);
}
static GdbmiResult
GdbmiHandleInfoAllRegisters (int i)
{
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (i);
GdbmiHandleInfoRegisters (0);
GdbmiHandleInfoIoRegisters (0);
return (GdbmiCmdDone);
}
static GdbmiResult
GdbmiHandleInfoProgram (int i)
{
printf ("\tUsing the running image of child process 0.\n");
printf (
"Program stopped at 0x%04x.\n",
DbgLinearFixedAddr (State->Erasable[0][RegZ] & 07777,
037 & (State->Erasable[0][RegBB] >> 10),
(State->OutputChannel7 & 0100) ? 1 : 0));
printf ("It stopped after being stepped.\n");
return (GdbmiCmdDone);
}
/**
* Display the thread summaries of all currently known threads
* If no ISR is active only one thread the default execution
* thread will be shown. If an ISR is running (only one can run
* at a time then both the ISR as well as the default execution
* thread will be shown. With the ISR marked as the active thread
*/
static GdbmiResult
GdbmiHandleInfoThreads (int i)
{
SymbolLine_t* Line = NULL;
char threadName[10] = "main";
unsigned LinearAddress;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (i);
/* Check if we are dealing with 2 threads (i.e. in an ISR) */
if (State->InIsr)
{
/* Determine the thread name to be verbose when showing info */
switch (State->InterruptRequests[0])
{
case 1:
strcpy (threadName, "TIMER6");
break;
case 2:
strcpy (threadName, "TIMER5");
break;
case 3:
strcpy (threadName, "TIMER3");
break;
case 4:
strcpy (threadName, "TIMER4");
break;
case 5:
strcpy (threadName, "KEYBD1");
break;
case 6:
strcpy (threadName, "KEYBD2");
break;
case 7:
strcpy (threadName, "UPLINK");
break;
case 8:
strcpy (threadName, "DNLINK");
break;
case 9:
strcpy (threadName, "RADAR");
break;
case 10:
strcpy (threadName, "JOYSTK");
break;
default:
strcpy (threadName, "MAIN");
break;
}
/* Get head of the stack of ISR thread */
Line = DbgResolveCurrentLine ();
if (Line)
{
LinearAddress = DbgLinearAddr (&Line->CodeAddress);
printf ("* 2 thread %d (%s)\t0x%04x in %s ()\n",
State->InterruptRequests[0], threadName, LinearAddress,
DbgGetFrameNameByAddr (LinearAddress));
printf (" at %s:%d\n", Line->FileName, Line->LineNumber);
}
Line = FindLastLineMain ();
if (Line)
{
LinearAddress = DbgLinearAddr (&Line->CodeAddress);
printf (" 1 thread 0 (MAIN)\t0x%04x in %s ()\n", LinearAddress,
DbgGetFrameNameByAddr (LinearAddress));
}
}
else
{
Line = DbgResolveCurrentLine ();
if (Line)
{
LinearAddress = DbgLinearAddr (&Line->CodeAddress);
printf ("* 1 thread 0 (MAIN)\t0x%04x in %s ()\n", LinearAddress,
DbgGetFrameNameByAddr (LinearAddress));
printf (" at %s:%d\n", Line->FileName, Line->LineNumber);
}
}
return (GdbmiCmdDone);
}
static GdbmiResult
GdbmiHandleBacktrace (int i)
{
int LimitList = MAX_BACKTRACE_POINTS;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (i);
sscanf (s, "%d", &LimitList);
BacktraceDisplay (State, LimitList);
return (GdbmiCmdDone);
}
//Current source file is main.c
//Compilation directory is C:/Code/virtualagc/yaAGC/
//Located in C:/Code/virtualagc/yaAGC/main.c
//Contains 1733 lines.
//Source language is c.
//Compiled with stabs debugging format.
static GdbmiResult
GdbmiHandleInfoSource (int i)
{
printf ("Current source file is \"%s\"\n", CurrentSourceFile);
printf ("Current source directory is \"%s\"\n", SourcePathName);
printf ("Located in %s\n",
NormalizeSourceName (SourcePathName, CurrentSourceFile));
printf ("Source language is assembler.\n");
printf ("Compiled with proprietary debugging format.\n");
return (GdbmiCmdDone);
}
/**
Display the list of source files for which symbols are loaded.
Since the list can be quite long the command allows for a pattern
to be passed to reduce the output list in console mode.
*/
static GdbmiResult
GdbmiHandleInfoSources (int i)
{
int j;
regex_t preg;
int UsePattern = 0;
int Match = 0;
GdbmiResult GdbmiStat = GdbmiCmdUnhandled;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (i);
/* Check if a pattern search is used */
if (strlen (s) > 0)
{
GdbmiAdjustCmdPtr (1);
j = regcomp (&preg, sraw, REG_ICASE | REG_NOSUB | REG_EXTENDED);
if (j)
{
printf ("Illegal regular-expression.\n");
regfree (&preg);
GdbmiStat = GdbmiCmdError;
}
else
UsePattern = 1;
}
if (GdbmiStat != GdbmiCmdError)
{
printf ("Source files for which symbols have been read in:\n\n");
/* Loop through and print out the file names */
for (j = 0; j < NumberFiles; j++)
{
Match = 0;
if (UsePattern)
{
if (0 == regexec (&preg, SourceFiles[j], 0, NULL, 0))
{
Match = 1;
}
}
else
Match = 1;
if (Match)
{
printf ("%s\n",
NormalizeSourceName (SourcePathName, SourceFiles[j]));
}
}
fflush (stdout);
if (UsePattern)
regfree (&preg);
GdbmiStat = GdbmiCmdUnhandled;
}
return GdbmiStat;
}
static GdbmiResult
GdbmiHandleInfoInterrupts (int j)
{
int i;
GdbmiAdjustCmdPtr (j);
if (!DebuggerInterruptMasks[0])
printf ("All interrupts are blocked.\n");
else
printf ("Interrupts are allowed.\n");
printf ("Debugger interrupt mask:");
for (i = 1; i <= NUM_INTERRUPT_TYPES; i++)
printf (" %d", !DebuggerInterruptMasks[i]);
printf ("\nInterrupt-request flags:");
for (i = 1; i <= NUM_INTERRUPT_TYPES; i++)
printf (" %d", State->InterruptRequests[i]);
if (State->InIsr)
printf ("\nIn ISR #%d.\n", State->InterruptRequests[0]);
else
printf ("\nLast ISR: #%d.\n", State->InterruptRequests[0]);
return (GdbmiCmdDone);
}
static GdbmiResult
GdbmiHandleInfoSymbols (int i, int type)
{
int j;
regex_t preg;
int UsePattern = 0;
int Match = 0;
char* LastFileName = (char*) 0;
GdbmiResult GdbmiStat = GdbmiCmdUnhandled;
GdbmiAdjustCmdPtr (i);
/* Check if a pattern search is used */
if (strlen (s) > 0)
{
GdbmiAdjustCmdPtr (1);
j = regcomp (&preg, sraw, REG_ICASE | REG_NOSUB | REG_EXTENDED);
if (j)
{
printf ("Illegal regular-expression.\n");
regfree (&preg);
GdbmiStat = GdbmiCmdError;
}
else
UsePattern = 1;
}
if (GdbmiStat != GdbmiCmdError)
{
if (UsePattern)
{
if (type == SYMBOL_VARIABLE)
printf ("All variables matching regular expression \"%s\":\n",
sraw);
else if (type == SYMBOL_CONSTANT)
printf ("All constants matching regular expression \"%s\":\n",
sraw);
else if (type == SYMBOL_LABEL)
printf ("All functions matching regular expression \"%s\":\n",
sraw);
}
else
{
if (type == SYMBOL_VARIABLE)
printf ("All defined variables:\n");
else if (type == SYMBOL_CONSTANT)
printf ("All defined constants:\n");
else if (type == SYMBOL_LABEL)
printf ("All defined functions:\n");
}
LastFileName = SymbolTable[0].FileName;
// Loop through and print out the entire symbol table
for (j = 0; j < SymbolTableSize; j++)
{
Match = 0;
if (UsePattern)
{
if (0 == regexec (&preg, SymbolTable[j].Name, 0, NULL, 0))
{
Match = 1;
}
}
else
Match = 1;
if (Match)
{
if (SymbolTable[j].Type == type)
{
if (strcmp (LastFileName, SymbolTable[j].FileName))
{
LastFileName = SymbolTable[j].FileName;
printf ("\nFile %s:\n", LastFileName);
}
if (type == SYMBOL_VARIABLE)
printf ("var %s;\n", SymbolTable[j].Name);
else if (type == SYMBOL_CONSTANT)
printf ("const %s;\n", SymbolTable[j].Name);
else if (type == SYMBOL_LABEL)
printf ("func %s();\n", SymbolTable[j].Name);
}
}
fflush (stdout);
}
if (UsePattern)
regfree (&preg);
printf ("\n");
}
return GdbmiStat;
}
static GdbmiResult
GdbmiHandleInfoVariables (int i)
{
return GdbmiHandleInfoSymbols (i, SYMBOL_VARIABLE);
}
static GdbmiResult
GdbmiHandleInfoConstants (int i)
{
return GdbmiHandleInfoSymbols (i, SYMBOL_CONSTANT);
}
static GdbmiResult
GdbmiHandleInfoFunctions (int i)
{
return GdbmiHandleInfoSymbols (i, SYMBOL_LABEL);
}
static GdbmiResult
GdbmiHandleInfoFrame (int i)
{
printf ("Stack level 0, frame at 0x0801:\n");
printf (
" pc = 0x0803 in MAIN (c:\\Code\\virtualagc\\Luminary131\\INTERRUPT_LEAD_INS.s:23); saved pc 0x0800\n");
printf (" source language AGC assembler.\n");
printf (" Testing CodeBlocks only not functional yet.\n");
return (GdbmiCmdDone);
}
GdbmiCommands_t GdbmiConsoleInfoCommands[19] =
{
{ "ALL-REGISTERS", GdbmiHandleInfoAllRegisters },
{ "REGISTERS", GdbmiHandleInfoRegisters },
{ "BREAKPOINTS", GdbmiHandleInfoBreakpoints },
{ "LINE", GdbmiHandleInfoLine },
{ "TARGET", GdbmiHandleInfoTarget },
{ "FILES", GdbmiHandleInfoTarget },
{ "CHANNELS", GdbmiHandleInfoChannels },
{ "IO_REGISTERS", GdbmiHandleInfoIoRegisters },
{ "PROGRAM", GdbmiHandleInfoProgram },
{ "STACK", GdbmiHandleBacktrace },
{ "THREADS", GdbmiHandleInfoThreads },
{ "INTERRUPTS", GdbmiHandleInfoInterrupts },
{ "SOURCES", GdbmiHandleInfoSources },
{ "VARIABLES", GdbmiHandleInfoVariables },
{ "FUNCTIONS", GdbmiHandleInfoFunctions },
{ "CONSTANTS", GdbmiHandleInfoConstants },
{ "SOURCE", GdbmiHandleInfoSource },
{ "FRAME", GdbmiHandleInfoFrame },
{ 0, 0 } };
static GdbmiResult
GdbmiHandleInfo (int i)
{
GdbmiResult GdbmiStat = GdbmiCmdUnhandled;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (i);
/* Parse and Execute Commands */
GdbmiStat = GdbmiParseConsoleCommands (GdbmiConsoleInfoCommands);
/* During the new construct transition allow both fbk's*/
if (GdbmiStat == GdbmiCmdUnhandled)
GdbmiStat = gdbmi_status;
return (GdbmiStat);
}
static GdbmiResult
GdbmiHandleSetPrompt (int i)
{
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (i);
strncpy (agcPrompt, sraw, 15);
#ifdef USE_READLINE
{
extern char nbPrompt[16];
strncpy(nbPrompt,agcPrompt,15);
}
#endif
return (GdbmiCmdDone);
}
int
GdbmiString2Num (char* s, unsigned* Num)
{
int Result = -1;
if (1 == sscanf (s, "0X%x", Num))
Result = 0;
else if (1 == sscanf (s, "0%o", Num))
Result = 0;
else if (1 == sscanf (s, "%d", Num))
Result = 0;
return Result;
}
/** This function parses the expression for setting a value in memory
*/
static GdbmiResult
GdbmiHandleSetVariable (int i)
{
unsigned gdbmi_addr, gdbmi_val;
char *operand1, *operand2;
Symbol_t *Symbol = NULL;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (i);
operand1 = strtok(s,"=");
operand2 = strtok(NULL, "=");
if (operand1 && operand2)
{
/* Set value using address */
if (operand1[0] == '*')
{
gdbmi_addr = DbgLinearAddrFromAddrStr (++operand1);
if ((gdbmi_addr != ~0) && (GdbmiString2Num (operand2, &gdbmi_val) == 0))
DbgSetValueByAddress (gdbmi_addr, (unsigned short) gdbmi_val);
}
else /* Must be a symbol */
{
Symbol = ResolveSymbol (operand1, SYMBOL_VARIABLE);
if (Symbol != NULL && !Symbol->Value.Erasable)
Symbol = NULL;
if (Symbol != NULL)
{
/* Get linear address for display */
gdbmi_addr = DbgLinearAddr (&Symbol->Value);
if (GdbmiString2Num (operand2, &gdbmi_val) == 0)
DbgSetValueByAddress (gdbmi_addr, (unsigned short) gdbmi_val);
}
}
}
return (GdbmiCmdDone);
}
static GdbmiResult
GdbmiHandleSet (int i)
{
GdbmiResult GdbmiStat = GdbmiCmdUnhandled;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (i);
if (!strncmp (s, "PROMPT ", 7))
GdbmiStat = GdbmiHandleSetPrompt (7);
else if (!strncmp (s, "CONFIRM ", 8))
GdbmiStat = GdbmiCmdDone; /* Ignore for now */
else if (!strncmp (s, "WIDTH ", 6))
GdbmiStat = GdbmiCmdDone; /* Ignore for now */
else if (!strncmp (s, "HEIGHT ", 7))
GdbmiStat = GdbmiCmdDone; /* Ignore for now */
else if (!strncmp (s, "BREAKPOINT ", 11))
GdbmiStat = GdbmiCmdDone; /* Ignore for now */
else if (!strncmp (s, "PRINT ", 6))
GdbmiStat = GdbmiCmdDone; /* Ignore for now */
else if (!strncmp (s, "UNWINDONSIGNAL ", 15))
GdbmiStat = GdbmiCmdDone; /* Ignore for now */
else if (!strncmp (s, "DISASSEMBLY-FLAVOR ", 19))
GdbmiStat = GdbmiCmdDone; /* Ignore for now */
else if (!strncmp (s, "DEBUGEVENTS ", 12))
GdbmiStat = GdbmiCmdDone; /* Ignore for now */
else if (!strncmp (s, "VARIABLE ", 9))
GdbmiStat = GdbmiHandleSetVariable (9);
else
GdbmiStat = GdbmiHandleSetVariable (0);
return (GdbmiStat);
}
/**
* This function implements the console command disassemble (a.k.a. disas)
* Without USER arguments it displays a block of disassembled code around the
* current program counter. If the USER provided the start and end addresses
* then the debugger will dump a disassemble from the start address (inclusive)
* to the end address (exclusive).
*/
static GdbmiResult
GdbmiHandleDisassemble (int i)
{
// unsigned gdbmiFromAddr,gdbmiToAddr;
// Address_t agc_addr;
// SymbolLine_t* Line = NULL;
GdbmiResult GdbmiStat = GdbmiCmdUnhandled;
unsigned LinearAddress;
unsigned DumpAddress, EndAddress;
int argc = 0;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (i);
/* Use address values if provided */
if (*sraw == ' ')
{
argc = sscanf (sraw + 1, "0x%x 0x%x", &DumpAddress, &EndAddress);
if (argc == 2)
{
LinearAddress = DumpAddress;
}
if (argc == 1)
{
LinearAddress = DumpAddress;
EndAddress = DumpAddress + 9;
}
}
else
{
LinearAddress = DbgGetCurrentProgramCounter ();
DumpAddress = LinearAddress - 4;
EndAddress = DumpAddress + 9;
}
if (DumpAddress < 2048)
DumpAddress = 2048;
printf ("Dump of assembler code from 0x%04x to 0x%04x:\n", DumpAddress,
EndAddress);
while (DumpAddress < EndAddress)
{
/* This next line is only to check if the new method works */
//if (CurrentAddress == LinearAddress ) Disassemble(State);
printf ("0x%04x", DumpAddress);
printf (" <%s+%d>:\t", DbgGetFrameNameByAddr (DumpAddress),
DbgGetFrameNameOffsetByAddr (DumpAddress));
DasPrintInstructionAtAddr (DumpAddress);
++DumpAddress;
}
GdbmiStat = GdbmiCmdDone;
printf ("End of assembler dump.\n");
return (GdbmiStat);
}
static GdbmiResult
GdbmiHandleDefine (int i)
{
char* gdbmi_custom;
char gdbmi_element[256];
unsigned cmd_idx;
unsigned arg_idx;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (i);
gdbmi_custom = s;
gdbmi_element[0] = (char) 0;
if (strlen (gdbmi_custom) > 0)
{
for (cmd_idx = 0; cmd_idx < GDBMI_MAX_CUSTOM_CMDS; cmd_idx++)
{
if (gdbmiCustomCmds[cmd_idx].Command == NULL)
break;
}
if (cmd_idx < GDBMI_MAX_CUSTOM_CMDS)
{
gdbmiCustomCmds[cmd_idx].Command = strdup (gdbmi_custom);
printf ("Type commands for definition of \"%s\".\n", sraw);
printf ("End with a line saying just \"end\".\n");
arg_idx = 0;
while (1)
{
//printf(">");
//gets((char*)gdbmi_element);
nbfgets_ready (">");
fflush (stdout);
while (nbfgets (gdbmi_element, 256) == 0)
;
if (strcmp (gdbmi_element, "end"))
gdbmiCustomCmds[cmd_idx].Arguments[arg_idx++] = strdup (
gdbmi_element);
else
{
gdbmiCustomCmds[cmd_idx].Arguments[arg_idx] = NULL;
break;
}
}
}
}
return (GdbmiCmdDone);
}
static GdbmiResult
GdbmiHandleList (int i)
{
int LineNumber, LineNumberTo;
char Dummy[MAX_FILE_LENGTH + 1];
char* FileName;
char* LineStr;
Symbol_t *Symbol;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (i);
/* Is this just the list command */
if (!strcmp (s, ""))
ListSource (NULL, -1);
/* Do we want to just backup and list */
else if (!strcmp (s, " -"))
ListBackupSource ();
else if (2 == sscanf (s, " %d,%d", &LineNumber, &LineNumberTo))
{
/* This case where we want to list between two line numbers.
* sscanf seems to handle this case ok, unlike its inability
* to parse name:line. We leave the range checking for the
* ListSourceRange() routine.*/
ListSourceRange (LineNumber, LineNumberTo);
}
else if (1 == sscanf (s, " %d", &LineNumber))
{
/* The case where we want to list a file number in the
* currently opened file */
ListSource (NULL, LineNumber);
}
else if (1 == sscanf (sraw, " %s", Dummy))
{
/* The case where we want to list a file number from a
* given file. We actually need to take the file name
* from the raw string to keep the case. I can't seem
* to figure out how to get sscanf() to recognize the
* colon so I need to do this painfully. */
FileName = strtok (Dummy, ":");
LineStr = strtok (NULL, ":");
if (LineStr)
LineNumber = atoi (LineStr);
/* If there is no ":" then we will assume we want to
* list a symbol (function), otherwise, we assume the
* debug command is of the form FILE:LINENUM. */
if (LineStr != NULL && (FileName != NULL))
{
ListSource (FileName, LineNumber);
}
else
{
/* Try to resolve the symbol and then list the
* source for that symbol*/
if (FileName
&& (Symbol = ResolveSymbol (FileName, SYMBOL_LABEL)) != NULL)
{
printf ("%s:\n", Symbol->FileName);
ListSource (Symbol->FileName, Symbol->LineNumber);
}
else
printf ("Function or Symbol not defined.\n");
}
}
return (GdbmiCmdDone);
}
GdbmiResult
GdbmiHandleDelete (int i)
{
int gdbmi_breakpoint = 0;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (i);
if (strlen (s) == 0)
NumBreakpoints = 0;
else
{
s++;
sraw++;
if (1 == sscanf (s, "%d", &gdbmi_breakpoint))
{
DbgDeleteBreakpoint (gdbmi_breakpoint);
}
}
return (GdbmiCmdDone);
}
static GdbmiResult
GdbmiHandleDisable (int j)
{
int gdbmi_breakpoint = 0;
int i;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (j);
if (strlen (s) > 0) /* There must be an argument */
{
if (1 == sscanf (s, "%d", &gdbmi_breakpoint))
{
for (i = 0; i < NumBreakpoints; i++)
if (Breakpoints[i].Id == gdbmi_breakpoint)
{
Breakpoints[i].Enable = 'n';
break;
}
}
}
return (GdbmiCmdDone);
}
static GdbmiResult
GdbmiHandleEnable (int j)
{
int gdbmi_breakpoint = 0;
int i;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (j);
if (strlen (s) > 0) /* There must be an argument */
{
if (1 == sscanf (s, "%d", &gdbmi_breakpoint))
{
for (i = 0; i < NumBreakpoints; i++)
if (Breakpoints[i].Id == gdbmi_breakpoint)
{
Breakpoints[i].Enable = 'y';
break;
}
}
}
return (GdbmiCmdDone);
}
static GdbmiResult
GdbmiHandleRun (int i)
{
printf ("[New Thread 11]\n");
printf ("[Switching to Thread 11]\n");
return (GdbmiCmdRun);
}
static GdbmiResult
GdbmiHandleDumpMemory (int i)
{
unsigned start_addr, end_addr, gdbmi_addr;
unsigned short value;
char filename[256];
FILE* target;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (i);
if (3 == sscanf (sraw, "%s 0x%x 0x%x", filename, &start_addr, &end_addr))
{
if (end_addr >= start_addr && /*start_addr >= 0 &&*/ end_addr < 0114000)
{
target = fopen (filename, "w");
if (target != NULL)
{
for (gdbmi_addr = start_addr; gdbmi_addr <= end_addr;
gdbmi_addr++)
{
value = DbgGetValueByAddress (gdbmi_addr);
fwrite (&value, 2, 1, target);
}
fclose (target);
}
}
}
return (GdbmiCmdDone);
}
static GdbmiResult
GdbmiHandleRestoreMemory (int i)
{
unsigned start_addr, end_addr, gdbmi_addr;
unsigned short value;
char filename[256];
FILE* source;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (i);
end_addr = 0114000;
if (3 >= sscanf (sraw, "%s 0x%x 0x%x", filename, &start_addr, &end_addr))
{
if (/*start_addr >= 0 &&*/ start_addr < 0114000)
{
gdbmi_addr = start_addr;
source = fopen (filename, "r");
if (source != NULL)
{
while (fread (&value, 2, 1, source) && gdbmi_addr < end_addr)
{
DbgSetValueByAddress (gdbmi_addr++, value);
}
fclose (source);
}
}
}
return (GdbmiCmdDone);
}
static GdbmiResult
GdbmiHandleDump (int i)
{
GdbmiResult GdbmiStat = GdbmiCmdUnhandled;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (i);
if (!strncmp (s, "MEMORY ", 7))
GdbmiStat = GdbmiHandleDumpMemory (7);
return (GdbmiStat);
}
static GdbmiResult
GdbmiHandleShow (int i)
{
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (i);
if (!strncmp (s, " VERSION", 8))
GdbmiHandleShowVersion ();
return (GdbmiCmdDone);
}
static GdbmiResult
GdbmiHandleStart (int i)
{
DbgSetRunState ();
return (GdbmiCmdDone);
}
static GdbmiResult
GdbmiHandleWhatIs (int i)
{
/* All types will be considered unsigned */
printf ("type = <unknown type>\n");
return (GdbmiCmdDone);
}
int
GdbmiIntFromAgc(unsigned short value, GdbmiComplement_t format)
{
int result = value; /* Assume 15 bit 2s Comp positive*/
if (format == 1 )
{ /* 14 bit 1s Comp */
if (value & 0x4000) result = ((value ^ 0x3fff) & 0x3fff) * -1;
else result = value & 0x3fff;
}
return result;
}
double
GdbmiDoubleFromAgc(unsigned value)
{
int precision = GdbmiScalarMap[GdbmiScalar].precision;
GdbmiComplement_t c = 1;
double scalar = GdbmiScalarMap[GdbmiScalar].scalar;
unsigned lower = value & 0x0000ffff;
unsigned upper = (value & 0xffff0000) >> 16;
double result = 0;
if (GdbmiScalarMap[GdbmiScalar].type[0] == 'D' ||
GdbmiScalarMap[GdbmiScalar].type[0] == 'J') c = 2; /* Use Twos Complement */
if (precision == SP){
result = GdbmiIntFromAgc(upper,c) * scalar;
}
else { /* Double Precision */
result = (GdbmiIntFromAgc(upper,c) * 16384 + GdbmiIntFromAgc(lower,c)) * scalar;
}
return result;
}
void GdbmiPrintFmt(GdbmiFmt_t fmt, unsigned value)
{
int i;
switch(fmt)
{
case 'o':
printf("%#o",value);
break;
case 'u':
printf("%u",value); // RSB -- changed %#u to %u.
break;
case 'd':
if (value & 0x00004000) printf("-%d",((value ^ 0x3fff) & 0x3fff));
else printf("+%d",(value & 0x3fff));
break;
case 'f':
printf("%.*f",9,GdbmiDoubleFromAgc(value));
break;
case 'c':
printf("%c",(char)value);
break;
case 't':
for (i = 14 ;i >= 0; i--)
{
if (value & (1 << i)) printf("1");
else printf("0");
/* Format binary in groups of three for easy octal view */
if ((i % 3) == 0) printf(" ");
}
break;
case 'x':
default:
printf("0x%04x",value);
}
}
static GdbmiResult
GdbmiHandlePrint (int i)
{
int AddrFlag = 0;
char* AddrStr;
Symbol_t *Symbol = NULL;
Address_t *agc_addr;
unsigned agc_value;
unsigned gdbmi_addr;
GdbmiFmt_t fmt;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (i);
if (strlen (s) > 1)
{
GdbmiSkipSpace();
GdbmiParseFmt(&fmt);
/* we have an expression */
GdbmiSkipSpace();
AddrStr = sraw;
if (*AddrStr == '&')
{
AddrFlag++;
AddrStr++;
}
/* I like to also see values of constants eventhough the default
agc implementation did not do this */
Symbol = ResolveSymbol (
AddrStr, SYMBOL_VARIABLE | SYMBOL_REGISTER | SYMBOL_CONSTANT);
if (Symbol)
{
agc_addr = &Symbol->Value;
gdbmi_addr = DbgLinearAddr (agc_addr);
if (AddrFlag){
printf ("$1 = ");
GdbmiPrintFmt(fmt,gdbmi_addr);
printf ("\n");
}
else
{
printf ("$1 = ");
agc_value = DbgGetValueByAddress (gdbmi_addr);
if (fmt == 'f') agc_value = (agc_value << 16) | DbgGetValueByAddress (gdbmi_addr + 1);
GdbmiPrintFmt(fmt,agc_value);
printf ("\n");
}
}
else
{
if (*AddrStr == '*')
{
gdbmi_addr = DbgLinearAddrFromAddrStr (++AddrStr);
printf ("$1 = ");
agc_value = DbgGetValueByAddress (gdbmi_addr);
if (fmt == 'f') agc_value = (agc_value << 16) | DbgGetValueByAddress (gdbmi_addr + 1);
GdbmiPrintFmt(fmt,agc_value);
printf ("\n");
}
else
printf ("$1 = %s\n", sraw);
}
}
return (GdbmiCmdDone);
}
static GdbmiResult
GdbmiHandleOutput (int i)
{
int AddrFlag = 0;
char* AddrStr;
Symbol_t *Symbol = NULL;
Address_t *agc_addr;
unsigned gdbmi_addr;
GdbmiFmt_t fmt;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (i);
if (strlen (s) > 1)
{
GdbmiSkipSpace();
GdbmiParseFmt(&fmt);
/* we have an expression */
GdbmiSkipSpace();
AddrStr = sraw;
if (*AddrStr == '&')
{
AddrFlag++;
AddrStr++;
}
/* I like to also see values of constants eventhough the default
agc implementation did not do this */
Symbol = ResolveSymbol (
AddrStr, SYMBOL_VARIABLE | SYMBOL_REGISTER | SYMBOL_CONSTANT);
if (Symbol)
{
agc_addr = &Symbol->Value;
gdbmi_addr = DbgLinearAddr (agc_addr);
if (AddrFlag)
GdbmiPrintFmt(fmt,gdbmi_addr);
else
GdbmiPrintFmt(fmt,DbgGetValueByAddress (gdbmi_addr));
}
else
{
if (*AddrStr == '*')
{
gdbmi_addr = DbgLinearAddrFromAddrStr (++AddrStr);
GdbmiPrintFmt(fmt,DbgGetValueByAddress (gdbmi_addr));
}
else
printf ("%s", sraw);
}
}
return (GdbmiCmdDone);
}
static GdbmiExamCfg_t GdbmiExamCfg = {1,'u','h',0,4};
static GdbmiResult
GdbmiHandleExamine (int j)
{
int i = 0;
unsigned gdbmi_addr = 0;
int gdbmi_value = 0;
char* gdbmi_ptr = NULL;
GdbmiResult GdbmiStat = GdbmiCmdUnhandled;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (j);
/* Do we see arguments */
if (s)
{
/* Is there a format Specifier */
if (*s++ == '/')
{
/* Looks like some specifies a format string... lets parse it */
GdbmiExamCfg.count = (int) strtol (s, &gdbmi_ptr, 0);
if (GdbmiExamCfg.count == 0 ) GdbmiExamCfg.count = 1;
s = gdbmi_ptr;
/* Look for size and format specifiers */
while (*s != 0 && *s != ' ')
{
switch(*s++){
case 'B':
GdbmiExamCfg.unit = 'b';
GdbmiExamCfg.apl = 4;
break;
case 'H':
GdbmiExamCfg.unit = 'h';
GdbmiExamCfg.apl = 8;
break;
case 'W':
GdbmiExamCfg.unit = 'w';
GdbmiExamCfg.apl = 4;
break;
case 'X':
GdbmiExamCfg.fmt = 'x';
break;
case 'O':
GdbmiExamCfg.fmt = 'o';
break;
case 'D':
GdbmiExamCfg.fmt = 'd';
break;
default:
/* Unsupported Character */
GdbmiStat = GdbmiCmdError;
break;
} /* End Switch */
} /* End While */
if (*s == ' ') ++s;
} /* End Format Parsing */
/* Get linear address */
if (strlen(s) > 0)
{
GdbmiExamCfg.addr = DbgLinearAddrFromAddrStr (s);
}
/* Use new or last Set Base Address */
gdbmi_addr = GdbmiExamCfg.addr;
if ((GdbmiExamCfg.count > 0) && (gdbmi_addr != ~0) && GdbmiStat != GdbmiCmdError)
{
/* Print first lead in address */
printf ("0x%07x:", gdbmi_addr);
for (i = 1; i <= GdbmiExamCfg.count; i++)
{
//agc_addr = gdbmiNativeAddr(gdbmi_addr);
gdbmi_value = DbgGetValueByAddress (gdbmi_addr++);
if (GdbmiExamCfg.unit == 'w')
{
/* Word Size so fetch next address too */
gdbmi_value = (gdbmi_value << 16) | DbgGetValueByAddress (gdbmi_addr++);
}
switch (GdbmiExamCfg.unit)
{
case 'h':
printf ("\t0x%04x", (unsigned short) gdbmi_value);
break;
case 'b':
printf ("\t0x%02x\t0x%02x",
(unsigned char) ((gdbmi_value >> 8) & 0xff),
(unsigned char) (gdbmi_value & 0xff));
break;
default:
printf ("\t0x%08x", (unsigned) gdbmi_value);
break;
}
/* Do we need an address lead inprinted */
if ((i % GdbmiExamCfg.apl) == 0 && i < GdbmiExamCfg.count)
printf ("\n0x%07x:", gdbmi_addr);
}
printf ("\n");
GdbmiStat = GdbmiCmdDone;
}
else {
GdbmiStat = GdbmiCmdError;
}
}
if (GdbmiStat == GdbmiCmdError)
printf ("Invalid address or FMT\n");
return (GdbmiStat);
}
static GdbmiResult
GdbmiHandleGetOct (int i)
{
CheckDec (s);
return (GdbmiCmdDone);
}
static GdbmiResult
GdbmiHandleQuit (int i)
{
return (GdbmiCmdQuit);
}
/**
* GDB/MI Root Table of Commands and associated handlers.
*/
GdbmiCommands_t GdbmiConsoleRootCommands[33] =
{
{ "INFO ", GdbmiHandleInfo },
{ "SET ", GdbmiHandleSet },
{ "START", GdbmiHandleStart },
{ "SHOW", GdbmiHandleShow },
{ "BREAK", GdbmiHandleNormBrk },
{ "TBREAK", GdbmiHandleTmpBrk },
{ "PRINT", GdbmiHandlePrint },
{ "WHERE", GdbmiHandleBacktrace },
{ "BT", GdbmiHandleBacktrace },
{ "WATCH", GdbmiHandleWatch },
{ "DISASSEMBLE", GdbmiHandleDisassemble },
{ "DISAS", GdbmiHandleDisassemble },
{ "DEFINE", GdbmiHandleDefine },
{ "LIST", GdbmiHandleList },
{ "GETOCT", GdbmiHandleGetOct },
{ "WHATIS", GdbmiHandleWhatIs },
{ "OUTPUT", GdbmiHandleOutput },
{ "DUMP", GdbmiHandleDump },
{ "RESTORE", GdbmiHandleRestoreMemory },
{ "DELETE BREAKPOINTS", GdbmiHandleDelete },
{ "DELETE", GdbmiHandleDelete },
{ "DISABLE", GdbmiHandleDisable },
{ "ENABLE", GdbmiHandleEnable },
{ "QUIT", GdbmiHandleQuit },
{ "EXIT", GdbmiHandleQuit },
{ "CONT", GdbmiHandleRun },
{ "RUN", GdbmiHandleRun },
{ "P", GdbmiHandlePrint },
{ "B", GdbmiHandleNormBrk },
{ "D", GdbmiHandleDelete },
{ "X", GdbmiHandleExamine },
{ 0, 0 } };
static GdbmiResult
GdbmiConsoleInterpreter (int i)
{
GdbmiResult GdbmiStat = GdbmiCmdUnhandled;
/* Adjust the CmdPtr to point to the next token */
GdbmiAdjustCmdPtr (i);
/* Ensure command s is in uppercase */
GdbmiStringToUpper (s);
/* Parse and Execute Commands */
GdbmiStat = GdbmiParseConsoleCommands (GdbmiConsoleRootCommands);
/* Special Case KDbg defined command hard coded for now */
if (!strncmp (s, "KDBG_INFOLINEMAIN", 17))
{
GdbmiHandleList (17);
GdbmiStat = GdbmiHandleInfoLine (17);
}
else
gdbmi_status = GdbmiCmdError;
if (GdbmiStat == GdbmiCmdUnhandled)
GdbmiStat = gdbmi_status;
return (GdbmiStat);
}
static GdbmiResult
GdbmiHandleCustom (int i)
{
char *arg_s, *arg_sraw;
unsigned cmd_idx;
unsigned arg_idx;
for (cmd_idx = 0; cmd_idx < GDBMI_MAX_CUSTOM_CMDS; cmd_idx++)
{
if (gdbmiCustomCmds[cmd_idx].Command)
{
if (strncmp (gdbmiCustomCmds[cmd_idx].Command, sraw,
strlen (gdbmiCustomCmds[cmd_idx].Command)))
{
++gdbmi_status;
for (arg_idx = 0; arg_idx < GDBMI_MAX_CUSTOM_ARGS; arg_idx++)
{
arg_sraw = gdbmiCustomCmds[cmd_idx].Arguments[arg_idx];
if (arg_sraw)
arg_s = strdup (arg_sraw);
else
break;
if (arg_s)
{
GdbmiInterpreter (State, arg_s, arg_sraw);
free (arg_s);
}
}
break;
}
}
}
return (GdbmiCmdDone);
}
/**
* This function is the entry point for the high level GDBMI interaction
* For now it is just a stub until the code will work with full GDB/MI
*/
GdbmiResult
GdbmiHandleMachineInterface (int i)
{
return (GdbmiCmdUnhandled);
}
/**
* This function is the main entry into the GDBMI command handler. It requires
* the state of the AGC machine as well as the Command string and the raw
* version of the command string.
* \param a pointer to the AGC state machine
* \param the command string
* \param the raw command string
*/
GdbmiResult
GdbmiInterpreter (agc_t *agc_state, char* dbg_s, char* dbg_sraw)
{
GdbmiResult GdbmiStat = GdbmiCmdUnhandled;
/* Set the static GDBMI values and avoid passing around */
State = agc_state;
s = dbg_s;
sraw = dbg_sraw;
/* Handle Basic GDB Command Line Options */
GdbmiStat = GdbmiConsoleInterpreter (0);
gdbmi_status = 0;
/* Use the new GDB/MI Capabilities */
if (GdbmiStat == GdbmiCmdUnhandled)
GdbmiStat = GdbmiHandleMachineInterface (0);
/* Executed Custom defined Debug Commands */
if (GdbmiStat == GdbmiCmdUnhandled)
GdbmiStat = GdbmiHandleCustom (0);
if (GdbmiStat == GdbmiCmdUnhandled && gdbmi_status > 0)
GdbmiStat = GdbmiCmdDone;
return (GdbmiStat);
}
Computing file changes ...