Initial creation of sourceware repository

This commit is contained in:
Stan Shebs 1999-04-16 01:35:26 +00:00
parent cd946cff9e
commit c906108c21
2470 changed files with 976797 additions and 0 deletions

9
gdb/29k-share/README Normal file
View File

@ -0,0 +1,9 @@
The files in this directory are shared with other debuggers and
debug interfaces that use Advanced Micro Devices' UDI (universal debug
interface) protocol. The protocol provides a common interface among
debuggers, logic analyzers, emulators, and embedded systems that use
AMD 29000 family processors.
Do not change these files without coordinating with Advanced Micro
Devices, Embedded Processor Division, 5204 E. Ben White Blvd, Austin, TX 78741.
Maybe postmaster@cayman.amd.com can direct you to the current maintainers.

View File

@ -0,0 +1,607 @@
/*
Interface from UDI calls in 32-bit mode to go32 in 16-bit mode.
Communication is done through a single interrupt vector, which passes
data through two linear buffers.
Call:
AH = 0xfe
AL = UDI function number
ECX = IN length
ESI = pointer to IN buffer
EDI = pointer to OUT buffer
Return:
EAX = return value of UDI function
Vector:
0x21
*/
#ifdef __GO32__
#include <stdlib.h>
#include "udiproc.h"
#include "udisoc.h"
char dfe_errmsg[500];
static char in_buffer[4096];
static char out_buffer[4096];
static char *in_ptr;
static char *out_ptr;
#define IN_INIT() in_ptr = in_buffer
#define IN_VAL(t,v) *((t *)in_ptr)++ = v
#define IN_DATA(ptr, cnt) memcpy(in_ptr, ptr, cnt), in_ptr += cnt
#define OUT_INIT() out_ptr = out_buffer
#define OUT_VAL(t) (*((t *)out_ptr)++)
#define OUT_DATA(ptr, cnt) memcpy(ptr, out_ptr, cnt), out_ptr += cnt
static int DO_CALL(int function)
{
asm("pushl %esi");
asm("pushl %edi");
asm("movb %0, %%al" : : "g" (function));
asm("movl _in_ptr, %ecx");
asm("movl $_in_buffer, %esi");
asm("subl %esi, %ecx");
asm("movl $_out_buffer, %edi");
asm("movb $0xfe, %ah");
asm("int $0x21");
asm("popl %edi");
asm("popl %esi");
}
/*----------------------------------------------------------------------*/
#ifdef TEST_UDI
int main()
{
int r;
long p2;
short p1;
IN_INIT();
IN_VAL(long, 11111111);
IN_VAL(short, 2222);
IN_DATA("Hello, world\n", 17);
r = DO_CALL(42);
OUT_INIT();
p1 = OUT_VAL(short);
p2 = OUT_VAL(long);
printf("main: p1=%d p2=%d rv=%d\n", p1, p2, r);
return r;
}
#endif
/*----------------------------------------------------------------------*/
unsupported(char *s)
{
printf("unsupported UDI host call %s\n", s);
abort();
}
UDIError UDIConnect (
char *Configuration, /* In */
UDISessionId *Session /* Out */
)
{
int r;
out_buffer[0] = 0; /* DJ - test */
IN_INIT();
IN_DATA(Configuration, strlen(Configuration)+1);
r = DO_CALL(UDIConnect_c);
OUT_INIT();
*Session = OUT_VAL(UDISessionId);
return r;
}
UDIError UDIDisconnect (
UDISessionId Session, /* In */
UDIBool Terminate /* In */
)
{
int r;
IN_INIT();
IN_VAL(UDISessionId, Session);
IN_VAL(UDIBool, Terminate);
return DO_CALL(UDIDisconnect_c);
}
UDIError UDISetCurrentConnection (
UDISessionId Session /* In */
)
{
IN_INIT();
IN_VAL(UDISessionId, Session);
return DO_CALL(UDISetCurrentConnection_c);
}
UDIError UDICapabilities (
UDIUInt32 *TIPId, /* Out */
UDIUInt32 *TargetId, /* Out */
UDIUInt32 DFEId, /* In */
UDIUInt32 DFE, /* In */
UDIUInt32 *TIP, /* Out */
UDIUInt32 *DFEIPCId, /* Out */
UDIUInt32 *TIPIPCId, /* Out */
char *TIPString /* Out */
)
{
int r;
IN_INIT();
IN_VAL(UDIUInt32, DFEId);
IN_VAL(UDIUInt32, DFE);
r = DO_CALL(UDICapabilities_c);
OUT_INIT();
*TIPId = OUT_VAL(UDIUInt32);
*TargetId = OUT_VAL(UDIUInt32);
*TIP = OUT_VAL(UDIUInt32);
*DFEIPCId = OUT_VAL(UDIUInt32);
*TIPIPCId = OUT_VAL(UDIUInt32);
strcpy(TIPString, out_ptr);
return r;
}
UDIError UDIEnumerateTIPs (
UDIInt (*UDIETCallback) /* In */
( char *Configuration ) /* In to callback() */
)
{
UDIETCallback("montip.exe");
}
UDIError UDIGetErrorMsg (
UDIError ErrorCode, /* In */
UDISizeT MsgSize, /* In */
char *Msg, /* Out */
UDISizeT *CountDone /* Out */
)
{
int r;
if (MsgSize > 4000)
MsgSize = 4000;
IN_INIT();
IN_VAL(UDIError, ErrorCode);
IN_VAL(UDISizeT, MsgSize);
r = DO_CALL(UDIGetErrorMsg_c);
OUT_INIT();
*CountDone = OUT_VAL(UDISizeT);
OUT_DATA(Msg, *CountDone);
return r;
}
UDIError UDIGetTargetConfig (
UDIMemoryRange KnownMemory[], /* Out */
UDIInt *NumberOfRanges, /* In/Out */
UDIUInt32 ChipVersions[], /* Out */
UDIInt *NumberOfChips /* In/Out */
)
{
int r, i;
int nr = *NumberOfRanges;
int nc = *NumberOfChips;
IN_INIT();
IN_VAL(UDIInt, *NumberOfRanges);
IN_VAL(UDIInt, *NumberOfChips);
r = DO_CALL(UDIGetTargetConfig_c);
if (r == UDIErrorIncomplete)
return r;
OUT_INIT();
*NumberOfRanges = OUT_VAL(UDIInt);
*NumberOfChips = OUT_VAL(UDIInt);
for (i=0; i<nr; i++)
{
KnownMemory[i].Space = OUT_VAL(short);
KnownMemory[i].Offset = OUT_VAL(CPUOffset);
KnownMemory[i].Size = OUT_VAL(CPUSizeT);
}
for (i=0; i<nc; i++)
{
ChipVersions[i] = OUT_VAL(UDIUInt32);
}
return r;
}
UDIError UDICreateProcess (
UDIPId *PId /* Out */
)
{
int r = DO_CALL(UDICreateProcess_c);
OUT_INIT();
*PId = OUT_VAL(UDIPId);
return r;
}
UDIError UDISetCurrentProcess (
UDIPId PId /* In */
)
{
IN_INIT();
IN_VAL(UDIPId, PId);
return DO_CALL(UDISetCurrentProcess_c);
}
UDIError UDIDestroyProcess (
UDIPId PId /* In */
)
{
IN_INIT();
IN_VAL(UDIPId, PId);
return DO_CALL(UDIDestroyProcess_c);
}
UDIError UDIInitializeProcess (
UDIMemoryRange ProcessMemory[], /* In */
UDIInt NumberOfRanges, /* In */
UDIResource EntryPoint, /* In */
CPUSizeT StackSizes[], /* In */
UDIInt NumberOfStacks, /* In */
char *ArgString /* In */
)
{
int i, r;
IN_INIT();
IN_VAL(UDIInt, NumberOfRanges);
for (i=0; i<NumberOfRanges; i++)
{
IN_VAL(short, ProcessMemory[i].Space);
IN_VAL(CPUOffset, ProcessMemory[i].Offset);
IN_VAL(CPUSizeT, ProcessMemory[i].Size);
}
IN_VAL(short, EntryPoint.Space);
IN_VAL(CPUOffset, EntryPoint.Offset);
IN_VAL(UDIInt, NumberOfStacks);
for (i=0; i<NumberOfStacks; i++)
IN_VAL(CPUSizeT, StackSizes[i]);
IN_DATA(ArgString, strlen(ArgString)+1);
return DO_CALL(UDIInitializeProcess_c);
}
UDIError UDIRead (
UDIResource From, /* In */
UDIHostMemPtr To, /* Out */
UDICount Count, /* In */
UDISizeT Size, /* In */
UDICount *CountDone, /* Out */
UDIBool HostEndian /* In */
)
{
int cleft = Count, cthis, dthis;
int cdone = 0, r, bsize=2048/Size;
while (cleft)
{
cthis = (cleft<bsize) ? cleft : bsize;
IN_INIT();
IN_VAL(short, From.Space);
IN_VAL(CPUOffset, From.Offset);
IN_VAL(UDICount, cthis);
IN_VAL(UDISizeT, Size);
IN_VAL(UDIBool, HostEndian);
r = DO_CALL(UDIRead_c);
OUT_INIT();
dthis = OUT_VAL(UDICount);
OUT_DATA(To, dthis*Size);
cdone += dthis;
To += dthis*Size;
if (r != UDINoError)
{
*CountDone = cdone;
return r;
}
cleft -= cthis;
}
*CountDone = cdone;
return UDINoError;
}
UDIError UDIWrite (
UDIHostMemPtr From, /* In */
UDIResource To, /* In */
UDICount Count, /* In */
UDISizeT Size, /* In */
UDICount *CountDone, /* Out */
UDIBool HostEndian /* In */
)
{
int cleft = Count, cthis, dthis;
int cdone = 0, r, bsize=2048/Size;
while (cleft)
{
cthis = (cleft<bsize) ? cleft : bsize;
IN_INIT();
IN_VAL(short, To.Space);
IN_VAL(CPUOffset, To.Offset);
IN_VAL(UDICount, cthis);
IN_VAL(UDISizeT, Size);
IN_VAL(UDIBool, HostEndian);
IN_DATA(From, cthis*Size);
From += cthis*Size;
r = DO_CALL(UDIWrite_c);
OUT_INIT();
cdone += OUT_VAL(UDICount);
if (r != UDINoError)
{
*CountDone = cdone;
return r;
}
cleft -= cthis;
}
*CountDone = cdone;
return UDINoError;
}
UDIError UDICopy (
UDIResource From, /* In */
UDIResource To, /* In */
UDICount Count, /* In */
UDISizeT Size, /* In */
UDICount *CountDone, /* Out */
UDIBool Direction /* In */
)
{
int r;
IN_INIT();
IN_VAL(short, From.Space);
IN_VAL(CPUOffset, From.Offset);
IN_VAL(short, To.Space);
IN_VAL(CPUOffset, To.Offset);
IN_VAL(UDICount, Count);
IN_VAL(UDISizeT, Size);
IN_VAL(UDIBool, Direction);
r = DO_CALL(UDICopy_c);
OUT_INIT();
*CountDone = OUT_VAL(UDICount);
return r;
}
UDIError UDIExecute (
void
)
{
return DO_CALL(UDIExecute_c);
}
UDIError UDIStep (
UDIUInt32 Steps, /* In */
UDIStepType StepType, /* In */
UDIRange Range /* In */
)
{
IN_INIT();
IN_VAL(UDIUInt32, Steps);
IN_VAL(UDIStepType, StepType);
IN_VAL(UDIRange, Range);
return DO_CALL(UDIStep_c);
}
UDIVoid UDIStop (
void
)
{
DO_CALL(UDIStop_c);
}
UDIError UDIWait (
UDIInt32 MaxTime, /* In */
UDIPId *PId, /* Out */
UDIUInt32 *StopReason /* Out */
)
{
int r;
IN_INIT();
IN_VAL(UDIInt32, MaxTime);
r = DO_CALL(UDIWait_c);
OUT_INIT();
*PId = OUT_VAL(UDIPId);
*StopReason = OUT_VAL(UDIUInt32);
return r;
}
UDIError UDISetBreakpoint (
UDIResource Addr, /* In */
UDIInt32 PassCount, /* In */
UDIBreakType Type, /* In */
UDIBreakId *BreakId /* Out */
)
{
int r;
IN_INIT();
IN_VAL(short, Addr.Space);
IN_VAL(CPUOffset, Addr.Offset);
IN_VAL(UDIInt32, PassCount);
IN_VAL(UDIBreakType, Type);
r = DO_CALL(UDISetBreakpoint_c);
OUT_INIT();
*BreakId = OUT_VAL(UDIBreakId);
return r;
}
UDIError UDIQueryBreakpoint (
UDIBreakId BreakId, /* In */
UDIResource *Addr, /* Out */
UDIInt32 *PassCount, /* Out */
UDIBreakType *Type, /* Out */
UDIInt32 *CurrentCount /* Out */
)
{
int r;
IN_INIT();
IN_VAL(UDIBreakId, BreakId);
r = DO_CALL(UDIQueryBreakpoint_c);
OUT_INIT();
Addr->Space = OUT_VAL(short);
Addr->Offset = OUT_VAL(CPUOffset);
*PassCount = OUT_VAL(UDIInt32);
*Type = OUT_VAL(UDIBreakType);
*CurrentCount = OUT_VAL(UDIInt32);
return r;
}
UDIError UDIClearBreakpoint (
UDIBreakId BreakId /* In */
)
{
IN_INIT();
IN_VAL(UDIBreakId, BreakId);
return DO_CALL(UDIClearBreakpoint_c);
}
UDIError UDIGetStdout (
UDIHostMemPtr Buf, /* Out */
UDISizeT BufSize, /* In */
UDISizeT *CountDone /* Out */
)
{
int r;
IN_INIT();
if (BufSize > 4000)
BufSize = 4000;
IN_VAL(UDISizeT,BufSize);
r = DO_CALL(UDIGetStdout_c);
OUT_INIT();
*CountDone = OUT_VAL(UDISizeT);
if (*CountDone <= BufSize)
OUT_DATA(Buf, *CountDone);
return r;
}
UDIError UDIGetStderr (
UDIHostMemPtr Buf, /* Out */
UDISizeT BufSize, /* In */
UDISizeT *CountDone /* Out */
)
{
int r;
IN_INIT();
if (BufSize > 4000)
BufSize = 4000;
IN_VAL(UDISizeT,BufSize);
r = DO_CALL(UDIGetStderr_c);
OUT_INIT();
*CountDone = OUT_VAL(UDISizeT);
OUT_DATA(Buf, *CountDone);
return r;
}
UDIError UDIPutStdin (
UDIHostMemPtr Buf, /* In */
UDISizeT Count, /* In */
UDISizeT *CountDone /* Out */
)
{
int r;
IN_INIT();
if (Count > 4000)
Count = 4000;
IN_VAL(UDISizeT,Count);
IN_DATA(Buf, Count);
r = DO_CALL(UDIPutStdin_c);
OUT_INIT();
*CountDone = OUT_VAL(UDISizeT);
return r;
}
UDIError UDIStdinMode (
UDIMode *Mode /* Out */
)
{
int r;
IN_INIT();
r = DO_CALL(UDIStdinMode_c);
OUT_INIT();
*Mode = OUT_VAL(UDIMode);
return r;
}
UDIError UDIPutTrans (
UDIHostMemPtr Buf, /* In */
UDISizeT Count, /* In */
UDISizeT *CountDone /* Out */
)
{
int r;
IN_INIT();
if (Count > 4000)
Count = 4000;
IN_VAL(UDISizeT,Count);
IN_DATA(Buf, Count);
r = DO_CALL(UDIPutTrans_c);
OUT_INIT();
*CountDone = OUT_VAL(UDISizeT);
return r;
}
UDIError UDIGetTrans (
UDIHostMemPtr Buf, /* Out */
UDISizeT BufSize, /* In */
UDISizeT *CountDone /* Out */
)
{
int r;
IN_INIT();
if (BufSize > 4000)
BufSize = 4000;
IN_VAL(UDISizeT,BufSize);
r = DO_CALL(UDIGetTrans_c);
OUT_INIT();
*CountDone = OUT_VAL(UDISizeT);
OUT_DATA(Buf, *CountDone);
return r;
}
UDIError UDITransMode (
UDIMode *Mode /* Out */
)
{
int r;
IN_INIT();
r = DO_CALL(UDITransMode_c);
OUT_INIT();
*Mode = OUT_VAL(UDIMode);
return r;
}
#define DFEIPCIdCompany 0x0001 /* Company ID AMD */
#define DFEIPCIdProduct 0x1 /* Product ID 0 */
#define DFEIPCIdVersion 0x125 /* 1.2.5 */
unsigned UDIGetDFEIPCId ()
{
return((((UDIUInt32)DFEIPCIdCompany) << 16) |(DFEIPCIdProduct << 12) | DFEIPCIdVersion);
}
#endif /* __GO32__ */

View File

@ -0,0 +1,48 @@
/* This file contains the DFE and TIP IDs to be used by AMD products for
the UDICapabilities call.
Copyright 1993 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Company Codes -- AMD assigns these */
#define UDICompanyCode_AMD 1
/* Build a UDIID given a CompanyProdCode and 3 version pieces */
#define UDIID(CompanyProdCode, v1,v2,v3) ((((CompanyProdCode) & 0xfffff)<<12)+\
(((v1)&0xf)<<8) + (((v2)&0xf)<<4) + ((v3)&0xf))
/* Extract a CompanyProdCode or a Version from a UDIID */
#define UDIID_CompanyProdCode(id) (((id)>>12) & 0xfffff)
#define UDIID_Version(id) ((id)&0xfff)
#define UDIAMDProduct(ProdCode) ((UDICompanyCode_AMD<<4) + (ProdCode&0xf))
/* AMD DFE Product Codes */
#define UDIProductCode_Mondfe UDIAMDProduct(0)
#define UDIProductCode_XRAY UDIAMDProduct(1)
#define UDIProductCode_TIPTester UDIAMDProduct(2)
/* AMD TIP Product Codes (need not be distinct from DFE Product Codes) */
#define UDIProductCode_Montip UDIAMDProduct(0)
#define UDIProductCode_Isstip UDIAMDProduct(1)
#define UDILatestVersion 0x120 /* UDI 1.2.0, can be used in DFE and TIP desired UDI params */

1250
gdb/29k-share/udi/udip2soc.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,44 @@
/* This file just picks the correct udiphxxx.h depending on the host.
The two hosts that are now defined are UNIX and MSDOS.
Copyright 1993 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/*
* For the moment, we will default to BSD_IPC; this might change if/when
* another type of IPC (Mach? SysV?) is implemented.
*/
#if 0
/* We don't seem to have a copy of udiphdos.h. Furthermore, all the
things in udiphunix.h are pretty much generic 32-bit machine defines
which don't have anything to do with IPC. */
#ifdef DOS_IPC
#include "udiphdos.h"
#else
/*#ifdef BSD_IPC */
#include "udiphunix.h"
#endif
#else
#include "udiphunix.h"
#endif

View File

@ -0,0 +1,81 @@
/* Originally called "udiphsun.h", however it was not very
Sun-specific; now it is used for generic-unix-with-bsd-ipc.
Copyright 1993 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* This file is to be used to reconfigure the UDI Procedural interface
for a given host. This file should be placed so that it will be
included from udiproc.h. Everything in here may need to be changed
when you change either the host CPU or its compiler. Nothing in
here should change to support different targets. There are multiple
versions of this file, one for each of the different host/compiler
combinations in use.
*/
#define UDIStruct struct /* _packed not needed on unix */
/* First, we need some types */
/* Types with at least the specified number of bits */
typedef double UDIReal64; /* 64-bit real value */
typedef float UDIReal32; /* 32-bit real value */
typedef unsigned long UDIUInt32; /* unsigned integers */
typedef unsigned short UDIUInt16;
typedef unsigned char UDIUInt8;
typedef long UDIInt32; /* 32-bit integer */
typedef short UDIInt16; /* 16-bit integer */
typedef char UDIInt8; /* unreliable signedness */
/* To aid in supporting environments where the DFE and TIP use
different compilers or hosts (like DOS 386 on one side, 286 on the
other, or different Unix machines connected by sockets), we define
two abstract types - UDIInt and UDISizeT.
UDIInt should be defined to be int except for host/compiler combinations
that are intended to talk to existing UDI components that have a different
sized int. Similarly for UDISizeT.
*/
typedef int UDIInt;
typedef unsigned int UDIUInt;
typedef unsigned int UDISizeT;
/* Now two void types. The first is for function return types,
the other for pointers to no particular type. Since these types
are used solely for documentational clarity, if your host/compiler
doesn't support either one, replace them with int and char *
respectively.
*/
typedef void UDIVoid; /* void type */
typedef void * UDIVoidPtr; /* void pointer type */
typedef void * UDIHostMemPtr; /* Arbitrary memory pointer */
/* Now we want a type optimized for boolean values. Normally this
would be int, but on some machines (Z80s, 8051s, etc) it might
be better to map it onto a char
*/
typedef int UDIBool;
/* Now indicate whether your compiler support full ANSI style
prototypes. If so, use #if 1. If not use #if 0.
*/
#if 0
#define UDIParams(x) x
#else
#define UDIParams(x) ()
#endif

308
gdb/29k-share/udi/udiproc.h Normal file
View File

@ -0,0 +1,308 @@
/* local type decs. and macro defs.
Copyright 1993 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "udiphcfg.h" /* Get host specific configuration */
#include "udiptcfg.h" /* Get target specific configuration */
/* Here are all of the CPU Families for which UDI is currently defined */
#define Am29K 1 /* AMD's Am290xx and Am292xx parts */
typedef UDIInt UDIError;
typedef UDIInt UDISessionId;
typedef UDIInt UDIPId;
typedef UDIInt UDIStepType;
typedef UDIInt UDIBreakType;
typedef UDIUInt UDIBreakId;
typedef UDIUInt UDIMode;
typedef UDIStruct
{
CPUSpace Space;
CPUOffset Offset;
} UDIResource;
typedef UDIStruct
{
CPUOffset Low;
CPUOffset High;
} UDIRange;
typedef UDIStruct
{
CPUSpace Space;
CPUOffset Offset;
CPUSizeT Size;
} UDIMemoryRange;
/* Values for UDIStepType parameters */
#define UDIStepNatural 0x0000
#define UDIStepOverTraps 0x0001
#define UDIStepOverCalls 0x0002
#define UDIStepInRange 0x0004
#define UDIStepNatural 0x0000
/* Values for UDIBreakType parameters */
#define UDIBreakFlagExecute 0x0001
#define UDIBreakFlagRead 0x0002
#define UDIBreakFlagWrite 0x0004
#define UDIBreakFlagFetch 0x0008
/* Special values for UDIWait MaxTime parameter */
#define UDIWaitForever (UDIInt32) -1 /* Infinite time delay */
/* Special values for PId */
#define UDIProcessProcessor -1 /* Raw Hardware, if possible */
/* Values for UDIWait StopReason */
#define UDIGrossState 0xff
#define UDITrapped 0 /* Fine state - which trap */
#define UDINotExecuting 1
#define UDIRunning 2
#define UDIStopped 3
#define UDIWarned 4
#define UDIStepped 5
#define UDIWaiting 6
#define UDIHalted 7
#define UDIStdoutReady 8 /* fine state - size */
#define UDIStderrReady 9 /* fine state - size */
#define UDIStdinNeeded 10 /* fine state - size */
#define UDIStdinModeX 11 /* fine state - mode */
#define UDIBreak 12 /* Fine state - Breakpoint Id */
#define UDIExited 13 /* Fine state - exit code */
/* Enumerate the return values from the callback function
for UDIEnumerateTIPs.
*/
#define UDITerminateEnumeration 0
#define UDIContinueEnumeration 1
/* Enumerate values for Terminate parameter to UDIDisconnect */
#define UDITerminateSession 1
#define UDIContinueSession 0
/* Error codes */
#define UDINoError 0 /* No error occured */
#define UDIErrorNoSuchConfiguration 1
#define UDIErrorCantHappen 2
#define UDIErrorCantConnect 3
#define UDIErrorNoSuchConnection 4
#define UDIErrorNoConnection 5
#define UDIErrorCantOpenConfigFile 6
#define UDIErrorCantStartTIP 7
#define UDIErrorConnectionUnavailable 8
#define UDIErrorTryAnotherTIP 9
#define UDIErrorExecutableNotTIP 10
#define UDIErrorInvalidTIPOption 11
#define UDIErrorCantDisconnect 12
#define UDIErrorUnknownError 13
#define UDIErrorCantCreateProcess 14
#define UDIErrorNoSuchProcess 15
#define UDIErrorUnknownResourceSpace 16
#define UDIErrorInvalidResource 17
#define UDIErrorUnsupportedStepType 18
#define UDIErrorCantSetBreakpoint 19
#define UDIErrorTooManyBreakpoints 20
#define UDIErrorInvalidBreakId 21
#define UDIErrorNoMoreBreakIds 22
#define UDIErrorUnsupportedService 23
#define UDIErrorTryAgain 24
#define UDIErrorIPCLimitation 25
#define UDIErrorIncomplete 26
#define UDIErrorAborted 27
#define UDIErrorTransDone 28
#define UDIErrorCantAccept 29
#define UDIErrorTransInputNeeded 30
#define UDIErrorTransModeX 31
#define UDIErrorInvalidSize 32
#define UDIErrorBadConfigFileEntry 33
#define UDIErrorIPCInternal 34
/* TBD */
/****************************************************************** PROCEDURES
*/
UDIError UDIConnect UDIParams((
char *Configuration, /* In */
UDISessionId *Session /* Out */
));
UDIError UDIDisconnect UDIParams((
UDISessionId Session, /* In */
UDIBool Terminate /* In */
));
UDIError UDISetCurrentConnection UDIParams((
UDISessionId Session /* In */
));
UDIError UDICapabilities UDIParams((
UDIUInt32 *TIPId, /* Out */
UDIUInt32 *TargetId, /* Out */
UDIUInt32 DFEId, /* In */
UDIUInt32 DFE, /* In */
UDIUInt32 *TIP, /* Out */
UDIUInt32 *DFEIPCId, /* Out */
UDIUInt32 *TIPIPCId, /* Out */
char *TIPString /* Out */
));
UDIError UDIEnumerateTIPs UDIParams((
UDIInt (*UDIETCallback) /* In */
UDIParams(( char *Configuration )) /* In to callback() */
));
UDIError UDIGetErrorMsg UDIParams((
UDIError ErrorCode, /* In */
UDISizeT MsgSize, /* In */
char *Msg, /* Out */
UDISizeT *CountDone /* Out */
));
UDIError UDIGetTargetConfig UDIParams((
UDIMemoryRange KnownMemory[], /* Out */
UDIInt *NumberOfRanges, /* In/Out */
UDIUInt32 ChipVersions[], /* Out */
UDIInt *NumberOfChips /* In/Out */
));
UDIError UDICreateProcess UDIParams((
UDIPId *PId /* Out */
));
UDIError UDISetCurrentProcess UDIParams((
UDIPId PId /* In */
));
UDIError UDIDestroyProcess UDIParams((
UDIPId PId /* In */
));
UDIError UDIInitializeProcess UDIParams((
UDIMemoryRange ProcessMemory[], /* In */
UDIInt NumberOfRanges, /* In */
UDIResource EntryPoint, /* In */
CPUSizeT StackSizes[], /* In */
UDIInt NumberOfStacks, /* In */
char *ArgString /* In */
));
UDIError UDIRead UDIParams((
UDIResource From, /* In */
UDIHostMemPtr To, /* Out */
UDICount Count, /* In */
UDISizeT Size, /* In */
UDICount *CountDone, /* Out */
UDIBool HostEndian /* In */
));
UDIError UDIWrite UDIParams((
UDIHostMemPtr From, /* In */
UDIResource To, /* In */
UDICount Count, /* In */
UDISizeT Size, /* In */
UDICount *CountDone, /* Out */
UDIBool HostEndian /* In */
));
UDIError UDICopy UDIParams((
UDIResource From, /* In */
UDIResource To, /* In */
UDICount Count, /* In */
UDISizeT Size, /* In */
UDICount *CountDone, /* Out */
UDIBool Direction /* In */
));
UDIError UDIExecute UDIParams((
void
));
UDIError UDIStep UDIParams((
UDIUInt32 Steps, /* In */
UDIStepType StepType, /* In */
UDIRange Range /* In */
));
UDIVoid UDIStop UDIParams((
void
));
UDIError UDIWait UDIParams((
UDIInt32 MaxTime, /* In */
UDIPId *PId, /* Out */
UDIUInt32 *StopReason /* Out */
));
UDIError UDISetBreakpoint UDIParams((
UDIResource Addr, /* In */
UDIInt32 PassCount, /* In */
UDIBreakType Type, /* In */
UDIBreakId *BreakId /* Out */
));
UDIError UDIQueryBreakpoint UDIParams((
UDIBreakId BreakId, /* In */
UDIResource *Addr, /* Out */
UDIInt32 *PassCount, /* Out */
UDIBreakType *Type, /* Out */
UDIInt32 *CurrentCount /* Out */
));
UDIError UDIClearBreakpoint UDIParams((
UDIBreakId BreakId /* In */
));
UDIError UDIGetStdout UDIParams((
UDIHostMemPtr Buf, /* Out */
UDISizeT BufSize, /* In */
UDISizeT *CountDone /* Out */
));
UDIError UDIGetStderr UDIParams((
UDIHostMemPtr Buf, /* Out */
UDISizeT BufSize, /* In */
UDISizeT *CountDone /* Out */
));
UDIError UDIPutStdin UDIParams((
UDIHostMemPtr Buf, /* In */
UDISizeT Count, /* In */
UDISizeT *CountDone /* Out */
));
UDIError UDIStdinMode UDIParams((
UDIMode *Mode /* Out */
));
UDIError UDIPutTrans UDIParams((
UDIHostMemPtr Buf, /* In */
UDISizeT Count, /* In */
UDISizeT *CountDone /* Out */
));
UDIError UDIGetTrans UDIParams((
UDIHostMemPtr Buf, /* Out */
UDISizeT BufSize, /* In */
UDISizeT *CountDone /* Out */
));
UDIError UDITransMode UDIParams((
UDIMode *Mode /* Out */
));

View File

@ -0,0 +1,87 @@
/* This file is to be used to reconfigure the UDI Procedural interface
for a given target.
Copyright 1993 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* This file should be placed so that it will be
included from udiproc.h. Everything in here will probably need to
be changed when you change the target processor. Nothing in here
should need to change when you change hosts or compilers.
*/
/* Select a target CPU Family */
#define TargetCPUFamily Am29K
/* Enumerate the processor specific values for Space in a resource */
#define UDI29KDRAMSpace 0
#define UDI29KIOSpace 1
#define UDI29KCPSpace0 2
#define UDI29KCPSpace1 3
#define UDI29KIROMSpace 4
#define UDI29KIRAMSpace 5
#define UDI29KLocalRegs 8
#define UDI29KGlobalRegs 9
#define UDI29KRealRegs 10
#define UDI29KSpecialRegs 11
#define UDI29KTLBRegs 12 /* Not Am29005 */
#define UDI29KACCRegs 13 /* Am29050 only */
#define UDI29KICacheSpace 14 /* Am2903x only */
#define UDI29KAm29027Regs 15 /* When available */
#define UDI29KPC 16
#define UDI29KDCacheSpace 17 /* When available */
/* Enumerate the Co-processor registers */
#define UDI29KCP_F 0
#define UDI29KCP_Flag 8
#define UDI29KCP_I 12
#define UDI29KCP_ITmp 16
#define UDI29KCP_R 20
#define UDI29KCP_S 28
#define UDI29KCP_RTmp 36
#define UDI29KCP_STmp 44
#define UDI29KCP_Stat 52
#define UDI29KCP_Prec 56
#define UDI29KCP_Reg0 60
#define UDI29KCP_Reg1 68
#define UDI29KCP_Reg2 76
#define UDI29KCP_Reg3 84
#define UDI29KCP_Reg4 92
#define UDI29KCP_Reg5 100
#define UDI29KCP_Reg6 108
#define UDI29KCP_Reg7 116
#define UDI29KCP_Mode 124
/* Enumerate the stacks in StackSizes array */
#define UDI29KMemoryStack 0
#define UDI29KRegisterStack 1
/* Enumerate the chips for ChipVersions array */
#define UDI29K29KVersion 0
#define UDI29K29027Version 1
/* Define special value for elements of ChipVersions array for
* chips not present */
#define UDI29KChipNotPresent -1
typedef UDIInt32 UDICount;
typedef UDIUInt32 UDISize;
typedef UDIInt CPUSpace;
typedef UDIUInt32 CPUOffset;
typedef UDIUInt32 CPUSizeT;

View File

@ -0,0 +1,19 @@
/* Copyright 1993 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "udipt29k.h"

184
gdb/29k-share/udi/udisoc.h Normal file
View File

@ -0,0 +1,184 @@
/* This module defines constants used in the UDI IPC modules.
Copyright 1993 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
static char udisoc_h[]="@(#)udisoc.h 2.6 Daniel Mann";
static char udisoc_h_AMD[]="@(#)udisoc.h 2.4, AMD";
#define LOCAL static
#define company_c 1 /* AMD Company id */
#define product_c 1 /* socket IPC id */
/* Enumerate the UDI procedure services
*/
#define UDIConnect_c 0
#define UDIDisconnect_c 1
#define UDISetCurrentConnection_c 2
#define UDICapabilities_c 3
#define UDIEnumerateTIPs_c 4
#define UDIGetErrorMsg_c 5
#define UDIGetTargetConfig_c 6
#define UDICreateProcess_c 7
#define UDISetCurrentProcess_c 8
#define UDIDestroyProcess_c 9
#define UDIInitializeProcess_c 10
#define UDIRead_c 11
#define UDIWrite_c 12
#define UDICopy_c 13
#define UDIExecute_c 14
#define UDIStep_c 15
#define UDIStop_c 16
#define UDIWait_c 17
#define UDISetBreakpoint_c 18
#define UDIQueryBreakpoint_c 19
#define UDIClearBreakpoint_c 20
#define UDIGetStdout_c 21
#define UDIGetStderr_c 22
#define UDIPutStdin_c 23
#define UDIStdinMode_c 24
#define UDIPutTrans_c 25
#define UDIGetTrans_c 26
#define UDITransMode_c 27
#define UDITest_c 28
#define UDIKill_c 29
#define udr_UDIInt8(udrs, obj) udr_work(udrs, obj, 1)
#define udr_UDIInt16(udrs, obj) udr_work(udrs, obj, 2)
#define udr_UDIInt32(udrs, obj) udr_work(udrs, obj, 4)
#define udr_UDIInt(udrs, obj) udr_work(udrs, obj, 4)
#define udr_UDIUInt8(udrs, obj) udr_work(udrs, obj, 1)
#define udr_UDIUInt16(udrs, obj) udr_work(udrs, obj, 2)
#define udr_UDIUInt32(udrs, obj) udr_work(udrs, obj, 4)
#define udr_UDIUInt(udrs, obj) udr_work(udrs, obj, 4)
#define udr_UDIBool(udrs, obj) udr_UDIInt32(udrs, obj)
#define udr_UDICount(udrs, obj) udr_UDIInt32(udrs, obj)
#define udr_UDISize(udrs, obj) udr_UDIUInt32(udrs, obj)
#define udr_CPUSpace(udrs, obj) udr_UDIInt32(udrs, obj)
#define udr_CPUOffset(udrs, obj) udr_UDIUInt32(udrs, obj)
#define udr_CPUSizeT(udrs, obj) udr_UDIUInt32(udrs, obj)
#define udr_UDIBreakId(udrs,obj) udr_UDIUInt(udrs, obj)
#define udr_UDISizeT(udrs, obj) udr_UDIUInt(udrs, obj)
#define udr_UDIMode(udrs, obj) udr_UDIUInt(udrs, obj)
#define udr_UDIHostMemPtr(udrs, obj) udr_UDIUInt32(udrs, obj)
#define udr_UDIVoidPtr(udrs, obj) udr_UDIUInt32(udrs, obj)
#define udr_UDIPId(udrs, obj) udr_UDIUInt(udrs, obj)
#define udr_UDISessionId(udrs, obj) udr_UDIInt32(udrs, obj)
#define udr_UDIError(udrs, obj) udr_UDIInt32(udrs, obj)
#define udr_UDIStepType(udrs, obj) udr_UDIInt32(udrs, obj)
#define udr_UDIBreakType(udrs, obj) udr_UDIInt32(udrs, obj)
#define UDR_ENCODE 1
#define UDR_DECODE 2
typedef struct UDR_str
{
int udr_op; /* UDR operation */
int previous_op;
int sd;
int bufsize;
char* buff;
char* getbytes;
char* putbytes;
char* putend;
int domain;
char* soc_name;
} UDR;
/******************************************* Declare UDR suport functions */
int udr_create UDIParams((
UDR* udrs,
int sd,
int size
));
int udr_free UDIParams((
UDR* udrs,
));
int udr_signal UDIParams((
UDR* udrs,
));
int udr_sendnow UDIParams((
UDR* udrs
));
int udr_work UDIParams((
UDR* udrs,
void* object_p,
int size
));
int udr_UDIResource UDIParams((
UDR* udrs,
UDIResource* object_p
));
int udr_UDIRange UDIParams((
UDR* udrs,
UDIRange* object_p
));
int udr_UDIMemoryRange UDIParams((
UDR* udrs,
UDIMemoryRange* object_p
));
int udr_UDIMemoryRange UDIParams((
UDR* udrs,
UDIMemoryRange* object_p
));
int udr_int UDIParams((
UDR* udrs,
int* int_p
));
int udr_bytes UDIParams((
UDR* udrs,
char* ptr,
int len
));
char* udr_inline UDIParams((
UDR* udrs,
int size
));
char* udr_getpos UDIParams((
UDR* udrs
));
int udr_setpos UDIParams((
UDR* udrs,
char* pos
));
int udr_readnow UDIParams((
UDR* udrs,
int size
));
int udr_align UDIParams((
UDR* udrs,
int size,
));

427
gdb/29k-share/udi/udr.c Normal file
View File

@ -0,0 +1,427 @@
/* This module supports sending and receiving data objects over a
socket conection.
Copyright 1993 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
static char udr_c[]="@(#)udr.c 2.8 Daniel Mann";
static char udr_c_AMD[]="@(#)udr.c 2.3, AMD";
/*
* All data is serialised into a character stream,
* and de-serialised back into the approproiate objects.
********************************************************************** HISTORY
*/
/* This is all unneeded on DOS machines. */
#ifndef __GO32__
#include <stdio.h>
#include <sys/types.h>
/* This used to say sys/fcntl.h, but the only systems I know of that
require that are old (pre-4.3, at least) BSD systems, which we
probably don't need to worry about. */
#include <fcntl.h>
#include <sys/socket.h>
#include "udiproc.h"
#include "udisoc.h"
extern int errno;
extern char* malloc();
/* local type decs. and macro defs. not in a .h file ************* MACRO/TYPE
*/
/* global dec/defs. which are not in a .h file ************* EXPORT DEC/DEFS
*/
int udr_errno; /* error occurs during UDR service */
/* local dec/defs. which are not in a .h file *************** LOCAL DEC/DEFS
*/
/****************************************************************** UDR_CREATE
* Build UDR structure for character stream processing.
*/
int udr_create(udrs, sd, size)
UDR* udrs;
int sd;
int size;
{
udrs->sd = sd;
if(!udrs->buff) udrs->buff = malloc(size);
udrs->getbytes = udrs->buff; /* set the buffer to the start */
udrs->putbytes = udrs->buff;
udrs->putend = udrs->buff;
udrs->udr_op = -1; /* don't know the direction */
udrs->previous_op = -1; /* don't know the direction */
udrs->bufsize = size;
return 0;
}
/******************************************************************** UDR_FREE
* Free USR structure and close socket.
*/
int udr_free(udrs)
UDR* udrs;
{
close(udrs->sd);
free(udrs->buff);
return 0;
}
/****************************************************************** UDR_SIGNAL
* Send a signal to the process at the other end of the socket,
* indicating that it should expect to recieve a new message shortly.
*/
int udr_signal(udrs)
UDR* udrs;
{
if(send(udrs->sd, "I", 1, MSG_OOB) == -1)
{ perror("ERROR, udr_signal(), send(...MSG_OOB)");
udr_errno = UDIErrorIPCInternal;
return -1; /* return error code */
}
return 0;
}
/***************************************************************** UDR_SENDNOW
* used to flush the current character stream buffer to
* the associated socket. */
int udr_sendnow(udrs)
UDR* udrs;
{
int size = (UDIUInt32)(udrs->putend) - (UDIUInt32)(udrs->buff);
if(udrs->previous_op == 0)
{ udr_errno = UDIErrorIPCInternal;
return -1;
}
udrs->putbytes = udrs->buff;
udrs->putend = udrs->buff;
if (write(udrs->sd, udrs->buff, size) == -1)
{ perror("ERROR, udr_sendnow(), write() call: ");
udr_errno = UDIErrorIPCInternal;
return -1; /* return error code */
}
return 0;
}
/******************************************************************** UDR_WORK
* Function to send or recieve data from the buffers supporting
* socket communication. The buffer contains serialised objects
* sent/recieved over a socket connection.
*/
int udr_work(udrs, object_p, size)
UDR* udrs;
void* object_p;
int size;
{
int cnt, remain;
if(udrs->udr_op != udrs->previous_op)
{ if(udrs->previous_op == 0)
{ udr_errno = UDIErrorIPCInternal;
return -1;
}
udrs->previous_op= udrs->udr_op;
udrs->putbytes = udrs->buff;
udrs->getbytes = udrs->buff;
}
if(udrs->udr_op == UDR_ENCODE)
{ /* write data into character stream buffer */
if( (UDIUInt32)(udrs->putbytes) + size >
(UDIUInt32)(udrs->buff) + (UDIUInt32)(udrs->bufsize) )
{ udr_errno = UDIErrorIPCInternal;
return -1;
}
memcpy(udrs->putbytes, (char*)object_p, size);
udrs->putbytes += size;
if(udrs->putbytes > udrs->putend) udrs->putend = udrs->putbytes;
}
else if(udrs->udr_op == UDR_DECODE)
{
if( (UDIUInt32)(udrs->putbytes)-(UDIUInt32)(udrs->getbytes) < size )
{ /* need more data in character stream buffer */
remain = (UDIUInt32)(udrs->bufsize) -
( (UDIUInt32)(udrs->putbytes)-(UDIUInt32)(udrs->buff) );
if( ((UDIUInt32)(udrs->bufsize) + (UDIUInt32)(udrs->buff)
- (UDIUInt32)(udrs->getbytes)) < size)
{ udr_errno = UDIErrorIPCInternal;
return -1;
}
cnt = read(udrs->sd, (char*)udrs->putbytes, remain);
if(cnt == -1) perror("ERROR udr_work(), read() failure: ");
udrs->putbytes += cnt;
if( (UDIUInt32)(udrs->putbytes)-(UDIUInt32)(udrs->getbytes) < size )
{ udr_errno = UDIErrorIPCInternal;
return -1; /* return error code */
}
} /* read data from character stream buffer */
memcpy((char*)object_p, udrs->getbytes, size);
udrs->getbytes += size;
}
else
{ udr_errno = UDIErrorIPCInternal;
return -1;
}
return 0;
}
/************************************************************* UDR_UDIResource
*/
int udr_UDIResource(udrs, object_p)
UDR* udrs;
UDIResource* object_p;
{
int retval;
retval = udr_CPUSpace(udrs, &object_p->Space);
retval = retval | udr_CPUOffset(udrs, &object_p->Offset);
return retval;
}
/**************************************************************** UDR_UDIRange
*/
int udr_UDIRange(udrs, object_p)
UDR* udrs;
UDIRange* object_p;
{
int retval;
retval = udr_CPUOffset(udrs, &object_p->Low);
retval = retval | udr_CPUOffset(udrs, &object_p->High);
return retval;
}
/********************************************************** UDR_UDIMemoryRange
*/
int udr_UDIMemoryRange(udrs, object_p)
UDR* udrs;
UDIMemoryRange* object_p;
{
int retval;
retval = udr_CPUSpace(udrs, &object_p->Space);
retval = retval | udr_CPUOffset(udrs, &object_p->Offset);
retval = retval | udr_CPUSizeT(udrs, &object_p->Size);
return retval;
}
/****************************************************************** UDR_string
*/
int udr_string(udrs, sp)
UDR* udrs;
char* sp;
{
int len, retval;
if(udrs->udr_op == UDR_ENCODE)
{
if(sp)
{ len = strlen(sp) + 1;
retval = udr_UDIInt32(udrs, &len);
retval = retval | udr_work(udrs, sp, len);
}
else /* deal with NULL pointer */
{ len = 0;
retval = udr_UDIInt32(udrs, &len);
}
}
else if(udrs->udr_op == UDR_DECODE)
{
retval = udr_UDIInt32(udrs, &len);
if(len)
retval = retval | udr_work(udrs, sp, len);
else *sp = '\0'; /* terminate string */
}
else
{ udr_errno = UDIErrorIPCInternal;
return -1;
}
return retval;
}
/******************************************************************* UDR_BYTES
*/
int udr_bytes(udrs, ptr, len)
UDR* udrs;
char* ptr;
int len;
{
return udr_work(udrs, ptr, len);
}
/********************************************************************* UDR_INT
*/
int udr_int(udrs, int_p)
UDR* udrs;
int* int_p;
{
int ret_val;
UDIInt32 udr_obj; /* object of know size */
if(udrs->udr_op == UDR_ENCODE)
{
udr_obj = *int_p; /* copy into know object size */
return udr_UDIInt32(udrs, &udr_obj);
}
else if(udrs->udr_op == UDR_DECODE)
{
ret_val = udr_UDIInt32(udrs, &udr_obj); /* get object of known size */
*int_p = udr_obj;
return ret_val;
}
else
{ udr_errno = UDIErrorIPCInternal;
return -1;
}
}
/****************************************************************** UDR_INLINE
*/
char* udr_inline(udrs, size)
UDR* udrs;
int size;
{
if(udrs->udr_op != udrs->previous_op)
{ if(udrs->previous_op == 0)
{ udr_errno = UDIErrorIPCInternal;
return 0;
}
udrs->previous_op= udrs->udr_op;
udrs->putbytes = udrs->buff;
udrs->getbytes = udrs->buff;
}
if(udrs->udr_op == UDR_ENCODE)
{
if(udrs->putbytes + size > udrs->bufsize + udrs->buff)
return 0;
udrs->putbytes += size;
return udrs->putbytes - size;
}
else if(udrs->udr_op == UDR_DECODE)
{
if(udrs->getbytes + size > udrs->bufsize + udrs->buff)
return 0;
udrs->getbytes += size;
return udrs->getbytes - size;
}
else
{ udr_errno = UDIErrorIPCInternal;
return 0;
}
}
/****************************************************************** UDR_GETPOS
*/
char* udr_getpos(udrs)
UDR* udrs;
{
if(udrs->udr_op == UDR_ENCODE)
{
return udrs->putbytes;
}
else if(udrs->udr_op == UDR_DECODE)
{
return udrs->getbytes;
}
else
{ udr_errno = UDIErrorIPCInternal;
return 0;
}
}
/****************************************************************** UDR_SETPOS
*/
int udr_setpos(udrs, pos)
UDR* udrs;
char* pos;
{
if( ((UDIUInt32)pos > (UDIUInt32)(udrs->buff) + (UDIUInt32)(udrs->bufsize))
|| ((UDIUInt32)pos < (UDIUInt32)(udrs->buff) ) )
{ udr_errno = UDIErrorIPCInternal;
return 0;
}
if(udrs->udr_op == UDR_ENCODE)
{
udrs->putbytes = pos;
return 1;
}
else if(udrs->udr_op == UDR_DECODE)
{
udrs->getbytes = pos;
return 1;
}
else
{ udr_errno = UDIErrorIPCInternal;
return 0;
}
}
/***************************************************************** UDR_READNOW
* Try and ensure "size" bytes are available in the
* receive buffer character stream.
*/
int udr_readnow(udrs, size)
UDR* udrs;
int size;
{
int cnt, remain;
if(udrs->udr_op == UDR_ENCODE)
{
udr_errno = UDIErrorIPCInternal;
return -1;
}
else if(udrs->udr_op == UDR_DECODE)
{
if( (UDIUInt32)(udrs->putbytes)-(UDIUInt32)(udrs->getbytes) < size )
{ /* need more data in character stream buffer */
remain = (UDIUInt32)(udrs->bufsize) -
( (UDIUInt32)(udrs->putbytes)-(UDIUInt32)(udrs->buff) );
cnt = read(udrs->sd, (char*)udrs->putbytes, remain);
if(cnt == -1) perror("ERROR udr_work(), read() failure: ");
udrs->putbytes += cnt;
if( (UDIUInt32)(udrs->putbytes)-(UDIUInt32)(udrs->getbytes) < size )
{ fprintf(stderr,"ERROR, udr_readnow() too few bytes in stream\n");
return -1; /* return error code */
}
}
}
else
{ udr_errno = UDIErrorIPCInternal;
return -1;
}
return 0;
}
/******************************************************************* UDR_ALIGN
*/
int udr_align(udrs, size)
UDR* udrs;
int size;
{
char* align;
int offset;
align = udr_getpos(udrs);
offset = size - ((int)align & (size -1));
offset = offset & (size -1);
if(offset) udr_setpos(udrs, align + offset);
}
#endif /* __GO32__ */

9
gdb/29k-share/udi_soc Normal file
View File

@ -0,0 +1,9 @@
# @(#)udi_soc 2.1 Daniel Mann
# NOTE: the Session string must not start whith white-space characters.
# Format of string is:
# <session> <domain> <soc_name|host_name> <tip_exe> <pass to UDIconnect>
soc2cayman AF_INET cayman /bin/udi_tip ...
soc2tip AF_UNIX astring tip.exe ...
cuba AF_UNIX soc_name ../bin.68020/udi_tip stuff to pass
cayman AF_INET cayman this_entry_not_matter stuff to pass
iss AF_UNIX * sun4/isstip -r osboot

340
gdb/COPYING Normal file
View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

1116
gdb/ChangeLog Normal file

File diff suppressed because it is too large Load Diff

4838
gdb/ChangeLog-3.x Normal file

File diff suppressed because it is too large Load Diff

8322
gdb/ChangeLog-9091 Normal file

File diff suppressed because it is too large Load Diff

6285
gdb/ChangeLog-92 Normal file

File diff suppressed because it is too large Load Diff

7597
gdb/ChangeLog-93 Normal file

File diff suppressed because it is too large Load Diff

5705
gdb/ChangeLog-94 Normal file

File diff suppressed because it is too large Load Diff

4915
gdb/ChangeLog-95 Normal file

File diff suppressed because it is too large Load Diff

5116
gdb/ChangeLog-96 Normal file

File diff suppressed because it is too large Load Diff

2855
gdb/ChangeLog-97 Normal file

File diff suppressed because it is too large Load Diff

7122
gdb/ChangeLog-98 Normal file

File diff suppressed because it is too large Load Diff

1619
gdb/Makefile.in Normal file

File diff suppressed because it is too large Load Diff

1611
gdb/NEWS Normal file

File diff suppressed because it is too large Load Diff

618
gdb/README Normal file
View File

@ -0,0 +1,618 @@
README for gdb-4.18 release
Updated 4 Apr 1999 by Jim Blandy
This is GDB, the GNU source-level debugger.
A summary of new features is in the file `NEWS'.
See the GDB home page at http://www.cygnus.com/gdb/ for up to date
release information, mailing list links and archives, etc.
Unpacking and Installation -- quick overview
==========================
In this release, the GDB debugger sources, the generic GNU include
files, the BFD ("binary file description") library, the readline
library, and other libraries all have directories of their own
underneath the gdb-4.18 directory. The idea is that a variety of GNU
tools can share a common copy of these things. Be aware of variation
over time--for example don't try to build gdb with a copy of bfd from
a release other than the gdb release (such as a binutils or gas
release), especially if the releases are more than a few weeks apart.
Configuration scripts and makefiles exist to cruise up and down this
directory tree and automatically build all the pieces in the right
order.
When you unpack the gdb-4.18.tar.gz file, you'll find a directory
called `gdb-4.18', which contains:
COPYING config.sub* libiberty/ opcodes/
COPYING.LIB configure* mmalloc/ readline/
Makefile.in configure.in move-if-change* sim/
README etc/ mpw-README texinfo/
bfd/ gdb/ mpw-build.in utils/
config/ include/ mpw-config.in
config.guess* install.sh* mpw-configure
To build GDB, you can just do:
cd gdb-4.18
./configure
make
cp gdb/gdb /usr/local/bin/gdb (or wherever you want)
This will configure and build all the libraries as well as GDB.
If `configure' can't determine your system type, specify one as its
argument, e.g., sun4 or decstation.
If you get compiler warnings during this stage, see the `Reporting Bugs'
section below; there are a few known problems.
GDB requires an ANSI C compiler. If you do not have an ANSI C
compiler for your system, you may be able to download and install the
GNU CC compiler. It is available via anonymous FTP from ftp.gnu.org,
in /pub/gnu/gcc (as a URL, that's ftp://ftp.gnu.org/pub/gnu/gcc).
GDB can be used as a cross-debugger, running on a machine of one type
while debugging a program running on a machine of another type. See below.
More Documentation
******************
All the documentation for GDB comes as part of the machine-readable
distribution. The documentation is written in Texinfo format, which is
a documentation system that uses a single source file to produce both
on-line information and a printed manual. You can use one of the Info
formatting commands to create the on-line version of the documentation
and TeX (or `texi2roff') to typeset the printed version.
GDB includes an already formatted copy of the on-line Info version of
this manual in the `gdb/doc' subdirectory. The main Info file is
`gdb-4.18/gdb/doc/gdb.info', and it refers to subordinate files matching
`gdb.info*' in the same directory. If necessary, you can print out
these files, or read them with any editor; but they are easier to read
using the `info' subsystem in GNU Emacs or the standalone `info' program,
available as part of the GNU Texinfo distribution.
If you want to format these Info files yourself, you need one of the
Info formatting programs, such as `texinfo-format-buffer' or
`makeinfo'.
If you have `makeinfo' installed, and are in the top level GDB
source directory (`gdb-4.18', in the case of version 4.18), you can make
the Info file by typing:
cd gdb/doc
make info
If you want to typeset and print copies of this manual, you need
TeX, a program to print its DVI output files, and `texinfo.tex', the
Texinfo definitions file. This file is included in the GDB
distribution, in the directory `gdb-4.18/texinfo'.
TeX is a typesetting program; it does not print files directly, but
produces output files called DVI files. To print a typeset document,
you need a program to print DVI files. If your system has TeX
installed, chances are it has such a program. The precise command to
use depends on your system; `lpr -d' is common; another (for PostScript
devices) is `dvips'. The DVI print command may require a file name
without any extension or a `.dvi' extension.
TeX also requires a macro definitions file called `texinfo.tex'.
This file tells TeX how to typeset a document written in Texinfo
format. On its own, TeX cannot read, much less typeset a Texinfo file.
`texinfo.tex' is distributed with GDB and is located in the
`gdb-4.18/texinfo' directory.
If you have TeX and a DVI printer program installed, you can typeset
and print this manual. First switch to the the `gdb' subdirectory of
the main source directory (for example, to `gdb-4.18/gdb') and then type:
make gdb.dvi
Installing GDB
**************
GDB comes with a `configure' script that automates the process of
preparing GDB for installation; you can then use `make' to build the
`gdb' program.
The GDB distribution includes all the source code you need for GDB in
a single directory, whose name is usually composed by appending the
version number to `gdb'.
For example, the GDB version 4.18 distribution is in the `gdb-4.18'
directory. That directory contains:
`gdb-4.18/{COPYING,COPYING.LIB}'
Standard GNU license files. Please read them.
`gdb-4.18/bfd'
source for the Binary File Descriptor library
`gdb-4.18/config*'
script for configuring GDB, along with other support files
`gdb-4.18/gdb'
the source specific to GDB itself
`gdb-4.18/include'
GNU include files
`gdb-4.18/libiberty'
source for the `-liberty' free software library
`gdb-4.18/mmalloc'
source for the GNU memory-mapped malloc package
`gdb-4.18/opcodes'
source for the library of opcode tables and disassemblers
`gdb-4.18/readline'
source for the GNU command-line interface
`gdb-4.18/sim'
source for some simulators (ARM, D10V, SPARC, M32R, MIPS, PPC, V850, etc)
`gdb-4.18/intl'
source for the GNU gettext library, for internationalization.
This is slightly modified from the standalone gettext
distribution you can get from GNU.
`gdb-4.18/texinfo'
The `texinfo.tex' file, which you need in order to make a printed
manual using TeX.
`gdb-4.18/etc'
Coding standards, useful files for editing GDB, and other
miscellanea.
`gdb-4.18/utils'
A grab bag of random utilities.
The simplest way to configure and build GDB is to run `configure'
from the `gdb-VERSION-NUMBER' source directory, which in this example
is the `gdb-4.18' directory.
First switch to the `gdb-VERSION-NUMBER' source directory if you are
not already in it; then run `configure'.
For example:
cd gdb-4.18
./configure
make
Running `configure' followed by `make' builds the `bfd',
`readline', `mmalloc', and `libiberty' libraries, then `gdb' itself.
The configured source files, and the binaries, are left in the
corresponding source directories.
`configure' is a Bourne-shell (`/bin/sh') script; if your system
does not recognize this automatically when you run a different shell,
you may need to run `sh' on it explicitly:
sh configure
If you run `configure' from a directory that contains source
directories for multiple libraries or programs, such as the `gdb-4.18'
source directory for version 4.18, `configure' creates configuration
files for every directory level underneath (unless you tell it not to,
with the `--norecursion' option).
You can run the `configure' script from any of the subordinate
directories in the GDB distribution, if you only want to configure that
subdirectory; but be sure to specify a path to it.
For example, with version 4.18, type the following to configure only
the `bfd' subdirectory:
cd gdb-4.18/bfd
../configure
You can install `gdb' anywhere; it has no hardwired paths. However,
you should make sure that the shell on your path (named by the `SHELL'
environment variable) is publicly readable. Remember that GDB uses the
shell to start your program--some systems refuse to let GDB debug child
processes whose programs are not readable.
Compiling GDB in another directory
==================================
If you want to run GDB versions for several host or target machines,
you need a different `gdb' compiled for each combination of host and
target. `configure' is designed to make this easy by allowing you to
generate each configuration in a separate subdirectory, rather than in
the source directory. If your `make' program handles the `VPATH'
feature correctly (GNU `make' and SunOS 'make' are two that should),
running `make' in each of these directories builds the `gdb' program
specified there.
To build `gdb' in a separate directory, run `configure' with the
`--srcdir' option to specify where to find the source. (You also need
to specify a path to find `configure' itself from your working
directory. If the path to `configure' would be the same as the
argument to `--srcdir', you can leave out the `--srcdir' option; it
will be assumed.)
For example, with version 4.18, you can build GDB in a separate
directory for a Sun 4 like this:
cd gdb-4.18
mkdir ../gdb-sun4
cd ../gdb-sun4
../gdb-4.18/configure sun4
make
When `configure' builds a configuration using a remote source
directory, it creates a tree for the binaries with the same structure
(and using the same names) as the tree under the source directory. In
the example, you'd find the Sun 4 library `libiberty.a' in the
directory `gdb-sun4/libiberty', and GDB itself in `gdb-sun4/gdb'.
One popular reason to build several GDB configurations in separate
directories is to configure GDB for cross-compiling (where GDB runs on
one machine--the host--while debugging programs that run on another
machine--the target). You specify a cross-debugging target by giving
the `--target=TARGET' option to `configure'.
When you run `make' to build a program or library, you must run it
in a configured directory--whatever directory you were in when you
called `configure' (or one of its subdirectories).
The `Makefile' that `configure' generates in each source directory
also runs recursively. If you type `make' in a source directory such
as `gdb-4.18' (or in a separate configured directory configured with
`--srcdir=PATH/gdb-4.18'), you will build all the required libraries,
and then build GDB.
When you have multiple hosts or targets configured in separate
directories, you can run `make' on them in parallel (for example, if
they are NFS-mounted on each of the hosts); they will not interfere
with each other.
Specifying names for hosts and targets
======================================
The specifications used for hosts and targets in the `configure'
script are based on a three-part naming scheme, but some short
predefined aliases are also supported. The full naming scheme encodes
three pieces of information in the following pattern:
ARCHITECTURE-VENDOR-OS
For example, you can use the alias `sun4' as a HOST argument or in a
`--target=TARGET' option. The equivalent full name is
`sparc-sun-sunos4'.
The `configure' script accompanying GDB does not provide any query
facility to list all supported host and target names or aliases.
`configure' calls the Bourne shell script `config.sub' to map
abbreviations to full names; you can read the script, if you wish, or
you can use it to test your guesses on abbreviations--for example:
% sh config.sub sun4
sparc-sun-sunos4.1.1
% sh config.sub sun3
m68k-sun-sunos4.1.1
% sh config.sub decstation
mips-dec-ultrix4.2
% sh config.sub hp300bsd
m68k-hp-bsd
% sh config.sub i386v
i386-pc-sysv
% sh config.sub i786v
Invalid configuration `i786v': machine `i786v' not recognized
`config.sub' is also distributed in the GDB source directory
(`gdb-4.18', for version 4.18).
`configure' options
===================
Here is a summary of the `configure' options and arguments that are
most often useful for building GDB. `configure' also has several other
options not listed here. *note : (configure.info)What Configure Does,
for a full explanation of `configure'.
configure [--help]
[--prefix=DIR]
[--srcdir=PATH]
[--norecursion] [--rm]
[--enable-build-warnings]
[--target=TARGET]
[--host=HOST]
[HOST]
You may introduce options with a single `-' rather than `--' if you
prefer; but you may abbreviate option names if you use `--'.
`--help'
Display a quick summary of how to invoke `configure'.
`-prefix=DIR'
Configure the source to install programs and files under directory
`DIR'.
`--srcdir=PATH'
*Warning: using this option requires GNU `make', or another `make'
that compatibly implements the `VPATH' feature.*
Use this option to make configurations in directories separate
from the GDB source directories. Among other things, you can use
this to build (or maintain) several configurations simultaneously,
in separate directories. `configure' writes configuration
specific files in the current directory, but arranges for them to
use the source in the directory PATH. `configure' will create
directories under the working directory in parallel to the source
directories below PATH.
`--norecursion'
Configure only the directory level where `configure' is executed;
do not propagate configuration to subdirectories.
`--rm'
Remove the configuration that the other arguments specify.
`--enable-build-warnings'
When building the GDB sources, ask the compiler to warn about any
code which looks even vaguely suspicious. You should only using
this feature if you're compiling with GNU CC. It passes the
following flags:
-Wall
-Wpointer-arith
-Wstrict-prototypes
-Wmissing-prototypes
-Wmissing-declarations
`--target=TARGET'
Configure GDB for cross-debugging programs running on the specified
TARGET. Without this option, GDB is configured to debug programs
that run on the same machine (HOST) as GDB itself.
There is no convenient way to generate a list of all available
targets.
`--host=HOST'
Configure GDB to run on the specified HOST.
There is no convenient way to generate a list of all available
hosts.
`HOST ...'
Same as `--host=HOST'. If you omit this, GDB will guess; it's
quite accurate.
`configure' accepts other options, for compatibility with configuring
other GNU tools recursively; but these are the only options that affect
GDB or its supporting libraries.
Languages other than C
=======================
See the GDB manual (gdb/doc/gdb.texinfo) for information on this.
Kernel debugging
=================
I have't done this myself so I can't really offer any advice.
Remote debugging over serial lines works fine, but the kernel debugging
code in here has not been tested in years. Van Jacobson has
better kernel debugging, but the UC lawyers won't let FSF have it.
Remote debugging
=================
The files m68k-stub.c, i386-stub.c, and sparc-stub.c are examples of
remote stubs to be used with remote.c. They are designed to run
standalone on an m68k, i386, or SPARC cpu and communicate properly with
the remote.c stub over a serial line.
The directory gdb/gdbserver/ contains `gdbserver', a program that
allows remote debugging for Unix applications. gdbserver is only
supported for some native configurations, including Sun 3, Sun 4,
and Linux.
There are a number of remote interfaces for talking to existing ROM
monitors and other hardware:
remote-adapt.c AMD 29000 "Adapt"
remote-array.c Array Tech RAID controller
remote-bug.c Motorola BUG monitor
remote-d10v.c GDB protocol, talking to a d10v chip
remote-e7000.c Hitachi E7000 ICE
remote-eb.c AMD 29000 "EBMON"
remote-es.c Ericsson 1800 monitor
remote-est.c EST emulator
remote-hms.c Hitachi Micro Systems H8/300 monitor
remote-mips.c MIPS remote debugging protocol
remote-mm.c AMD 29000 "minimon"
remote-nindy.c Intel 960 "Nindy"
remote-nrom.c NetROM ROM emulator
remote-os9k.c PC running OS/9000
remote-rdi.c ARM with Angel monitor
remote-rdp.c ARM with Demon monitor
remote-sds.c PowerPC SDS monitor
remote-sim.c Generalized simulator protocol
remote-st.c Tandem ST-2000 monitor
remote-udi.c AMD 29000 using the AMD "Universal Debug Interface"
remote-vx.c VxWorks realtime kernel
Remote-vx.c and the vx-share subdirectory contain a remote interface for the
VxWorks realtime kernel, which communicates over TCP using the Sun
RPC library. This would be a useful starting point for other remote-
via-ethernet back ends.
Remote-udi.c and the 29k-share subdirectory contain a remote interface
for AMD 29000 programs, which uses the AMD "Universal Debug Interface".
This allows GDB to talk to software simulators, emulators, and/or bare
hardware boards, via network or serial interfaces. Note that GDB only
provides an interface that speaks UDI, not a complete solution. You
will need something on the other end that also speaks UDI.
Reporting Bugs
===============
The correct address for reporting bugs found in gdb is
"bug-gdb@gnu.org". Please email all bugs, and all requests for
help with GDB, to that address. Please include the GDB version number
(e.g., gdb-4.18), and how you configured it (e.g., "sun4" or "mach386
host, i586-intel-synopsys target"). Since GDB now supports so many
different configurations, it is important that you be precise about this.
If at all possible, you should include the actual banner that GDB prints
when it starts up, or failing that, the actual configure command that
you used when configuring GDB.
For more information on how/whether to report bugs, see the GDB Bugs
section of the GDB manual (gdb/doc/gdb.texinfo).
Known bugs:
* Under Ultrix 4.2 (DECstation-3100) or Alphas under OSF/1, we have
seen problems with backtraces after interrupting the inferior out
of a read(). The problem is caused by ptrace() returning an
incorrect value for the frame pointer register (register 15 or
30). As far as we can tell, this is a kernel problem. Any help
with this would be greatly appreciated.
* Under Ultrix 4.4 (DECstation-3100), setting the TERMCAP environment
variable to a string without a trailing ':' can cause GDB to dump
core upon startup. Although the core file makes it look as though
GDB code failed, the crash actually occurs within a call to the
termcap library function tgetent(). The problem can be solved by
using the GNU Termcap library.
Alphas running OSF/1 (versions 1.0 through 2.1) have the same buggy
termcap code, but GDB behaves strangely rather than crashing.
* On DECstations there are warnings about shift counts out of range in
various BFD modules. None of them is a cause for alarm, they are actually
a result of bugs in the DECstation compiler.
* Notes for the DEC Alpha using OSF/1:
The debugging output of native cc has two known problems; we view these
as compiler bugs.
The linker miscompacts symbol tables, which causes gdb to confuse the
type of variables or results in `struct <illegal>' type outputs.
dbx has the same problems with those executables. A workaround is to
specify -Wl,-b when linking, but that will increase the executable size
considerably.
If a structure has incomplete type in one file (e.g., "struct foo *"
without a definition for "struct foo"), gdb will be unable to find the
structure definition from another file.
It has been reported that the Ultrix 4.3A compiler on decstations has the
same problems.
* Notes for Solaris 2.x, using the SPARCworks cc compiler:
You have to compile your program with the -xs option of the SPARCworks
compiler to be able to debug your program with gdb.
Under Solaris 2.3 you also need patch 101409-03 (Jumbo linker patch).
Under Solaris 2.2, if you have patch 101052 installed, make sure
that it is at least at revision 101052-06.
* Under Irix 5 for SGIs, you must have installed the `compiler_dev.hdr'
subsystem that is on the IDO CD, otherwise you will get complaints
that certain files such as `/usr/include/syms.h' cannot be found.
* Notes for BSD/386:
To compile gdb-4.18 on BSD/386, you must run the configure script and
its subscripts with bash. Here is an easy way to do this:
bash -c 'CONFIG_SHELL=/bin/bash ./configure'
(configure will report i386-unknown-bsd). Then, compile with the
standard "make" command.
GDB can produce warnings about symbols that it does not understand. By
default, these warnings are disabled. You can enable them by executing
`set complaint 10' (which you can put in your ~/.gdbinit if you like).
I recommend doing this if you are working on a compiler, assembler,
linker, or GDB, since it will point out problems that you may be able
to fix. Warnings produced during symbol reading indicate some mismatch
between the object file and GDB's symbol reading code. In many cases,
it's a mismatch between the specs for the object file format, and what
the compiler actually outputs or the debugger actually understands.
X Windows versus GDB
=====================
You should check out DDD, the Data Display Debugger. Here's the blurb
from the DDD web site, http://www.cs.tu-bs.de/softech/ddd:
The Data Display Debugger (DDD) is a popular graphical user
interface for command-line debuggers such as GDB, DBX, JDB, WDB,
XDB, the Perl debugger, and the Python debugger. Besides ``usual''
front-end features such as viewing source texts, DDD has become
famous through its interactive graphical data display, where data
structures are displayed as graphs. A simple mouse click
dereferences pointers or views structure contents, updated each
time the program stops. Using DDD, you can reason about your
application by watching its data, not just by viewing it execute
lines of source code.
Emacs users will very likely enjoy the Grand Unified Debugger mode;
try typing `M-x gdb RET'.
Those interested in experimenting with a new kind of gdb-mode
should load gdb/gdba.el into GNU Emacs 19.25 or later. Comments
on this mode are also welcome.
Writing Code for GDB
=====================
There is a lot of information about writing code for GDB in the
internals manual, distributed with GDB in gdb/doc/gdbint.texinfo. You
can read it by hand, print it by using TeX and texinfo, or process it
into an `info' file for use with Emacs' info mode or the standalone
`info' program.
If you are pondering writing anything but a short patch, especially
take note of the information about copyrights in the node Submitting
Patches. It can take quite a while to get all the paperwork done, so
we encourage you to start that process as soon as you decide you are
planning to work on something, or at least well ahead of when you
think you will be ready to submit the patches.
GDB Testsuite
=============
There is a DejaGNU based testsuite available for testing your newly
built GDB, or for regression testing GDBs with local modifications.
Running the testsuite requires the prior installation of DejaGNU,
which is generally available via ftp; you'll need a pretty recent
release. Once DejaGNU is installed, you can run the tests in one of
two ways:
(1) cd gdb-4.18/gdb (assuming you also unpacked gdb)
make check
or
(2) cd gdb-4.18/gdb/testsuite
make site.exp (builds the site specific file)
runtest -tool gdb GDB=../gdb (or GDB=<somepath> as appropriate)
The second method gives you slightly more control in case of problems with
building one or more test executables or if you are using the testsuite
'standalone', without it being part of the GDB source tree.
See the DejaGNU documentation for further details.
(this is for editing this file with GNU emacs)
Local Variables:
mode: text
End:

471
gdb/TODO Normal file
View File

@ -0,0 +1,471 @@
If you find inaccuracies in this list, please send mail to
bug-gdb@prep.ai.mit.edu. If you would like to work on any of these,
you should consider sending mail to the same address, to find out
whether anyone else is working on it.
General To Do List
------------------
This list is probably not up to date, and opinions vary about the
importance or even desirability of some of the items.
Add an "info bfd" command that displays supported object formats,
similarly to objdump -i.
START_INFERIOR_TRAPS_EXPECTED need never be defined to 2, since that
is its default value. Clean this up.
It should be possible to use symbols from shared libraries before we know
exactly where the libraries will be loaded. E.g. "b perror" before running
the program. This could maybe be done as an extension of the "breakpoint
re-evaluation" after new symbols are loaded.
Make single_step() insert and remove breakpoints in one operation.
Speed up single stepping by avoiding extraneous ptrace calls.
Speed up single stepping by not inserting and removing breakpoints
each time the inferior starts and stops.
Breakpoints should not be inserted and deleted all the time. Only the
one(s) there should be removed when we have to step over one. Support
breakpoints that don't have to be removed to step over them.
Update gdbint.texinfo to include doc on the directory structure and
the various tricks of building gdb.
Do a tutorial in gdb.texinfo on how to do simple things in gdb.
E.g. how to set a breakpoint that just prints something and continues.
How to break on aborts. Etc.
Provide "voodoo" debugging of core files. This creates a zombie
process as a child of the debugger, and loads it up with the data,
stack, and regs of the core file. This allows you to call functions
in the executable, to manipulate the data in the core file.
GDB reopens the source file on every line, as you "next" through it.
Referencing the vtbl member of a struct doesn't work. It prints OK
if you print the struct, but it gets 0 if you try to deref it.
Persistent command history: A feature where you could save off a list
of the commands you did, so you can edit it into something that will bring
the target to the same place every time you source it.
This would also be useful for automated fast watchpointing; if you go
past the place where it watchpoints, you just start it over again and
do it more carefully.
Deal with the SunOS 4.0 and 4.1.1 ptrace bug that loses the registers if
the stack is paged out.
Finish the C++ exception handling stub routines. Lint points them out
as unused statics functions.
Perhaps "i source" should take an argument like that of "list".
See if core-aout.c's fetch_core_registers can be used on more machines.
E.g. MIPS (mips-xdep.c).
unpack_double() does not handle IEEE float on the target unless the host
is also IEEE. Death on a vax.
Set up interface between GDB and INFO so that you can hop into interactive
INFO and back out again. When running under Emacs, should use Emacs
info, else fork the info program. Installation of GDB should install
its texinfo files into the info tree automagically, including the readline
texinfo files.
"help address" ought to find the "help set print address" entry.
Remove the VTBL internal guts from printouts of C++ structs, unless
vtblprint is set.
Remove "at 0xnnnn" from the "b foo" response, if `print address off' and if
it matches the source line indicated.
The prompt at end of screen should accept space as well as CR.
Check STORE_RETURN_VALUE on all architectures. Check near it in tm-sparc.h
for other bogosities.
Check for storage leaks in GDB, I'm sure there are a lot!
vtblprint of a vtbl should demangle the names it's printing.
Backtrace should point out what the currently selected frame is, in
its display, perhaps showing "@3 foo (bar, ...)" or ">3 foo (bar,
...)" rather than "#3 foo (bar, ...)".
"i program" should work for core files, and display more info, like what
actually caused it to die.
"x/10i" should shorten the long name, if any, on subsequent lines.
Check through the code for FIXME comments and fix them. dbxread.c,
blockframe.c, and plenty more. (I count 634 as of 940621 - sts)
"next" over a function that longjumps, never stops until next time you happen
to get to that spot by accident. E.g. "n" over execute_command which has
an error.
"set zeroprint off", don't bother printing members of structs which
are entirely zero. Useful for those big structs with few useful
members.
GDB does four ioctl's for every command, probably switching terminal modes
to/from inferior or for readline or something.
terminal_ours versus terminal_inferior: cache state. Switch should be a noop
if the state is the same, too.
ptype $i6 = void??!
Clean up invalid_float handling so gdb doesn't coredump when it tries to
access a NaN. While this might work on SPARC, other machines are not
configured right.
"b value_at ; commands ; continue ; end" stops EVERY OTHER TIME!
Then once you enter a command, it does the command, runs two more
times, and then stops again! Bizarre... (This behaviour has been
modified, but it is not yet 100% predictable when e.g. the commands
call functions in the child, and while there, the child is interrupted
with a signal, or hits a breakpoint.)
help completion, help history should work.
Check that we can handle stack trace through varargs AND alloca in same
function, on 29K.
wait_for_inferior loops forever if wait() gives it an error.
"i frame" shows wrong "arglist at" location, doesn't show where the args
should be found, only their actual values.
There should be a way for "set" commands to validate the new setting
before it takes effect.
A mess of floating point opcodes are missing from sparc-opcode.h.
Also, a little program should test the table for bits that are
overspecified or underspecified. E.g. if the must-be-ones bits
and the must-be-zeroes bits leave some fields unexamined, and the format
string leaves them unprinted, then point this out. If multiple
non-alias patterns match, point this out too. Finally, there should
be a sparc-optest.s file that tries each pattern out. This file
should end up coming back the same (modulo transformation comments)
if fed to "gas" then the .o is fed to gdb for disassembly.
Eliminate all the core_file_command's in all the xdep files.
Eliminate separate declarations of registers[] everywhere.
"ena d" is ambiguous, why? "ena delete" seems to think it is a command!
Perhaps move the tdep, xdep, and nat files, into the config
subdirectories. If not, at least straighten out their names so that
they all start with the machine name.
inferior_status should include stop_print_frame. It won't need to be
reset in wait_for_inferior after bpstat_stop_status call, then.
i line VAR produces "Line number not known for symbol ``var''.". I
thought we were stashing that info now!
We should be able to write to random files at hex offsets like adb.
Make "target xxx" command interruptible.
Handle add_file with separate text, data, and bss addresses. Maybe
handle separate addresses for each segment in the object file?
Handle free_named_symtab to cope with multiply-loaded object files
in a dynamic linking environment. Should remember the last copy loaded,
but not get too snowed if it finds references to the older copy.
Generalize and Standardize the RPC interface to a target program,
improve it beyond the "ptrace" interface, and see if it can become a
standard for remote debugging. (This is talking about the vxworks
interface. Seems unlikely to me that there will be "a standard" for
remote debugging anytime soon --kingdon, 8 Nov 1994).
Remove all references to:
text_offset
data_offset
text_data_start
text_end
exec_data_offset
...
now that we have BFD. All remaining are in machine dependent files.
When quitting with a running program, if a core file was previously
examined, you get "Couldn't read float regs from core file"...if
indeed it can't. generic_mourn_inferior...
Have remote targets give a warning on a signal argument to
target_resume. Or better yet, extend the protocols so that it works
like it does on the Unix-like systems.
Sort help and info output.
Re-organize help categories into things that tend to fit on a screen
and hang together.
renote-nindy.c handles interrupts poorly; it error()s out of badly
chosen places, e.g. leaving current_frame zero, which causes core dumps
on the next command.
Add in commands like ADB's for searching for patterns, etc. We should
be able to examine and patch raw unsymboled binaries as well in gdb as
we can in adb. (E.g. increase the timeout in /bin/login without source).
Those xdep files that call register_addr without defining it are
probably simply broken. When reconfiguring this part of gdb, I could
only make guesses about how to redo some of those files, and I
probably guessed wrong, or left them "for later" when I have a
machine that can attempt to build them.
When doing "step" or "next", if a few lines of source are skipped between
the previous line and the current one, print those lines, not just the
last line of a multiline statement.
When searching for C++ superclasses in value_cast in valops.c, we must
not search the "fields", only the "superclasses". There might be a
struct with a field name that matches the superclass name. This can
happen when the struct was defined before the superclass (before the
name became a typedef).
Handling of "&" address-of operator needs some serious overhaul
for ANSI C and consistency on arrays and functions.
For "float point[15];":
ptype &point[4] ==> Attempt to take address of non-lvalue.
For "char *malloc();":
ptype malloc ==> "char *()"; should be same as
ptype &malloc ==> "char *(*)()"
call printf ("%x\n", malloc) ==> weird value, should be same as
call printf ("%x\n", &malloc) ==> correct value
Fix dbxread.c symbol reading in the presence of interrupts. It
currently leaves a cleanup to blow away the entire symbol table when a
QUIT occurs. (What's wrong with that? -kingdon, 28 Oct 1993).
Mipsread.c reads include files depth-first, because the dependencies
in the psymtabs are way too inclusive (it seems to me). Figure out what
really depends on what, to avoid recursing 20 or 30 times while reading
real symtabs.
value_add() should be subtracting the lower bound of arrays, if known,
and possibly checking against the upper bound for error reporting.
mipsread.c symbol table allocation and deallocation should be checked.
My suspicion is that it's full of memory leaks.
SunOS should have a target_lookup_symbol() for common'd things allocated
by the shared library linker ld.so.
When listing source lines, check for a preceding \n, to verify that
the file hasn't changed out from under us.
When listing source lines, eat leading whitespace corresponding to the
line-number prefix we print. This avoids long lines wrapping.
mipsread.c needs to check for old symtabs and psymtabs for the same
files, the way it happens for dbxread.c and coffread.c, for VxWorks
incremental symbol table reloading.
Get all the remote systems (where the protocol allows it) to be able to
stop the remote system when the GDB user types ^C (like remote.c
does). For ebmon, use ^Ak.
Possible feature: A version of the "disassemble" command which shows
both source and assembly code ("set symbol-filename on" is a partial
solution).
investigate "x/s 0" (right now stops early) (I think maybe GDB is
using a 0 address for bad purposes internally).
Make "info path" and path_command work again (but independent of the
environment either of gdb or that we'll pass to the inferior).
Make GDB understand the GCC feature for putting octal constants in
enums. Make it so overflow on an enum constant does not error_type
the whole type. Allow arbitrarily large enums with type attributes.
Put all this stuff in the testsuite.
Make TYPE_CODE_ERROR with a non-zero TYPE_LENGTH more useful (print
the value in hex; process type attributes). Add this to the
testsuite. This way future compilers can add new types and old
versions of GDB can do something halfway reasonable.
Clean up formatting of "info registers" on MIPS and 88k. See if it
is possible to do this generically across all target architectures.
GDB gets bfd/corefile.c and gdb/corefile.c confused (this should be easy to
repeat even with something more recent than GDB 4.9).
Check that unmatched RBRAC doesn't abort().
Fix mdebugread.c:parse_type to do fundamental types right (see
rs6000_builtin_type in stabsread.c for what "right" is--the point is
that the debug format fixes the sizes of these things and it shouldn't
depend on stuff like TARGET_PTR_BIT and so on. For mdebug, there seem
to be separate bt* codes for 64 bit and 32 bit things, and GDB should
be aware of that). Also use a switch statement for clarity and speed.
Investigate adding symbols in target_load--some targets do, some
don't.
Put dirname in psymtabs and change lookup*symtab to use dirname (so
/foo/bar.c works whether compiled by cc /foo/bar.c, or cd /foo; cc
bar.c).
Merge xcoffread.c and coffread.c. Use breakpoint_re_set instead of
fixup_breakpoints.
Fix byte order and int size sins in tm-a29k.h
(EXTRACT_RETURN_VALUE). Perhaps should reproduce bug and verify fix
(or perhaps should just fix it...).
Make a watchpoint on a constant expression an error (or warning
perhaps)
Make a watchpoint which contains a function call an error (it is
broken now, making it work is probably not worth the effort).
Re-do calls to signal() in remote.c, and inflow.c (set_sigint_trap and
so on) to be independent of the debugging target, using target_stop to
stop the inferior. Probably the part which is now handled by
interrupt_query in remote.c can be done without any new features in
the debugging target.
New test case based on weird.exp but in which type numbers are not
renumbered (thus multiply defining a type). This currently causes an
infinite loop on "p v_comb".
Nuke baseclass_addr.
Nuke USG define.
"source file more recent" loses on re-read
Fix 386 floating point so that floating point registers are real
registers (but code can deal at run-time if they are missing, like
mips and 68k). This would clean up "info float" and related stuff.
Look at Solaris bug in interrupt.exp. Can get out of syscall with
PRSABORT (syscall will return EINTR) but merely doing that leads to a
"can't read memory" error.
gcc -g -c enummask.c then gdb enummask.o, then "p v". GDB complains
about not being able to access memory location 0.
-------------------- enummask.c
enum mask
{
ANIMAL = 0,
VEGETABLE = 1,
MINERAL = 2,
BASIC_CATEGORY = 3,
WHITE = 0,
BLUE = 4,
GREEN = 8,
BLACK = 0xc,
COLOR = 0xc,
ALIVE = 0x10,
LARGE = 0x20
} v;
If try to modify value in file with "set write off" should give
appropriate error not "cannot access memory at address 0x65e0".
Why do we allow a target to omit standard register names (NO_STD_REGS
in tm-z8k.h)? I thought the standard register names were supposed to
be just that, standard.
Make DEBUG_EXPRESSIONS a maintenance command, dependent on
MAINTENANCE_COMMANDS.
Allow core file without exec file on RS/6000.
Make sure "shell" with no arguments works right on DOS.
Make gdb.ini (as well as .gdbinit) be checked on all platforms, so
the same directory can be NFS-mounted on unix or DOS, and work the
same way.
cd ~/tmp/<M-?> causes infinite loop (where ~/tmp is a directory).
Get SECT_OFF_TEXT stuff out of objfile_relocate (might be needed to
get RS/6000 to work right, might not be immediately relevant).
Clean up add_toc_to_loadinfo
Think about attached processes and sharing terminal.
John sez in reference to ignoring errors from tcsegpgrp if attach_flag:
set_tty_state should not have any trouble with attached processes.
Instead, the tty handling should leave the pgrp of the tty alone when
attaching to processes (perhaps pass terminal_init_inferior a flag
saying whether we're attaching).
PAGE_SIZE redefined warnings on AIX. Probably should be using
BFD_PAGE_SIZE throughout BFD.
Rewrite proceed, wait_for_inferior, and normal_stop to clean them up.
Suggestions:
1) Make each test in wait_for_inferior a seperate subroutine
call.
2) Combine wait_for_inferior and normal_stop to clean up
communication via global variables.
3) See if you can find some way to clean up the global
variables that are used; possibly group them by data flow
and information content?
Work out some kind of way to allow running the inferior to be done as
a sub-execution of, eg. breakpoint command lists. Currently running
the inferior interupts any command list execution. This would require
some rewriting of wait_for_inferior & friends, and hence should
probably be done in concert with the above.
Add function arguments to gdb user defined functions.
Add convenience variables that refer to exec file, symbol file,
selected frame source file, selected frame function, selected frame
line number, etc.
Add a "suspend" subcommand of the "continue" command to suspend gdb
while continuing execution of the subprocess. Useful when you are
debugging servers and you want to dodge out and initiate a connection
to a server running under gdb.
Add stab information to allow reasonable debugging of inline functions
(possibly they should show up on a stack backtrace? With a note
indicating that they weren't "real"?).
Modify the naked "until" command to step until past the current source
line, rather than past the current pc value. This is tricky simply
because the low level routines have no way of specifying a multi-line
step range, and there is no way of saying "don't print stuff when we
stop" from above (otherwise could just call step many times).
Modify the handling of symbols grouped through BINCL/EINCL stabs to
allocate a partial symtab for each BINCL/EINCL grouping. This will
seriously decrease the size of inter-psymtab dependencies and hence
lessen the amount that needs to be read in when a new source file is
accessed.
Do an "x/i $pc" after each stepi or nexti.
Modify all of the disassemblers to use printf_filtered to get correct
more filtering.
Modify gdb to work correctly with Pascal.
Add a command for searching memory, a la adb. It specifies size,
mask, value, start address. ADB searches until it finds it or hits
an error (or is interrupted).
# Local Variables:
# mode: text
# End:

1040
gdb/a29k-tdep.c Normal file

File diff suppressed because it is too large Load Diff

123
gdb/a68v-nat.c Normal file
View File

@ -0,0 +1,123 @@
/* Host-dependent code for Apollo-68ks for GDB, the GNU debugger.
Copyright 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "inferior.h"
#ifndef _ISP__M68K
#define _ISP__M68K 1
#endif
#include <ptrace.h>
extern int errno;
void
fetch_inferior_registers (ignored)
int ignored;
{
struct ptrace_$data_regs_m68k inferior_registers;
struct ptrace_$floating_regs_m68k inferior_fp_registers;
struct ptrace_$control_regs_m68k inferior_control_registers;
extern char registers[];
ptrace_$init_control(&inferior_control_registers);
inferior_fp_registers.size = sizeof(inferior_fp_registers);
registers_fetched ();
ptrace (PTRACE_GETREGS, inferior_pid,
(PTRACE_ARG3_TYPE) &inferior_registers,
ptrace_$data_set,
(PTRACE_ARG3_TYPE) &inferior_registers,
ptrace_$data_set);
ptrace (PTRACE_GETREGS, inferior_pid,
(PTRACE_ARG3_TYPE) &inferior_fp_registers,
ptrace_$floating_set_m68k,
(PTRACE_ARG3_TYPE) &inferior_fp_registers,
ptrace_$floating_set_m68k);
ptrace (PTRACE_GETREGS, inferior_pid,
(PTRACE_ARG3_TYPE) &inferior_control_registers,
ptrace_$control_set_m68k,
(PTRACE_ARG3_TYPE) &inferior_control_registers,
ptrace_$control_set_m68k);
bcopy (&inferior_registers, registers, 16 * 4);
bcopy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
sizeof inferior_fp_registers.regs);
*(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_control_registers.sr;
*(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_control_registers.pc;
}
/* Store our register values back into the inferior.
If REGNO is -1, do this for all registers.
Otherwise, REGNO specifies which register (so we can save time). */
void
store_inferior_registers (regno)
int regno;
{
struct ptrace_$data_regs_m68k inferior_registers;
struct ptrace_$floating_regs_m68k inferior_fp_registers;
struct ptrace_$control_regs_m68k inferior_control_registers;
extern char registers[];
ptrace_$init_control(&inferior_control_registers);
inferior_fp_registers.size = sizeof(inferior_fp_registers);
ptrace (PTRACE_GETREGS, inferior_pid,
(PTRACE_ARG3_TYPE) &inferior_fp_registers,
ptrace_$floating_set_m68k,
(PTRACE_ARG3_TYPE) &inferior_fp_registers,
ptrace_$floating_set_m68k);
ptrace (PTRACE_GETREGS, inferior_pid,
(PTRACE_ARG3_TYPE) &inferior_control_registers,
ptrace_$control_set_m68k,
(PTRACE_ARG3_TYPE) &inferior_control_registers,
ptrace_$control_set_m68k);
bcopy (registers, &inferior_registers, sizeof(inferior_registers));
bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)], inferior_fp_registers.regs,
sizeof inferior_fp_registers.regs);
inferior_control_registers.sr = *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
inferior_control_registers.pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
ptrace (PTRACE_SETREGS, inferior_pid,
(PTRACE_ARG3_TYPE) &inferior_registers,
ptrace_$data_set_m68k,
(PTRACE_ARG3_TYPE) &inferior_registers,
ptrace_$data_set_m68k);
ptrace (PTRACE_SETREGS, inferior_pid,
(PTRACE_ARG3_TYPE) &inferior_fp_registers,
ptrace_$floating_set_m68k,
(PTRACE_ARG3_TYPE) &inferior_fp_registers,
ptrace_$floating_set_m68k);
ptrace (PTRACE_SETREGS, inferior_pid,
(PTRACE_ARG3_TYPE) &inferior_control_registers,
ptrace_$control_set_m68k,
(PTRACE_ARG3_TYPE) &inferior_control_registers,
ptrace_$control_set_m68k);
}

169
gdb/abug-rom.c Normal file
View File

@ -0,0 +1,169 @@
/* Remote debugging interface for ABug Rom monitor for GDB, the GNU debugger.
Copyright 1995, 1996, 1998 Free Software Foundation, Inc.
Written by Rob Savoye of Cygnus Support
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "gdbcore.h"
#include "target.h"
#include "monitor.h"
#include "serial.h"
/* Prototypes for local functions. */
static void abug_open PARAMS ((char *args, int from_tty));
static void
abug_supply_register (regname, regnamelen, val, vallen)
char *regname;
int regnamelen;
char *val;
int vallen;
{
int regno;
if (regnamelen != 2)
return;
switch (regname[0])
{
case 'S':
if (regname[1] != 'R')
return;
regno = PS_REGNUM;
break;
case 'P':
if (regname[1] != 'C')
return;
regno = PC_REGNUM;
break;
case 'D':
if (regname[1] < '0' || regname[1] > '7')
return;
regno = regname[1] - '0' + D0_REGNUM;
break;
case 'A':
if (regname[1] < '0' || regname[1] > '7')
return;
regno = regname[1] - '0' + A0_REGNUM;
break;
default:
return;
}
monitor_supply_register (regno, val);
}
/*
* This array of registers needs to match the indexes used by GDB. The
* whole reason this exists is because the various ROM monitors use
* different names than GDB does, and don't support all the
* registers either. So, typing "info reg sp" becomes an "A7".
*/
static char *abug_regnames[NUM_REGS] =
{
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
"PC",
};
/*
* Define the monitor command strings. Since these are passed directly
* through to a printf style function, we need can include formatting
* strings. We also need a CR or LF on the end.
*/
static struct target_ops abug_ops;
static char *abug_inits[] = {"\r", NULL};
static struct monitor_ops abug_cmds ;
static void
init_abug_cmds(void)
{
abug_cmds.flags = MO_CLR_BREAK_USES_ADDR;
abug_cmds.init = abug_inits; /* Init strings */
abug_cmds.cont = "g\r"; /* continue command */
abug_cmds.step = "t\r"; /* single step */
abug_cmds.stop = NULL; /* interrupt command */
abug_cmds.set_break = "br %x\r"; /* set a breakpoint */
abug_cmds.clr_break = "nobr %x\r"; /* clear a breakpoint */
abug_cmds.clr_all_break = "nobr\r"; /* clear all breakpoints */
abug_cmds.fill = "bf %x:%x %x;b\r"; /* fill (start count val) */
abug_cmds.setmem.cmdb = "ms %x %02x\r"; /* setmem.cmdb (addr, value) */
abug_cmds.setmem.cmdw = "ms %x %04x\r"; /* setmem.cmdw (addr, value) */
abug_cmds.setmem.cmdl = "ms %x %08x\r"; /* setmem.cmdl (addr, value) */
abug_cmds.setmem.cmdll = NULL; /* setmem.cmdll (addr, value) */
abug_cmds.setmem.resp_delim = NULL; /* setreg.resp_delim */
abug_cmds.setmem.term = NULL; /* setreg.term */
abug_cmds.setmem.term_cmd = NULL; /* setreg.term_cmd */
abug_cmds.getmem.cmdb = "md %x:%x;b\r"; /* getmem.cmdb (addr, len) */
abug_cmds.getmem.cmdw = "md %x:%x;b\r"; /* getmem.cmdw (addr, len) */
abug_cmds.getmem.cmdl = "md %x:%x;b\r"; /* getmem.cmdl (addr, len) */
abug_cmds.getmem.cmdll = NULL; /* getmem.cmdll (addr, len) */
abug_cmds.getmem.resp_delim = " "; /* getmem.resp_delim */
abug_cmds.getmem.term = NULL; /* getmem.term */
abug_cmds.getmem.term_cmd = NULL; /* getmem.term_cmd */
abug_cmds.setreg.cmd = "rm %s %x\r"; /* setreg.cmd (name, value) */
abug_cmds.setreg.resp_delim = "="; /* setreg.resp_delim */
abug_cmds.setreg.term = "? "; /* setreg.term */
abug_cmds.setreg.term_cmd = ".\r" ; /* setreg.term_cmd */
abug_cmds.getreg.cmd = "rm %s\r"; /* getreg.cmd (name) */
abug_cmds.getreg.resp_delim = "="; /* getreg.resp_delim */
abug_cmds.getreg.term = "? "; /* getreg.term */
abug_cmds.getreg.term_cmd = ".\r" ; /* getreg.term_cmd */
abug_cmds.dump_registers = "rd\r"; /* dump_registers */
abug_cmds.register_pattern = "\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)"; /* register_pattern */
abug_cmds.supply_register = abug_supply_register; /* supply_register */
abug_cmds.load_routine = NULL; /* load_routine (defaults to SRECs) */
abug_cmds.load = "lo 0\r"; /* download command */
abug_cmds.loadresp = "\n"; /* load response */
abug_cmds.prompt = "135Bug>"; /* monitor command prompt */
abug_cmds.line_term = "\r"; /* end-of-line terminator */
abug_cmds.cmd_end = NULL; /* optional command terminator */
abug_cmds.target = &abug_ops; /* target operations */
abug_cmds.stopbits = SERIAL_1_STOPBITS; /* number of stop bits */
abug_cmds.regnames = abug_regnames; /* registers names */
abug_cmds.magic = MONITOR_OPS_MAGIC ; /* magic */
};
static void
abug_open(args, from_tty)
char *args;
int from_tty;
{
monitor_open (args, &abug_cmds, from_tty);
}
void
_initialize_abug_rom ()
{
init_abug_cmds() ;
init_monitor_ops (&abug_ops);
abug_ops.to_shortname = "abug";
abug_ops.to_longname = "ABug monitor";
abug_ops.to_doc = "Debug via the ABug monitor.\n\
Specify the serial device it is connected to (e.g. /dev/ttya).";
abug_ops.to_open = abug_open;
add_target (&abug_ops);
}

95
gdb/acconfig.h Normal file
View File

@ -0,0 +1,95 @@
/* Whether malloc must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_MALLOC
/* Whether realloc must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_REALLOC
/* Whether free must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_FREE
/* Whether strerror must be declared even if <string.h> is included. */
#undef NEED_DECLARATION_STRERROR
@TOP@
/* Define if pstatus_t type is available */
#undef HAVE_PSTATUS_T
/* Define if prrun_t type is available */
#undef HAVE_PRRUN_T
/* Define if fpregset_t type is available. */
#undef HAVE_FPREGSET_T
/* Define if gregset_t type is available. */
#undef HAVE_GREGSET_T
/* Define if ioctl argument PIOCSET is available. */
#undef HAVE_PROCFS_PIOCSET
/* /proc PID entries are directories containing the files
ctl as map status */
#undef HAVE_MULTIPLE_PROC_FDS
/* Define if the `long long' type works. */
#undef CC_HAS_LONG_LONG
/* Define if the "ll" format works to print long long ints. */
#undef PRINTF_HAS_LONG_LONG
/* Define if the "%Lg" format works to print long doubles. */
#undef PRINTF_HAS_LONG_DOUBLE
/* Define if the "%Lg" format works to scan long doubles. */
#undef SCANF_HAS_LONG_DOUBLE
/* Define if using Solaris thread debugging. */
#undef HAVE_THREAD_DB_LIB
/* Define on a GNU/Linux system to work around problems in sys/procfs.h. */
#undef START_INFERIOR_TRAPS_EXPECTED
#undef sys_quotactl
/* Define if you have HPUX threads */
#undef HAVE_HPUX_THREAD_SUPPORT
/* Define if you want to use the memory mapped malloc package (mmalloc). */
#undef USE_MMALLOC
/* Define if the runtime uses a routine from mmalloc before gdb has a chance
to initialize mmalloc, and we want to force checking to be used anyway.
This may cause spurious memory corruption messages if the runtime tries
to explicitly deallocate that memory when gdb calls exit. */
#undef MMCHECK_FORCE
/* Define to 1 if NLS is requested. */
#undef ENABLE_NLS
/* Define as 1 if you have catgets and don't want to use GNU gettext. */
#undef HAVE_CATGETS
/* Define as 1 if you have gettext and don't want to use GNU gettext. */
#undef HAVE_GETTEXT
/* Define as 1 if you have the stpcpy function. */
#undef HAVE_STPCPY
/* Define if your locale.h file contains LC_MESSAGES. */
#undef HAVE_LC_MESSAGES
/* Define if you want to use the full-screen terminal user interface. */
#undef TUI
/* Define if <proc_service.h> on solaris uses int instead of
size_t, and assorted other type changes. */
#undef PROC_SERVICE_IS_OLD
/* If you want to specify a default CPU variant, define this to be its
name, as a C string. */
#undef TARGET_CPU_DEFAULT
/* Set to true if the save_state_t structure is present */
#define HAVE_STRUCT_SAVE_STATE_T 0
/* Set to true if the save_state_t structure has the ss_wide member */
#define HAVE_STRUCT_MEMBER_SS_WIDE 0

861
gdb/acinclude.m4 Normal file
View File

@ -0,0 +1,861 @@
dnl written by Rob Savoye <rob@cygnus.com> for Cygnus Support
dnl major rewriting for Tcl 7.5 by Don Libes <libes@nist.gov>
dnl gdb/configure.in uses BFD_NEED_DECLARATION, so get its definition.
sinclude(../bfd/acinclude.m4)
dnl This gets the standard macros, like the TCL, TK, etc ones.
sinclude(../config/acinclude.m4)
dnl CYGNUS LOCAL: This gets the right posix flag for gcc
AC_DEFUN(CY_AC_TCL_LYNX_POSIX,
[AC_REQUIRE([AC_PROG_CC])AC_REQUIRE([AC_PROG_CPP])
AC_MSG_CHECKING([if running LynxOS])
AC_CACHE_VAL(ac_cv_os_lynx,
[AC_EGREP_CPP(yes,
[/*
* The old Lynx "cc" only defines "Lynx", but the newer one uses "__Lynx__"
*/
#if defined(__Lynx__) || defined(Lynx)
yes
#endif
], ac_cv_os_lynx=yes, ac_cv_os_lynx=no)])
#
if test "$ac_cv_os_lynx" = "yes" ; then
AC_MSG_RESULT(yes)
AC_DEFINE(LYNX)
AC_MSG_CHECKING([whether -mposix or -X is available])
AC_CACHE_VAL(ac_cv_c_posix_flag,
[AC_TRY_COMPILE(,[
/*
* This flag varies depending on how old the compiler is.
* -X is for the old "cc" and "gcc" (based on 1.42).
* -mposix is for the new gcc (at least 2.5.8).
*/
#if defined(__GNUC__) && __GNUC__ >= 2
choke me
#endif
], ac_cv_c_posix_flag=" -mposix", ac_cv_c_posix_flag=" -X")])
CC="$CC $ac_cv_c_posix_flag"
AC_MSG_RESULT($ac_cv_c_posix_flag)
else
AC_MSG_RESULT(no)
fi
])
#
# Sometimes the native compiler is a bogus stub for gcc or /usr/ucb/cc. This
# makes configure think it's cross compiling. If --target wasn't used, then
# we can't configure, so something is wrong. We don't use the cache
# here cause if somebody fixes their compiler install, we want this to work.
AC_DEFUN(CY_AC_C_WORKS,
[# If we cannot compile and link a trivial program, we can't expect anything to work
AC_MSG_CHECKING(whether the compiler ($CC) actually works)
AC_TRY_COMPILE(, [/* don't need anything here */],
c_compiles=yes, c_compiles=no)
AC_TRY_LINK(, [/* don't need anything here */],
c_links=yes, c_links=no)
if test x"${c_compiles}" = x"no" ; then
AC_MSG_ERROR(the native compiler is broken and won't compile.)
fi
if test x"${c_links}" = x"no" ; then
AC_MSG_ERROR(the native compiler is broken and won't link.)
fi
AC_MSG_RESULT(yes)
])
AC_DEFUN(CY_AC_PATH_TCLH, [
#
# Ok, lets find the tcl source trees so we can use the headers
# Warning: transition of version 9 to 10 will break this algorithm
# because 10 sorts before 9. We also look for just tcl. We have to
# be careful that we don't match stuff like tclX by accident.
# the alternative search directory is involked by --with-tclinclude
#
no_tcl=true
AC_MSG_CHECKING(for Tcl private headers. dir=${configdir})
AC_ARG_WITH(tclinclude, [ --with-tclinclude=DIR Directory where tcl private headers are], with_tclinclude=${withval})
AC_CACHE_VAL(ac_cv_c_tclh,[
# first check to see if --with-tclinclude was specified
if test x"${with_tclinclude}" != x ; then
if test -f ${with_tclinclude}/tclInt.h ; then
ac_cv_c_tclh=`(cd ${with_tclinclude}; pwd)`
elif test -f ${with_tclinclude}/generic/tclInt.h ; then
ac_cv_c_tclh=`(cd ${with_tclinclude}/generic; pwd)`
else
AC_MSG_ERROR([${with_tclinclude} directory doesn't contain private headers])
fi
fi
# next check if it came with Tcl configuration file
if test x"${ac_cv_c_tclconfig}" = x ; then
if test -f $ac_cv_c_tclconfig/../generic/tclInt.h ; then
ac_cv_c_tclh=`(cd $ac_cv_c_tclconfig/..; pwd)`
fi
fi
# next check in private source directory
#
# since ls returns lowest version numbers first, reverse its output
if test x"${ac_cv_c_tclh}" = x ; then
for i in \
${srcdir}/../tcl \
`ls -dr ${srcdir}/../tcl[[7-9]]* 2>/dev/null` \
${srcdir}/../../tcl \
`ls -dr ${srcdir}/../../tcl[[7-9]]* 2>/dev/null` \
${srcdir}/../../../tcl \
`ls -dr ${srcdir}/../../../tcl[[7-9]]* 2>/dev/null ` ; do
if test -f $i/generic/tclInt.h ; then
ac_cv_c_tclh=`(cd $i/generic; pwd)`
break
fi
done
fi
# finally check in a few common install locations
#
# since ls returns lowest version numbers first, reverse its output
if test x"${ac_cv_c_tclh}" = x ; then
for i in \
`ls -dr /usr/local/src/tcl[[7-9]]* 2>/dev/null` \
`ls -dr /usr/local/lib/tcl[[7-9]]* 2>/dev/null` \
/usr/local/src/tcl \
/usr/local/lib/tcl \
${prefix}/include ; do
if test -f $i/generic/tclInt.h ; then
ac_cv_c_tclh=`(cd $i/generic; pwd)`
break
fi
done
fi
# see if one is installed
if test x"${ac_cv_c_tclh}" = x ; then
AC_HEADER_CHECK(tclInt.h, ac_cv_c_tclh=installed, ac_cv_c_tclh="")
fi
])
if test x"${ac_cv_c_tclh}" = x ; then
TCLHDIR="# no Tcl private headers found"
AC_MSG_ERROR([Can't find Tcl private headers])
fi
if test x"${ac_cv_c_tclh}" != x ; then
no_tcl=""
if test x"${ac_cv_c_tclh}" = x"installed" ; then
AC_MSG_RESULT([is installed])
TCLHDIR=""
else
AC_MSG_RESULT([found in ${ac_cv_c_tclh}])
# this hack is cause the TCLHDIR won't print if there is a "-I" in it.
TCLHDIR="-I${ac_cv_c_tclh}"
fi
fi
AC_SUBST(TCLHDIR)
])
AC_DEFUN(CY_AC_PATH_TCLCONFIG, [
#
# Ok, lets find the tcl configuration
# First, look for one uninstalled.
# the alternative search directory is invoked by --with-tclconfig
#
if test x"${no_tcl}" = x ; then
# we reset no_tcl in case something fails here
no_tcl=true
AC_ARG_WITH(tclconfig, [ --with-tclconfig=DIR Directory containing tcl configuration (tclConfig.sh)],
with_tclconfig=${withval})
AC_MSG_CHECKING([for Tcl configuration])
AC_CACHE_VAL(ac_cv_c_tclconfig,[
# First check to see if --with-tclconfig was specified.
if test x"${with_tclconfig}" != x ; then
if test -f "${with_tclconfig}/tclConfig.sh" ; then
ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)`
else
AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh])
fi
fi
# then check for a private Tcl installation
if test x"${ac_cv_c_tclconfig}" = x ; then
for i in \
../tcl \
`ls -dr ../tcl[[7-9]]* 2>/dev/null` \
../../tcl \
`ls -dr ../../tcl[[7-9]]* 2>/dev/null` \
../../../tcl \
`ls -dr ../../../tcl[[7-9]]* 2>/dev/null` ; do
if test -f "$i/${configdir}/tclConfig.sh" ; then
ac_cv_c_tclconfig=`(cd $i/${configdir}; pwd)`
break
fi
done
fi
# check in a few common install locations
if test x"${ac_cv_c_tclconfig}" = x ; then
for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
if test -f "$i/tclConfig.sh" ; then
ac_cv_c_tclconfig=`(cd $i; pwd)`
break
fi
done
fi
# check in a few other private locations
if test x"${ac_cv_c_tclconfig}" = x ; then
for i in \
${srcdir}/../tcl \
`ls -dr ${srcdir}/../tcl[[7-9]]* 2>/dev/null` ; do
if test -f "$i/${configdir}/tclConfig.sh" ; then
ac_cv_c_tclconfig=`(cd $i/${configdir}; pwd)`
break
fi
done
fi
])
if test x"${ac_cv_c_tclconfig}" = x ; then
TCLCONFIG="# no Tcl configs found"
AC_MSG_WARN(Can't find Tcl configuration definitions)
else
no_tcl=
TCLCONFIG=${ac_cv_c_tclconfig}/tclConfig.sh
AC_MSG_RESULT(found $TCLCONFIG)
fi
fi
])
# Defined as a separate macro so we don't have to cache the values
# from PATH_TCLCONFIG (because this can also be cached).
AC_DEFUN(CY_AC_LOAD_TCLCONFIG, [
. $TCLCONFIG
AC_SUBST(TCL_VERSION)
AC_SUBST(TCL_MAJOR_VERSION)
AC_SUBST(TCL_MINOR_VERSION)
AC_SUBST(TCL_CC)
AC_SUBST(TCL_DEFS)
dnl not used, don't export to save symbols
dnl AC_SUBST(TCL_LIB_FILE)
dnl don't export, not used outside of configure
dnl AC_SUBST(TCL_LIBS)
dnl not used, don't export to save symbols
dnl AC_SUBST(TCL_PREFIX)
dnl not used, don't export to save symbols
dnl AC_SUBST(TCL_EXEC_PREFIX)
AC_SUBST(TCL_SHLIB_CFLAGS)
AC_SUBST(TCL_SHLIB_LD)
dnl don't export, not used outside of configure
AC_SUBST(TCL_SHLIB_LD_LIBS)
AC_SUBST(TCL_SHLIB_SUFFIX)
dnl not used, don't export to save symbols
AC_SUBST(TCL_DL_LIBS)
AC_SUBST(TCL_LD_FLAGS)
dnl don't export, not used outside of configure
AC_SUBST(TCL_LD_SEARCH_FLAGS)
AC_SUBST(TCL_COMPAT_OBJS)
AC_SUBST(TCL_RANLIB)
AC_SUBST(TCL_BUILD_LIB_SPEC)
AC_SUBST(TCL_LIB_SPEC)
AC_SUBST(TCL_LIB_VERSIONS_OK)
dnl not used, don't export to save symbols
dnl AC_SUBST(TCL_SHARED_LIB_SUFFIX)
dnl not used, don't export to save symbols
dnl AC_SUBST(TCL_UNSHARED_LIB_SUFFIX)
])
# Warning: Tk definitions are very similar to Tcl definitions but
# are not precisely the same. There are a couple of differences,
# so don't do changes to Tcl thinking you can cut and paste it do
# the Tk differences and later simply substitute "Tk" for "Tcl".
# Known differences:
# - Acceptable Tcl major version #s is 7-9 while Tk is 4-9
# - Searching for Tcl includes looking for tclInt.h, Tk looks for tk.h
# - Computing major/minor versions is different because Tk depends on
# headers to Tcl, Tk, and X.
# - Symbols in tkConfig.sh are different than tclConfig.sh
# - Acceptable for Tk to be missing but not Tcl.
AC_DEFUN(CY_AC_PATH_TKH, [
#
# Ok, lets find the tk source trees so we can use the headers
# If the directory (presumably symlink) named "tk" exists, use that one
# in preference to any others. Same logic is used when choosing library
# and again with Tcl. The search order is the best place to look first, then in
# decreasing significance. The loop breaks if the trigger file is found.
# Note the gross little conversion here of srcdir by cd'ing to the found
# directory. This converts the path from a relative to an absolute, so
# recursive cache variables for the path will work right. We check all
# the possible paths in one loop rather than many seperate loops to speed
# things up.
# the alternative search directory is involked by --with-tkinclude
#
no_tk=true
AC_MSG_CHECKING(for Tk private headers)
AC_ARG_WITH(tkinclude, [ --with-tkinclude=DIR Directory where tk private headers are], with_tkinclude=${withval})
AC_CACHE_VAL(ac_cv_c_tkh,[
# first check to see if --with-tkinclude was specified
if test x"${with_tkinclude}" != x ; then
if test -f ${with_tkinclude}/tk.h ; then
ac_cv_c_tkh=`(cd ${with_tkinclude}; pwd)`
elif test -f ${with_tkinclude}/generic/tk.h ; then
ac_cv_c_tkh=`(cd ${with_tkinclude}/generic; pwd)`
else
AC_MSG_ERROR([${with_tkinclude} directory doesn't contain private headers])
fi
fi
# next check if it came with Tk configuration file
if test x"${ac_cv_c_tkconfig}" = x ; then
if test -f $ac_cv_c_tkconfig/../generic/tk.h ; then
ac_cv_c_tkh=`(cd $ac_cv_c_tkconfig/..; pwd)`
fi
fi
# next check in private source directory
#
# since ls returns lowest version numbers first, reverse its output
if test x"${ac_cv_c_tkh}" = x ; then
for i in \
${srcdir}/../tk \
`ls -dr ${srcdir}/../tk[[4-9]]* 2>/dev/null` \
${srcdir}/../../tk \
`ls -dr ${srcdir}/../../tk[[4-9]]* 2>/dev/null` \
${srcdir}/../../../tk \
`ls -dr ${srcdir}/../../../tk[[4-9]]* 2>/dev/null ` ; do
if test -f $i/generic/tk.h ; then
ac_cv_c_tkh=`(cd $i/generic; pwd)`
break
fi
done
fi
# finally check in a few common install locations
#
# since ls returns lowest version numbers first, reverse its output
if test x"${ac_cv_c_tkh}" = x ; then
for i in \
`ls -dr /usr/local/src/tk[[4-9]]* 2>/dev/null` \
`ls -dr /usr/local/lib/tk[[4-9]]* 2>/dev/null` \
/usr/local/src/tk \
/usr/local/lib/tk \
${prefix}/include ; do
if test -f $i/generic/tk.h ; then
ac_cv_c_tkh=`(cd $i/generic; pwd)`
break
fi
done
fi
# see if one is installed
if test x"${ac_cv_c_tkh}" = x ; then
AC_HEADER_CHECK(tk.h, ac_cv_c_tkh=installed, ac_cv_c_tkh="")
fi
])
if test x"${ac_cv_c_tkh}" != x ; then
no_tk=""
if test x"${ac_cv_c_tkh}" = x"installed" ; then
AC_MSG_RESULT([is installed])
TKHDIR=""
else
AC_MSG_RESULT([found in ${ac_cv_c_tkh}])
# this hack is cause the TKHDIR won't print if there is a "-I" in it.
TKHDIR="-I${ac_cv_c_tkh}"
fi
else
TKHDIR="# no Tk directory found"
AC_MSG_WARN([Can't find Tk private headers])
no_tk=true
fi
AC_SUBST(TKHDIR)
])
AC_DEFUN(CY_AC_PATH_TKCONFIG, [
#
# Ok, lets find the tk configuration
# First, look for one uninstalled.
# the alternative search directory is invoked by --with-tkconfig
#
if test x"${no_tk}" = x ; then
# we reset no_tk in case something fails here
no_tk=true
AC_ARG_WITH(tkconfig, [ --with-tkconfig=DIR Directory containing tk configuration (tkConfig.sh)],
with_tkconfig=${withval})
AC_MSG_CHECKING([for Tk configuration])
AC_CACHE_VAL(ac_cv_c_tkconfig,[
# First check to see if --with-tkconfig was specified.
if test x"${with_tkconfig}" != x ; then
if test -f "${with_tkconfig}/tkConfig.sh" ; then
ac_cv_c_tkconfig=`(cd ${with_tkconfig}; pwd)`
else
AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh])
fi
fi
# then check for a private Tk library
if test x"${ac_cv_c_tkconfig}" = x ; then
for i in \
../tk \
`ls -dr ../tk[[4-9]]* 2>/dev/null` \
../../tk \
`ls -dr ../../tk[[4-9]]* 2>/dev/null` \
../../../tk \
`ls -dr ../../../tk[[4-9]]* 2>/dev/null` ; do
if test -f "$i/${configdir}/tkConfig.sh" ; then
ac_cv_c_tkconfig=`(cd $i/${configdir}; pwd)`
break
fi
done
fi
# check in a few common install locations
if test x"${ac_cv_c_tkconfig}" = x ; then
for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
if test -f "$i/tkConfig.sh" ; then
ac_cv_c_tkconfig=`(cd $i; pwd)`
break
fi
done
fi
# check in a few other private locations
if test x"${ac_cv_c_tkconfig}" = x ; then
for i in \
${srcdir}/../tk \
`ls -dr ${srcdir}/../tk[[4-9]]* 2>/dev/null` ; do
if test -f "$i/${configdir}/tkConfig.sh" ; then
ac_cv_c_tkconfig=`(cd $i/${configdir}; pwd)`
break
fi
done
fi
])
if test x"${ac_cv_c_tkconfig}" = x ; then
TKCONFIG="# no Tk configs found"
AC_MSG_WARN(Can't find Tk configuration definitions)
else
no_tk=
TKCONFIG=${ac_cv_c_tkconfig}/tkConfig.sh
AC_MSG_RESULT(found $TKCONFIG)
fi
fi
])
# Defined as a separate macro so we don't have to cache the values
# from PATH_TKCONFIG (because this can also be cached).
AC_DEFUN(CY_AC_LOAD_TKCONFIG, [
if test -f "$TKCONFIG" ; then
. $TKCONFIG
fi
AC_SUBST(TK_VERSION)
dnl not actually used, don't export to save symbols
dnl AC_SUBST(TK_MAJOR_VERSION)
dnl AC_SUBST(TK_MINOR_VERSION)
AC_SUBST(TK_DEFS)
dnl not used, don't export to save symbols
dnl AC_SUBST(TK_LIB_FILE)
dnl not used outside of configure
dnl AC_SUBST(TK_LIBS)
dnl not used, don't export to save symbols
dnl AC_SUBST(TK_PREFIX)
dnl not used, don't export to save symbols
dnl AC_SUBST(TK_EXEC_PREFIX)
AC_SUBST(TK_BUILD_INCLUDES)
AC_SUBST(TK_XINCLUDES)
AC_SUBST(TK_XLIBSW)
AC_SUBST(TK_BUILD_LIB_SPEC)
AC_SUBST(TK_LIB_SPEC)
])
# check for Itcl headers.
AC_DEFUN(CY_AC_PATH_ITCLCONFIG, [
#
# Ok, lets find the itcl configuration
# First, look for one uninstalled.
# the alternative search directory is invoked by --with-itclconfig
#
if test x"${no_itcl}" = x ; then
# we reset no_itcl in case something fails here
no_itcl=true
AC_ARG_WITH(itclconfig, [ --with-itclconfig directory containing itcl configuration (itclConfig.sh)],
with_itclconfig=${withval})
AC_MSG_CHECKING([for Itcl configuration])
AC_CACHE_VAL(ac_cv_c_itclconfig,[
# First check to see if --with-itclconfig was specified.
if test x"${with_itclconfig}" != x ; then
if test -f "${with_itclconfig}/itclConfig.sh" ; then
ac_cv_c_itclconfig=`(cd ${with_itclconfig}; pwd)`
else
AC_MSG_ERROR([${with_itclconfig} directory doesn't contain itclConfig.sh])
fi
fi
# then check for a private Itcl library
if test x"${ac_cv_c_itclconfig}" = x ; then
for i in \
../itcl/itcl \
`ls -dr ../itcl[[4-9]]*/itcl 2>/dev/null` \
../../itcl \
`ls -dr ../../itcl[[4-9]]*/itcl 2>/dev/null` \
../../../itcl \
`ls -dr ../../../itcl[[4-9]]*/itcl 2>/dev/null` ; do
if test -f "$i/itclConfig.sh" ; then
ac_cv_c_itclconfig=`(cd $i; pwd)`
break
fi
done
fi
# check in a few common install locations
if test x"${ac_cv_c_itclconfig}" = x ; then
for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
if test -f "$i/itclConfig.sh" ; then
ac_cv_c_itclconfig=`(cd $i; pwd)`
break
fi
done
fi
# check in a few other private locations
if test x"${ac_cv_c_itclconfig}" = x ; then
for i in \
${srcdir}/../itcl/itcl \
`ls -dr ${srcdir}/../itcl[[4-9]]*/itcl 2>/dev/null` ; do
if test -f "$i/itclConfig.sh" ; then
ac_cv_c_itclconfig=`(cd $i; pwd)`
break
fi
done
fi
])
if test x"${ac_cv_c_itclconfig}" = x ; then
ITCLCONFIG="# no Itcl configs found"
AC_MSG_WARN(Can't find Itcl configuration definitions)
else
no_itcl=
ITCLCONFIG=${ac_cv_c_itclconfig}/itclConfig.sh
AC_MSG_RESULT(found $ITCLCONFIG)
fi
fi
])
# Defined as a separate macro so we don't have to cache the values
# from PATH_ITCLCONFIG (because this can also be cached).
AC_DEFUN(CY_AC_LOAD_ITCLCONFIG, [
if test -f "$ITCLCONFIG" ; then
. $ITCLCONFIG
fi
AC_SUBST(ITCL_VERSION)
dnl not actually used, don't export to save symbols
dnl AC_SUBST(ITCL_MAJOR_VERSION)
dnl AC_SUBST(ITCL_MINOR_VERSION)
AC_SUBST(ITCL_DEFS)
dnl not used, don't export to save symbols
dnl AC_SUBST(ITCL_LIB_FILE)
dnl not used outside of configure
dnl AC_SUBST(ITCL_LIBS)
dnl not used, don't export to save symbols
dnl AC_SUBST(ITCL_PREFIX)
dnl not used, don't export to save symbols
dnl AC_SUBST(ITCL_EXEC_PREFIX)
AC_SUBST(ITCL_BUILD_INCLUDES)
AC_SUBST(ITCL_BUILD_LIB_SPEC)
AC_SUBST(ITCL_LIB_SPEC)
])
# check for Itcl headers.
AC_DEFUN(CY_AC_PATH_ITCLH, [
AC_MSG_CHECKING(for Itcl private headers. srcdir=${srcdir})
if test x"${ac_cv_c_itclh}" = x ; then
for i in ${srcdir}/../itcl ${srcdir}/../../itcl ${srcdir}/../../../itcl ${srcdir}/../itcl/itcl; do
if test -f $i/generic/itcl.h ; then
ac_cv_c_itclh=`(cd $i/generic; pwd)`
break
fi
done
fi
if test x"${ac_cv_c_itclh}" = x ; then
ITCLHDIR="# no Itcl private headers found"
AC_MSG_ERROR([Can't find Itcl private headers])
fi
if test x"${ac_cv_c_itclh}" != x ; then
ITCLHDIR="-I${ac_cv_c_itclh}"
fi
# should always be here
# ITCLLIB="../itcl/itcl/unix/libitcl.a"
AC_SUBST(ITCLHDIR)
#AC_SUBST(ITCLLIB)
])
AC_DEFUN(CY_AC_PATH_ITKCONFIG, [
#
# Ok, lets find the itk configuration
# First, look for one uninstalled.
# the alternative search directory is invoked by --with-itkconfig
#
if test x"${no_itk}" = x ; then
# we reset no_itk in case something fails here
no_itk=true
AC_ARG_WITH(itkconfig, [ --with-itkconfig directory containing itk configuration (itkConfig.sh)],
with_itkconfig=${withval})
AC_MSG_CHECKING([for Itk configuration])
AC_CACHE_VAL(ac_cv_c_itkconfig,[
# First check to see if --with-itkconfig was specified.
if test x"${with_itkconfig}" != x ; then
if test -f "${with_itkconfig}/itkConfig.sh" ; then
ac_cv_c_itkconfig=`(cd ${with_itkconfig}; pwd)`
else
AC_MSG_ERROR([${with_itkconfig} directory doesn't contain itkConfig.sh])
fi
fi
# then check for a private Itk library
if test x"${ac_cv_c_itkconfig}" = x ; then
for i in \
../itcl/itk \
`ls -dr ../itcl[[4-9]]*/itk 2>/dev/null` \
../../itk \
`ls -dr ../../itcl[[4-9]]*/itk 2>/dev/null` \
../../../itk \
`ls -dr ../../../itcl[[4-9]]*/itk 2>/dev/null` ; do
if test -f "$i/itkConfig.sh" ; then
ac_cv_c_itkconfig=`(cd $i; pwd)`
break
fi
done
fi
# check in a few common install locations
if test x"${ac_cv_c_itkconfig}" = x ; then
for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
if test -f "$i/itkConfig.sh" ; then
ac_cv_c_itkconfig=`(cd $i; pwd)`
break
fi
done
fi
# check in a few other private locations
if test x"${ac_cv_c_itkconfig}" = x ; then
for i in \
${srcdir}/../itcl/itk \
`ls -dr ${srcdir}/../itcl[[4-9]]*/itk 2>/dev/null` ; do
if test -f "$i/itkConfig.sh" ; then
ac_cv_c_itkconfig=`(cd $i; pwd)`
break
fi
done
fi
])
if test x"${ac_cv_c_itkconfig}" = x ; then
ITKCONFIG="# no Itk configs found"
AC_MSG_WARN(Can't find Itk configuration definitions)
else
no_itk=
ITKCONFIG=${ac_cv_c_itkconfig}/itkConfig.sh
AC_MSG_RESULT(found $ITKCONFIG)
fi
fi
])
# Defined as a separate macro so we don't have to cache the values
# from PATH_ITKCONFIG (because this can also be cached).
AC_DEFUN(CY_AC_LOAD_ITKCONFIG, [
if test -f "$ITKCONFIG" ; then
. $ITKCONFIG
fi
AC_SUBST(ITK_VERSION)
dnl not actually used, don't export to save symbols
dnl AC_SUBST(ITK_MAJOR_VERSION)
dnl AC_SUBST(ITK_MINOR_VERSION)
AC_SUBST(ITK_DEFS)
dnl not used, don't export to save symbols
dnl AC_SUBST(ITK_LIB_FILE)
dnl not used outside of configure
dnl AC_SUBST(ITK_LIBS)
dnl not used, don't export to save symbols
dnl AC_SUBST(ITK_PREFIX)
dnl not used, don't export to save symbols
dnl AC_SUBST(ITK_EXEC_PREFIX)
AC_SUBST(ITK_BUILD_INCLUDES)
AC_SUBST(ITK_BUILD_LIB_SPEC)
AC_SUBST(ITK_LIB_SPEC)
])
AC_DEFUN(CY_AC_PATH_ITKH, [
AC_MSG_CHECKING(for Itk private headers. srcdir=${srcdir})
if test x"${ac_cv_c_itkh}" = x ; then
for i in ${srcdir}/../itcl ${srcdir}/../../itcl ${srcdir}/../../../itcl ${srcdir}/../itcl/itk; do
if test -f $i/generic/itk.h ; then
ac_cv_c_itkh=`(cd $i/generic; pwd)`
break
fi
done
fi
if test x"${ac_cv_c_itkh}" = x ; then
ITKHDIR="# no Itk private headers found"
AC_MSG_ERROR([Can't find Itk private headers])
fi
if test x"${ac_cv_c_itkh}" != x ; then
ITKHDIR="-I${ac_cv_c_itkh}"
fi
# should always be here
# ITKLIB="../itcl/itk/unix/libitk.a"
AC_SUBST(ITKHDIR)
#AC_SUBST(ITKLIB)
])
# check for Tix headers.
AC_DEFUN(CY_AC_PATH_TIXH, [
AC_MSG_CHECKING(for Tix private headers. srcdir=${srcdir})
if test x"${ac_cv_c_tixh}" = x ; then
for i in ${srcdir}/../tix ${srcdir}/../../tix ${srcdir}/../../../tix ; do
if test -f $i/generic/tix.h ; then
ac_cv_c_tixh=`(cd $i/generic; pwd)`
break
fi
done
fi
if test x"${ac_cv_c_tixh}" = x ; then
TIXHDIR="# no Tix private headers found"
AC_MSG_ERROR([Can't find Tix private headers])
fi
if test x"${ac_cv_c_tixh}" != x ; then
TIXHDIR="-I${ac_cv_c_tixh}"
fi
AC_SUBST(TIXHDIR)
])
AC_DEFUN(CY_AC_PATH_TIXCONFIG, [
#
# Ok, lets find the tix configuration
# First, look for one uninstalled.
# the alternative search directory is invoked by --with-itkconfig
#
if test x"${no_tix}" = x ; then
# we reset no_tix in case something fails here
no_tix=true
AC_ARG_WITH(tixconfig, [ --with-tixconfig directory containing tix configuration (tixConfig.sh)],
with_tixconfig=${withval})
AC_MSG_CHECKING([for Tix configuration])
AC_CACHE_VAL(ac_cv_c_tixconfig,[
# First check to see if --with-tixconfig was specified.
if test x"${with_tixconfig}" != x ; then
if test -f "${with_tixconfig}/tixConfig.sh" ; then
ac_cv_c_tixconfig=`(cd ${with_tixconfig}; pwd)`
else
AC_MSG_ERROR([${with_tixconfig} directory doesn't contain tixConfig.sh])
fi
fi
# then check for a private Tix library
if test x"${ac_cv_c_tixconfig}" = x ; then
for i in \
../tix \
`ls -dr ../tix 2>/dev/null` \
../../tix \
`ls -dr ../../tix 2>/dev/null` \
../../../tix \
`ls -dr ../../../tix 2>/dev/null` ; do
echo "**** Looking at $i - with ${configdir}"
if test -f "$i/tixConfig.sh" ; then
ac_cv_c_tixconfig=`(cd $i; pwd)`
break
fi
done
fi
# check in a few common install locations
if test x"${ac_cv_c_tixconfig}" = x ; then
for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
echo "**** Looking at $i"
if test -f "$i/tixConfig.sh" ; then
ac_cv_c_tixconfig=`(cd $i; pwd)`
break
fi
done
fi
# check in a few other private locations
echo "**** Other private locations"
if test x"${ac_cv_c_tixconfig}" = x ; then
for i in \
${srcdir}/../tix \
`ls -dr ${srcdir}/../tix 2>/dev/null` ; do
echo "**** Looking at $i - with ${configdir}"
if test -f "$i/${configdir}/tixConfig.sh" ; then
ac_cv_c_tixconfig=`(cd $i/${configdir}; pwd)`
break
fi
done
fi
])
if test x"${ac_cv_c_tixconfig}" = x ; then
TIXCONFIG="# no Tix configs found"
AC_MSG_WARN(Can't find Tix configuration definitions)
else
no_tix=
TIXCONFIG=${ac_cv_c_tixconfig}/tixConfig.sh
AC_MSG_RESULT(found $TIXCONFIG)
fi
fi
])
# Defined as a separate macro so we don't have to cache the values
# from PATH_TIXCONFIG (because this can also be cached).
AC_DEFUN(CY_AC_LOAD_TIXCONFIG, [
if test -f "$TIXCONFIG" ; then
. $TIXCONFIG
fi
AC_SUBST(TIX_VERSION)
dnl not actually used, don't export to save symbols
dnl AC_SUBST(TIX_MAJOR_VERSION)
dnl AC_SUBST(TIX_MINOR_VERSION)
dnl AC_SUBST(TIX_DEFS)
dnl not used, don't export to save symbols
dnl dnl AC_SUBST(TIX_LIB_FILE)
dnl not used outside of configure
dnl AC_SUBST(TIX_LIBS)
dnl not used, don't export to save symbols
dnl AC_SUBST(TIX_PREFIX)
dnl not used, don't export to save symbols
dnl AC_SUBST(TIX_EXEC_PREFIX)
dnl AC_SUBST(TIX_BUILD_INCLUDES)
AC_SUBST(TIX_BUILD_LIB_SPEC)
dnl AC_SUBST(TIX_LIB_SPEC)
])

1307
gdb/aclocal.m4 vendored Normal file

File diff suppressed because it is too large Load Diff

297
gdb/alpha-nat.c Normal file
View File

@ -0,0 +1,297 @@
/* Low level Alpha interface, for GDB when running native.
Copyright 1993, 1995, 1996, 1998 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "inferior.h"
#include "gdbcore.h"
#include "target.h"
#include <sys/ptrace.h>
#ifdef __linux__
# include <asm/reg.h>
# include <alpha/ptrace.h>
#else
# include <machine/reg.h>
#endif
#include <sys/user.h>
/* Prototypes for local functions. */
static void fetch_osf_core_registers PARAMS ((char *,
unsigned, int, CORE_ADDR));
static void fetch_elf_core_registers PARAMS ((char *,
unsigned, int, CORE_ADDR));
/* Size of elements in jmpbuf */
#define JB_ELEMENT_SIZE 8
/* The definition for JB_PC in machine/reg.h is wrong.
And we can't get at the correct definition in setjmp.h as it is
not always available (eg. if _POSIX_SOURCE is defined which is the
default). As the defintion is unlikely to change (see comment
in <setjmp.h>, define the correct value here. */
#undef JB_PC
#define JB_PC 2
/* Figure out where the longjmp will land.
We expect the first arg to be a pointer to the jmp_buf structure from which
we extract the pc (JB_PC) that we will land at. The pc is copied into PC.
This routine returns true on success. */
int
get_longjmp_target (pc)
CORE_ADDR *pc;
{
CORE_ADDR jb_addr;
char raw_buffer[MAX_REGISTER_RAW_SIZE];
jb_addr = read_register(A0_REGNUM);
if (target_read_memory(jb_addr + JB_PC * JB_ELEMENT_SIZE, raw_buffer,
sizeof(CORE_ADDR)))
return 0;
*pc = extract_address (raw_buffer, sizeof(CORE_ADDR));
return 1;
}
/* Extract the register values out of the core file and store
them where `read_register' will find them.
CORE_REG_SECT points to the register values themselves, read into memory.
CORE_REG_SIZE is the size of that area.
WHICH says which set of registers we are handling (0 = int, 2 = float
on machines where they are discontiguous).
REG_ADDR is the offset from u.u_ar0 to the register values relative to
core_reg_sect. This is used with old-fashioned core files to
locate the registers in a large upage-plus-stack ".reg" section.
Original upage address X is at location core_reg_sect+x+reg_addr.
*/
static void
fetch_osf_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
char *core_reg_sect;
unsigned core_reg_size;
int which;
CORE_ADDR reg_addr;
{
register int regno;
register int addr;
int bad_reg = -1;
/* Table to map a gdb regnum to an index in the core register section.
The floating point register values are garbage in OSF/1.2 core files. */
static int core_reg_mapping[NUM_REGS] =
{
#define EFL (EF_SIZE / 8)
EF_V0, EF_T0, EF_T1, EF_T2, EF_T3, EF_T4, EF_T5, EF_T6,
EF_T7, EF_S0, EF_S1, EF_S2, EF_S3, EF_S4, EF_S5, EF_S6,
EF_A0, EF_A1, EF_A2, EF_A3, EF_A4, EF_A5, EF_T8, EF_T9,
EF_T10, EF_T11, EF_RA, EF_T12, EF_AT, EF_GP, EF_SP, -1,
EFL+0, EFL+1, EFL+2, EFL+3, EFL+4, EFL+5, EFL+6, EFL+7,
EFL+8, EFL+9, EFL+10, EFL+11, EFL+12, EFL+13, EFL+14, EFL+15,
EFL+16, EFL+17, EFL+18, EFL+19, EFL+20, EFL+21, EFL+22, EFL+23,
EFL+24, EFL+25, EFL+26, EFL+27, EFL+28, EFL+29, EFL+30, EFL+31,
EF_PC, -1
};
static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
for (regno = 0; regno < NUM_REGS; regno++)
{
if (CANNOT_FETCH_REGISTER (regno))
{
supply_register (regno, zerobuf);
continue;
}
addr = 8 * core_reg_mapping[regno];
if (addr < 0 || addr >= core_reg_size)
{
if (bad_reg < 0)
bad_reg = regno;
}
else
{
supply_register (regno, core_reg_sect + addr);
}
}
if (bad_reg >= 0)
{
error ("Register %s not found in core file.", REGISTER_NAME (bad_reg));
}
}
static void
fetch_elf_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
char *core_reg_sect;
unsigned core_reg_size;
int which;
CORE_ADDR reg_addr;
{
if (core_reg_size < 32*8)
{
error ("Core file register section too small (%u bytes).", core_reg_size);
return;
}
if (which == 2)
{
/* The FPU Registers. */
memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], core_reg_sect, 31*8);
memset (&registers[REGISTER_BYTE (FP0_REGNUM+31)], 0, 8);
memset (&register_valid[FP0_REGNUM], 1, 32);
}
else
{
/* The General Registers. */
memcpy (&registers[REGISTER_BYTE (V0_REGNUM)], core_reg_sect, 31*8);
memcpy (&registers[REGISTER_BYTE (PC_REGNUM)], core_reg_sect+31*8, 8);
memset (&registers[REGISTER_BYTE (ZERO_REGNUM)], 0, 8);
memset (&register_valid[V0_REGNUM], 1, 32);
register_valid[PC_REGNUM] = 1;
}
}
/* Map gdb internal register number to a ptrace ``address''.
These ``addresses'' are defined in <sys/ptrace.h> */
#define REGISTER_PTRACE_ADDR(regno) \
(regno < FP0_REGNUM ? GPR_BASE + (regno) \
: regno == PC_REGNUM ? PC \
: regno >= FP0_REGNUM ? FPR_BASE + ((regno) - FP0_REGNUM) \
: 0)
/* Return the ptrace ``address'' of register REGNO. */
CORE_ADDR
register_addr (regno, blockend)
int regno;
CORE_ADDR blockend;
{
return REGISTER_PTRACE_ADDR (regno);
}
int
kernel_u_size ()
{
return (sizeof (struct user));
}
#if defined(USE_PROC_FS) || defined(HAVE_GREGSET_T)
#include <sys/procfs.h>
/*
* See the comment in m68k-tdep.c regarding the utility of these functions.
*/
void
supply_gregset (gregsetp)
gregset_t *gregsetp;
{
register int regi;
register long *regp = ALPHA_REGSET_BASE (gregsetp);
static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
for (regi = 0; regi < 31; regi++)
supply_register (regi, (char *)(regp + regi));
supply_register (PC_REGNUM, (char *)(regp + 31));
/* Fill inaccessible registers with zero. */
supply_register (ZERO_REGNUM, zerobuf);
supply_register (FP_REGNUM, zerobuf);
}
void
fill_gregset (gregsetp, regno)
gregset_t *gregsetp;
int regno;
{
int regi;
register long *regp = ALPHA_REGSET_BASE (gregsetp);
for (regi = 0; regi < 31; regi++)
if ((regno == -1) || (regno == regi))
*(regp + regi) = *(long *) &registers[REGISTER_BYTE (regi)];
if ((regno == -1) || (regno == PC_REGNUM))
*(regp + 31) = *(long *) &registers[REGISTER_BYTE (PC_REGNUM)];
}
/*
* Now we do the same thing for floating-point registers.
* Again, see the comments in m68k-tdep.c.
*/
void
supply_fpregset (fpregsetp)
fpregset_t *fpregsetp;
{
register int regi;
register long *regp = ALPHA_REGSET_BASE (fpregsetp);
for (regi = 0; regi < 32; regi++)
supply_register (regi + FP0_REGNUM, (char *)(regp + regi));
}
void
fill_fpregset (fpregsetp, regno)
fpregset_t *fpregsetp;
int regno;
{
int regi;
register long *regp = ALPHA_REGSET_BASE (fpregsetp);
for (regi = FP0_REGNUM; regi < FP0_REGNUM + 32; regi++)
{
if ((regno == -1) || (regno == regi))
{
*(regp + regi - FP0_REGNUM) =
*(long *) &registers[REGISTER_BYTE (regi)];
}
}
}
#endif
/* Register that we are able to handle alpha core file formats. */
static struct core_fns alpha_osf_core_fns =
{
/* This really is bfd_target_unknown_flavour. */
bfd_target_unknown_flavour,
fetch_osf_core_registers,
NULL
};
static struct core_fns alpha_elf_core_fns =
{
bfd_target_elf_flavour,
fetch_elf_core_registers,
NULL
};
void
_initialize_core_alpha ()
{
add_core_fns (&alpha_osf_core_fns);
add_core_fns (&alpha_elf_core_fns);
}

1410
gdb/alpha-tdep.c Normal file

File diff suppressed because it is too large Load Diff

164
gdb/altos-xdep.c Normal file
View File

@ -0,0 +1,164 @@
/* Low level interface to ptrace, for GDB when running under m68k SVR2 Unix
on Altos 3068. Report bugs to Jyrki Kuoppala <jkp@cs.hut.fi>
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "frame.h"
#include "inferior.h"
#ifdef USG
#include <sys/types.h>
#endif
#include <sys/param.h>
#include <sys/dir.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#ifdef USG
#include <sys/page.h>
#ifdef ALTOS
#include <sys/net.h>
#include <errno.h>
#endif
#endif
#include "gdbcore.h"
#include <sys/user.h> /* After a.out.h */
#include <sys/file.h>
#include "gdb_stat.h"
/* Work with core dump and executable files, for GDB.
This code would be in corefile.c if it weren't machine-dependent. */
void
core_file_command (filename, from_tty)
char *filename;
int from_tty;
{
int val;
extern char registers[];
/* Discard all vestiges of any previous core file
and mark data and stack spaces as empty. */
if (corefile)
free (corefile);
corefile = 0;
if (corechan >= 0)
close (corechan);
corechan = -1;
data_start = 0;
data_end = 0;
stack_start = STACK_END_ADDR;
stack_end = STACK_END_ADDR;
/* Now, if a new core file was specified, open it and digest it. */
if (filename)
{
filename = tilde_expand (filename);
make_cleanup (free, filename);
if (have_inferior_p ())
error ("To look at a core file, you must kill the program with \"kill\".");
corechan = open (filename, O_RDONLY, 0);
if (corechan < 0)
perror_with_name (filename);
/* 4.2-style (and perhaps also sysV-style) core dump file. */
{
struct user u;
unsigned int reg_offset;
val = myread (corechan, &u, sizeof u);
if (val < 0)
perror_with_name ("Not a core file: reading upage");
if (val != sizeof u)
error ("Not a core file: could only read %d bytes", val);
data_start = exec_data_start;
#if !defined (NBPG)
#define NBPG NBPP
#endif
#if !defined (UPAGES)
#define UPAGES USIZE
#endif
data_end = data_start + NBPG * u.u_dsize;
stack_start = stack_end - NBPG * u.u_ssize;
data_offset = NBPG * UPAGES + exec_data_start % NBPG /* Not sure about this //jkp */;
stack_offset = NBPG * (UPAGES + u.u_dsize);
/* Some machines put an absolute address in here and some put
the offset in the upage of the regs. */
reg_offset = (int) u.u_state;
if (reg_offset > NBPG * UPAGES)
reg_offset -= KERNEL_U_ADDR;
memcpy (&core_aouthdr, &u.u_exdata, sizeof (AOUTHDR));
printf_unfiltered ("Core file is from \"%s\".\n", u.u_comm);
/* I don't know where to find this info.
So, for now, mark it as not available. */
N_SET_MAGIC (core_aouthdr, 0);
/* Read the register values out of the core file and store
them where `read_register' will find them. */
{
register int regno;
for (regno = 0; regno < NUM_REGS; regno++)
{
char buf[MAX_REGISTER_RAW_SIZE];
val = lseek (corechan, register_addr (regno, reg_offset), 0);
if (val < 0
|| (val = myread (corechan, buf, sizeof buf)) < 0)
{
char * buffer = (char *) alloca (strlen (REGISTER_NAME (regno))
+ 30);
strcpy (buffer, "Reading register ");
strcat (buffer, REGISTER_NAME (regno));
perror_with_name (buffer);
}
supply_register (regno, buf);
}
}
}
if (filename[0] == '/')
corefile = savestring (filename, strlen (filename));
else
{
corefile = concat (current_directory, "/", filename, NULL);
}
flush_cached_frames ();
select_frame (get_current_frame (), 0);
validate_files ();
}
else if (from_tty)
printf_unfiltered ("No core file now.\n");
}

577
gdb/annotate.c Normal file
View File

@ -0,0 +1,577 @@
/* Annotation routines for GDB.
Copyright 1986, 89, 90, 91, 92, 95, 1998 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "annotate.h"
#include "value.h"
#include "target.h"
#include "gdbtypes.h"
#include "breakpoint.h"
/* Prototypes for local functions. */
static void print_value_flags PARAMS ((struct type *));
static void breakpoint_changed PARAMS ((struct breakpoint *));
void (*annotate_starting_hook) PARAMS ((void));
void (*annotate_stopped_hook) PARAMS ((void));
void (*annotate_signalled_hook) PARAMS ((void));
void (*annotate_exited_hook) PARAMS ((void));
static void
print_value_flags (t)
struct type *t;
{
if (can_dereference (t))
printf_filtered ("*");
else
printf_filtered ("-");
}
void
breakpoints_changed ()
{
if (annotation_level > 1)
{
target_terminal_ours ();
printf_unfiltered ("\n\032\032breakpoints-invalid\n");
}
}
void
annotate_breakpoint (num)
int num;
{
if (annotation_level > 1)
printf_filtered ("\n\032\032breakpoint %d\n", num);
}
void
annotate_catchpoint (num)
int num;
{
if (annotation_level > 1)
printf_filtered ("\n\032\032catchpoint %d\n", num);
}
void
annotate_watchpoint (num)
int num;
{
if (annotation_level > 1)
printf_filtered ("\n\032\032watchpoint %d\n", num);
}
void
annotate_starting ()
{
if (annotate_starting_hook)
annotate_starting_hook ();
else
{
if (annotation_level > 1)
{
printf_filtered ("\n\032\032starting\n");
}
}
}
void
annotate_stopped ()
{
if (annotate_stopped_hook)
annotate_stopped_hook ();
else
{
if (annotation_level > 1)
printf_filtered ("\n\032\032stopped\n");
}
}
void
annotate_exited (exitstatus)
int exitstatus;
{
if (annotate_exited_hook)
annotate_exited_hook ();
else
{
if (annotation_level > 1)
printf_filtered ("\n\032\032exited %d\n", exitstatus);
}
}
void
annotate_signalled ()
{
if (annotate_signalled_hook)
annotate_signalled_hook ();
if (annotation_level > 1)
printf_filtered ("\n\032\032signalled\n");
}
void
annotate_signal_name ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032signal-name\n");
}
void
annotate_signal_name_end ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032signal-name-end\n");
}
void
annotate_signal_string ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032signal-string\n");
}
void
annotate_signal_string_end ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032signal-string-end\n");
}
void
annotate_signal ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032signal\n");
}
void
annotate_breakpoints_headers ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032breakpoints-headers\n");
}
void
annotate_field (num)
int num;
{
if (annotation_level > 1)
printf_filtered ("\n\032\032field %d\n", num);
}
void
annotate_breakpoints_table ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032breakpoints-table\n");
}
void
annotate_record ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032record\n");
}
void
annotate_breakpoints_table_end ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032breakpoints-table-end\n");
}
void
annotate_frames_invalid ()
{
if (annotation_level > 1)
{
target_terminal_ours ();
printf_unfiltered ("\n\032\032frames-invalid\n");
}
}
void
annotate_field_begin (type)
struct type *type;
{
if (annotation_level > 1)
{
printf_filtered ("\n\032\032field-begin ");
print_value_flags (type);
printf_filtered ("\n");
}
}
void
annotate_field_name_end ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032field-name-end\n");
}
void
annotate_field_value ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032field-value\n");
}
void
annotate_field_end ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032field-end\n");
}
void
annotate_quit ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032quit\n");
}
void
annotate_error ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032error\n");
}
void
annotate_error_begin ()
{
if (annotation_level > 1)
fprintf_filtered (gdb_stderr, "\n\032\032error-begin\n");
}
void
annotate_value_history_begin (histindex, type)
int histindex;
struct type *type;
{
if (annotation_level > 1)
{
printf_filtered ("\n\032\032value-history-begin %d ", histindex);
print_value_flags (type);
printf_filtered ("\n");
}
}
void
annotate_value_begin (type)
struct type *type;
{
if (annotation_level > 1)
{
printf_filtered ("\n\032\032value-begin ");
print_value_flags (type);
printf_filtered ("\n");
}
}
void
annotate_value_history_value ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032value-history-value\n");
}
void
annotate_value_history_end ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032value-history-end\n");
}
void
annotate_value_end ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032value-end\n");
}
void
annotate_display_begin ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032display-begin\n");
}
void
annotate_display_number_end ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032display-number-end\n");
}
void
annotate_display_format ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032display-format\n");
}
void
annotate_display_expression ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032display-expression\n");
}
void
annotate_display_expression_end ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032display-expression-end\n");
}
void
annotate_display_value ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032display-value\n");
}
void
annotate_display_end ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032display-end\n");
}
void
annotate_arg_begin ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032arg-begin\n");
}
void
annotate_arg_name_end ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032arg-name-end\n");
}
void
annotate_arg_value (type)
struct type *type;
{
if (annotation_level > 1)
{
printf_filtered ("\n\032\032arg-value ");
print_value_flags (type);
printf_filtered ("\n");
}
}
void
annotate_arg_end ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032arg-end\n");
}
void
annotate_source (filename, line, character, mid, pc)
char *filename;
int line;
int character;
int mid;
CORE_ADDR pc;
{
if (annotation_level > 1)
printf_filtered ("\n\032\032source ");
else
printf_filtered ("\032\032");
printf_filtered ("%s:%d:%d:%s:0x", filename,
line, character,
mid ? "middle" : "beg");
print_address_numeric (pc, 0, gdb_stdout);
printf_filtered ("\n");
}
void
annotate_frame_begin (level, pc)
int level;
CORE_ADDR pc;
{
if (annotation_level > 1)
{
printf_filtered ("\n\032\032frame-begin %d 0x", level);
print_address_numeric (pc, 0, gdb_stdout);
printf_filtered ("\n");
}
}
void
annotate_function_call ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032function-call\n");
}
void
annotate_signal_handler_caller ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032signal-handler-caller\n");
}
void
annotate_frame_address ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032frame-address\n");
}
void
annotate_frame_address_end ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032frame-address-end\n");
}
void
annotate_frame_function_name ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032frame-function-name\n");
}
void
annotate_frame_args ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032frame-args\n");
}
void
annotate_frame_source_begin ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032frame-source-begin\n");
}
void
annotate_frame_source_file ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032frame-source-file\n");
}
void
annotate_frame_source_file_end ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032frame-source-file-end\n");
}
void
annotate_frame_source_line ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032frame-source-line\n");
}
void
annotate_frame_source_end ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032frame-source-end\n");
}
void
annotate_frame_where ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032frame-where\n");
}
void
annotate_frame_end ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032frame-end\n");
}
void
annotate_array_section_begin (index, elttype)
int index;
struct type *elttype;
{
if (annotation_level > 1)
{
printf_filtered ("\n\032\032array-section-begin %d ", index);
print_value_flags (elttype);
printf_filtered ("\n");
}
}
void
annotate_elt_rep (repcount)
unsigned int repcount;
{
if (annotation_level > 1)
printf_filtered ("\n\032\032elt-rep %u\n", repcount);
}
void
annotate_elt_rep_end ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032elt-rep-end\n");
}
void
annotate_elt ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032elt\n");
}
void
annotate_array_section_end ()
{
if (annotation_level > 1)
printf_filtered ("\n\032\032array-section-end\n");
}
static void
breakpoint_changed (b)
struct breakpoint *b;
{
breakpoints_changed ();
}
void
_initialize_annotate ()
{
if (annotation_level > 1)
{
delete_breakpoint_hook = breakpoint_changed;
modify_breakpoint_hook = breakpoint_changed;
}
}

104
gdb/annotate.h Normal file
View File

@ -0,0 +1,104 @@
/* Annotation routines for GDB.
Copyright 1986, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "symtab.h"
#include "gdbtypes.h"
extern void breakpoints_changed PARAMS ((void));
extern void annotate_breakpoint PARAMS ((int));
extern void annotate_catchpoint PARAMS ((int));
extern void annotate_watchpoint PARAMS ((int));
extern void annotate_starting PARAMS ((void));
extern void annotate_stopped PARAMS ((void));
extern void annotate_exited PARAMS ((int));
extern void annotate_signalled PARAMS ((void));
extern void annotate_signal_name PARAMS ((void));
extern void annotate_signal_name_end PARAMS ((void));
extern void annotate_signal_string PARAMS ((void));
extern void annotate_signal_string_end PARAMS ((void));
extern void annotate_signal PARAMS ((void));
extern void annotate_breakpoints_headers PARAMS ((void));
extern void annotate_field PARAMS ((int));
extern void annotate_breakpoints_table PARAMS ((void));
extern void annotate_record PARAMS ((void));
extern void annotate_breakpoints_table_end PARAMS ((void));
extern void annotate_frames_invalid PARAMS ((void));
#ifdef __STDC__
struct type;
#endif
extern void annotate_field_begin PARAMS ((struct type *));
extern void annotate_field_name_end PARAMS ((void));
extern void annotate_field_value PARAMS ((void));
extern void annotate_field_end PARAMS ((void));
extern void annotate_quit PARAMS ((void));
extern void annotate_error PARAMS ((void));
extern void annotate_error_begin PARAMS ((void));
extern void annotate_value_history_begin PARAMS ((int, struct type *));
extern void annotate_value_begin PARAMS ((struct type *));
extern void annotate_value_history_value PARAMS ((void));
extern void annotate_value_history_end PARAMS ((void));
extern void annotate_value_end PARAMS ((void));
extern void annotate_display_begin PARAMS ((void));
extern void annotate_display_number_end PARAMS ((void));
extern void annotate_display_format PARAMS ((void));
extern void annotate_display_expression PARAMS ((void));
extern void annotate_display_expression_end PARAMS ((void));
extern void annotate_display_value PARAMS ((void));
extern void annotate_display_end PARAMS ((void));
extern void annotate_arg_begin PARAMS ((void));
extern void annotate_arg_name_end PARAMS ((void));
extern void annotate_arg_value PARAMS ((struct type *));
extern void annotate_arg_end PARAMS ((void));
extern void annotate_source PARAMS ((char *, int, int, int, CORE_ADDR));
extern void annotate_frame_begin PARAMS ((int, CORE_ADDR));
extern void annotate_function_call PARAMS ((void));
extern void annotate_signal_handler_caller PARAMS ((void));
extern void annotate_frame_address PARAMS ((void));
extern void annotate_frame_address_end PARAMS ((void));
extern void annotate_frame_function_name PARAMS ((void));
extern void annotate_frame_args PARAMS ((void));
extern void annotate_frame_source_begin PARAMS ((void));
extern void annotate_frame_source_file PARAMS ((void));
extern void annotate_frame_source_file_end PARAMS ((void));
extern void annotate_frame_source_line PARAMS ((void));
extern void annotate_frame_source_end PARAMS ((void));
extern void annotate_frame_where PARAMS ((void));
extern void annotate_frame_end PARAMS ((void));
extern void annotate_array_section_begin PARAMS ((int, struct type *));
extern void annotate_elt_rep PARAMS ((unsigned int));
extern void annotate_elt_rep_end PARAMS ((void));
extern void annotate_elt PARAMS ((void));
extern void annotate_array_section_end PARAMS ((void));
extern void (*annotate_starting_hook) PARAMS ((void));
extern void (*annotate_stopped_hook) PARAMS ((void));
extern void (*annotate_signalled_hook) PARAMS ((void));
extern void (*annotate_exited_hook) PARAMS ((void));

733
gdb/arc-tdep.c Normal file
View File

@ -0,0 +1,733 @@
/* ARC target-dependent stuff.
Copyright (C) 1995, 1997 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "frame.h"
#include "inferior.h"
#include "gdbcore.h"
#include "target.h"
#include "floatformat.h"
#include "symtab.h"
#include "gdbcmd.h"
/* Current CPU, set with the "set cpu" command. */
static int arc_bfd_mach_type;
char *arc_cpu_type;
char *tmp_arc_cpu_type;
/* Table of cpu names. */
struct {
char *name;
int value;
} arc_cpu_type_table[] = {
{ "base", bfd_mach_arc_base },
{ NULL, 0 }
};
/* Used by simulator. */
int display_pipeline_p;
int cpu_timer;
/* This one must have the same type as used in the emulator.
It's currently an enum so this should be ok for now. */
int debug_pipeline_p;
#define ARC_CALL_SAVED_REG(r) ((r) >= 16 && (r) < 24)
#define OPMASK 0xf8000000
/* Instruction field accessor macros.
See the Programmer's Reference Manual. */
#define X_OP(i) (((i) >> 27) & 0x1f)
#define X_A(i) (((i) >> 21) & 0x3f)
#define X_B(i) (((i) >> 15) & 0x3f)
#define X_C(i) (((i) >> 9) & 0x3f)
#define X_D(i) ((((i) & 0x1ff) ^ 0x100) - 0x100)
#define X_L(i) (((((i) >> 5) & 0x3ffffc) ^ 0x200000) - 0x200000)
#define X_N(i) (((i) >> 5) & 3)
#define X_Q(i) ((i) & 0x1f)
/* Return non-zero if X is a short immediate data indicator. */
#define SHIMM_P(x) ((x) == 61 || (x) == 63)
/* Return non-zero if X is a "long" (32 bit) immediate data indicator. */
#define LIMM_P(x) ((x) == 62)
/* Build a simple instruction. */
#define BUILD_INSN(op, a, b, c, d) \
((((op) & 31) << 27) \
| (((a) & 63) << 21) \
| (((b) & 63) << 15) \
| (((c) & 63) << 9) \
| ((d) & 511))
/* Codestream stuff. */
static void codestream_read PARAMS ((unsigned int *, int));
static void codestream_seek PARAMS ((CORE_ADDR));
static unsigned int codestream_fill PARAMS ((int));
#define CODESTREAM_BUFSIZ 16
static CORE_ADDR codestream_next_addr;
static CORE_ADDR codestream_addr;
static unsigned int codestream_buf[CODESTREAM_BUFSIZ];
static int codestream_off;
static int codestream_cnt;
#define codestream_tell() \
(codestream_addr + codestream_off * sizeof (codestream_buf[0]))
#define codestream_peek() \
(codestream_cnt == 0 \
? codestream_fill (1) \
: codestream_buf[codestream_off])
#define codestream_get() \
(codestream_cnt-- == 0 \
? codestream_fill (0) \
: codestream_buf[codestream_off++])
static unsigned int
codestream_fill (peek_flag)
int peek_flag;
{
codestream_addr = codestream_next_addr;
codestream_next_addr += CODESTREAM_BUFSIZ * sizeof (codestream_buf[0]);
codestream_off = 0;
codestream_cnt = CODESTREAM_BUFSIZ;
read_memory (codestream_addr, (char *) codestream_buf,
CODESTREAM_BUFSIZ * sizeof (codestream_buf[0]));
/* FIXME: check return code? */
/* Handle byte order differences. */
if (HOST_BYTE_ORDER != TARGET_BYTE_ORDER)
{
register unsigned int i, j, n = sizeof (codestream_buf[0]);
register char tmp, *p;
for (i = 0, p = (char *) codestream_buf; i < CODESTREAM_BUFSIZ;
++i, p += n)
for (j = 0; j < n / 2; ++j)
tmp = p[j], p[j] = p[n - 1 - j], p[n - 1 - j] = tmp;
}
if (peek_flag)
return codestream_peek ();
else
return codestream_get ();
}
static void
codestream_seek (place)
CORE_ADDR place;
{
codestream_next_addr = place / CODESTREAM_BUFSIZ;
codestream_next_addr *= CODESTREAM_BUFSIZ;
codestream_cnt = 0;
codestream_fill (1);
while (codestream_tell () != place)
codestream_get ();
}
/* This function is currently unused but leave in for now. */
static void
codestream_read (buf, count)
unsigned int *buf;
int count;
{
unsigned int *p;
int i;
p = buf;
for (i = 0; i < count; i++)
*p++ = codestream_get ();
}
/* Set up prologue scanning and return the first insn. */
static unsigned int
setup_prologue_scan (pc)
CORE_ADDR pc;
{
unsigned int insn;
codestream_seek (pc);
insn = codestream_get ();
return insn;
}
/*
* Find & return amount a local space allocated, and advance codestream to
* first register push (if any).
* If entry sequence doesn't make sense, return -1, and leave
* codestream pointer random.
*/
static long
arc_get_frame_setup (pc)
CORE_ADDR pc;
{
unsigned int insn;
/* Size of frame or -1 if unrecognizable prologue. */
int frame_size = -1;
/* An initial "sub sp,sp,N" may or may not be for a stdarg fn. */
int maybe_stdarg_decr = -1;
insn = setup_prologue_scan (pc);
/* The authority for what appears here is the home-grown ABI.
The most recent version is 1.2. */
/* First insn may be "sub sp,sp,N" if stdarg fn. */
if ((insn & BUILD_INSN (-1, -1, -1, -1, 0))
== BUILD_INSN (10, SP_REGNUM, SP_REGNUM, SHIMM_REGNUM, 0))
{
maybe_stdarg_decr = X_D (insn);
insn = codestream_get ();
}
if ((insn & BUILD_INSN (-1, 0, -1, -1, -1)) /* st blink,[sp,4] */
== BUILD_INSN (2, 0, SP_REGNUM, BLINK_REGNUM, 4))
{
insn = codestream_get ();
/* Frame may not be necessary, even though blink is saved.
At least this is something we recognize. */
frame_size = 0;
}
if ((insn & BUILD_INSN (-1, 0, -1, -1, -1)) /* st fp,[sp] */
== BUILD_INSN (2, 0, SP_REGNUM, FP_REGNUM, 0))
{
insn = codestream_get ();
if ((insn & BUILD_INSN (-1, -1, -1, -1, 0))
!= BUILD_INSN (12, FP_REGNUM, SP_REGNUM, SP_REGNUM, 0))
return -1;
/* Check for stack adjustment sub sp,sp,N. */
insn = codestream_peek ();
if ((insn & BUILD_INSN (-1, -1, -1, 0, 0))
== BUILD_INSN (10, SP_REGNUM, SP_REGNUM, 0, 0))
{
if (LIMM_P (X_C (insn)))
frame_size = codestream_get ();
else if (SHIMM_P (X_C (insn)))
frame_size = X_D (insn);
else
return -1;
if (frame_size < 0)
return -1;
codestream_get ();
/* This sequence is used to get the address of the return
buffer for a function that returns a structure. */
insn = codestream_peek ();
if (insn & OPMASK == 0x60000000)
codestream_get ();
}
/* Frameless fn. */
else
{
frame_size = 0;
}
}
/* If we found a "sub sp,sp,N" and nothing else, it may or may not be a
stdarg fn. The stdarg decrement is not treated as part of the frame size,
so we have a dilemma: what do we return? For now, if we get a
"sub sp,sp,N" and nothing else assume this isn't a stdarg fn. One way
to fix this completely would be to add a bit to the function descriptor
that says the function is a stdarg function. */
if (frame_size < 0 && maybe_stdarg_decr > 0)
return maybe_stdarg_decr;
return frame_size;
}
/* Given a pc value, skip it forward past the function prologue by
disassembling instructions that appear to be a prologue.
If FRAMELESS_P is set, we are only testing to see if the function
is frameless. If it is a frameless function, return PC unchanged.
This allows a quicker answer. */
CORE_ADDR
skip_prologue (pc, frameless_p)
CORE_ADDR pc;
int frameless_p;
{
unsigned int insn;
int i, frame_size;
if ((frame_size = arc_get_frame_setup (pc)) < 0)
return (pc);
if (frameless_p)
return frame_size == 0 ? pc : codestream_tell ();
/* Skip over register saves. */
for (i = 0; i < 8; i++)
{
insn = codestream_peek ();
if ((insn & BUILD_INSN (-1, 0, -1, 0, 0))
!= BUILD_INSN (2, 0, SP_REGNUM, 0, 0))
break; /* not st insn */
if (! ARC_CALL_SAVED_REG (X_C (insn)))
break;
codestream_get ();
}
return codestream_tell ();
}
/* Return the return address for a frame.
This is used to implement FRAME_SAVED_PC.
This is taken from frameless_look_for_prologue. */
CORE_ADDR
arc_frame_saved_pc (frame)
struct frame_info *frame;
{
CORE_ADDR func_start;
unsigned int insn;
func_start = get_pc_function_start (frame->pc) + FUNCTION_START_OFFSET;
if (func_start == 0)
{
/* Best guess. */
return ARC_PC_TO_REAL_ADDRESS (read_memory_integer (FRAME_FP (frame) + 4, 4));
}
/* The authority for what appears here is the home-grown ABI.
The most recent version is 1.2. */
insn = setup_prologue_scan (func_start);
/* First insn may be "sub sp,sp,N" if stdarg fn. */
if ((insn & BUILD_INSN (-1, -1, -1, -1, 0))
== BUILD_INSN (10, SP_REGNUM, SP_REGNUM, SHIMM_REGNUM, 0))
insn = codestream_get ();
/* If the next insn is "st blink,[sp,4]" we can get blink from there.
Otherwise this is a leaf function and we can use blink. Note that
this still allows for the case where a leaf function saves/clobbers/
restores blink. */
if ((insn & BUILD_INSN (-1, 0, -1, -1, -1)) /* st blink,[sp,4] */
!= BUILD_INSN (2, 0, SP_REGNUM, BLINK_REGNUM, 4))
return ARC_PC_TO_REAL_ADDRESS (read_register (BLINK_REGNUM));
else
return ARC_PC_TO_REAL_ADDRESS (read_memory_integer (FRAME_FP (frame) + 4, 4));
}
/*
* Parse the first few instructions of the function to see
* what registers were stored.
*
* The startup sequence can be at the start of the function.
* 'st blink,[sp+4], st fp,[sp], mov fp,sp'
*
* Local space is allocated just below by sub sp,sp,nnn.
* Next, the registers used by this function are stored (as offsets from sp).
*/
void
frame_find_saved_regs (fip, fsrp)
struct frame_info *fip;
struct frame_saved_regs *fsrp;
{
long locals;
unsigned int insn;
CORE_ADDR dummy_bottom;
CORE_ADDR adr;
int i, regnum, offset;
memset (fsrp, 0, sizeof *fsrp);
/* If frame is the end of a dummy, compute where the beginning would be. */
dummy_bottom = fip->frame - 4 - REGISTER_BYTES - CALL_DUMMY_LENGTH;
/* Check if the PC is in the stack, in a dummy frame. */
if (dummy_bottom <= fip->pc && fip->pc <= fip->frame)
{
/* all regs were saved by push_call_dummy () */
adr = fip->frame;
for (i = 0; i < NUM_REGS; i++)
{
adr -= REGISTER_RAW_SIZE (i);
fsrp->regs[i] = adr;
}
return;
}
locals = arc_get_frame_setup (get_pc_function_start (fip->pc));
if (locals >= 0)
{
/* Set `adr' to the value of `sp'. */
adr = fip->frame - locals;
for (i = 0; i < 8; i++)
{
insn = codestream_get ();
if ((insn & BUILD_INSN (-1, 0, -1, 0, 0))
!= BUILD_INSN (2, 0, SP_REGNUM, 0, 0))
break;
regnum = X_C (insn);
offset = X_D (insn);
fsrp->regs[regnum] = adr + offset;
}
}
fsrp->regs[PC_REGNUM] = fip->frame + 4;
fsrp->regs[FP_REGNUM] = fip->frame;
}
void
push_dummy_frame ()
{
CORE_ADDR sp = read_register (SP_REGNUM);
int regnum;
char regbuf[MAX_REGISTER_RAW_SIZE];
read_register_gen (PC_REGNUM, regbuf);
write_memory (sp+4, regbuf, REGISTER_SIZE);
read_register_gen (FP_REGNUM, regbuf);
write_memory (sp, regbuf, REGISTER_SIZE);
write_register (FP_REGNUM, sp);
for (regnum = 0; regnum < NUM_REGS; regnum++)
{
read_register_gen (regnum, regbuf);
sp = push_bytes (sp, regbuf, REGISTER_RAW_SIZE (regnum));
}
sp += (2*REGISTER_SIZE);
write_register (SP_REGNUM, sp);
}
void
pop_frame ()
{
struct frame_info *frame = get_current_frame ();
CORE_ADDR fp;
int regnum;
struct frame_saved_regs fsr;
char regbuf[MAX_REGISTER_RAW_SIZE];
fp = FRAME_FP (frame);
get_frame_saved_regs (frame, &fsr);
for (regnum = 0; regnum < NUM_REGS; regnum++)
{
CORE_ADDR adr;
adr = fsr.regs[regnum];
if (adr)
{
read_memory (adr, regbuf, REGISTER_RAW_SIZE (regnum));
write_register_bytes (REGISTER_BYTE (regnum), regbuf,
REGISTER_RAW_SIZE (regnum));
}
}
write_register (FP_REGNUM, read_memory_integer (fp, 4));
write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));
write_register (SP_REGNUM, fp + 8);
flush_cached_frames ();
}
/* Simulate single-step. */
typedef enum
{
NORMAL4, /* a normal 4 byte insn */
NORMAL8, /* a normal 8 byte insn */
BRANCH4, /* a 4 byte branch insn, including ones without delay slots */
BRANCH8, /* an 8 byte branch insn, including ones with delay slots */
} insn_type;
/* Return the type of INSN and store in TARGET the destination address of a
branch if this is one. */
/* ??? Need to verify all cases are properly handled. */
static insn_type
get_insn_type (insn, pc, target)
unsigned long insn;
CORE_ADDR pc, *target;
{
unsigned long limm;
switch (insn >> 27)
{
case 0 : case 1 : case 2 : /* load/store insns */
if (LIMM_P (X_A (insn))
|| LIMM_P (X_B (insn))
|| LIMM_P (X_C (insn)))
return NORMAL8;
return NORMAL4;
case 4 : case 5 : case 6 : /* branch insns */
*target = pc + 4 + X_L (insn);
/* ??? It isn't clear that this is always the right answer.
The problem occurs when the next insn is an 8 byte insn. If the
branch is conditional there's no worry as there shouldn't be an 8
byte insn following. The programmer may be cheating if s/he knows
the branch will never be taken, but we don't deal with that.
Note that the programmer is also allowed to play games by putting
an insn with long immediate data in the delay slot and then duplicate
the long immediate data at the branch target. Ugh! */
if (X_N (insn) == 0)
return BRANCH4;
return BRANCH8;
case 7 : /* jump insns */
if (LIMM_P (X_B (insn)))
{
limm = read_memory_integer (pc + 4, 4);
*target = ARC_PC_TO_REAL_ADDRESS (limm);
return BRANCH8;
}
if (SHIMM_P (X_B (insn)))
*target = ARC_PC_TO_REAL_ADDRESS (X_D (insn));
else
*target = ARC_PC_TO_REAL_ADDRESS (read_register (X_B (insn)));
if (X_Q (insn) == 0 && X_N (insn) == 0)
return BRANCH4;
return BRANCH8;
default : /* arithmetic insns, etc. */
if (LIMM_P (X_A (insn))
|| LIMM_P (X_B (insn))
|| LIMM_P (X_C (insn)))
return NORMAL8;
return NORMAL4;
}
}
/* single_step() is called just before we want to resume the inferior, if we
want to single-step it but there is no hardware or kernel single-step
support. We find all the possible targets of the coming instruction and
breakpoint them.
single_step is also called just after the inferior stops. If we had
set up a simulated single-step, we undo our damage. */
void
arc_software_single_step (ignore, insert_breakpoints_p)
enum target_signal ignore; /* sig but we don't need it */
int insert_breakpoints_p;
{
static CORE_ADDR next_pc, target;
static int brktrg_p;
typedef char binsn_quantum[BREAKPOINT_MAX];
static binsn_quantum break_mem[2];
if (insert_breakpoints_p)
{
insn_type type;
CORE_ADDR pc;
unsigned long insn;
pc = read_register (PC_REGNUM);
insn = read_memory_integer (pc, 4);
type = get_insn_type (insn, pc, &target);
/* Always set a breakpoint for the insn after the branch. */
next_pc = pc + ((type == NORMAL8 || type == BRANCH8) ? 8 : 4);
target_insert_breakpoint (next_pc, break_mem[0]);
brktrg_p = 0;
if ((type == BRANCH4 || type == BRANCH8)
/* Watch out for branches to the following location.
We just stored a breakpoint there and another call to
target_insert_breakpoint will think the real insn is the
breakpoint we just stored there. */
&& target != next_pc)
{
brktrg_p = 1;
target_insert_breakpoint (target, break_mem[1]);
}
}
else
{
/* Remove breakpoints. */
target_remove_breakpoint (next_pc, break_mem[0]);
if (brktrg_p)
target_remove_breakpoint (target, break_mem[1]);
/* Fix the pc. */
stop_pc -= DECR_PC_AFTER_BREAK;
write_pc (stop_pc);
}
}
#ifdef GET_LONGJMP_TARGET
/* Figure out where the longjmp will land. Slurp the args out of the stack.
We expect the first arg to be a pointer to the jmp_buf structure from which
we extract the pc (JB_PC) that we will land at. The pc is copied into PC.
This routine returns true on success. */
int
get_longjmp_target(pc)
CORE_ADDR *pc;
{
char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
CORE_ADDR sp, jb_addr;
sp = read_register (SP_REGNUM);
if (target_read_memory (sp + SP_ARG0, /* Offset of first arg on stack */
buf,
TARGET_PTR_BIT / TARGET_CHAR_BIT))
return 0;
jb_addr = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
TARGET_PTR_BIT / TARGET_CHAR_BIT))
return 0;
*pc = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
return 1;
}
#endif /* GET_LONGJMP_TARGET */
/* Disassemble one instruction. */
static int
arc_print_insn (vma, info)
bfd_vma vma;
disassemble_info *info;
{
static int current_mach;
static int current_endian;
static disassembler_ftype current_disasm;
if (current_disasm == NULL
|| arc_bfd_mach_type != current_mach
|| TARGET_BYTE_ORDER != current_endian)
{
current_mach = arc_bfd_mach_type;
current_endian = TARGET_BYTE_ORDER;
current_disasm = arc_get_disassembler (current_mach,
current_endian == BIG_ENDIAN);
}
return (*current_disasm) (vma, info);
}
/* Command to set cpu type. */
void
arc_set_cpu_type_command (args, from_tty)
char *args;
int from_tty;
{
int i;
if (tmp_arc_cpu_type == NULL || *tmp_arc_cpu_type == '\0')
{
printf_unfiltered ("The known ARC cpu types are as follows:\n");
for (i = 0; arc_cpu_type_table[i].name != NULL; ++i)
printf_unfiltered ("%s\n", arc_cpu_type_table[i].name);
/* Restore the value. */
tmp_arc_cpu_type = strsave (arc_cpu_type);
return;
}
if (!arc_set_cpu_type (tmp_arc_cpu_type))
{
error ("Unknown cpu type `%s'.", tmp_arc_cpu_type);
/* Restore its value. */
tmp_arc_cpu_type = strsave (arc_cpu_type);
}
}
static void
arc_show_cpu_type_command (args, from_tty)
char *args;
int from_tty;
{
}
/* Modify the actual cpu type.
Result is a boolean indicating success. */
int
arc_set_cpu_type (str)
char *str;
{
int i, j;
if (str == NULL)
return 0;
for (i = 0; arc_cpu_type_table[i].name != NULL; ++i)
{
if (strcasecmp (str, arc_cpu_type_table[i].name) == 0)
{
arc_cpu_type = str;
arc_bfd_mach_type = arc_cpu_type_table[i].value;
return 1;
}
}
return 0;
}
void
_initialize_arc_tdep ()
{
struct cmd_list_element *c;
c = add_set_cmd ("cpu", class_support, var_string_noescape,
(char *) &tmp_arc_cpu_type,
"Set the type of ARC cpu in use.\n\
This command has two purposes. In a multi-cpu system it lets one\n\
change the cpu being debugged. It also gives one access to\n\
cpu-type-specific registers and recognize cpu-type-specific instructions.\
",
&setlist);
c->function.cfunc = arc_set_cpu_type_command;
c = add_show_from_set (c, &showlist);
c->function.cfunc = arc_show_cpu_type_command;
/* We have to use strsave here because the `set' command frees it before
setting a new value. */
tmp_arc_cpu_type = strsave (DEFAULT_ARC_CPU_TYPE);
arc_set_cpu_type (tmp_arc_cpu_type);
c = add_set_cmd ("displaypipeline", class_support, var_zinteger,
(char *) &display_pipeline_p,
"Set pipeline display (simulator only).\n\
When enabled, the state of the pipeline after each cycle is displayed.",
&setlist);
c = add_show_from_set (c, &showlist);
c = add_set_cmd ("debugpipeline", class_support, var_zinteger,
(char *) &debug_pipeline_p,
"Set pipeline debug display (simulator only).\n\
When enabled, debugging information about the pipeline is displayed.",
&setlist);
c = add_show_from_set (c, &showlist);
c = add_set_cmd ("cputimer", class_support, var_zinteger,
(char *) &cpu_timer,
"Set maximum cycle count (simulator only).\n\
Control will return to gdb if the timer expires.\n\
A negative value disables the timer.",
&setlist);
c = add_show_from_set (c, &showlist);
tm_print_insn = arc_print_insn;
}

16
gdb/arm-convert.s Normal file
View File

@ -0,0 +1,16 @@
.text
.global _convert_from_extended
_convert_from_extended:
ldfe f0,[a1]
stfd f0,[a2]
movs pc,lr
.global _convert_to_extended
_convert_to_extended:
ldfd f0,[a1]
stfe f0,[a2]
movs pc,lr

1626
gdb/arm-tdep.c Normal file

File diff suppressed because it is too large Load Diff

559
gdb/arm-xdep.c Normal file
View File

@ -0,0 +1,559 @@
/* Acorn Risc Machine host machine support.
Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "frame.h"
#include "inferior.h"
#include "arm-opcode.h"
#include <sys/param.h>
#include <sys/dir.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/ptrace.h>
#include <machine/reg.h>
#define N_TXTADDR(hdr) 0x8000
#define N_DATADDR(hdr) (hdr.a_text + 0x8000)
#include "gdbcore.h"
#include <sys/user.h> /* After a.out.h */
#include <sys/file.h>
#include "gdb_stat.h"
#include <errno.h>
void
fetch_inferior_registers (regno)
int regno; /* Original value discarded */
{
register unsigned int regaddr;
char buf[MAX_REGISTER_RAW_SIZE];
register int i;
struct user u;
unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
offset = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0)
- KERNEL_U_ADDR;
registers_fetched ();
for (regno = 0; regno < 16; regno++)
{
regaddr = offset + regno * 4;
*(int *)&buf[0] = ptrace (PT_READ_U, inferior_pid,
(PTRACE_ARG3_TYPE) regaddr, 0);
if (regno == PC_REGNUM)
*(int *)&buf[0] = GET_PC_PART(*(int *)&buf[0]);
supply_register (regno, buf);
}
*(int *)&buf[0] = ptrace (PT_READ_U, inferior_pid,
(PTRACE_ARG3_TYPE) (offset + PC*4), 0);
supply_register (PS_REGNUM, buf); /* set virtual register ps same as pc */
/* read the floating point registers */
offset = (char *) &u.u_fp_regs - (char *)&u;
*(int *)buf = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0);
supply_register (FPS_REGNUM, buf);
for (regno = 16; regno < 24; regno++) {
regaddr = offset + 4 + 12 * (regno - 16);
for (i = 0; i < 12; i += sizeof(int))
*(int *) &buf[i] = ptrace (PT_READ_U, inferior_pid,
(PTRACE_ARG3_TYPE) (regaddr + i), 0);
supply_register (regno, buf);
}
}
/* Store our register values back into the inferior.
If REGNO is -1, do this for all registers.
Otherwise, REGNO specifies which register (so we can save time). */
void
store_inferior_registers (regno)
int regno;
{
register unsigned int regaddr;
char buf[80];
struct user u;
unsigned long value;
unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
offset = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0)
- KERNEL_U_ADDR;
if (regno >= 0) {
if (regno >= 16) return;
regaddr = offset + 4 * regno;
errno = 0;
value = read_register(regno);
if (regno == PC_REGNUM)
value = SET_PC_PART(read_register (PS_REGNUM), value);
ptrace (PT_WRITE_U, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, value);
if (errno != 0)
{
sprintf (buf, "writing register number %d", regno);
perror_with_name (buf);
}
}
else for (regno = 0; regno < 15; regno++)
{
regaddr = offset + regno * 4;
errno = 0;
value = read_register(regno);
if (regno == PC_REGNUM)
value = SET_PC_PART(read_register (PS_REGNUM), value);
ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, value);
if (errno != 0)
{
sprintf (buf, "writing all regs, number %d", regno);
perror_with_name (buf);
}
}
}
/* Work with core dump and executable files, for GDB.
This code would be in corefile.c if it weren't machine-dependent. */
/* Structure to describe the chain of shared libraries used
by the execfile.
e.g. prog shares Xt which shares X11 which shares c. */
struct shared_library {
struct exec_header header;
char name[SHLIBLEN];
CORE_ADDR text_start; /* CORE_ADDR of 1st byte of text, this file */
long data_offset; /* offset of data section in file */
int chan; /* file descriptor for the file */
struct shared_library *shares; /* library this one shares */
};
static struct shared_library *shlib = 0;
/* Hook for `exec_file_command' command to call. */
extern void (*exec_file_display_hook) ();
static CORE_ADDR unshared_text_start;
/* extended header from exec file (for shared library info) */
static struct exec_header exec_header;
void
core_file_command (filename, from_tty)
char *filename;
int from_tty;
{
int val;
extern char registers[];
/* Discard all vestiges of any previous core file
and mark data and stack spaces as empty. */
if (corefile)
free (corefile);
corefile = 0;
if (corechan >= 0)
close (corechan);
corechan = -1;
data_start = 0;
data_end = 0;
stack_start = STACK_END_ADDR;
stack_end = STACK_END_ADDR;
/* Now, if a new core file was specified, open it and digest it. */
if (filename)
{
filename = tilde_expand (filename);
make_cleanup (free, filename);
if (have_inferior_p ())
error ("To look at a core file, you must kill the program with \"kill\".");
corechan = open (filename, O_RDONLY, 0);
if (corechan < 0)
perror_with_name (filename);
/* 4.2-style (and perhaps also sysV-style) core dump file. */
{
struct user u;
unsigned int reg_offset, fp_reg_offset;
val = myread (corechan, &u, sizeof u);
if (val < 0)
perror_with_name ("Not a core file: reading upage");
if (val != sizeof u)
error ("Not a core file: could only read %d bytes", val);
/* We are depending on exec_file_command having been called
previously to set exec_data_start. Since the executable
and the core file share the same text segment, the address
of the data segment will be the same in both. */
data_start = exec_data_start;
data_end = data_start + NBPG * u.u_dsize;
stack_start = stack_end - NBPG * u.u_ssize;
data_offset = NBPG * UPAGES;
stack_offset = NBPG * (UPAGES + u.u_dsize);
/* Some machines put an absolute address in here and some put
the offset in the upage of the regs. */
reg_offset = (int) u.u_ar0;
if (reg_offset > NBPG * UPAGES)
reg_offset -= KERNEL_U_ADDR;
fp_reg_offset = (char *) &u.u_fp_regs - (char *)&u;
/* I don't know where to find this info.
So, for now, mark it as not available. */
N_SET_MAGIC (core_aouthdr, 0);
/* Read the register values out of the core file and store
them where `read_register' will find them. */
{
register int regno;
for (regno = 0; regno < NUM_REGS; regno++)
{
char buf[MAX_REGISTER_RAW_SIZE];
if (regno < 16)
val = lseek (corechan, reg_offset + 4 * regno, 0);
else if (regno < 24)
val = lseek (corechan, fp_reg_offset + 4 + 12*(regno - 24), 0);
else if (regno == 24)
val = lseek (corechan, fp_reg_offset, 0);
else if (regno == 25)
val = lseek (corechan, reg_offset + 4 * PC, 0);
if (val < 0
|| (val = myread (corechan, buf, sizeof buf)) < 0)
{
char * buffer = (char *) alloca (strlen (REGISTER_NAME (regno))
+ 30);
strcpy (buffer, "Reading register ");
strcat (buffer, REGISTER_NAME (regno));
perror_with_name (buffer);
}
if (regno == PC_REGNUM)
*(int *)buf = GET_PC_PART(*(int *)buf);
supply_register (regno, buf);
}
}
}
if (filename[0] == '/')
corefile = savestring (filename, strlen (filename));
else
{
corefile = concat (current_directory, "/", filename, NULL);
}
flush_cached_frames ();
select_frame (get_current_frame (), 0);
validate_files ();
}
else if (from_tty)
printf ("No core file now.\n");
}
#if 0
/* Work with core dump and executable files, for GDB.
This code would be in corefile.c if it weren't machine-dependent. */
/* Structure to describe the chain of shared libraries used
by the execfile.
e.g. prog shares Xt which shares X11 which shares c. */
struct shared_library {
struct exec_header header;
char name[SHLIBLEN];
CORE_ADDR text_start; /* CORE_ADDR of 1st byte of text, this file */
long data_offset; /* offset of data section in file */
int chan; /* file descriptor for the file */
struct shared_library *shares; /* library this one shares */
};
static struct shared_library *shlib = 0;
/* Hook for `exec_file_command' command to call. */
extern void (*exec_file_display_hook) ();
static CORE_ADDR unshared_text_start;
/* extended header from exec file (for shared library info) */
static struct exec_header exec_header;
void
exec_file_command (filename, from_tty)
char *filename;
int from_tty;
{
int val;
/* Eliminate all traces of old exec file.
Mark text segment as empty. */
if (execfile)
free (execfile);
execfile = 0;
data_start = 0;
data_end -= exec_data_start;
text_start = 0;
unshared_text_start = 0;
text_end = 0;
exec_data_start = 0;
exec_data_end = 0;
if (execchan >= 0)
close (execchan);
execchan = -1;
if (shlib) {
close_shared_library(shlib);
shlib = 0;
}
/* Now open and digest the file the user requested, if any. */
if (filename)
{
filename = tilde_expand (filename);
make_cleanup (free, filename);
execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
&execfile);
if (execchan < 0)
perror_with_name (filename);
{
struct stat st_exec;
#ifdef HEADER_SEEK_FD
HEADER_SEEK_FD (execchan);
#endif
val = myread (execchan, &exec_header, sizeof exec_header);
exec_aouthdr = exec_header.a_exec;
if (val < 0)
perror_with_name (filename);
text_start = 0x8000;
/* Look for shared library if needed */
if (exec_header.a_exec.a_magic & MF_USES_SL)
shlib = open_shared_library(exec_header.a_shlibname, text_start);
text_offset = N_TXTOFF (exec_aouthdr);
exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
if (shlib) {
unshared_text_start = shared_text_end(shlib) & ~0x7fff;
stack_start = shlib->header.a_exec.a_sldatabase;
stack_end = STACK_END_ADDR;
} else
unshared_text_start = 0x8000;
text_end = unshared_text_start + exec_aouthdr.a_text;
exec_data_start = unshared_text_start + exec_aouthdr.a_text;
exec_data_end = exec_data_start + exec_aouthdr.a_data;
data_start = exec_data_start;
data_end += exec_data_start;
fstat (execchan, &st_exec);
exec_mtime = st_exec.st_mtime;
}
validate_files ();
}
else if (from_tty)
printf ("No executable file now.\n");
/* Tell display code (if any) about the changed file name. */
if (exec_file_display_hook)
(*exec_file_display_hook) (filename);
}
#endif
#if 0
/* Read from the program's memory (except for inferior processes).
This function is misnamed, since it only reads, never writes; and
since it will use the core file and/or executable file as necessary.
It should be extended to write as well as read, FIXME, for patching files.
Return 0 if address could be read, EIO if addresss out of bounds. */
int
xfer_core_file (memaddr, myaddr, len)
CORE_ADDR memaddr;
char *myaddr;
int len;
{
register int i;
register int val;
int xferchan;
char **xferfile;
int fileptr;
int returnval = 0;
while (len > 0)
{
xferfile = 0;
xferchan = 0;
/* Determine which file the next bunch of addresses reside in,
and where in the file. Set the file's read/write pointer
to point at the proper place for the desired address
and set xferfile and xferchan for the correct file.
If desired address is nonexistent, leave them zero.
i is set to the number of bytes that can be handled
along with the next address.
We put the most likely tests first for efficiency. */
/* Note that if there is no core file
data_start and data_end are equal. */
if (memaddr >= data_start && memaddr < data_end)
{
i = min (len, data_end - memaddr);
fileptr = memaddr - data_start + data_offset;
xferfile = &corefile;
xferchan = corechan;
}
/* Note that if there is no core file
stack_start and stack_end define the shared library data. */
else if (memaddr >= stack_start && memaddr < stack_end)
{
if (corechan < 0) {
struct shared_library *lib;
for (lib = shlib; lib; lib = lib->shares)
if (memaddr >= lib->header.a_exec.a_sldatabase &&
memaddr < lib->header.a_exec.a_sldatabase +
lib->header.a_exec.a_data)
break;
if (lib) {
i = min (len, lib->header.a_exec.a_sldatabase +
lib->header.a_exec.a_data - memaddr);
fileptr = lib->data_offset + memaddr -
lib->header.a_exec.a_sldatabase;
xferfile = execfile;
xferchan = lib->chan;
}
} else {
i = min (len, stack_end - memaddr);
fileptr = memaddr - stack_start + stack_offset;
xferfile = &corefile;
xferchan = corechan;
}
}
else if (corechan < 0
&& memaddr >= exec_data_start && memaddr < exec_data_end)
{
i = min (len, exec_data_end - memaddr);
fileptr = memaddr - exec_data_start + exec_data_offset;
xferfile = &execfile;
xferchan = execchan;
}
else if (memaddr >= text_start && memaddr < text_end)
{
struct shared_library *lib;
for (lib = shlib; lib; lib = lib->shares)
if (memaddr >= lib->text_start &&
memaddr < lib->text_start + lib->header.a_exec.a_text)
break;
if (lib) {
i = min (len, lib->header.a_exec.a_text +
lib->text_start - memaddr);
fileptr = memaddr - lib->text_start + text_offset;
xferfile = &execfile;
xferchan = lib->chan;
} else {
i = min (len, text_end - memaddr);
fileptr = memaddr - unshared_text_start + text_offset;
xferfile = &execfile;
xferchan = execchan;
}
}
else if (memaddr < text_start)
{
i = min (len, text_start - memaddr);
}
else if (memaddr >= text_end
&& memaddr < (corechan >= 0? data_start : exec_data_start))
{
i = min (len, data_start - memaddr);
}
else if (corechan >= 0
&& memaddr >= data_end && memaddr < stack_start)
{
i = min (len, stack_start - memaddr);
}
else if (corechan < 0 && memaddr >= exec_data_end)
{
i = min (len, - memaddr);
}
else if (memaddr >= stack_end && stack_end != 0)
{
i = min (len, - memaddr);
}
else
{
/* Address did not classify into one of the known ranges.
This shouldn't happen; we catch the endpoints. */
fatal ("Internal: Bad case logic in xfer_core_file.");
}
/* Now we know which file to use.
Set up its pointer and transfer the data. */
if (xferfile)
{
if (*xferfile == 0)
if (xferfile == &execfile)
error ("No program file to examine.");
else
error ("No core dump file or running program to examine.");
val = lseek (xferchan, fileptr, 0);
if (val < 0)
perror_with_name (*xferfile);
val = myread (xferchan, myaddr, i);
if (val < 0)
perror_with_name (*xferfile);
}
/* If this address is for nonexistent memory,
read zeros if reading, or do nothing if writing.
Actually, we never right. */
else
{
memset (myaddr, '\0', i);
returnval = EIO;
}
memaddr += i;
myaddr += i;
len -= i;
}
return returnval;
}
#endif

1942
gdb/ax-gdb.c Normal file

File diff suppressed because it is too large Load Diff

111
gdb/ax-gdb.h Normal file
View File

@ -0,0 +1,111 @@
/* GDB-specific functions for operating on agent expressions
Copyright 1998 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* $Id$ */
#ifndef AX_GDB_H
#define AX_GDB_H
/* Types and enums */
/* GDB stores expressions in the form of a flattened tree (struct
expression), so we just walk that tree and generate agent bytecodes
as we go along.
GDB's normal evaluation uses struct value, which contains the
expression's value as well as its address or the register it came
from. The `+' operator uses the value, whereas the unary `&'
operator will use the address portion. The `=' operator will use
the address or register number of its left hand side.
The issues are different when generating agent bytecode. Given a
variable reference expression, we should not necessarily generate
code to fetch its value, because the next operator may be `=' or
unary `&'. Instead, when we recurse on a subexpression, we
indicate whether we want that expression to produce an lvalue or an
rvalue. If we requested an lvalue, then the recursive call tells
us whether it generated code to compute an address on the stack, or
whether the lvalue lives in a register.
The `axs' prefix here means `agent expression, static', because
this is all static analysis of the expression, i.e. analysis which
doesn't depend on the contents of memory and registers. */
/* Different kinds of agent expression static values. */
enum axs_lvalue_kind {
/* We generated code to compute the subexpression's value.
Constants and arithmetic operators yield this. */
axs_rvalue,
/* We generated code to yield the subexpression's value's address on
the top of the stack. If the caller needs an rvalue, it should
call require_rvalue to produce the rvalue from this address. */
axs_lvalue_memory,
/* We didn't generate any code, and the stack is undisturbed,
because the subexpression's value lives in a register; u.reg is
the register number. If the caller needs an rvalue, it should
call require_rvalue to produce the rvalue from this register
number. */
axs_lvalue_register
};
/* Structure describing what we got from a subexpression. Think of
this as parallel to value.h's enum lval_type, except that we're
describing a value which will exist when the expression is
evaluated in the future, not a value we have in our hand. */
struct axs_value {
enum axs_lvalue_kind kind; /* see above */
/* The type of the subexpression. Even if lvalue == axs_lvalue_memory,
this is the type of the value itself; the value on the stack is a
"pointer to" an object of this type. */
struct type *type;
union {
/* if kind == axs_lvalue_register, this is the register number */
int reg;
} u;
};
/* Translating GDB expressions into agent expressions. */
/* Given a GDB expression EXPR, translate it into the agent bytecode,
and return it. FLAGS are from enum expr_to_agent_flags. */
extern struct agent_expr *expr_to_agent PARAMS ((struct expression *EXPR,
struct axs_value *VALUE));
/* Given a GDB expression EXPR denoting an lvalue in memory, produce a
string of agent bytecode which will leave its address and size on
the top of stack. Return the agent expression. */
extern struct agent_expr *expr_to_address_and_size
PARAMS ((struct expression *EXPR));
/* Given a GDB expression EXPR, return bytecode to trace its value.
The result will use the `trace' and `trace_quick' bytecodes to
record the value of all memory touched by the expression, and leave
no values on the stack. The caller can then use the ax_reqs
function to discover which registers the expression uses. */
extern struct agent_expr *gen_trace_for_expr PARAMS ((CORE_ADDR,
struct expression *));
#endif /* AX_GDB_H */

552
gdb/ax-general.c Normal file
View File

@ -0,0 +1,552 @@
/* Functions for manipulating expressions designed to be executed on the agent
Copyright 1998 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* $Id$ */
/* Despite what the above comment says about this file being part of
GDB, we would like to keep these functions free of GDB
dependencies, since we want to be able to use them in contexts
outside of GDB (test suites, the stub, etc.) */
#include "defs.h"
#include "ax.h"
/* Functions for building expressions. */
/* Allocate a new, empty agent expression. */
struct agent_expr *
new_agent_expr (scope)
CORE_ADDR scope;
{
struct agent_expr *x = xmalloc (sizeof (*x));
x->len = 0;
x->size = 1; /* Change this to a larger value once
reallocation code is tested. */
x->buf = xmalloc (x->size);
x->scope = scope;
return x;
}
/* Free a agent expression. */
void
free_agent_expr (x)
struct agent_expr *x;
{
free (x->buf);
free (x);
}
/* Make sure that X has room for at least N more bytes. This doesn't
affect the length, just the allocated size. */
static void
grow_expr (x, n)
struct agent_expr *x;
int n;
{
if (x->len + n > x->size)
{
x->size *= 2;
if (x->size < x->len + n)
x->size = x->len + n + 10;
x->buf = xrealloc (x->buf, x->size);
}
}
/* Append the low N bytes of VAL as an N-byte integer to the
expression X, in big-endian order. */
static void
append_const (x, val, n)
struct agent_expr *x;
LONGEST val;
int n;
{
int i;
grow_expr (x, n);
for (i = n - 1; i >= 0; i--)
{
x->buf[x->len + i] = val & 0xff;
val >>= 8;
}
x->len += n;
}
/* Extract an N-byte big-endian unsigned integer from expression X at
offset O. */
static LONGEST
read_const (x, o, n)
struct agent_expr *x;
int o, n;
{
int i;
LONGEST accum = 0;
/* Make sure we're not reading off the end of the expression. */
if (o + n > x->len)
error ("GDB bug: ax-general.c (read_const): incomplete constant");
for (i = 0; i < n; i++)
accum = (accum << 8) | x->buf[o + i];
return accum;
}
/* Append a simple operator OP to EXPR. */
void
ax_simple (x, op)
struct agent_expr *x;
enum agent_op op;
{
grow_expr (x, 1);
x->buf[x->len++] = op;
}
/* Append a sign-extension or zero-extension instruction to EXPR, to
extend an N-bit value. */
static void
generic_ext (x, op, n)
struct agent_expr *x;
enum agent_op op;
int n;
{
/* N must fit in a byte. */
if (n < 0 || n > 255)
error ("GDB bug: ax-general.c (generic_ext): bit count out of range");
/* That had better be enough range. */
if (sizeof (LONGEST) * 8 > 255)
error ("GDB bug: ax-general.c (generic_ext): opcode has inadequate range");
grow_expr (x, 2);
x->buf[x->len++] = op;
x->buf[x->len++] = n;
}
/* Append a sign-extension instruction to EXPR, to extend an N-bit value. */
void
ax_ext (x, n)
struct agent_expr *x;
int n;
{
generic_ext (x, aop_ext, n);
}
/* Append a zero-extension instruction to EXPR, to extend an N-bit value. */
void
ax_zero_ext (x, n)
struct agent_expr *x;
int n;
{
generic_ext (x, aop_zero_ext, n);
}
/* Append a trace_quick instruction to EXPR, to record N bytes. */
void
ax_trace_quick (x, n)
struct agent_expr *x;
int n;
{
/* N must fit in a byte. */
if (n < 0 || n > 255)
error ("GDB bug: ax-general.c (ax_trace_quick): size out of range for trace_quick");
grow_expr (x, 2);
x->buf[x->len++] = aop_trace_quick;
x->buf[x->len++] = n;
}
/* Append a goto op to EXPR. OP is the actual op (must be aop_goto or
aop_if_goto). We assume we don't know the target offset yet,
because it's probably a forward branch, so we leave space in EXPR
for the target, and return the offset in EXPR of that space, so we
can backpatch it once we do know the target offset. Use ax_label
to do the backpatching. */
int ax_goto (x, op)
struct agent_expr *x;
enum agent_op op;
{
grow_expr (x, 3);
x->buf[x->len + 0] = op;
x->buf[x->len + 1] = 0xff;
x->buf[x->len + 2] = 0xff;
x->len += 3;
return x->len - 2;
}
/* Suppose a given call to ax_goto returns some value PATCH. When you
know the offset TARGET that goto should jump to, call
ax_label (EXPR, PATCH, TARGET)
to patch TARGET into the ax_goto instruction. */
void
ax_label (x, patch, target)
struct agent_expr *x;
int patch;
int target;
{
/* Make sure the value is in range. Don't accept 0xffff as an
offset; that's our magic sentinel value for unpatched branches. */
if (target < 0 || target >= 0xffff)
error ("GDB bug: ax-general.c (ax_label): label target out of range");
x->buf[patch] = (target >> 8) & 0xff;
x->buf[patch + 1] = target & 0xff;
}
/* Assemble code to push a constant on the stack. */
void
ax_const_l (x, l)
struct agent_expr *x;
LONGEST l;
{
static enum agent_op ops[]
= { aop_const8, aop_const16, aop_const32, aop_const64 };
int size;
int op;
/* How big is the number? 'op' keeps track of which opcode to use.
Notice that we don't really care whether the original number was
signed or unsigned; we always reproduce the value exactly, and
use the shortest representation. */
for (op = 0, size = 8; size < 64; size *= 2, op++)
if (-((LONGEST) 1 << size) <= l && l < ((LONGEST) 1 << size))
break;
/* Emit the right opcode... */
ax_simple (x, ops[op]);
/* Emit the low SIZE bytes as an unsigned number. We know that
sign-extending this will yield l. */
append_const (x, l, size / 8);
/* Now, if it was negative, and not full-sized, sign-extend it. */
if (l < 0 && size < 64)
ax_ext (x, size);
}
void
ax_const_d (x, d)
struct agent_expr *x;
LONGEST d;
{
/* FIXME: floating-point support not present yet. */
error ("GDB bug: ax-general.c (ax_const_d): floating point not supported yet");
}
/* Assemble code to push the value of register number REG on the
stack. */
void ax_reg (x, reg)
struct agent_expr *x;
int reg;
{
/* Make sure the register number is in range. */
if (reg < 0 || reg > 0xffff)
error ("GDB bug: ax-general.c (ax_reg): register number out of range");
grow_expr (x, 3);
x->buf[x->len ] = aop_reg;
x->buf[x->len + 1] = (reg >> 8) & 0xff;
x->buf[x->len + 2] = (reg ) & 0xff;
x->len += 3;
}
/* Functions for disassembling agent expressions, and otherwise
debugging the expression compiler. */
struct aop_map aop_map[] = {
{ 0, 0, 0, 0, 0 },
{ "float", 0, 0, 0, 0 }, /* 0x01 */
{ "add", 0, 0, 2, 1 }, /* 0x02 */
{ "sub", 0, 0, 2, 1 }, /* 0x03 */
{ "mul", 0, 0, 2, 1 }, /* 0x04 */
{ "div_signed", 0, 0, 2, 1 }, /* 0x05 */
{ "div_unsigned", 0, 0, 2, 1 }, /* 0x06 */
{ "rem_signed", 0, 0, 2, 1 }, /* 0x07 */
{ "rem_unsigned", 0, 0, 2, 1 }, /* 0x08 */
{ "lsh", 0, 0, 2, 1 }, /* 0x09 */
{ "rsh_signed", 0, 0, 2, 1 }, /* 0x0a */
{ "rsh_unsigned", 0, 0, 2, 1 }, /* 0x0b */
{ "trace", 0, 0, 2, 0 }, /* 0x0c */
{ "trace_quick", 1, 0, 1, 1 }, /* 0x0d */
{ "log_not", 0, 0, 1, 1 }, /* 0x0e */
{ "bit_and", 0, 0, 2, 1 }, /* 0x0f */
{ "bit_or", 0, 0, 2, 1 }, /* 0x10 */
{ "bit_xor", 0, 0, 2, 1 }, /* 0x11 */
{ "bit_not", 0, 0, 1, 1 }, /* 0x12 */
{ "equal", 0, 0, 2, 1 }, /* 0x13 */
{ "less_signed", 0, 0, 2, 1 }, /* 0x14 */
{ "less_unsigned", 0, 0, 2, 1 }, /* 0x15 */
{ "ext", 1, 0, 1, 1 }, /* 0x16 */
{ "ref8", 0, 8, 1, 1 }, /* 0x17 */
{ "ref16", 0, 16, 1, 1 }, /* 0x18 */
{ "ref32", 0, 32, 1, 1 }, /* 0x19 */
{ "ref64", 0, 64, 1, 1 }, /* 0x1a */
{ "ref_float", 0, 0, 1, 1 }, /* 0x1b */
{ "ref_double", 0, 0, 1, 1 }, /* 0x1c */
{ "ref_long_double", 0, 0, 1, 1 }, /* 0x1d */
{ "l_to_d", 0, 0, 1, 1 }, /* 0x1e */
{ "d_to_l", 0, 0, 1, 1 }, /* 0x1f */
{ "if_goto", 2, 0, 1, 0 }, /* 0x20 */
{ "goto", 2, 0, 0, 0 }, /* 0x21 */
{ "const8", 1, 8, 0, 1 }, /* 0x22 */
{ "const16", 2, 16, 0, 1 }, /* 0x23 */
{ "const32", 4, 32, 0, 1 }, /* 0x24 */
{ "const64", 8, 64, 0, 1 }, /* 0x25 */
{ "reg", 2, 0, 0, 1 }, /* 0x26 */
{ "end", 0, 0, 0, 0 }, /* 0x27 */
{ "dup", 0, 0, 1, 2 }, /* 0x28 */
{ "pop", 0, 0, 1, 0 }, /* 0x29 */
{ "zero_ext", 1, 0, 1, 1 }, /* 0x2a */
{ "swap", 0, 0, 2, 2 }, /* 0x2b */
{ 0, 0, 0, 0, 0 }, /* 0x2c */
{ 0, 0, 0, 0, 0 }, /* 0x2d */
{ 0, 0, 0, 0, 0 }, /* 0x2e */
{ 0, 0, 0, 0, 0 }, /* 0x2f */
{ "trace16", 2, 0, 1, 1 }, /* 0x30 */
};
/* Disassemble the expression EXPR, writing to F. */
void
ax_print (f, x)
GDB_FILE *f;
struct agent_expr *x;
{
int i;
int is_float = 0;
/* Check the size of the name array against the number of entries in
the enum, to catch additions that people didn't sync. */
if ((sizeof (aop_map) / sizeof (aop_map[0]))
!= aop_last)
error ("GDB bug: ax-general.c (ax_print): opcode map out of sync");
for (i = 0; i < x->len; )
{
enum agent_op op = x->buf[i];
if (op >= (sizeof (aop_map) / sizeof (aop_map[0]))
|| ! aop_map[op].name)
{
fprintf_filtered (f, "%3d <bad opcode %02x>\n", i, op);
i++;
continue;
}
if (i + 1 + aop_map[op].op_size > x->len)
{
fprintf_filtered (f, "%3d <incomplete opcode %s>\n",
i, aop_map[op].name);
break;
}
fprintf_filtered (f, "%3d %s", i, aop_map[op].name);
if (aop_map[op].op_size > 0)
{
fputs_filtered (" ", f);
print_longest (f, 'd', 0,
read_const (x, i + 1, aop_map[op].op_size));
}
fprintf_filtered (f, "\n");
i += 1 + aop_map[op].op_size;
is_float = (op == aop_float);
}
}
/* Given an agent expression AX, fill in an agent_reqs structure REQS
describing it. */
void
ax_reqs (ax, reqs)
struct agent_expr *ax;
struct agent_reqs *reqs;
{
int i;
int height;
/* Bit vector for registers used. */
int reg_mask_len = 1;
unsigned char *reg_mask = xmalloc (reg_mask_len * sizeof (reg_mask[0]));
/* Jump target table. targets[i] is non-zero iff there is a jump to
offset i. */
char *targets = (char *) alloca (ax->len * sizeof (targets[0]));
/* Instruction boundary table. boundary[i] is non-zero iff an
instruction starts at offset i. */
char *boundary = (char *) alloca (ax->len * sizeof (boundary[0]));
/* Stack height record. iff either targets[i] or boundary[i] is
non-zero, heights[i] is the height the stack should have before
executing the bytecode at that point. */
int *heights = (int *) alloca (ax->len * sizeof (heights[0]));
/* Pointer to a description of the present op. */
struct aop_map *op;
memset (reg_mask, 0, reg_mask_len * sizeof (reg_mask[0]));
memset (targets, 0, ax->len * sizeof (targets[0]));
memset (boundary, 0, ax->len * sizeof (boundary[0]));
reqs->max_height = reqs->min_height = height = 0;
reqs->flaw = agent_flaw_none;
reqs->max_data_size = 0;
for (i = 0; i < ax->len; i += 1 + op->op_size)
{
if (ax->buf[i] > (sizeof (aop_map) / sizeof (aop_map[0])))
{
reqs->flaw = agent_flaw_bad_instruction;
free (reg_mask);
return;
}
op = &aop_map[ax->buf[i]];
if (! op->name)
{
reqs->flaw = agent_flaw_bad_instruction;
free (reg_mask);
return;
}
if (i + 1 + op->op_size > ax->len)
{
reqs->flaw = agent_flaw_incomplete_instruction;
free (reg_mask);
return;
}
/* If this instruction is a jump target, does the current stack
height match the stack height at the jump source? */
if (targets[i] && (heights[i] != height))
{
reqs->flaw = agent_flaw_height_mismatch;
free (reg_mask);
return;
}
boundary[i] = 1;
heights[i] = height;
height -= op->consumed;
if (height < reqs->min_height)
reqs->min_height = height;
height += op->produced;
if (height > reqs->max_height)
reqs->max_height = height;
if (op->data_size > reqs->max_data_size)
reqs->max_data_size = op->data_size;
/* For jump instructions, check that the target is a valid
offset. If it is, record the fact that that location is a
jump target, and record the height we expect there. */
if (aop_goto == op - aop_map
|| aop_if_goto == op - aop_map)
{
int target = read_const (ax, i + 1, 2);
if (target < 0 || target >= ax->len)
{
reqs->flaw = agent_flaw_bad_jump;
free (reg_mask);
return;
}
/* Have we already found other jumps to the same location? */
else if (targets[target])
{
if (heights[i] != height)
{
reqs->flaw = agent_flaw_height_mismatch;
free (reg_mask);
return;
}
}
else
{
targets[target] = 1;
heights[target] = height;
}
}
/* For unconditional jumps with a successor, check that the
successor is a target, and pick up its stack height. */
if (aop_goto == op - aop_map
&& i + 3 < ax->len)
{
if (! targets[i + 3])
{
reqs->flaw = agent_flaw_hole;
free (reg_mask);
return;
}
height = heights[i + 3];
}
/* For reg instructions, record the register in the bit mask. */
if (aop_reg == op - aop_map)
{
int reg = read_const (ax, i + 1, 2);
int byte = reg / 8;
/* Grow the bit mask if necessary. */
if (byte >= reg_mask_len)
{
/* It's not appropriate to double here. This isn't a
string buffer. */
int new_len = byte + 1;
reg_mask = xrealloc (reg_mask,
new_len * sizeof (reg_mask[0]));
memset (reg_mask + reg_mask_len, 0,
(new_len - reg_mask_len) * sizeof (reg_mask[0]));
reg_mask_len = new_len;
}
reg_mask[byte] |= 1 << (reg % 8);
}
}
/* Check that all the targets are on boundaries. */
for (i = 0; i < ax->len; i++)
if (targets[i] && !boundary[i])
{
reqs->flaw = agent_flaw_bad_jump;
free (reg_mask);
return;
}
reqs->final_height = height;
reqs->reg_mask_len = reg_mask_len;
reqs->reg_mask = reg_mask;
}

285
gdb/ax.h Normal file
View File

@ -0,0 +1,285 @@
/* Definitions for expressions designed to be executed on the agent
Copyright 1998 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* $Id$ */
#ifndef AGENTEXPR_H
#define AGENTEXPR_H
/* It's sometimes useful to be able to debug programs that you can't
really stop for more than a fraction of a second. To this end, the
user can specify a tracepoint (like a breakpoint, but you don't
stop at it), and specify a bunch of expressions to record the
values of when that tracepoint is reached. As the program runs,
GDB collects the values. At any point (possibly while values are
still being collected), the user can display the collected values.
This is used with remote debugging; we don't really support it on
native configurations.
This means that expressions are being evaluated by the remote agent,
which doesn't have any access to the symbol table information, and
needs to be small and simple.
The agent_expr routines and datatypes are a bytecode language
designed to be executed by the agent. Agent expressions work in
terms of fixed-width values, operators, memory references, and
register references. You can evaluate a agent expression just given
a bunch of memory and register values to sniff at; you don't need
any symbolic information like variable names, types, etc.
GDB translates source expressions, whose meaning depends on
symbolic information, into agent bytecode expressions, whose meaning
is independent of symbolic information. This means the agent can
evaluate them on the fly without reference to data only available
to the host GDB. */
/* Agent expression data structures. */
/* The type of an element of the agent expression stack.
The bytecode operation indicates which element we should access;
the value itself has no typing information. GDB generates all
bytecode streams, so we don't have to worry about type errors. */
union agent_val {
LONGEST l;
DOUBLEST d;
};
/* A buffer containing a agent expression. */
struct agent_expr {
unsigned char *buf;
int len; /* number of characters used */
int size; /* allocated size */
CORE_ADDR scope;
};
/* The actual values of the various bytecode operations.
Other independent implementations of the agent bytecode engine will
rely on the exact values of these enums, and may not be recompiled
when we change this table. The numeric values should remain fixed
whenever possible. Thus, we assign them values explicitly here (to
allow gaps to form safely), and the disassembly table in
agentexpr.h behaves like an opcode map. If you want to see them
grouped logically, see doc/agentexpr.texi. */
enum agent_op {
aop_float = 0x01,
aop_add = 0x02,
aop_sub = 0x03,
aop_mul = 0x04,
aop_div_signed = 0x05,
aop_div_unsigned = 0x06,
aop_rem_signed = 0x07,
aop_rem_unsigned = 0x08,
aop_lsh = 0x09,
aop_rsh_signed = 0x0a,
aop_rsh_unsigned = 0x0b,
aop_trace = 0x0c,
aop_trace_quick = 0x0d,
aop_log_not = 0x0e,
aop_bit_and = 0x0f,
aop_bit_or = 0x10,
aop_bit_xor = 0x11,
aop_bit_not = 0x12,
aop_equal = 0x13,
aop_less_signed = 0x14,
aop_less_unsigned = 0x15,
aop_ext = 0x16,
aop_ref8 = 0x17,
aop_ref16 = 0x18,
aop_ref32 = 0x19,
aop_ref64 = 0x1a,
aop_ref_float = 0x1b,
aop_ref_double = 0x1c,
aop_ref_long_double = 0x1d,
aop_l_to_d = 0x1e,
aop_d_to_l = 0x1f,
aop_if_goto = 0x20,
aop_goto = 0x21,
aop_const8 = 0x22,
aop_const16 = 0x23,
aop_const32 = 0x24,
aop_const64 = 0x25,
aop_reg = 0x26,
aop_end = 0x27,
aop_dup = 0x28,
aop_pop = 0x29,
aop_zero_ext = 0x2a,
aop_swap = 0x2b,
aop_trace16 = 0x30,
aop_last
};
/* Functions for building expressions. */
/* Allocate a new, empty agent expression. */
extern struct agent_expr *new_agent_expr PARAMS ((CORE_ADDR));
/* Free a agent expression. */
extern void free_agent_expr PARAMS ((struct agent_expr *));
/* Append a simple operator OP to EXPR. */
extern void ax_simple PARAMS ((struct agent_expr *EXPR, enum agent_op OP));
/* Append the floating-point prefix, for the next bytecode. */
#define ax_float(EXPR) (ax_simple ((EXPR), aop_float))
/* Append a sign-extension instruction to EXPR, to extend an N-bit value. */
extern void ax_ext PARAMS ((struct agent_expr *EXPR, int N));
/* Append a zero-extension instruction to EXPR, to extend an N-bit value. */
extern void ax_zero_ext PARAMS ((struct agent_expr *EXPR, int N));
/* Append a trace_quick instruction to EXPR, to record N bytes. */
extern void ax_trace_quick PARAMS ((struct agent_expr *EXPR, int N));
/* Append a goto op to EXPR. OP is the actual op (must be aop_goto or
aop_if_goto). We assume we don't know the target offset yet,
because it's probably a forward branch, so we leave space in EXPR
for the target, and return the offset in EXPR of that space, so we
can backpatch it once we do know the target offset. Use ax_label
to do the backpatching. */
extern int ax_goto PARAMS ((struct agent_expr *EXPR, enum agent_op OP));
/* Suppose a given call to ax_goto returns some value PATCH. When you
know the offset TARGET that goto should jump to, call
ax_label (EXPR, PATCH, TARGET)
to patch TARGET into the ax_goto instruction. */
extern void ax_label PARAMS ((struct agent_expr *EXPR, int patch, int target));
/* Assemble code to push a constant on the stack. */
extern void ax_const_l PARAMS ((struct agent_expr *EXPR, LONGEST l));
extern void ax_const_d PARAMS ((struct agent_expr *EXPR, LONGEST d));
/* Assemble code to push the value of register number REG on the
stack. */
extern void ax_reg PARAMS ((struct agent_expr *EXPR, int REG));
/* Functions for printing out expressions, and otherwise debugging
things. */
/* Disassemble the expression EXPR, writing to F. */
extern void ax_print PARAMS ((GDB_FILE *f, struct agent_expr *EXPR));
/* An entry in the opcode map. */
struct aop_map {
/* The name of the opcode. Null means that this entry is not a
valid opcode --- a hole in the opcode space. */
char *name;
/* All opcodes take no operands from the bytecode stream, or take
unsigned integers of various sizes. If this is a positive number
n, then the opcode is followed by an n-byte operand, which should
be printed as an unsigned integer. If this is zero, then the
opcode takes no operands from the bytecode stream.
If we get more complicated opcodes in the future, don't add other
magic values of this; that's a crock. Add an `enum encoding'
field to this, or something like that. */
int op_size;
/* The size of the data operated upon, in bits, for bytecodes that
care about that (ref and const). Zero for all others. */
int data_size;
/* Number of stack elements consumed, and number produced. */
int consumed, produced;
};
/* Map of the bytecodes, indexed by bytecode number. */
extern struct aop_map aop_map[];
/* Different kinds of flaws an agent expression might have, as
detected by agent_reqs. */
enum agent_flaws {
agent_flaw_none = 0, /* code is good */
/* There is an invalid instruction in the stream. */
agent_flaw_bad_instruction,
/* There is an incomplete instruction at the end of the expression. */
agent_flaw_incomplete_instruction,
/* agent_reqs was unable to prove that every jump target is to a
valid offset. Valid offsets are within the bounds of the
expression, and to a valid instruction boundary. */
agent_flaw_bad_jump,
/* agent_reqs was unable to prove to its satisfaction that, for each
jump target location, the stack will have the same height whether
that location is reached via a jump or by straight execution. */
agent_flaw_height_mismatch,
/* agent_reqs was unable to prove that every instruction following
an unconditional jump was the target of some other jump. */
agent_flaw_hole
};
/* Structure describing the requirements of a bytecode expression. */
struct agent_reqs {
/* If the following is not equal to agent_flaw_none, the rest of the
information in this structure is suspect. */
enum agent_flaws flaw;
/* Number of elements left on stack at end; may be negative if expr
only consumes elements. */
int final_height;
/* Maximum and minimum stack height, relative to initial height. */
int max_height, min_height;
/* Largest `ref' or `const' opcode used, in bits. Zero means the
expression has no such instructions. */
int max_data_size;
/* Bit vector of registers used. Register R is used iff
reg_mask[R / 8] & (1 << (R % 8))
is non-zero. Note! You may not assume that this bitmask is long
enough to hold bits for all the registers of the machine; the
agent expression code has no idea how many registers the machine
has. However, the bitmask is reg_mask_len bytes long, so the
valid register numbers run from 0 to reg_mask_len * 8 - 1.
We're assuming eight-bit bytes. So sue me.
The caller should free reg_list when done. */
int reg_mask_len;
unsigned char *reg_mask;
};
/* Given an agent expression AX, fill in an agent_reqs structure REQS
describing it. */
extern void ax_reqs PARAMS ((struct agent_expr *ax,
struct agent_reqs *reqs));
#endif /* AGENTEXPR_H */

219
gdb/bcache.c Normal file
View File

@ -0,0 +1,219 @@
/* Implement a cached obstack.
Written by Fred Fish (fnf@cygnus.com)
Copyright 1995, 1998 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "obstack.h"
#include "bcache.h"
#include "gdb_string.h" /* For memcpy declaration */
/* Prototypes for local functions. */
static unsigned int hash PARAMS ((void *, int));
static void *lookup_cache PARAMS ((void *, int, int, struct bcache *));
/* FIXME: Incredibly simplistic hash generator. Probably way too expensive
(consider long strings) and unlikely to have good distribution across hash
values for typical input. */
static unsigned int
hash (bytes, count)
void *bytes;
int count;
{
unsigned int len;
unsigned long hashval;
unsigned int c;
const unsigned char *data = bytes;
hashval = 0;
len = 0;
while (count-- > 0)
{
c = *data++;
hashval += c + (c << 17);
hashval ^= hashval >> 2;
++len;
}
hashval += len + (len << 17);
hashval ^= hashval >> 2;
return (hashval % BCACHE_HASHSIZE);
}
static void *
lookup_cache (bytes, count, hashval, bcachep)
void *bytes;
int count;
int hashval;
struct bcache *bcachep;
{
void *location = NULL;
struct hashlink **hashtablep;
struct hashlink *linkp;
hashtablep = bcachep -> indextable[count];
if (hashtablep != NULL)
{
linkp = hashtablep[hashval];
while (linkp != NULL)
{
if (memcmp (BCACHE_DATA (linkp), bytes, count) == 0)
{
location = BCACHE_DATA (linkp);
break;
}
linkp = linkp -> next;
}
}
return (location);
}
void *
bcache (bytes, count, bcachep)
void *bytes;
int count;
struct bcache *bcachep;
{
int hashval;
void *location;
struct hashlink *newlink;
struct hashlink **linkpp;
struct hashlink ***hashtablepp;
if (count >= BCACHE_MAXLENGTH)
{
/* Rare enough to just stash unique copies */
location = (void *) obstack_alloc (&bcachep->cache, count);
bcachep -> cache_bytes += count;
memcpy (location, bytes, count);
bcachep -> bcache_overflows++;
}
else
{
hashval = hash (bytes, count);
location = lookup_cache (bytes, count, hashval, bcachep);
if (location != NULL)
{
bcachep -> cache_savings += count;
bcachep -> cache_hits++;
}
else
{
bcachep -> cache_misses++;
hashtablepp = &bcachep -> indextable[count];
if (*hashtablepp == NULL)
{
*hashtablepp = (struct hashlink **)
obstack_alloc (&bcachep->cache, BCACHE_HASHSIZE * sizeof (struct hashlink *));
bcachep -> cache_bytes += BCACHE_HASHSIZE * sizeof (struct hashlink *);
memset (*hashtablepp, 0, BCACHE_HASHSIZE * sizeof (struct hashlink *));
}
linkpp = &(*hashtablepp)[hashval];
newlink = (struct hashlink *)
obstack_alloc (&bcachep->cache, BCACHE_DATA_ALIGNMENT + count);
bcachep -> cache_bytes += BCACHE_DATA_ALIGNMENT + count;
memcpy (BCACHE_DATA (newlink), bytes, count);
newlink -> next = *linkpp;
*linkpp = newlink;
location = BCACHE_DATA (newlink);
}
}
return (location);
}
#if MAINTENANCE_CMDS
void
print_bcache_statistics (bcachep, id)
struct bcache *bcachep;
char *id;
{
struct hashlink **hashtablep;
struct hashlink *linkp;
int tidx, tcount, hidx, hcount, lcount, lmax, temp, lmaxt, lmaxh;
for (lmax = lcount = tcount = hcount = tidx = 0; tidx < BCACHE_MAXLENGTH; tidx++)
{
hashtablep = bcachep -> indextable[tidx];
if (hashtablep != NULL)
{
tcount++;
for (hidx = 0; hidx < BCACHE_HASHSIZE; hidx++)
{
linkp = hashtablep[hidx];
if (linkp != NULL)
{
hcount++;
for (temp = 0; linkp != NULL; linkp = linkp -> next)
{
lcount++;
temp++;
}
if (temp > lmax)
{
lmax = temp;
lmaxt = tidx;
lmaxh = hidx;
}
}
}
}
}
printf_filtered (" Cached '%s' statistics:\n", id);
printf_filtered (" Cache hits: %d\n", bcachep -> cache_hits);
printf_filtered (" Cache misses: %d\n", bcachep -> cache_misses);
printf_filtered (" Cache hit ratio: ");
if (bcachep -> cache_hits + bcachep -> cache_misses > 0)
{
printf_filtered ("%d%%\n", ((bcachep -> cache_hits) * 100) /
(bcachep -> cache_hits + bcachep -> cache_misses));
}
else
{
printf_filtered ("(not applicable)\n");
}
printf_filtered (" Space used for caching: %d\n", bcachep -> cache_bytes);
printf_filtered (" Space saved by cache hits: %d\n", bcachep -> cache_savings);
printf_filtered (" Number of bcache overflows: %d\n", bcachep -> bcache_overflows);
printf_filtered (" Number of index buckets used: %d\n", tcount);
printf_filtered (" Number of hash table buckets used: %d\n", hcount);
printf_filtered (" Number of chained items: %d\n", lcount);
printf_filtered (" Average hash table population: ");
if (tcount > 0)
{
printf_filtered ("%d%%\n", (hcount * 100) / (tcount * BCACHE_HASHSIZE));
}
else
{
printf_filtered ("(not applicable)\n");
}
printf_filtered (" Average chain length ");
if (hcount > 0)
{
printf_filtered ("%d\n", lcount / hcount);
}
else
{
printf_filtered ("(not applicable)\n");
}
printf_filtered (" Maximum chain length %d at %d:%d\n", lmax, lmaxt, lmaxh);
}
#endif /* MAINTENANCE_CMDS */

72
gdb/bcache.h Normal file
View File

@ -0,0 +1,72 @@
/* Include file cached obstack implementation.
Written by Fred Fish (fnf@cygnus.com)
Copyright 1995 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef BCACHE_H
#define BCACHE_H 1
#define BCACHE_HASHLENGTH 12 /* Number of bits in hash value */
#define BCACHE_HASHSIZE (1 << BCACHE_HASHLENGTH)
#define BCACHE_MAXLENGTH 128
/* Note that the user data is stored in data[]. Since it can be any type,
it needs to have the same alignment as the most strict alignment of
any type on the host machine. So do it the same way obstack does. */
struct hashlink {
struct hashlink *next;
union {
char data[1];
double dummy;
} d;
};
/* BCACHE_DATA is used to get the address of the cached data. */
#define BCACHE_DATA(p) ((p)->d.data)
/* BCACHE_DATA_ALIGNMENT is used to get the offset of the start of
cached data within the hashlink struct. This value, plus the
size of the cached data, is the amount of space to allocate for
a hashlink struct to hold the next pointer and the data. */
#define BCACHE_DATA_ALIGNMENT \
(((char *) BCACHE_DATA((struct hashlink*) 0) - (char *) 0))
struct bcache {
struct obstack cache;
struct hashlink **indextable[BCACHE_MAXLENGTH];
int cache_hits;
int cache_misses;
int cache_bytes;
int cache_savings;
int bcache_overflows;
};
extern void *
bcache PARAMS ((void *bytes, int count, struct bcache *bcachep));
#if MAINTENANCE_CMDS
extern void
print_bcache_statistics PARAMS ((struct bcache *, char *));
#endif /* MAINTENANCE_CMDS */
#endif /* BCACHE_H */

1301
gdb/blockframe.c Normal file

File diff suppressed because it is too large Load Diff

6686
gdb/breakpoint.c Normal file

File diff suppressed because it is too large Load Diff

604
gdb/breakpoint.h Normal file
View File

@ -0,0 +1,604 @@
/* Data structures associated with breakpoints in GDB.
Copyright (C) 1992, 93, 94, 95, 96, 98, 1999 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if !defined (BREAKPOINT_H)
#define BREAKPOINT_H 1
#include "frame.h"
#include "value.h"
/* This is the maximum number of bytes a breakpoint instruction can take.
Feel free to increase it. It's just used in a few places to size
arrays that should be independent of the target architecture. */
#define BREAKPOINT_MAX 16
/* Type of breakpoint. */
/* FIXME In the future, we should fold all other breakpoint-like things into
here. This includes:
* single-step (for machines where we have to simulate single stepping)
(probably, though perhaps it is better for it to look as much as
possible like a single-step to wait_for_inferior). */
enum bptype {
bp_none = 0, /* Eventpoint has been deleted. */
bp_breakpoint, /* Normal breakpoint */
bp_hardware_breakpoint, /* Hardware assisted breakpoint */
bp_until, /* used by until command */
bp_finish, /* used by finish command */
bp_watchpoint, /* Watchpoint */
bp_hardware_watchpoint, /* Hardware assisted watchpoint */
bp_read_watchpoint, /* read watchpoint, (hardware assisted) */
bp_access_watchpoint, /* access watchpoint, (hardware assisted) */
bp_longjmp, /* secret breakpoint to find longjmp() */
bp_longjmp_resume, /* secret breakpoint to escape longjmp() */
/* Used by wait_for_inferior for stepping over subroutine calls, for
stepping over signal handlers, and for skipping prologues. */
bp_step_resume,
/* Used by wait_for_inferior for stepping over signal handlers. */
bp_through_sigtramp,
/* Used to detect when a watchpoint expression has gone out of
scope. These breakpoints are usually not visible to the user.
This breakpoint has some interesting properties:
1) There's always a 1:1 mapping between watchpoints
on local variables and watchpoint_scope breakpoints.
2) It automatically deletes itself and the watchpoint it's
associated with when hit.
3) It can never be disabled. */
bp_watchpoint_scope,
/* The breakpoint at the end of a call dummy. */
/* FIXME: What if the function we are calling longjmp()s out of the
call, or the user gets out with the "return" command? We currently
have no way of cleaning up the breakpoint in these (obscure) situations.
(Probably can solve this by noticing longjmp, "return", etc., it's
similar to noticing when a watchpoint on a local variable goes out
of scope (with hardware support for watchpoints)). */
bp_call_dummy,
/* Some dynamic linkers (HP, maybe Solaris) can arrange for special
code in the inferior to run when significant events occur in the
dynamic linker (for example a library is loaded or unloaded).
By placing a breakpoint in this magic code GDB will get control
when these significant events occur. GDB can then re-examine
the dynamic linker's data structures to discover any newly loaded
dynamic libraries. */
bp_shlib_event,
/* These breakpoints are used to implement the "catch load" command
on platforms whose dynamic linkers support such functionality. */
bp_catch_load,
/* These breakpoints are used to implement the "catch unload" command
on platforms whose dynamic linkers support such functionality. */
bp_catch_unload,
/* These are not really breakpoints, but are catchpoints that
implement the "catch fork", "catch vfork" and "catch exec" commands
on platforms whose kernel support such functionality. (I.e.,
kernels which can raise an event when a fork or exec occurs, as
opposed to the debugger setting breakpoints on functions named
"fork" or "exec".) */
bp_catch_fork,
bp_catch_vfork,
bp_catch_exec,
/* These are catchpoints to implement "catch catch" and "catch throw"
commands for C++ exception handling. */
bp_catch_catch,
bp_catch_throw
};
/* States of enablement of breakpoint. */
enum enable {
disabled, /* The eventpoint is inactive, and cannot trigger. */
enabled, /* The eventpoint is active, and can trigger. */
shlib_disabled, /* The eventpoint's address is within an unloaded solib.
The eventpoint will be automatically enabled & reset
when that solib is loaded. */
call_disabled /* The eventpoint has been disabled while a call into
the inferior is "in flight", because some eventpoints
interfere with the implementation of a call on some
targets. The eventpoint will be automatically enabled
& reset when the call "lands" (either completes, or
stops at another eventpoint). */
};
/* Disposition of breakpoint. Ie: what to do after hitting it. */
enum bpdisp {
del, /* Delete it */
del_at_next_stop, /* Delete at next stop, whether hit or not */
disable, /* Disable it */
donttouch /* Leave it alone */
};
/* Note that the ->silent field is not currently used by any commands
(though the code is in there if it was to be, and set_raw_breakpoint
does set it to 0). I implemented it because I thought it would be
useful for a hack I had to put in; I'm going to leave it in because
I can see how there might be times when it would indeed be useful */
/* This is for a breakpoint or a watchpoint. */
struct breakpoint
{
struct breakpoint *next;
/* Type of breakpoint. */
enum bptype type;
/* Zero means disabled; remember the info but don't break here. */
enum enable enable;
/* What to do with this breakpoint after we hit it. */
enum bpdisp disposition;
/* Number assigned to distinguish breakpoints. */
int number;
/* Address to break at, or NULL if not a breakpoint. */
CORE_ADDR address;
/* Line number of this address. Only matters if address is
non-NULL. */
int line_number;
/* Source file name of this address. Only matters if address is
non-NULL. */
char *source_file;
/* Non-zero means a silent breakpoint (don't print frame info
if we stop here). */
unsigned char silent;
/* Number of stops at this breakpoint that should
be continued automatically before really stopping. */
int ignore_count;
/* "Real" contents of byte where breakpoint has been inserted.
Valid only when breakpoints are in the program. Under the complete
control of the target insert_breakpoint and remove_breakpoint routines.
No other code should assume anything about the value(s) here. */
char shadow_contents[BREAKPOINT_MAX];
/* Nonzero if this breakpoint is now inserted. Only matters if address
is non-NULL. */
char inserted;
/* Nonzero if this is not the first breakpoint in the list
for the given address. Only matters if address is non-NULL. */
char duplicate;
/* Chain of command lines to execute when this breakpoint is hit. */
struct command_line *commands;
/* Stack depth (address of frame). If nonzero, break only if fp
equals this. */
CORE_ADDR frame;
/* Conditional. Break only if this expression's value is nonzero. */
struct expression *cond;
/* String we used to set the breakpoint (malloc'd). Only matters if
address is non-NULL. */
char *addr_string;
/* Language we used to set the breakpoint. */
enum language language;
/* Input radix we used to set the breakpoint. */
int input_radix;
/* String form of the breakpoint condition (malloc'd), or NULL if there
is no condition. */
char *cond_string;
/* String form of exp (malloc'd), or NULL if none. */
char *exp_string;
/* The expression we are watching, or NULL if not a watchpoint. */
struct expression *exp;
/* The largest block within which it is valid, or NULL if it is
valid anywhere (e.g. consists just of global symbols). */
struct block *exp_valid_block;
/* Value of the watchpoint the last time we checked it. */
value_ptr val;
/* Holds the value chain for a hardware watchpoint expression. */
value_ptr val_chain;
/* Holds the address of the related watchpoint_scope breakpoint
when using watchpoints on local variables (might the concept
of a related breakpoint be useful elsewhere, if not just call
it the watchpoint_scope breakpoint or something like that. FIXME). */
struct breakpoint *related_breakpoint;
/* Holds the frame address which identifies the frame this watchpoint
should be evaluated in, or NULL if the watchpoint should be evaluated
on the outermost frame. */
CORE_ADDR watchpoint_frame;
/* Thread number for thread-specific breakpoint, or -1 if don't care */
int thread;
/* Count of the number of times this breakpoint was taken, dumped
with the info, but not used for anything else. Useful for
seeing how many times you hit a break prior to the program
aborting, so you can back up to just before the abort. */
int hit_count;
/* Filename of a dynamically-linked library (dll), used for bp_catch_load
and bp_catch_unload (malloc'd), or NULL if any library is significant. */
char * dll_pathname;
/* Filename of a dll whose state change (e.g., load or unload)
triggered this catchpoint. This field is only vaid immediately
after this catchpoint has triggered. */
char * triggered_dll_pathname;
/* Process id of a child process whose forking triggered this catchpoint.
This field is only vaid immediately after this catchpoint has triggered. */
int forked_inferior_pid;
/* Filename of a program whose exec triggered this catchpoint. This
field is only vaid immediately after this catchpoint has triggered. */
char * exec_pathname;
asection *section;
};
/* The following stuff is an abstract data type "bpstat" ("breakpoint status").
This provides the ability to determine whether we have stopped at a
breakpoint, and what we should do about it. */
typedef struct bpstats *bpstat;
/* Interface: */
/* Clear a bpstat so that it says we are not at any breakpoint.
Also free any storage that is part of a bpstat. */
extern void bpstat_clear PARAMS ((bpstat *));
/* Return a copy of a bpstat. Like "bs1 = bs2" but all storage that
is part of the bpstat is copied as well. */
extern bpstat bpstat_copy PARAMS ((bpstat));
extern bpstat bpstat_stop_status PARAMS ((CORE_ADDR *, int));
/* This bpstat_what stuff tells wait_for_inferior what to do with a
breakpoint (a challenging task). */
enum bpstat_what_main_action {
/* Perform various other tests; that is, this bpstat does not
say to perform any action (e.g. failed watchpoint and nothing
else). */
BPSTAT_WHAT_KEEP_CHECKING,
/* Rather than distinguish between noisy and silent stops here, it
might be cleaner to have bpstat_print make that decision (also
taking into account stop_print_frame and source_only). But the
implications are a bit scary (interaction with auto-displays, etc.),
so I won't try it. */
/* Stop silently. */
BPSTAT_WHAT_STOP_SILENT,
/* Stop and print. */
BPSTAT_WHAT_STOP_NOISY,
/* Remove breakpoints, single step once, then put them back in and
go back to what we were doing. It's possible that this should be
removed from the main_action and put into a separate field, to more
cleanly handle BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE. */
BPSTAT_WHAT_SINGLE,
/* Set longjmp_resume breakpoint, remove all other breakpoints,
and continue. The "remove all other breakpoints" part is required
if we are also stepping over another breakpoint as well as doing
the longjmp handling. */
BPSTAT_WHAT_SET_LONGJMP_RESUME,
/* Clear longjmp_resume breakpoint, then handle as
BPSTAT_WHAT_KEEP_CHECKING. */
BPSTAT_WHAT_CLEAR_LONGJMP_RESUME,
/* Clear longjmp_resume breakpoint, then handle as BPSTAT_WHAT_SINGLE. */
BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE,
/* Clear step resume breakpoint, and keep checking. */
BPSTAT_WHAT_STEP_RESUME,
/* Clear through_sigtramp breakpoint, muck with trap_expected, and keep
checking. */
BPSTAT_WHAT_THROUGH_SIGTRAMP,
/* Check the dynamic linker's data structures for new libraries, then
keep checking. */
BPSTAT_WHAT_CHECK_SHLIBS,
/* Check the dynamic linker's data structures for new libraries, then
resume out of the dynamic linker's callback, stop and print. */
BPSTAT_WHAT_CHECK_SHLIBS_RESUME_FROM_HOOK,
/* This is just used to keep track of how many enums there are. */
BPSTAT_WHAT_LAST
};
struct bpstat_what {
enum bpstat_what_main_action main_action;
/* Did we hit a call dummy breakpoint? This only goes with a main_action
of BPSTAT_WHAT_STOP_SILENT or BPSTAT_WHAT_STOP_NOISY (the concept of
continuing from a call dummy without popping the frame is not a
useful one). */
int call_dummy;
};
/* Tell what to do about this bpstat. */
struct bpstat_what bpstat_what PARAMS ((bpstat));
/* Find the bpstat associated with a breakpoint. NULL otherwise. */
bpstat bpstat_find_breakpoint PARAMS ((bpstat, struct breakpoint *));
/* Find a step_resume breakpoint associated with this bpstat.
(If there are multiple step_resume bp's on the list, this function
will arbitrarily pick one.)
It is an error to use this function if BPSTAT doesn't contain a
step_resume breakpoint.
See wait_for_inferior's use of this function.
*/
extern struct breakpoint *
bpstat_find_step_resume_breakpoint PARAMS ((bpstat));
/* Nonzero if a signal that we got in wait() was due to circumstances
explained by the BS. */
/* Currently that is true if we have hit a breakpoint, or if there is
a watchpoint enabled. */
#define bpstat_explains_signal(bs) ((bs) != NULL)
/* Nonzero if we should step constantly (e.g. watchpoints on machines
without hardware support). This isn't related to a specific bpstat,
just to things like whether watchpoints are set. */
extern int bpstat_should_step PARAMS ((void));
/* Nonzero if there are enabled hardware watchpoints. */
extern int bpstat_have_active_hw_watchpoints PARAMS ((void));
/* Print a message indicating what happened. Returns nonzero to
say that only the source line should be printed after this (zero
return means print the frame as well as the source line). */
extern int bpstat_print PARAMS ((bpstat));
/* Return the breakpoint number of the first breakpoint we are stopped
at. *BSP upon return is a bpstat which points to the remaining
breakpoints stopped at (but which is not guaranteed to be good for
anything but further calls to bpstat_num).
Return 0 if passed a bpstat which does not indicate any breakpoints. */
extern int bpstat_num PARAMS ((bpstat *));
/* Perform actions associated with having stopped at *BSP. Actually, we just
use this for breakpoint commands. Perhaps other actions will go here
later, but this is executed at a late time (from the command loop). */
extern void bpstat_do_actions PARAMS ((bpstat *));
/* Modify BS so that the actions will not be performed. */
extern void bpstat_clear_actions PARAMS ((bpstat));
/* Given a bpstat that records zero or more triggered eventpoints, this
function returns another bpstat which contains only the catchpoints
on that first list, if any.
*/
extern void bpstat_get_triggered_catchpoints PARAMS ((bpstat, bpstat *));
/* Implementation: */
struct bpstats
{
/* Linked list because there can be two breakpoints at the
same place, and a bpstat reflects the fact that both have been hit. */
bpstat next;
/* Breakpoint that we are at. */
struct breakpoint *breakpoint_at;
/* Commands left to be done. */
struct command_line *commands;
/* Old value associated with a watchpoint. */
value_ptr old_val;
/* Nonzero if this breakpoint tells us to print the frame. */
char print;
/* Nonzero if this breakpoint tells us to stop. */
char stop;
/* Function called by bpstat_print to print stuff associated with
this element of the bpstat chain. Returns 0 or 1 just like
bpstat_print, or -1 if it can't deal with it. */
int (*print_it) PARAMS((bpstat bs));
};
enum inf_context
{
inf_starting,
inf_running,
inf_exited
};
/* Prototypes for breakpoint-related functions. */
#ifdef __STDC__ /* Forward declarations for prototypes */
struct frame_info;
#endif
extern int breakpoint_here_p PARAMS ((CORE_ADDR));
extern int breakpoint_inserted_here_p PARAMS ((CORE_ADDR));
extern int frame_in_dummy PARAMS ((struct frame_info *));
extern int breakpoint_thread_match PARAMS ((CORE_ADDR, int));
extern void until_break_command PARAMS ((char *, int));
extern void breakpoint_re_set PARAMS ((void));
extern void breakpoint_re_set_thread PARAMS ((struct breakpoint *));
extern int ep_is_exception_catchpoint PARAMS ((struct breakpoint *));
extern struct breakpoint *set_momentary_breakpoint
PARAMS ((struct symtab_and_line, struct frame_info *, enum bptype));
extern void set_ignore_count PARAMS ((int, int, int));
extern void set_default_breakpoint PARAMS ((int, CORE_ADDR, struct symtab *, int));
extern void mark_breakpoints_out PARAMS ((void));
extern void breakpoint_init_inferior PARAMS ((enum inf_context));
extern void delete_breakpoint PARAMS ((struct breakpoint *));
extern void breakpoint_auto_delete PARAMS ((bpstat));
extern void breakpoint_clear_ignore_counts PARAMS ((void));
extern void break_command PARAMS ((char *, int));
extern void tbreak_command PARAMS ((char *, int));
extern int insert_breakpoints PARAMS ((void));
extern int remove_breakpoints PARAMS ((void));
/* This function can be used to physically insert eventpoints from the
specified traced inferior process, without modifying the breakpoint
package's state. This can be useful for those targets which support
following the processes of a fork() or vfork() system call, when both
of the resulting two processes are to be followed. */
extern int reattach_breakpoints PARAMS ((int));
/* This function can be used to update the breakpoint package's state
after an exec() system call has been executed.
This function causes the following:
- All eventpoints are marked "not inserted".
- All eventpoints with a symbolic address are reset such that
the symbolic address must be reevaluated before the eventpoints
can be reinserted.
- The solib breakpoints are explicitly removed from the breakpoint
list.
- A step-resume breakpoint, if any, is explicitly removed from the
breakpoint list.
- All eventpoints without a symbolic address are removed from the
breakpoint list. */
extern void update_breakpoints_after_exec PARAMS ((void));
/* This function can be used to physically remove hardware breakpoints
and watchpoints from the specified traced inferior process, without
modifying the breakpoint package's state. This can be useful for
those targets which support following the processes of a fork() or
vfork() system call, when one of the resulting two processes is to
be detached and allowed to run free.
It is an error to use this function on the process whose id is
inferior_pid. */
extern int detach_breakpoints PARAMS ((int));
extern void enable_longjmp_breakpoint PARAMS ((void));
extern void disable_longjmp_breakpoint PARAMS ((void));
extern void set_longjmp_resume_breakpoint PARAMS ((CORE_ADDR,
struct frame_info *));
/* These functions respectively disable or reenable all currently
enabled watchpoints. When disabled, the watchpoints are marked
call_disabled. When reenabled, they are marked enabled.
The intended client of these functions is infcmd.c\run_stack_dummy.
The inferior must be stopped, and all breakpoints removed, when
these functions are used.
The need for these functions is that on some targets (e.g., HP-UX),
gdb is unable to unwind through the dummy frame that is pushed as
part of the implementation of a call command. Watchpoints can
cause the inferior to stop in places where this frame is visible,
and that can cause execution control to become very confused.
Note that if a user sets breakpoints in an interactively call
function, the call_disabled watchpoints will have been reenabled
when the first such breakpoint is reached. However, on targets
that are unable to unwind through the call dummy frame, watches
of stack-based storage may then be deleted, because gdb will
believe that their watched storage is out of scope. (Sigh.) */
extern void
disable_watchpoints_before_interactive_call_start PARAMS ((void));
extern void
enable_watchpoints_after_interactive_call_stop PARAMS ((void));
extern void clear_breakpoint_hit_counts PARAMS ((void));
/* The following are for displays, which aren't really breakpoints, but
here is as good a place as any for them. */
extern void disable_current_display PARAMS ((void));
extern void do_displays PARAMS ((void));
extern void disable_display PARAMS ((int));
extern void clear_displays PARAMS ((void));
extern void disable_breakpoint PARAMS ((struct breakpoint *));
extern void enable_breakpoint PARAMS ((struct breakpoint *));
extern void create_solib_event_breakpoint PARAMS ((CORE_ADDR));
extern void remove_solib_event_breakpoints PARAMS ((void));
extern void disable_breakpoints_in_shlibs PARAMS ((int silent));
extern void re_enable_breakpoints_in_shlibs PARAMS ((void));
extern void create_solib_load_event_breakpoint PARAMS ((char *, int, char *, char *));
extern void create_solib_unload_event_breakpoint PARAMS ((char *, int, char *, char *));
extern void create_fork_event_catchpoint PARAMS ((int, char *));
extern void create_vfork_event_catchpoint PARAMS ((int, char *));
extern void create_exec_event_catchpoint PARAMS ((int, char *));
/* This function returns TRUE if ep is a catchpoint. */
extern int ep_is_catchpoint PARAMS ((struct breakpoint *));
/* This function returns TRUE if ep is a catchpoint of a
shared library (aka dynamically-linked library) event,
such as a library load or unload. */
extern int ep_is_shlib_catchpoint PARAMS ((struct breakpoint *));
extern struct breakpoint *set_breakpoint_sal PARAMS ((struct symtab_and_line));
#endif /* !defined (BREAKPOINT_H) */

1130
gdb/buildsym.c Normal file

File diff suppressed because it is too large Load Diff

297
gdb/buildsym.h Normal file
View File

@ -0,0 +1,297 @@
/* Build symbol tables in GDB's internal format.
Copyright 1986-1993, 1996-1999 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if !defined (BUILDSYM_H)
#define BUILDSYM_H 1
/* This module provides definitions used for creating and adding to
the symbol table. These routines are called from various symbol-
file-reading routines.
They originated in dbxread.c of gdb-4.2, and were split out to
make xcoffread.c more maintainable by sharing code.
Variables declared in this file can be defined by #define-ing the
name EXTERN to null. It is used to declare variables that are
normally extern, but which get defined in a single module using
this technique. */
#ifndef EXTERN
#define EXTERN extern
#endif
#define HASHSIZE 127 /* Size of things hashed via
hashname() */
/* Name of source file whose symbol data we are now processing. This
comes from a symbol of type N_SO. */
EXTERN char *last_source_file;
/* Core address of start of text of current source file. This too
comes from the N_SO symbol. */
EXTERN CORE_ADDR last_source_start_addr;
/* The list of sub-source-files within the current individual
compilation. Each file gets its own symtab with its own linetable
and associated info, but they all share one blockvector. */
struct subfile
{
struct subfile *next;
char *name;
char *dirname;
struct linetable *line_vector;
int line_vector_length;
enum language language;
char *debugformat;
};
EXTERN struct subfile *subfiles;
EXTERN struct subfile *current_subfile;
/* Global variable which, when set, indicates that we are processing a
.o file compiled with gcc */
EXTERN unsigned char processing_gcc_compilation;
/* When set, we are processing a .o file compiled by sun acc. This is
misnamed; it refers to all stabs-in-elf implementations which use
N_UNDF the way Sun does, including Solaris gcc. Hopefully all
stabs-in-elf implementations ever invented will choose to be
compatible. */
EXTERN unsigned char processing_acc_compilation;
/* elz: added this flag to know when a block is compiled with HP
compilers (cc, aCC). This is necessary because of the macro
COERCE_FLOAT_TO_DOUBLE defined in tm_hppa.h, which causes a
coercion of float to double to always occur in parameter passing
for a function called by gdb (see the function value_arg_coerce in
valops.c). This is necessary only if the target was compiled with
gcc, not with HP compilers or with g++ */
EXTERN unsigned char processing_hp_compilation;
/* Count symbols as they are processed, for error messages. */
EXTERN unsigned int symnum;
/* Record the symbols defined for each context in a list. We don't
create a struct block for the context until we know how long to
make it. */
#define PENDINGSIZE 100
struct pending
{
struct pending *next;
int nsyms;
struct symbol *symbol[PENDINGSIZE];
};
/* Here are the three lists that symbols are put on. */
/* static at top level, and types */
EXTERN struct pending *file_symbols;
/* global functions and variables */
EXTERN struct pending *global_symbols;
/* everything local to lexical context */
EXTERN struct pending *local_symbols;
/* func params local to lexical context */
EXTERN struct pending *param_symbols;
/* Stack representing unclosed lexical contexts (that will become
blocks, eventually). */
struct context_stack
{
/* Outer locals at the time we entered */
struct pending *locals;
/* Pending func params at the time we entered */
struct pending *params;
/* Pointer into blocklist as of entry */
struct pending_block *old_blocks;
/* Name of function, if any, defining context */
struct symbol *name;
/* PC where this context starts */
CORE_ADDR start_addr;
/* Temp slot for exception handling. */
CORE_ADDR end_addr;
/* For error-checking matching push/pop */
int depth;
};
EXTERN struct context_stack *context_stack;
/* Index of first unused entry in context stack. */
EXTERN int context_stack_depth;
/* Currently allocated size of context stack. */
EXTERN int context_stack_size;
/* Macro "function" for popping contexts from the stack. Pushing is
done by a real function, push_context. This returns a pointer to a
struct context_stack. */
#define pop_context() (&context_stack[--context_stack_depth]);
/* Nonzero if within a function (so symbols should be local, if
nothing says specifically). */
EXTERN int within_function;
/* List of blocks already made (lexical contexts already closed).
This is used at the end to make the blockvector. */
struct pending_block
{
struct pending_block *next;
struct block *block;
};
/* Pointer to the head of a linked list of symbol blocks which have
already been finalized (lexical contexts already closed) and which
are just waiting to be built into a blockvector when finalizing the
associated symtab. */
EXTERN struct pending_block *pending_blocks;
struct subfile_stack
{
struct subfile_stack *next;
char *name;
};
EXTERN struct subfile_stack *subfile_stack;
#define next_symbol_text(objfile) (*next_symbol_text_func)(objfile)
/* Function to invoke get the next symbol. Return the symbol name. */
EXTERN char *(*next_symbol_text_func) (struct objfile *);
/* Vector of types defined so far, indexed by their type numbers.
Used for both stabs and coff. (In newer sun systems, dbx uses a
pair of numbers in parens, as in "(SUBFILENUM,NUMWITHINSUBFILE)".
Then these numbers must be translated through the type_translations
hash table to get the index into the type vector.) */
EXTERN struct type **type_vector;
/* Number of elements allocated for type_vector currently. */
EXTERN int type_vector_length;
/* Initial size of type vector. Is realloc'd larger if needed, and
realloc'd down to the size actually used, when completed. */
#define INITIAL_TYPE_VECTOR_LENGTH 160
extern void add_symbol_to_list (struct symbol *symbol,
struct pending **listhead);
extern struct symbol *find_symbol_in_list (struct pending *list,
char *name, int length);
extern void finish_block (struct symbol *symbol,
struct pending **listhead,
struct pending_block *old_blocks,
CORE_ADDR start, CORE_ADDR end,
struct objfile *objfile);
extern void really_free_pendings (int foo);
extern void start_subfile (char *name, char *dirname);
extern void patch_subfile_names (struct subfile *subfile, char *name);
extern void push_subfile (void);
extern char *pop_subfile (void);
extern struct symtab *end_symtab (CORE_ADDR end_addr,
struct objfile *objfile, int section);
/* Defined in stabsread.c. */
extern void scan_file_globals (struct objfile *objfile);
extern void buildsym_new_init (void);
extern void buildsym_init (void);
extern struct context_stack *push_context (int desc, CORE_ADDR valu);
extern void record_line (struct subfile *subfile, int line, CORE_ADDR pc);
extern void start_symtab (char *name, char *dirname, CORE_ADDR start_addr);
extern int hashname (char *name);
extern void free_pending_blocks (void);
/* FIXME: Note that this is used only in buildsym.c and dstread.c,
which should be fixed to not need direct access to
make_blockvector. */
extern struct blockvector *make_blockvector (struct objfile *objfile);
/* FIXME: Note that this is used only in buildsym.c and dstread.c,
which should be fixed to not need direct access to
record_pending_block. */
extern void record_pending_block (struct objfile *objfile,
struct block *block,
struct pending_block *opblock);
extern void record_debugformat (char *format);
extern void merge_symbol_lists (struct pending **srclist,
struct pending **targetlist);
#undef EXTERN
#endif /* defined (BUILDSYM_H) */

1740
gdb/c-exp.y Normal file

File diff suppressed because it is too large Load Diff

527
gdb/c-lang.c Normal file
View File

@ -0,0 +1,527 @@
/* C language support routines for GDB, the GNU debugger.
Copyright 1992, 1993, 1994 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "expression.h"
#include "parser-defs.h"
#include "language.h"
#include "c-lang.h"
static void c_emit_char PARAMS ((int c, GDB_FILE *stream, int quoter));
/* Print the character C on STREAM as part of the contents of a literal
string whose delimiter is QUOTER. Note that that format for printing
characters and strings is language specific. */
static void
c_emit_char (c, stream, quoter)
register int c;
GDB_FILE *stream;
int quoter;
{
c &= 0xFF; /* Avoid sign bit follies */
if (PRINT_LITERAL_FORM (c))
{
if (c == '\\' || c == quoter)
{
fputs_filtered ("\\", stream);
}
fprintf_filtered (stream, "%c", c);
}
else
{
switch (c)
{
case '\n':
fputs_filtered ("\\n", stream);
break;
case '\b':
fputs_filtered ("\\b", stream);
break;
case '\t':
fputs_filtered ("\\t", stream);
break;
case '\f':
fputs_filtered ("\\f", stream);
break;
case '\r':
fputs_filtered ("\\r", stream);
break;
case '\033':
fputs_filtered ("\\e", stream);
break;
case '\007':
fputs_filtered ("\\a", stream);
break;
default:
fprintf_filtered (stream, "\\%.3o", (unsigned int) c);
break;
}
}
}
void
c_printchar (c, stream)
int c;
GDB_FILE *stream;
{
fputc_filtered ('\'', stream);
LA_EMIT_CHAR (c, stream, '\'');
fputc_filtered ('\'', stream);
}
/* Print the character string STRING, printing at most LENGTH characters.
LENGTH is -1 if the string is nul terminated. Each character is WIDTH bytes
long. Printing stops early if the number hits print_max; repeat counts are
printed as appropriate. Print ellipses at the end if we had to stop before
printing LENGTH characters, or if FORCE_ELLIPSES. */
void
c_printstr (stream, string, length, width, force_ellipses)
GDB_FILE *stream;
char *string;
unsigned int length;
int width;
int force_ellipses;
{
register unsigned int i;
unsigned int things_printed = 0;
int in_quotes = 0;
int need_comma = 0;
extern int inspect_it;
extern int repeat_count_threshold;
extern int print_max;
/* If the string was not truncated due to `set print elements', and
the last byte of it is a null, we don't print that, in traditional C
style. */
if (!force_ellipses
&& length > 0
&& extract_unsigned_integer (string + (length - 1) * width, width) == '\0')
length--;
if (length == 0)
{
fputs_filtered ("\"\"", stream);
return;
}
for (i = 0; i < length && things_printed < print_max; ++i)
{
/* Position of the character we are examining
to see whether it is repeated. */
unsigned int rep1;
/* Number of repetitions we have detected so far. */
unsigned int reps;
unsigned long current_char;
QUIT;
if (need_comma)
{
fputs_filtered (", ", stream);
need_comma = 0;
}
current_char = extract_unsigned_integer (string + i * width, width);
rep1 = i + 1;
reps = 1;
while (rep1 < length
&& extract_unsigned_integer (string + rep1 * width, width)
== current_char)
{
++rep1;
++reps;
}
if (reps > repeat_count_threshold)
{
if (in_quotes)
{
if (inspect_it)
fputs_filtered ("\\\", ", stream);
else
fputs_filtered ("\", ", stream);
in_quotes = 0;
}
LA_PRINT_CHAR (current_char, stream);
fprintf_filtered (stream, " <repeats %u times>", reps);
i = rep1 - 1;
things_printed += repeat_count_threshold;
need_comma = 1;
}
else
{
if (!in_quotes)
{
if (inspect_it)
fputs_filtered ("\\\"", stream);
else
fputs_filtered ("\"", stream);
in_quotes = 1;
}
LA_EMIT_CHAR (current_char, stream, '"');
++things_printed;
}
}
/* Terminate the quotes if necessary. */
if (in_quotes)
{
if (inspect_it)
fputs_filtered ("\\\"", stream);
else
fputs_filtered ("\"", stream);
}
if (force_ellipses || i < length)
fputs_filtered ("...", stream);
}
/* Create a fundamental C type using default reasonable for the current
target machine.
Some object/debugging file formats (DWARF version 1, COFF, etc) do not
define fundamental types such as "int" or "double". Others (stabs or
DWARF version 2, etc) do define fundamental types. For the formats which
don't provide fundamental types, gdb can create such types using this
function.
FIXME: Some compilers distinguish explicitly signed integral types
(signed short, signed int, signed long) from "regular" integral types
(short, int, long) in the debugging information. There is some dis-
agreement as to how useful this feature is. In particular, gcc does
not support this. Also, only some debugging formats allow the
distinction to be passed on to a debugger. For now, we always just
use "short", "int", or "long" as the type name, for both the implicit
and explicitly signed types. This also makes life easier for the
gdb test suite since we don't have to account for the differences
in output depending upon what the compiler and debugging format
support. We will probably have to re-examine the issue when gdb
starts taking it's fundamental type information directly from the
debugging information supplied by the compiler. fnf@cygnus.com */
struct type *
c_create_fundamental_type (objfile, typeid)
struct objfile *objfile;
int typeid;
{
register struct type *type = NULL;
switch (typeid)
{
default:
/* FIXME: For now, if we are asked to produce a type not in this
language, create the equivalent of a C integer type with the
name "<?type?>". When all the dust settles from the type
reconstruction work, this should probably become an error. */
type = init_type (TYPE_CODE_INT,
TARGET_INT_BIT / TARGET_CHAR_BIT,
0, "<?type?>", objfile);
warning ("internal error: no C/C++ fundamental type %d", typeid);
break;
case FT_VOID:
type = init_type (TYPE_CODE_VOID,
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
0, "void", objfile);
break;
case FT_BOOLEAN:
type = init_type (TYPE_CODE_BOOL,
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
0, "bool", objfile);
break;
case FT_CHAR:
type = init_type (TYPE_CODE_INT,
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
0, "char", objfile);
TYPE_FLAGS (type) |= TYPE_FLAG_NOSIGN;
break;
case FT_SIGNED_CHAR:
type = init_type (TYPE_CODE_INT,
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
0, "signed char", objfile);
break;
case FT_UNSIGNED_CHAR:
type = init_type (TYPE_CODE_INT,
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
TYPE_FLAG_UNSIGNED, "unsigned char", objfile);
break;
case FT_SHORT:
type = init_type (TYPE_CODE_INT,
TARGET_SHORT_BIT / TARGET_CHAR_BIT,
0, "short", objfile);
break;
case FT_SIGNED_SHORT:
type = init_type (TYPE_CODE_INT,
TARGET_SHORT_BIT / TARGET_CHAR_BIT,
0, "short", objfile); /* FIXME-fnf */
break;
case FT_UNSIGNED_SHORT:
type = init_type (TYPE_CODE_INT,
TARGET_SHORT_BIT / TARGET_CHAR_BIT,
TYPE_FLAG_UNSIGNED, "unsigned short", objfile);
break;
case FT_INTEGER:
type = init_type (TYPE_CODE_INT,
TARGET_INT_BIT / TARGET_CHAR_BIT,
0, "int", objfile);
break;
case FT_SIGNED_INTEGER:
type = init_type (TYPE_CODE_INT,
TARGET_INT_BIT / TARGET_CHAR_BIT,
0, "int", objfile); /* FIXME -fnf */
break;
case FT_UNSIGNED_INTEGER:
type = init_type (TYPE_CODE_INT,
TARGET_INT_BIT / TARGET_CHAR_BIT,
TYPE_FLAG_UNSIGNED, "unsigned int", objfile);
break;
case FT_LONG:
type = init_type (TYPE_CODE_INT,
TARGET_LONG_BIT / TARGET_CHAR_BIT,
0, "long", objfile);
break;
case FT_SIGNED_LONG:
type = init_type (TYPE_CODE_INT,
TARGET_LONG_BIT / TARGET_CHAR_BIT,
0, "long", objfile); /* FIXME -fnf */
break;
case FT_UNSIGNED_LONG:
type = init_type (TYPE_CODE_INT,
TARGET_LONG_BIT / TARGET_CHAR_BIT,
TYPE_FLAG_UNSIGNED, "unsigned long", objfile);
break;
case FT_LONG_LONG:
type = init_type (TYPE_CODE_INT,
TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
0, "long long", objfile);
break;
case FT_SIGNED_LONG_LONG:
type = init_type (TYPE_CODE_INT,
TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
0, "signed long long", objfile);
break;
case FT_UNSIGNED_LONG_LONG:
type = init_type (TYPE_CODE_INT,
TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
TYPE_FLAG_UNSIGNED, "unsigned long long", objfile);
break;
case FT_FLOAT:
type = init_type (TYPE_CODE_FLT,
TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
0, "float", objfile);
break;
case FT_DBL_PREC_FLOAT:
type = init_type (TYPE_CODE_FLT,
TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
0, "double", objfile);
break;
case FT_EXT_PREC_FLOAT:
type = init_type (TYPE_CODE_FLT,
TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
0, "long double", objfile);
break;
case FT_TEMPLATE_ARG:
type = init_type (TYPE_CODE_TEMPLATE_ARG,
0,
0, "<template arg>", objfile);
break;
}
return (type);
}
/* Table mapping opcodes into strings for printing operators
and precedences of the operators. */
const struct op_print c_op_print_tab[] =
{
{",", BINOP_COMMA, PREC_COMMA, 0},
{"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
{"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
{"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
{"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
{"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
{"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
{"==", BINOP_EQUAL, PREC_EQUAL, 0},
{"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
{"<=", BINOP_LEQ, PREC_ORDER, 0},
{">=", BINOP_GEQ, PREC_ORDER, 0},
{">", BINOP_GTR, PREC_ORDER, 0},
{"<", BINOP_LESS, PREC_ORDER, 0},
{">>", BINOP_RSH, PREC_SHIFT, 0},
{"<<", BINOP_LSH, PREC_SHIFT, 0},
{"+", BINOP_ADD, PREC_ADD, 0},
{"-", BINOP_SUB, PREC_ADD, 0},
{"*", BINOP_MUL, PREC_MUL, 0},
{"/", BINOP_DIV, PREC_MUL, 0},
{"%", BINOP_REM, PREC_MUL, 0},
{"@", BINOP_REPEAT, PREC_REPEAT, 0},
{"-", UNOP_NEG, PREC_PREFIX, 0},
{"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
{"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
{"*", UNOP_IND, PREC_PREFIX, 0},
{"&", UNOP_ADDR, PREC_PREFIX, 0},
{"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
{"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
{"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
/* C++ */
{"::", BINOP_SCOPE, PREC_PREFIX, 0},
{NULL, 0, 0, 0}
};
struct type ** CONST_PTR (c_builtin_types[]) =
{
&builtin_type_int,
&builtin_type_long,
&builtin_type_short,
&builtin_type_char,
&builtin_type_float,
&builtin_type_double,
&builtin_type_void,
&builtin_type_long_long,
&builtin_type_signed_char,
&builtin_type_unsigned_char,
&builtin_type_unsigned_short,
&builtin_type_unsigned_int,
&builtin_type_unsigned_long,
&builtin_type_unsigned_long_long,
&builtin_type_long_double,
&builtin_type_complex,
&builtin_type_double_complex,
0
};
const struct language_defn c_language_defn = {
"c", /* Language name */
language_c,
c_builtin_types,
range_check_off,
type_check_off,
c_parse,
c_error,
evaluate_subexp_standard,
c_printchar, /* Print a character constant */
c_printstr, /* Function to print string constant */
c_emit_char, /* Print a single char */
c_create_fundamental_type, /* Create fundamental type in this language */
c_print_type, /* Print a type using appropriate syntax */
c_val_print, /* Print a value using appropriate syntax */
c_value_print, /* Print a top-level value */
{"", "", "", ""}, /* Binary format info */
{"0%lo", "0", "o", ""}, /* Octal format info */
{"%ld", "", "d", ""}, /* Decimal format info */
{"0x%lx", "0x", "x", ""}, /* Hex format info */
c_op_print_tab, /* expression operators for printing */
1, /* c-style arrays */
0, /* String lower bound */
&builtin_type_char, /* Type of string elements */
LANG_MAGIC
};
struct type ** const (cplus_builtin_types[]) =
{
&builtin_type_int,
&builtin_type_long,
&builtin_type_short,
&builtin_type_char,
&builtin_type_float,
&builtin_type_double,
&builtin_type_void,
&builtin_type_long_long,
&builtin_type_signed_char,
&builtin_type_unsigned_char,
&builtin_type_unsigned_short,
&builtin_type_unsigned_int,
&builtin_type_unsigned_long,
&builtin_type_unsigned_long_long,
&builtin_type_long_double,
&builtin_type_complex,
&builtin_type_double_complex,
&builtin_type_bool,
0
};
const struct language_defn cplus_language_defn = {
"c++", /* Language name */
language_cplus,
cplus_builtin_types,
range_check_off,
type_check_off,
c_parse,
c_error,
evaluate_subexp_standard,
c_printchar, /* Print a character constant */
c_printstr, /* Function to print string constant */
c_emit_char, /* Print a single char */
c_create_fundamental_type, /* Create fundamental type in this language */
c_print_type, /* Print a type using appropriate syntax */
c_val_print, /* Print a value using appropriate syntax */
c_value_print, /* Print a top-level value */
{"", "", "", ""}, /* Binary format info */
{"0%lo", "0", "o", ""}, /* Octal format info */
{"%ld", "", "d", ""}, /* Decimal format info */
{"0x%lx", "0x", "x", ""}, /* Hex format info */
c_op_print_tab, /* expression operators for printing */
1, /* c-style arrays */
0, /* String lower bound */
&builtin_type_char, /* Type of string elements */
LANG_MAGIC
};
const struct language_defn asm_language_defn = {
"asm", /* Language name */
language_asm,
c_builtin_types,
range_check_off,
type_check_off,
c_parse,
c_error,
evaluate_subexp_standard,
c_printchar, /* Print a character constant */
c_printstr, /* Function to print string constant */
c_emit_char, /* Print a single char */
c_create_fundamental_type, /* Create fundamental type in this language */
c_print_type, /* Print a type using appropriate syntax */
c_val_print, /* Print a value using appropriate syntax */
c_value_print, /* Print a top-level value */
{"", "", "", ""}, /* Binary format info */
{"0%lo", "0", "o", ""}, /* Octal format info */
{"%ld", "", "d", ""}, /* Decimal format info */
{"0x%lx", "0x", "x", ""}, /* Hex format info */
c_op_print_tab, /* expression operators for printing */
1, /* c-style arrays */
0, /* String lower bound */
&builtin_type_char, /* Type of string elements */
LANG_MAGIC
};
void
_initialize_c_language ()
{
add_language (&c_language_defn);
add_language (&cplus_language_defn);
add_language (&asm_language_defn);
}

87
gdb/c-lang.h Normal file
View File

@ -0,0 +1,87 @@
/* C language support definitions for GDB, the GNU debugger.
Copyright 1992, 1996 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if !defined (C_LANG_H)
#define C_LANG_H 1
#include "value.h"
extern int
c_parse PARAMS ((void)); /* Defined in c-exp.y */
extern void
c_error PARAMS ((char *)); /* Defined in c-exp.y */
extern void /* Defined in c-typeprint.c */
c_print_type PARAMS ((struct type *, char *, GDB_FILE *, int, int));
extern int
c_val_print PARAMS ((struct type *, char *, int, CORE_ADDR, GDB_FILE *, int, int,
int, enum val_prettyprint));
extern int
c_value_print PARAMS ((struct value *, GDB_FILE *, int, enum val_prettyprint));
/* These are in c-lang.c: */
extern void c_printchar PARAMS ((int, GDB_FILE*));
extern void c_printstr PARAMS ((GDB_FILE *stream, char *string,
unsigned int length, int width,
int force_ellipses));
extern struct type * c_create_fundamental_type PARAMS ((struct objfile*, int));
extern struct type ** CONST_PTR (c_builtin_types[]);
/* These are in c-typeprint.c: */
extern void
c_type_print_base PARAMS ((struct type *, GDB_FILE *, int, int));
extern void
c_type_print_varspec_prefix PARAMS ((struct type *, GDB_FILE *, int, int));
/* These are in cp-valprint.c */
extern int vtblprint; /* Controls printing of vtbl's */
extern int static_field_print;
extern void
cp_print_class_member PARAMS ((char *, struct type *, GDB_FILE *, char *));
extern void
cp_print_class_method PARAMS ((char *, struct type *, GDB_FILE *));
extern void
cp_print_value_fields PARAMS ((struct type *, struct type *, char *, int, CORE_ADDR,
GDB_FILE *, int, int, enum val_prettyprint,
struct type**, int));
extern int
cp_is_vtbl_ptr_type PARAMS ((struct type *));
extern int
cp_is_vtbl_member PARAMS ((struct type *));
#endif /* !defined (C_LANG_H) */

1089
gdb/c-typeprint.c Normal file

File diff suppressed because it is too large Load Diff

535
gdb/c-valprint.c Normal file
View File

@ -0,0 +1,535 @@
/* Support for printing C values for GDB, the GNU debugger.
Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997
Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "expression.h"
#include "value.h"
#include "demangle.h"
#include "valprint.h"
#include "language.h"
#include "c-lang.h"
/* Print data of type TYPE located at VALADDR (within GDB), which came from
the inferior at address ADDRESS, onto stdio stream STREAM according to
FORMAT (a letter or 0 for natural format). The data at VALADDR is in
target byte order.
If the data are a string pointer, returns the number of string characters
printed.
If DEREF_REF is nonzero, then dereference references, otherwise just print
them like pointers.
The PRETTY parameter controls prettyprinting. */
int
c_val_print (type, valaddr, embedded_offset, address, stream, format, deref_ref, recurse,
pretty)
struct type *type;
char *valaddr;
int embedded_offset;
CORE_ADDR address;
GDB_FILE *stream;
int format;
int deref_ref;
int recurse;
enum val_prettyprint pretty;
{
register unsigned int i = 0; /* Number of characters printed */
unsigned len;
struct type *elttype;
unsigned eltlen;
LONGEST val;
CORE_ADDR addr;
CHECK_TYPEDEF (type);
switch (TYPE_CODE (type))
{
case TYPE_CODE_ARRAY:
elttype = check_typedef (TYPE_TARGET_TYPE (type));
if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0)
{
eltlen = TYPE_LENGTH (elttype);
len = TYPE_LENGTH (type) / eltlen;
if (prettyprint_arrays)
{
print_spaces_filtered (2 + 2 * recurse, stream);
}
/* For an array of chars, print with string syntax. */
if (eltlen == 1 &&
((TYPE_CODE (elttype) == TYPE_CODE_INT)
|| ((current_language->la_language == language_m2)
&& (TYPE_CODE (elttype) == TYPE_CODE_CHAR)))
&& (format == 0 || format == 's'))
{
/* If requested, look for the first null char and only print
elements up to it. */
if (stop_print_at_null)
{
int temp_len;
/* Look for a NULL char. */
for (temp_len = 0;
(valaddr + embedded_offset)[temp_len]
&& temp_len < len && temp_len < print_max;
temp_len++);
len = temp_len;
}
LA_PRINT_STRING (stream, valaddr + embedded_offset, len, eltlen, 0);
i = len;
}
else
{
fprintf_filtered (stream, "{");
/* If this is a virtual function table, print the 0th
entry specially, and the rest of the members normally. */
if (cp_is_vtbl_ptr_type (elttype))
{
i = 1;
fprintf_filtered (stream, "%d vtable entries", len - 1);
}
else
{
i = 0;
}
val_print_array_elements (type, valaddr + embedded_offset, address, stream,
format, deref_ref, recurse, pretty, i);
fprintf_filtered (stream, "}");
}
break;
}
/* Array of unspecified length: treat like pointer to first elt. */
addr = address;
goto print_unpacked_pointer;
case TYPE_CODE_PTR:
if (format && format != 's')
{
print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
break;
}
if (vtblprint && cp_is_vtbl_ptr_type(type))
{
/* Print the unmangled name if desired. */
/* Print vtable entry - we only get here if we ARE using
-fvtable_thunks. (Otherwise, look under TYPE_CODE_STRUCT.) */
print_address_demangle(extract_address (valaddr + embedded_offset, TYPE_LENGTH (type)),
stream, demangle);
break;
}
elttype = check_typedef (TYPE_TARGET_TYPE (type));
if (TYPE_CODE (elttype) == TYPE_CODE_METHOD)
{
cp_print_class_method (valaddr + embedded_offset, type, stream);
}
else if (TYPE_CODE (elttype) == TYPE_CODE_MEMBER)
{
cp_print_class_member (valaddr + embedded_offset,
TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)),
stream, "&");
}
else
{
addr = unpack_pointer (type, valaddr + embedded_offset);
print_unpacked_pointer:
elttype = check_typedef (TYPE_TARGET_TYPE (type));
if (TYPE_CODE (elttype) == TYPE_CODE_FUNC)
{
/* Try to print what function it points to. */
print_address_demangle (addr, stream, demangle);
/* Return value is irrelevant except for string pointers. */
return (0);
}
if (addressprint && format != 's')
{
print_address_numeric (addr, 1, stream);
}
/* For a pointer to char or unsigned char, also print the string
pointed to, unless pointer is null. */
/* FIXME: need to handle wchar_t here... */
if (TYPE_LENGTH (elttype) == 1
&& TYPE_CODE (elttype) == TYPE_CODE_INT
&& (format == 0 || format == 's')
&& addr != 0)
{
i = val_print_string (addr, -1, TYPE_LENGTH (elttype), stream);
}
else if (cp_is_vtbl_member(type))
{
/* print vtbl's nicely */
CORE_ADDR vt_address = unpack_pointer (type, valaddr + embedded_offset);
struct minimal_symbol *msymbol =
lookup_minimal_symbol_by_pc (vt_address);
if ((msymbol != NULL) &&
(vt_address == SYMBOL_VALUE_ADDRESS (msymbol)))
{
fputs_filtered (" <", stream);
fputs_filtered (SYMBOL_SOURCE_NAME (msymbol), stream);
fputs_filtered (">", stream);
}
if (vt_address && vtblprint)
{
value_ptr vt_val;
struct symbol *wsym = (struct symbol *)NULL;
struct type *wtype;
struct symtab *s;
struct block *block = (struct block *)NULL;
int is_this_fld;
if (msymbol != NULL)
wsym = lookup_symbol (SYMBOL_NAME(msymbol), block,
VAR_NAMESPACE, &is_this_fld, &s);
if (wsym)
{
wtype = SYMBOL_TYPE(wsym);
}
else
{
wtype = TYPE_TARGET_TYPE(type);
}
vt_val = value_at (wtype, vt_address, NULL);
val_print (VALUE_TYPE (vt_val), VALUE_CONTENTS (vt_val), 0,
VALUE_ADDRESS (vt_val), stream, format,
deref_ref, recurse + 1, pretty);
if (pretty)
{
fprintf_filtered (stream, "\n");
print_spaces_filtered (2 + 2 * recurse, stream);
}
}
}
/* Return number of characters printed, including the terminating
'\0' if we reached the end. val_print_string takes care including
the terminating '\0' if necessary. */
return i;
}
break;
case TYPE_CODE_MEMBER:
error ("not implemented: member type in c_val_print");
break;
case TYPE_CODE_REF:
elttype = check_typedef (TYPE_TARGET_TYPE (type));
if (TYPE_CODE (elttype) == TYPE_CODE_MEMBER)
{
cp_print_class_member (valaddr + embedded_offset,
TYPE_DOMAIN_TYPE (elttype),
stream, "");
break;
}
if (addressprint)
{
fprintf_filtered (stream, "@");
print_address_numeric
(extract_address (valaddr + embedded_offset,
TARGET_PTR_BIT / HOST_CHAR_BIT), 1, stream);
if (deref_ref)
fputs_filtered (": ", stream);
}
/* De-reference the reference. */
if (deref_ref)
{
if (TYPE_CODE (elttype) != TYPE_CODE_UNDEF)
{
value_ptr deref_val =
value_at
(TYPE_TARGET_TYPE (type),
unpack_pointer (lookup_pointer_type (builtin_type_void),
valaddr + embedded_offset),
NULL);
val_print (VALUE_TYPE (deref_val),
VALUE_CONTENTS (deref_val),
0,
VALUE_ADDRESS (deref_val),
stream,
format,
deref_ref,
recurse,
pretty);
}
else
fputs_filtered ("???", stream);
}
break;
case TYPE_CODE_UNION:
if (recurse && !unionprint)
{
fprintf_filtered (stream, "{...}");
break;
}
/* Fall through. */
case TYPE_CODE_STRUCT:
if (vtblprint && cp_is_vtbl_ptr_type(type))
{
/* Print the unmangled name if desired. */
/* Print vtable entry - we only get here if NOT using
-fvtable_thunks. (Otherwise, look under TYPE_CODE_PTR.) */
print_address_demangle (extract_address (
valaddr + embedded_offset +
TYPE_FIELD_BITPOS (type, VTBL_FNADDR_OFFSET) / 8,
TYPE_LENGTH (TYPE_FIELD_TYPE (type, VTBL_FNADDR_OFFSET))),
stream, demangle);
}
else
cp_print_value_fields (type, type, valaddr, embedded_offset, address, stream, format,
recurse, pretty, NULL, 0);
break;
case TYPE_CODE_ENUM:
if (format)
{
print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
break;
}
len = TYPE_NFIELDS (type);
val = unpack_long (type, valaddr + embedded_offset);
for (i = 0; i < len; i++)
{
QUIT;
if (val == TYPE_FIELD_BITPOS (type, i))
{
break;
}
}
if (i < len)
{
fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
}
else
{
print_longest (stream, 'd', 0, val);
}
break;
case TYPE_CODE_FUNC:
if (format)
{
print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
break;
}
/* FIXME, we should consider, at least for ANSI C language, eliminating
the distinction made between FUNCs and POINTERs to FUNCs. */
fprintf_filtered (stream, "{");
type_print (type, "", stream, -1);
fprintf_filtered (stream, "} ");
/* Try to print what function it points to, and its address. */
print_address_demangle (address, stream, demangle);
break;
case TYPE_CODE_BOOL:
format = format ? format : output_format;
if (format)
print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
else
{
val = unpack_long (type, valaddr + embedded_offset);
if (val == 0)
fputs_filtered ("false", stream);
else if (val == 1)
fputs_filtered ("true", stream);
else
print_longest (stream, 'd', 0, val);
}
break;
case TYPE_CODE_RANGE:
/* FIXME: create_range_type does not set the unsigned bit in a
range type (I think it probably should copy it from the target
type), so we won't print values which are too large to
fit in a signed integer correctly. */
/* FIXME: Doesn't handle ranges of enums correctly. (Can't just
print with the target type, though, because the size of our type
and the target type might differ). */
/* FALLTHROUGH */
case TYPE_CODE_INT:
format = format ? format : output_format;
if (format)
{
print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
}
else
{
val_print_type_code_int (type, valaddr + embedded_offset, stream);
/* C and C++ has no single byte int type, char is used instead.
Since we don't know whether the value is really intended to
be used as an integer or a character, print the character
equivalent as well. */
if (TYPE_LENGTH (type) == 1)
{
fputs_filtered (" ", stream);
LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr + embedded_offset),
stream);
}
}
break;
case TYPE_CODE_CHAR:
format = format ? format : output_format;
if (format)
{
print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
}
else
{
fprintf_filtered (stream, TYPE_UNSIGNED (type) ? "%u" : "%d",
unpack_long (type, valaddr + embedded_offset));
fputs_filtered (" ", stream);
LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr + embedded_offset), stream);
}
break;
case TYPE_CODE_FLT:
if (format)
{
print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
}
else
{
print_floating (valaddr + embedded_offset, type, stream);
}
break;
case TYPE_CODE_METHOD:
cp_print_class_method (valaddr + embedded_offset, lookup_pointer_type (type), stream);
break;
case TYPE_CODE_VOID:
fprintf_filtered (stream, "void");
break;
case TYPE_CODE_ERROR:
fprintf_filtered (stream, "<error type>");
break;
case TYPE_CODE_UNDEF:
/* This happens (without TYPE_FLAG_STUB set) on systems which don't use
dbx xrefs (NO_DBX_XREFS in gcc) if a file has a "struct foo *bar"
and no complete type for struct foo in that file. */
fprintf_filtered (stream, "<incomplete type>");
break;
default:
error ("Invalid C/C++ type code %d in symbol table.", TYPE_CODE (type));
}
gdb_flush (stream);
return (0);
}
int
c_value_print (val, stream, format, pretty)
value_ptr val;
GDB_FILE *stream;
int format;
enum val_prettyprint pretty;
{
struct type *type = VALUE_TYPE (val);
struct type * real_type;
int full, top, using_enc;
/* If it is a pointer, indicate what it points to.
Print type also if it is a reference.
C++: if it is a member pointer, we will take care
of that when we print it. */
if (TYPE_CODE (type) == TYPE_CODE_PTR ||
TYPE_CODE (type) == TYPE_CODE_REF)
{
/* Hack: remove (char *) for char strings. Their
type is indicated by the quoted string anyway. */
if (TYPE_CODE (type) == TYPE_CODE_PTR &&
TYPE_NAME (type) == NULL &&
TYPE_NAME (TYPE_TARGET_TYPE (type)) != NULL &&
STREQ (TYPE_NAME (TYPE_TARGET_TYPE (type)), "char"))
{
/* Print nothing */
}
else if (objectprint && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS))
{
/* Pointer to class, check real type of object */
fprintf_filtered (stream, "(");
type = value_rtti_target_type (val, &full, &top, &using_enc);
if (type)
{
/* RTTI entry found */
type = lookup_pointer_type (type);
type_print (type, "", stream, -1);
}
else
{
/* No RTTI fields, do whatever we can */
type = VALUE_ENCLOSING_TYPE (val);
type_print (type, "", stream, -1);
fprintf_filtered (stream, " ?");
}
fprintf_filtered (stream, ") ");
}
else
{
/* normal case */
fprintf_filtered (stream, "(");
type_print (type, "", stream, -1);
fprintf_filtered (stream, ") ");
}
}
if (objectprint && (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_CLASS))
{
/* Attempt to determine real type of object */
real_type = value_rtti_type (val, &full, &top, &using_enc);
if (real_type)
{
/* We have RTTI information, so use it */
val = value_full_object (val, real_type, full, top, using_enc);
fprintf_filtered (stream, "(%s%s) ",
TYPE_NAME (real_type),
full ? "" : " [incomplete object]");
/* Print out object: enclosing type is same as real_type if full */
return val_print (VALUE_ENCLOSING_TYPE (val), VALUE_CONTENTS_ALL (val), 0,
VALUE_ADDRESS (val), stream, format, 1, 0, pretty);
}
else if (type != VALUE_ENCLOSING_TYPE (val))
{
/* No RTTI information, so let's do our best */
fprintf_filtered (stream, "(%s ?) ",
TYPE_NAME (VALUE_ENCLOSING_TYPE (val)));
return val_print (VALUE_ENCLOSING_TYPE (val), VALUE_CONTENTS_ALL (val), 0,
VALUE_ADDRESS (val), stream, format, 1, 0, pretty);
}
/* Otherwise, we end up at the return outside this "if" */
}
return val_print (type, VALUE_CONTENTS_ALL (val), VALUE_EMBEDDED_OFFSET (val),
VALUE_ADDRESS (val),
stream, format, 1, 0, pretty);
}

28
gdb/call-cmds.h Normal file
View File

@ -0,0 +1,28 @@
/* Prototypes for GDB commands that are called internally by other functions.
Copyright 1992 Free Software Foundation, Inc.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
extern void
initialize_all_files PARAMS ((void));
extern void
exec_file_command PARAMS ((char *, int));
extern void
core_file_command PARAMS ((char *, int));
extern void
break_command PARAMS ((char *, int));

2169
gdb/ch-exp.c Normal file

File diff suppressed because it is too large Load Diff

675
gdb/ch-lang.c Normal file
View File

@ -0,0 +1,675 @@
/* Chill language support routines for GDB, the GNU debugger.
Copyright 1992, 1995, 1996 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "value.h"
#include "expression.h"
#include "parser-defs.h"
#include "language.h"
#include "ch-lang.h"
static value_ptr
evaluate_subexp_chill PARAMS ((struct type *, struct expression *, int *, enum noside));
static value_ptr
value_chill_max_min PARAMS ((enum exp_opcode, value_ptr));
static value_ptr
value_chill_card PARAMS ((value_ptr));
static value_ptr
value_chill_length PARAMS ((value_ptr));
static struct type *
chill_create_fundamental_type PARAMS ((struct objfile *, int));
static void
chill_printstr PARAMS ((GDB_FILE *stream, char *string, unsigned int length, int width, int force_ellipses));
static void
chill_printchar PARAMS ((int, GDB_FILE *));
/* For now, Chill uses a simple mangling algorithm whereby you simply
discard everything after the occurance of two successive CPLUS_MARKER
characters to derive the demangled form. */
char *
chill_demangle (mangled)
const char *mangled;
{
const char *joiner = NULL;
char *demangled;
const char *cp = mangled;
while (*cp)
{
if (is_cplus_marker (*cp))
{
joiner = cp;
break;
}
cp++;
}
if (joiner != NULL && *(joiner + 1) == *joiner)
{
demangled = savestring (mangled, joiner - mangled);
}
else
{
demangled = NULL;
}
return (demangled);
}
static void
chill_printchar (c, stream)
register int c;
GDB_FILE *stream;
{
c &= 0xFF; /* Avoid sign bit follies */
if (PRINT_LITERAL_FORM (c))
{
if (c == '\'' || c == '^')
fprintf_filtered (stream, "'%c%c'", c, c);
else
fprintf_filtered (stream, "'%c'", c);
}
else
{
fprintf_filtered (stream, "'^(%u)'", (unsigned int) c);
}
}
/* Print the character string STRING, printing at most LENGTH characters.
Printing stops early if the number hits print_max; repeat counts
are printed as appropriate. Print ellipses at the end if we
had to stop before printing LENGTH characters, or if FORCE_ELLIPSES.
Note that gdb maintains the length of strings without counting the
terminating null byte, while chill strings are typically written with
an explicit null byte. So we always assume an implied null byte
until gdb is able to maintain non-null terminated strings as well
as null terminated strings (FIXME).
*/
static void
chill_printstr (stream, string, length, width, force_ellipses)
GDB_FILE *stream;
char *string;
unsigned int length;
int width;
int force_ellipses;
{
register unsigned int i;
unsigned int things_printed = 0;
int in_literal_form = 0;
int in_control_form = 0;
int need_slashslash = 0;
unsigned int c;
extern int repeat_count_threshold;
extern int print_max;
if (length == 0)
{
fputs_filtered ("\"\"", stream);
return;
}
for (i = 0; i < length && things_printed < print_max; ++i)
{
/* Position of the character we are examining
to see whether it is repeated. */
unsigned int rep1;
/* Number of repetitions we have detected so far. */
unsigned int reps;
QUIT;
if (need_slashslash)
{
fputs_filtered ("//", stream);
need_slashslash = 0;
}
rep1 = i + 1;
reps = 1;
while (rep1 < length && string[rep1] == string[i])
{
++rep1;
++reps;
}
c = string[i];
if (reps > repeat_count_threshold)
{
if (in_control_form || in_literal_form)
{
if (in_control_form)
fputs_filtered (")", stream);
fputs_filtered ("\"//", stream);
in_control_form = in_literal_form = 0;
}
chill_printchar (c, stream);
fprintf_filtered (stream, "<repeats %u times>", reps);
i = rep1 - 1;
things_printed += repeat_count_threshold;
need_slashslash = 1;
}
else
{
if (! in_literal_form && ! in_control_form)
fputs_filtered ("\"", stream);
if (PRINT_LITERAL_FORM (c))
{
if (!in_literal_form)
{
if (in_control_form)
{
fputs_filtered (")", stream);
in_control_form = 0;
}
in_literal_form = 1;
}
fprintf_filtered (stream, "%c", c);
if (c == '"' || c == '^')
/* duplicate this one as must be done at input */
fprintf_filtered (stream, "%c", c);
}
else
{
if (!in_control_form)
{
if (in_literal_form)
{
in_literal_form = 0;
}
fputs_filtered ("^(", stream);
in_control_form = 1;
}
else
fprintf_filtered (stream, ",");
c = c & 0xff;
fprintf_filtered (stream, "%u", (unsigned int) c);
}
++things_printed;
}
}
/* Terminate the quotes if necessary. */
if (in_control_form)
{
fputs_filtered (")", stream);
}
if (in_literal_form || in_control_form)
{
fputs_filtered ("\"", stream);
}
if (force_ellipses || (i < length))
{
fputs_filtered ("...", stream);
}
}
static struct type *
chill_create_fundamental_type (objfile, typeid)
struct objfile *objfile;
int typeid;
{
register struct type *type = NULL;
switch (typeid)
{
default:
/* FIXME: For now, if we are asked to produce a type not in this
language, create the equivalent of a C integer type with the
name "<?type?>". When all the dust settles from the type
reconstruction work, this should probably become an error. */
type = init_type (TYPE_CODE_INT, 2, 0, "<?type?>", objfile);
warning ("internal error: no chill fundamental type %d", typeid);
break;
case FT_VOID:
/* FIXME: Currently the GNU Chill compiler emits some DWARF entries for
typedefs, unrelated to anything directly in the code being compiled,
that have some FT_VOID types. Just fake it for now. */
type = init_type (TYPE_CODE_VOID, 0, 0, "<?VOID?>", objfile);
break;
case FT_BOOLEAN:
type = init_type (TYPE_CODE_BOOL, 1, TYPE_FLAG_UNSIGNED, "BOOL", objfile);
break;
case FT_CHAR:
type = init_type (TYPE_CODE_CHAR, 1, TYPE_FLAG_UNSIGNED, "CHAR", objfile);
break;
case FT_SIGNED_CHAR:
type = init_type (TYPE_CODE_INT, 1, 0, "BYTE", objfile);
break;
case FT_UNSIGNED_CHAR:
type = init_type (TYPE_CODE_INT, 1, TYPE_FLAG_UNSIGNED, "UBYTE", objfile);
break;
case FT_SHORT: /* Chill ints are 2 bytes */
type = init_type (TYPE_CODE_INT, 2, 0, "INT", objfile);
break;
case FT_UNSIGNED_SHORT: /* Chill ints are 2 bytes */
type = init_type (TYPE_CODE_INT, 2, TYPE_FLAG_UNSIGNED, "UINT", objfile);
break;
case FT_INTEGER: /* FIXME? */
case FT_SIGNED_INTEGER: /* FIXME? */
case FT_LONG: /* Chill longs are 4 bytes */
case FT_SIGNED_LONG: /* Chill longs are 4 bytes */
type = init_type (TYPE_CODE_INT, 4, 0, "LONG", objfile);
break;
case FT_UNSIGNED_INTEGER: /* FIXME? */
case FT_UNSIGNED_LONG: /* Chill longs are 4 bytes */
type = init_type (TYPE_CODE_INT, 4, TYPE_FLAG_UNSIGNED, "ULONG", objfile);
break;
case FT_FLOAT:
type = init_type (TYPE_CODE_FLT, 4, 0, "REAL", objfile);
break;
case FT_DBL_PREC_FLOAT:
type = init_type (TYPE_CODE_FLT, 8, 0, "LONG_REAL", objfile);
break;
}
return (type);
}
/* Table of operators and their precedences for printing expressions. */
static const struct op_print chill_op_print_tab[] = {
{"AND", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
{"OR", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
{"NOT", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
{"MOD", BINOP_MOD, PREC_MUL, 0},
{"REM", BINOP_REM, PREC_MUL, 0},
{"SIZE",UNOP_SIZEOF, PREC_BUILTIN_FUNCTION, 0},
{"LOWER",UNOP_LOWER, PREC_BUILTIN_FUNCTION, 0},
{"UPPER",UNOP_UPPER, PREC_BUILTIN_FUNCTION, 0},
{"CARD",UNOP_CARD, PREC_BUILTIN_FUNCTION, 0},
{"MAX",UNOP_CHMAX, PREC_BUILTIN_FUNCTION, 0},
{"MIN",UNOP_CHMIN, PREC_BUILTIN_FUNCTION, 0},
{":=", BINOP_ASSIGN, PREC_ASSIGN, 1},
{"=", BINOP_EQUAL, PREC_EQUAL, 0},
{"/=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
{"<=", BINOP_LEQ, PREC_ORDER, 0},
{">=", BINOP_GEQ, PREC_ORDER, 0},
{">", BINOP_GTR, PREC_ORDER, 0},
{"<", BINOP_LESS, PREC_ORDER, 0},
{"+", BINOP_ADD, PREC_ADD, 0},
{"-", BINOP_SUB, PREC_ADD, 0},
{"*", BINOP_MUL, PREC_MUL, 0},
{"/", BINOP_DIV, PREC_MUL, 0},
{"//", BINOP_CONCAT, PREC_PREFIX, 0}, /* FIXME: precedence? */
{"-", UNOP_NEG, PREC_PREFIX, 0},
{"->", UNOP_IND, PREC_SUFFIX, 1},
{"->", UNOP_ADDR, PREC_PREFIX, 0},
{":", BINOP_RANGE, PREC_ASSIGN, 0},
{NULL, 0, 0, 0}
};
/* The built-in types of Chill. */
struct type *builtin_type_chill_bool;
struct type *builtin_type_chill_char;
struct type *builtin_type_chill_long;
struct type *builtin_type_chill_ulong;
struct type *builtin_type_chill_real;
struct type ** CONST_PTR (chill_builtin_types[]) =
{
&builtin_type_chill_bool,
&builtin_type_chill_char,
&builtin_type_chill_long,
&builtin_type_chill_ulong,
&builtin_type_chill_real,
0
};
/* Calculate LOWER or UPPER of TYPE.
Returns the result as an integer.
*RESULT_TYPE is the appropriate type for the result. */
LONGEST
type_lower_upper (op, type, result_type)
enum exp_opcode op; /* Either UNOP_LOWER or UNOP_UPPER */
struct type *type;
struct type **result_type;
{
LONGEST low, high;
*result_type = type;
CHECK_TYPEDEF (type);
switch (TYPE_CODE (type))
{
case TYPE_CODE_STRUCT:
*result_type = builtin_type_int;
if (chill_varying_type (type))
return type_lower_upper (op, TYPE_FIELD_TYPE (type, 1), result_type);
break;
case TYPE_CODE_ARRAY:
case TYPE_CODE_BITSTRING:
case TYPE_CODE_STRING:
type = TYPE_FIELD_TYPE (type, 0); /* Get index type */
/* ... fall through ... */
case TYPE_CODE_RANGE:
*result_type = TYPE_TARGET_TYPE (type);
return op == UNOP_LOWER ? TYPE_LOW_BOUND (type) : TYPE_HIGH_BOUND (type);
case TYPE_CODE_ENUM:
case TYPE_CODE_BOOL:
case TYPE_CODE_INT:
case TYPE_CODE_CHAR:
if (get_discrete_bounds (type, &low, &high) >= 0)
{
*result_type = type;
return op == UNOP_LOWER ? low : high;
}
break;
case TYPE_CODE_UNDEF:
case TYPE_CODE_PTR:
case TYPE_CODE_UNION:
case TYPE_CODE_FUNC:
case TYPE_CODE_FLT:
case TYPE_CODE_VOID:
case TYPE_CODE_SET:
case TYPE_CODE_ERROR:
case TYPE_CODE_MEMBER:
case TYPE_CODE_METHOD:
case TYPE_CODE_REF:
case TYPE_CODE_COMPLEX:
default:
break;
}
error ("unknown mode for LOWER/UPPER builtin");
}
static value_ptr
value_chill_length (val)
value_ptr val;
{
LONGEST tmp;
struct type *type = VALUE_TYPE (val);
struct type *ttype;
CHECK_TYPEDEF (type);
switch (TYPE_CODE (type))
{
case TYPE_CODE_ARRAY:
case TYPE_CODE_BITSTRING:
case TYPE_CODE_STRING:
tmp = type_lower_upper (UNOP_UPPER, type, &ttype)
- type_lower_upper (UNOP_LOWER, type, &ttype) + 1;
break;
case TYPE_CODE_STRUCT:
if (chill_varying_type (type))
{
tmp = unpack_long (TYPE_FIELD_TYPE (type, 0), VALUE_CONTENTS (val));
break;
}
/* ... else fall through ... */
default:
error ("bad argument to LENGTH builtin");
}
return value_from_longest (builtin_type_int, tmp);
}
static value_ptr
value_chill_card (val)
value_ptr val;
{
LONGEST tmp = 0;
struct type *type = VALUE_TYPE (val);
CHECK_TYPEDEF (type);
if (TYPE_CODE (type) == TYPE_CODE_SET)
{
struct type *range_type = TYPE_INDEX_TYPE (type);
LONGEST lower_bound, upper_bound;
int i;
get_discrete_bounds (range_type, &lower_bound, &upper_bound);
for (i = lower_bound; i <= upper_bound; i++)
if (value_bit_index (type, VALUE_CONTENTS (val), i) > 0)
tmp++;
}
else
error ("bad argument to CARD builtin");
return value_from_longest (builtin_type_int, tmp);
}
static value_ptr
value_chill_max_min (op, val)
enum exp_opcode op;
value_ptr val;
{
LONGEST tmp = 0;
struct type *type = VALUE_TYPE (val);
struct type *elttype;
CHECK_TYPEDEF (type);
if (TYPE_CODE (type) == TYPE_CODE_SET)
{
LONGEST lower_bound, upper_bound;
int i, empty = 1;
elttype = TYPE_INDEX_TYPE (type);
CHECK_TYPEDEF (elttype);
get_discrete_bounds (elttype, &lower_bound, &upper_bound);
if (op == UNOP_CHMAX)
{
for (i = upper_bound; i >= lower_bound; i--)
{
if (value_bit_index (type, VALUE_CONTENTS (val), i) > 0)
{
tmp = i;
empty = 0;
break;
}
}
}
else
{
for (i = lower_bound; i <= upper_bound; i++)
{
if (value_bit_index (type, VALUE_CONTENTS (val), i) > 0)
{
tmp = i;
empty = 0;
break;
}
}
}
if (empty)
error ("%s for empty powerset", op == UNOP_CHMAX ? "MAX" : "MIN");
}
else
error ("bad argument to %s builtin", op == UNOP_CHMAX ? "MAX" : "MIN");
return value_from_longest (TYPE_CODE (elttype) == TYPE_CODE_RANGE
? TYPE_TARGET_TYPE (elttype)
: elttype,
tmp);
}
static value_ptr
evaluate_subexp_chill (expect_type, exp, pos, noside)
struct type *expect_type;
register struct expression *exp;
register int *pos;
enum noside noside;
{
int pc = *pos;
struct type *type;
int tem, nargs;
value_ptr arg1;
value_ptr *argvec;
enum exp_opcode op = exp->elts[*pos].opcode;
switch (op)
{
case MULTI_SUBSCRIPT:
if (noside == EVAL_SKIP)
break;
(*pos) += 3;
nargs = longest_to_int (exp->elts[pc + 1].longconst);
arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
type = check_typedef (VALUE_TYPE (arg1));
if (nargs == 1 && TYPE_CODE (type) == TYPE_CODE_INT)
{
/* Looks like string repetition. */
value_ptr string = evaluate_subexp_with_coercion (exp, pos, noside);
return value_concat (arg1, string);
}
switch (TYPE_CODE (type))
{
case TYPE_CODE_PTR:
type = check_typedef (TYPE_TARGET_TYPE (type));
if (!type || TYPE_CODE (type) != TYPE_CODE_FUNC)
error ("reference value used as function");
/* ... fall through ... */
case TYPE_CODE_FUNC:
/* It's a function call. */
if (noside == EVAL_AVOID_SIDE_EFFECTS)
break;
/* Allocate arg vector, including space for the function to be
called in argvec[0] and a terminating NULL */
argvec = (value_ptr *) alloca (sizeof (value_ptr) * (nargs + 2));
argvec[0] = arg1;
tem = 1;
for (; tem <= nargs && tem <= TYPE_NFIELDS (type); tem++)
{
argvec[tem]
= evaluate_subexp_chill (TYPE_FIELD_TYPE (type, tem-1),
exp, pos, noside);
}
for (; tem <= nargs; tem++)
argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
argvec[tem] = 0; /* signal end of arglist */
return call_function_by_hand (argvec[0], nargs, argvec + 1);
default:
break;
}
while (nargs-- > 0)
{
value_ptr index = evaluate_subexp_with_coercion (exp, pos, noside);
arg1 = value_subscript (arg1, index);
}
return (arg1);
case UNOP_LOWER:
case UNOP_UPPER:
(*pos)++;
if (noside == EVAL_SKIP)
{
(*exp->language_defn->evaluate_exp) (NULL_TYPE, exp, pos, EVAL_SKIP);
goto nosideret;
}
arg1 = (*exp->language_defn->evaluate_exp) (NULL_TYPE, exp, pos,
EVAL_AVOID_SIDE_EFFECTS);
tem = type_lower_upper (op, VALUE_TYPE (arg1), &type);
return value_from_longest (type, tem);
case UNOP_LENGTH:
(*pos)++;
arg1 = (*exp->language_defn->evaluate_exp) (NULL_TYPE, exp, pos, noside);
return value_chill_length (arg1);
case UNOP_CARD:
(*pos)++;
arg1 = (*exp->language_defn->evaluate_exp) (NULL_TYPE, exp, pos, noside);
return value_chill_card (arg1);
case UNOP_CHMAX:
case UNOP_CHMIN:
(*pos)++;
arg1 = (*exp->language_defn->evaluate_exp) (NULL_TYPE, exp, pos, noside);
return value_chill_max_min (op, arg1);
case BINOP_COMMA:
error ("',' operator used in invalid context");
default:
break;
}
return evaluate_subexp_standard (expect_type, exp, pos, noside);
nosideret:
return value_from_longest (builtin_type_long, (LONGEST) 1);
}
const struct language_defn chill_language_defn = {
"chill",
language_chill,
chill_builtin_types,
range_check_on,
type_check_on,
chill_parse, /* parser */
chill_error, /* parser error function */
evaluate_subexp_chill,
chill_printchar, /* print a character constant */
chill_printstr, /* function to print a string constant */
NULL, /* Function to print a single char */
chill_create_fundamental_type,/* Create fundamental type in this language */
chill_print_type, /* Print a type using appropriate syntax */
chill_val_print, /* Print a value using appropriate syntax */
chill_value_print, /* Print a top-levl value */
{"", "B'", "", ""}, /* Binary format info */
{"O'%lo", "O'", "o", ""}, /* Octal format info */
{"D'%ld", "D'", "d", ""}, /* Decimal format info */
{"H'%lx", "H'", "x", ""}, /* Hex format info */
chill_op_print_tab, /* expression operators for printing */
0, /* arrays are first-class (not c-style) */
0, /* String lower bound */
&builtin_type_chill_char, /* Type of string elements */
LANG_MAGIC
};
/* Initialization for Chill */
void
_initialize_chill_language ()
{
builtin_type_chill_bool =
init_type (TYPE_CODE_BOOL, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
TYPE_FLAG_UNSIGNED,
"BOOL", (struct objfile *) NULL);
builtin_type_chill_char =
init_type (TYPE_CODE_CHAR, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
TYPE_FLAG_UNSIGNED,
"CHAR", (struct objfile *) NULL);
builtin_type_chill_long =
init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT,
0,
"LONG", (struct objfile *) NULL);
builtin_type_chill_ulong =
init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT,
TYPE_FLAG_UNSIGNED,
"ULONG", (struct objfile *) NULL);
builtin_type_chill_real =
init_type (TYPE_CODE_FLT, TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
0,
"LONG_REAL", (struct objfile *) NULL);
add_language (&chill_language_defn);
}

42
gdb/ch-lang.h Normal file
View File

@ -0,0 +1,42 @@
/* Chill language support definitions for GDB, the GNU debugger.
Copyright 1992 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifdef __STDC__ /* Forward decls for prototypes */
struct value;
#endif
extern int
chill_parse PARAMS ((void)); /* Defined in ch-exp.y */
extern void
chill_error PARAMS ((char *)); /* Defined in ch-exp.y */
extern void /* Defined in ch-typeprint.c */
chill_print_type PARAMS ((struct type *, char *, GDB_FILE *, int, int));
extern int
chill_val_print PARAMS ((struct type *, char *, int, CORE_ADDR, GDB_FILE *, int, int,
int, enum val_prettyprint));
extern int
chill_value_print PARAMS ((struct value *, GDB_FILE *,
int, enum val_prettyprint));
extern LONGEST
type_lower_upper PARAMS ((enum exp_opcode, struct type *, struct type **));

346
gdb/ch-typeprint.c Normal file
View File

@ -0,0 +1,346 @@
/* Support for printing Chill types for GDB, the GNU debugger.
Copyright 1986, 1988, 1989, 1991 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "obstack.h"
#include "bfd.h" /* Binary File Description */
#include "symtab.h"
#include "gdbtypes.h"
#include "expression.h"
#include "value.h"
#include "gdbcore.h"
#include "target.h"
#include "command.h"
#include "gdbcmd.h"
#include "language.h"
#include "demangle.h"
#include "ch-lang.h"
#include "typeprint.h"
#include "gdb_string.h"
#include <errno.h>
static void
chill_type_print_base PARAMS ((struct type *, GDB_FILE *, int, int));
void
chill_print_type (type, varstring, stream, show, level)
struct type *type;
char *varstring;
GDB_FILE *stream;
int show;
int level;
{
if (varstring != NULL && *varstring != '\0')
{
fputs_filtered (varstring, stream);
fputs_filtered (" ", stream);
}
chill_type_print_base (type, stream, show, level);
}
/* Print the name of the type (or the ultimate pointer target,
function value or array element).
SHOW nonzero means don't print this type as just its name;
show its real definition even if it has a name.
SHOW zero means print just typename or tag if there is one
SHOW negative means abbreviate structure elements.
SHOW is decremented for printing of structure elements.
LEVEL is the depth to indent by.
We increase it for some recursive calls. */
static void
chill_type_print_base (type, stream, show, level)
struct type *type;
GDB_FILE *stream;
int show;
int level;
{
register int len;
register int i;
struct type *index_type;
struct type *range_type;
LONGEST low_bound;
LONGEST high_bound;
QUIT;
wrap_here (" ");
if (type == NULL)
{
fputs_filtered ("<type unknown>", stream);
return;
}
/* When SHOW is zero or less, and there is a valid type name, then always
just print the type name directly from the type. */
if ((show <= 0) && (TYPE_NAME (type) != NULL))
{
fputs_filtered (TYPE_NAME (type), stream);
return;
}
if (TYPE_CODE (type) != TYPE_CODE_TYPEDEF)
CHECK_TYPEDEF (type);
switch (TYPE_CODE (type))
{
case TYPE_CODE_TYPEDEF:
chill_type_print_base (TYPE_TARGET_TYPE (type), stream, 0, level);
break;
case TYPE_CODE_PTR:
if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_VOID)
{
fprintf_filtered (stream,
TYPE_NAME (type) ? TYPE_NAME (type) : "PTR");
break;
}
fprintf_filtered (stream, "REF ");
chill_type_print_base (TYPE_TARGET_TYPE (type), stream, 0, level);
break;
case TYPE_CODE_BOOL:
/* FIXME: we should probably just print the TYPE_NAME, in case
anyone ever fixes the compiler to give us the real names
in the presence of the chill equivalent of typedef (assuming
there is one). */
fprintf_filtered (stream,
TYPE_NAME (type) ? TYPE_NAME (type) : "BOOL");
break;
case TYPE_CODE_ARRAY:
fputs_filtered ("ARRAY (", stream);
range_type = TYPE_FIELD_TYPE (type, 0);
if (TYPE_CODE (range_type) != TYPE_CODE_RANGE)
chill_print_type (range_type, "", stream, 0, level);
else
{
index_type = TYPE_TARGET_TYPE (range_type);
low_bound = TYPE_FIELD_BITPOS (range_type, 0);
high_bound = TYPE_FIELD_BITPOS (range_type, 1);
print_type_scalar (index_type, low_bound, stream);
fputs_filtered (":", stream);
print_type_scalar (index_type, high_bound, stream);
}
fputs_filtered (") ", stream);
chill_print_type (TYPE_TARGET_TYPE (type), "", stream, 0, level);
break;
case TYPE_CODE_BITSTRING:
fprintf_filtered (stream, "BOOLS (%d)",
TYPE_FIELD_BITPOS (TYPE_FIELD_TYPE(type,0), 1) + 1);
break;
case TYPE_CODE_SET:
fputs_filtered ("POWERSET ", stream);
chill_print_type (TYPE_INDEX_TYPE (type), "", stream,
show - 1, level);
break;
case TYPE_CODE_STRING:
range_type = TYPE_FIELD_TYPE (type, 0);
index_type = TYPE_TARGET_TYPE (range_type);
high_bound = TYPE_FIELD_BITPOS (range_type, 1);
fputs_filtered ("CHARS (", stream);
print_type_scalar (index_type, high_bound + 1, stream);
fputs_filtered (")", stream);
break;
case TYPE_CODE_MEMBER:
fprintf_filtered (stream, "MEMBER ");
chill_type_print_base (TYPE_TARGET_TYPE (type), stream, 0, level);
break;
case TYPE_CODE_REF:
fprintf_filtered (stream, "/*LOC*/ ");
chill_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
break;
case TYPE_CODE_FUNC:
fprintf_filtered (stream, "PROC (");
len = TYPE_NFIELDS (type);
for (i = 0; i < len; i++)
{
struct type *param_type = TYPE_FIELD_TYPE (type, i);
if (i > 0)
{
fputs_filtered (", ", stream);
wrap_here (" ");
}
if (TYPE_CODE (param_type) == TYPE_CODE_REF)
{
chill_type_print_base (TYPE_TARGET_TYPE (param_type),
stream, 0, level);
fputs_filtered (" LOC", stream);
}
else
chill_type_print_base (param_type, stream, show, level);
}
fprintf_filtered (stream, ")");
if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID)
{
fputs_filtered (" RETURNS (", stream);
chill_type_print_base (TYPE_TARGET_TYPE (type), stream, 0, level);
fputs_filtered (")", stream);
}
break;
case TYPE_CODE_STRUCT:
if (chill_varying_type (type))
{
chill_type_print_base (TYPE_FIELD_TYPE (type, 1),
stream, 0, level);
fputs_filtered (" VARYING", stream);
}
else
{
fprintf_filtered (stream, "STRUCT ");
fprintf_filtered (stream, "(\n");
if ((TYPE_NFIELDS (type) == 0) && (TYPE_NFN_FIELDS (type) == 0))
{
if (TYPE_FLAGS (type) & TYPE_FLAG_STUB)
{
fprintfi_filtered (level + 4, stream, "<incomplete type>\n");
}
else
{
fprintfi_filtered (level + 4, stream, "<no data fields>\n");
}
}
else
{
len = TYPE_NFIELDS (type);
for (i = TYPE_N_BASECLASSES (type); i < len; i++)
{
struct type *field_type = TYPE_FIELD_TYPE (type, i);
QUIT;
print_spaces_filtered (level + 4, stream);
if (TYPE_CODE (field_type) == TYPE_CODE_UNION)
{ int j; /* variant number */
fputs_filtered ("CASE OF\n", stream);
for (j = 0; j < TYPE_NFIELDS (field_type); j++)
{ int k; /* variant field index */
struct type *variant_type
= TYPE_FIELD_TYPE (field_type, j);
int var_len = TYPE_NFIELDS (variant_type);
print_spaces_filtered (level + 4, stream);
if (strcmp (TYPE_FIELD_NAME (field_type, j),
"else") == 0)
fputs_filtered ("ELSE\n", stream);
else
fputs_filtered (":\n", stream);
if (TYPE_CODE (variant_type) != TYPE_CODE_STRUCT)
error ("variant record confusion");
for (k = 0; k < var_len; k++)
{
print_spaces_filtered (level + 8, stream);
chill_print_type (TYPE_FIELD_TYPE (variant_type, k),
TYPE_FIELD_NAME (variant_type, k),
stream, show - 1, level + 8);
if (k < (var_len - 1))
fputs_filtered (",", stream);
fputs_filtered ("\n", stream);
}
}
print_spaces_filtered (level + 4, stream);
fputs_filtered ("ESAC", stream);
}
else
chill_print_type (field_type,
TYPE_FIELD_NAME (type, i),
stream, show - 1, level + 4);
if (i < (len - 1))
{
fputs_filtered (",", stream);
}
fputs_filtered ("\n", stream);
}
}
fprintfi_filtered (level, stream, ")");
}
break;
case TYPE_CODE_RANGE:
{
struct type *target = TYPE_TARGET_TYPE (type);
if (target && TYPE_NAME (target))
fputs_filtered (TYPE_NAME (target), stream);
else
fputs_filtered ("RANGE", stream);
if (target == NULL)
target = builtin_type_long;
fputs_filtered (" (", stream);
print_type_scalar (target, TYPE_LOW_BOUND (type), stream);
fputs_filtered (":", stream);
print_type_scalar (target, TYPE_HIGH_BOUND (type), stream);
fputs_filtered (")", stream);
}
break;
case TYPE_CODE_ENUM:
{
register int lastval = 0;
fprintf_filtered (stream, "SET (");
len = TYPE_NFIELDS (type);
for (i = 0; i < len; i++)
{
QUIT;
if (i) fprintf_filtered (stream, ", ");
wrap_here (" ");
fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
if (lastval != TYPE_FIELD_BITPOS (type, i))
{
fprintf_filtered (stream, " = %d", TYPE_FIELD_BITPOS (type, i));
lastval = TYPE_FIELD_BITPOS (type, i);
}
lastval++;
}
fprintf_filtered (stream, ")");
}
break;
case TYPE_CODE_VOID:
case TYPE_CODE_UNDEF:
case TYPE_CODE_ERROR:
case TYPE_CODE_UNION:
case TYPE_CODE_METHOD:
error ("missing language support in chill_type_print_base");
break;
default:
/* Handle types not explicitly handled by the other cases,
such as fundamental types. For these, just print whatever
the type name is, as recorded in the type itself. If there
is no type name, then complain. */
if (TYPE_NAME (type) != NULL)
{
fputs_filtered (TYPE_NAME (type), stream);
}
else
{
error ("Unrecognized type code (%d) in symbol table.",
TYPE_CODE (type));
}
break;
}
}

630
gdb/ch-valprint.c Normal file
View File

@ -0,0 +1,630 @@
/* Support for printing Chill values for GDB, the GNU debugger.
Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994
Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "obstack.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "valprint.h"
#include "expression.h"
#include "value.h"
#include "language.h"
#include "demangle.h"
#include "c-lang.h" /* For c_val_print */
#include "typeprint.h"
#include "ch-lang.h"
#include "annotate.h"
static void
chill_print_value_fields PARAMS ((struct type *, char *, GDB_FILE *, int, int,
enum val_prettyprint, struct type **));
static void
chill_print_type_scalar PARAMS ((struct type *, LONGEST, GDB_FILE *));
static void
chill_val_print_array_elements PARAMS ((struct type *, char *, CORE_ADDR, GDB_FILE *,
int, int, int, enum val_prettyprint));
/* Print integral scalar data VAL, of type TYPE, onto stdio stream STREAM.
Used to print data from type structures in a specified type. For example,
array bounds may be characters or booleans in some languages, and this
allows the ranges to be printed in their "natural" form rather than as
decimal integer values. */
static void
chill_print_type_scalar (type, val, stream)
struct type *type;
LONGEST val;
GDB_FILE *stream;
{
switch (TYPE_CODE (type))
{
case TYPE_CODE_RANGE:
if (TYPE_TARGET_TYPE (type))
{
chill_print_type_scalar (TYPE_TARGET_TYPE (type), val, stream);
return;
}
break;
case TYPE_CODE_UNDEF:
case TYPE_CODE_PTR:
case TYPE_CODE_ARRAY:
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
case TYPE_CODE_ENUM:
case TYPE_CODE_FUNC:
case TYPE_CODE_INT:
case TYPE_CODE_FLT:
case TYPE_CODE_VOID:
case TYPE_CODE_SET:
case TYPE_CODE_STRING:
case TYPE_CODE_BITSTRING:
case TYPE_CODE_ERROR:
case TYPE_CODE_MEMBER:
case TYPE_CODE_METHOD:
case TYPE_CODE_REF:
case TYPE_CODE_CHAR:
case TYPE_CODE_BOOL:
case TYPE_CODE_COMPLEX:
case TYPE_CODE_TYPEDEF:
default:
break;
}
print_type_scalar (type, val, stream);
}
/* Print the elements of an array.
Similar to val_print_array_elements, but prints
element indexes (in Chill syntax). */
static void
chill_val_print_array_elements (type, valaddr, address, stream,
format, deref_ref, recurse, pretty)
struct type *type;
char *valaddr;
CORE_ADDR address;
GDB_FILE *stream;
int format;
int deref_ref;
int recurse;
enum val_prettyprint pretty;
{
unsigned int i = 0;
unsigned int things_printed = 0;
unsigned len;
struct type *elttype;
struct type *range_type = TYPE_FIELD_TYPE (type, 0);
struct type *index_type = TYPE_TARGET_TYPE (range_type);
unsigned eltlen;
/* Position of the array element we are examining to see
whether it is repeated. */
unsigned int rep1;
/* Number of repetitions we have detected so far. */
unsigned int reps;
LONGEST low_bound = TYPE_FIELD_BITPOS (range_type, 0);
elttype = check_typedef (TYPE_TARGET_TYPE (type));
eltlen = TYPE_LENGTH (elttype);
len = TYPE_LENGTH (type) / eltlen;
annotate_array_section_begin (i, elttype);
for (; i < len && things_printed < print_max; i++)
{
if (i != 0)
{
if (prettyprint_arrays)
{
fprintf_filtered (stream, ",\n");
print_spaces_filtered (2 + 2 * recurse, stream);
}
else
{
fprintf_filtered (stream, ", ");
}
}
wrap_here (n_spaces (2 + 2 * recurse));
rep1 = i + 1;
reps = 1;
while ((rep1 < len) &&
!memcmp (valaddr + i * eltlen, valaddr + rep1 * eltlen, eltlen))
{
++reps;
++rep1;
}
fputs_filtered ("(", stream);
chill_print_type_scalar (index_type, low_bound + i, stream);
if (reps > 1)
{
fputs_filtered (":", stream);
chill_print_type_scalar (index_type, low_bound + i + reps - 1,
stream);
fputs_filtered ("): ", stream);
val_print (elttype, valaddr + i * eltlen, 0, 0, stream, format,
deref_ref, recurse + 1, pretty);
i = rep1 - 1;
things_printed += 1;
}
else
{
fputs_filtered ("): ", stream);
val_print (elttype, valaddr + i * eltlen, 0, 0, stream, format,
deref_ref, recurse + 1, pretty);
annotate_elt ();
things_printed++;
}
}
annotate_array_section_end ();
if (i < len)
{
fprintf_filtered (stream, "...");
}
}
/* Print data of type TYPE located at VALADDR (within GDB), which came from
the inferior at address ADDRESS, onto stdio stream STREAM according to
FORMAT (a letter or 0 for natural format). The data at VALADDR is in
target byte order.
If the data are a string pointer, returns the number of string characters
printed.
If DEREF_REF is nonzero, then dereference references, otherwise just print
them like pointers.
The PRETTY parameter controls prettyprinting. */
int
chill_val_print (type, valaddr, embedded_offset, address,
stream, format, deref_ref, recurse, pretty)
struct type *type;
char *valaddr;
int embedded_offset;
CORE_ADDR address;
GDB_FILE *stream;
int format;
int deref_ref;
int recurse;
enum val_prettyprint pretty;
{
LONGEST val;
unsigned int i = 0; /* Number of characters printed. */
struct type *elttype;
CORE_ADDR addr;
CHECK_TYPEDEF (type);
switch (TYPE_CODE (type))
{
case TYPE_CODE_ARRAY:
if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0)
{
if (prettyprint_arrays)
{
print_spaces_filtered (2 + 2 * recurse, stream);
}
fprintf_filtered (stream, "[");
chill_val_print_array_elements (type, valaddr, address, stream,
format, deref_ref, recurse, pretty);
fprintf_filtered (stream, "]");
}
else
{
error ("unimplemented in chill_val_print; unspecified array length");
}
break;
case TYPE_CODE_INT:
format = format ? format : output_format;
if (format)
{
print_scalar_formatted (valaddr, type, format, 0, stream);
}
else
{
val_print_type_code_int (type, valaddr, stream);
}
break;
case TYPE_CODE_CHAR:
format = format ? format : output_format;
if (format)
{
print_scalar_formatted (valaddr, type, format, 0, stream);
}
else
{
LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr),
stream);
}
break;
case TYPE_CODE_FLT:
if (format)
{
print_scalar_formatted (valaddr, type, format, 0, stream);
}
else
{
print_floating (valaddr, type, stream);
}
break;
case TYPE_CODE_BOOL:
format = format ? format : output_format;
if (format)
{
print_scalar_formatted (valaddr, type, format, 0, stream);
}
else
{
/* FIXME: Why is this using builtin_type_chill_bool not type? */
val = unpack_long (builtin_type_chill_bool, valaddr);
fprintf_filtered (stream, val ? "TRUE" : "FALSE");
}
break;
case TYPE_CODE_UNDEF:
/* This happens (without TYPE_FLAG_STUB set) on systems which don't use
dbx xrefs (NO_DBX_XREFS in gcc) if a file has a "struct foo *bar"
and no complete type for struct foo in that file. */
fprintf_filtered (stream, "<incomplete type>");
break;
case TYPE_CODE_PTR:
if (format && format != 's')
{
print_scalar_formatted (valaddr, type, format, 0, stream);
break;
}
addr = unpack_pointer (type, valaddr);
elttype = check_typedef (TYPE_TARGET_TYPE (type));
/* We assume a NULL pointer is all zeros ... */
if (addr == 0)
{
fputs_filtered ("NULL", stream);
return 0;
}
if (TYPE_CODE (elttype) == TYPE_CODE_FUNC)
{
/* Try to print what function it points to. */
print_address_demangle (addr, stream, demangle);
/* Return value is irrelevant except for string pointers. */
return (0);
}
if (addressprint && format != 's')
{
print_address_numeric (addr, 1, stream);
}
/* For a pointer to char or unsigned char, also print the string
pointed to, unless pointer is null. */
if (TYPE_LENGTH (elttype) == 1
&& TYPE_CODE (elttype) == TYPE_CODE_CHAR
&& (format == 0 || format == 's')
&& addr != 0
&& /* If print_max is UINT_MAX, the alloca below will fail.
In that case don't try to print the string. */
print_max < UINT_MAX)
i = val_print_string (addr, -1, TYPE_LENGTH (elttype), stream);
/* Return number of characters printed, plus one for the
terminating null if we have "reached the end". */
return (i + (print_max && i != print_max));
break;
case TYPE_CODE_STRING:
i = TYPE_LENGTH (type);
LA_PRINT_STRING (stream, valaddr, i, 1, 0);
/* Return number of characters printed, plus one for the terminating
null if we have "reached the end". */
return (i + (print_max && i != print_max));
break;
case TYPE_CODE_BITSTRING:
case TYPE_CODE_SET:
elttype = TYPE_INDEX_TYPE (type);
CHECK_TYPEDEF (elttype);
if (TYPE_FLAGS (elttype) & TYPE_FLAG_STUB)
{
fprintf_filtered (stream, "<incomplete type>");
gdb_flush (stream);
break;
}
{
struct type *range = elttype;
LONGEST low_bound, high_bound;
int i;
int is_bitstring = TYPE_CODE (type) == TYPE_CODE_BITSTRING;
int need_comma = 0;
if (is_bitstring)
fputs_filtered ("B'", stream);
else
fputs_filtered ("[", stream);
i = get_discrete_bounds (range, &low_bound, &high_bound);
maybe_bad_bstring:
if (i < 0)
{
fputs_filtered ("<error value>", stream);
goto done;
}
for (i = low_bound; i <= high_bound; i++)
{
int element = value_bit_index (type, valaddr, i);
if (element < 0)
{
i = element;
goto maybe_bad_bstring;
}
if (is_bitstring)
fprintf_filtered (stream, "%d", element);
else if (element)
{
if (need_comma)
fputs_filtered (", ", stream);
chill_print_type_scalar (range, (LONGEST) i, stream);
need_comma = 1;
/* Look for a continuous range of true elements. */
if (i+1 <= high_bound && value_bit_index (type, valaddr, ++i))
{
int j = i; /* j is the upper bound so far of the range */
fputs_filtered (":", stream);
while (i+1 <= high_bound
&& value_bit_index (type, valaddr, ++i))
j = i;
chill_print_type_scalar (range, (LONGEST) j, stream);
}
}
}
done:
if (is_bitstring)
fputs_filtered ("'", stream);
else
fputs_filtered ("]", stream);
}
break;
case TYPE_CODE_STRUCT:
if (chill_varying_type (type))
{
struct type *inner = check_typedef (TYPE_FIELD_TYPE (type, 1));
long length = unpack_long (TYPE_FIELD_TYPE (type, 0), valaddr);
char *data_addr = valaddr + TYPE_FIELD_BITPOS (type, 1) / 8;
switch (TYPE_CODE (inner))
{
case TYPE_CODE_STRING:
if (length > TYPE_LENGTH (type) - 2)
{
fprintf_filtered (stream,
"<dynamic length %ld > static length %d> *invalid*",
length, TYPE_LENGTH (type));
/* Don't print the string; doing so might produce a
segfault. */
return length;
}
LA_PRINT_STRING (stream, data_addr, length, 1, 0);
return length;
default:
break;
}
}
chill_print_value_fields (type, valaddr, stream, format, recurse, pretty,
0);
break;
case TYPE_CODE_REF:
if (addressprint)
{
fprintf_filtered (stream, "LOC(");
print_address_numeric
(extract_address (valaddr, TARGET_PTR_BIT / HOST_CHAR_BIT),
1,
stream);
fprintf_filtered (stream, ")");
if (deref_ref)
fputs_filtered (": ", stream);
}
/* De-reference the reference. */
if (deref_ref)
{
if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_UNDEF)
{
value_ptr deref_val =
value_at
(TYPE_TARGET_TYPE (type),
unpack_pointer (lookup_pointer_type (builtin_type_void),
valaddr),
NULL);
val_print (VALUE_TYPE (deref_val),
VALUE_CONTENTS (deref_val),
0,
VALUE_ADDRESS (deref_val), stream, format,
deref_ref, recurse + 1, pretty);
}
else
fputs_filtered ("???", stream);
}
break;
case TYPE_CODE_ENUM:
c_val_print (type, valaddr, 0, address, stream, format,
deref_ref, recurse, pretty);
break;
case TYPE_CODE_RANGE:
if (TYPE_TARGET_TYPE (type))
chill_val_print (TYPE_TARGET_TYPE (type), valaddr, 0, address, stream,
format, deref_ref, recurse, pretty);
break;
case TYPE_CODE_MEMBER:
case TYPE_CODE_UNION:
case TYPE_CODE_FUNC:
case TYPE_CODE_VOID:
case TYPE_CODE_ERROR:
default:
/* Let's defer printing to the C printer, rather than
print an error message. FIXME! */
c_val_print (type, valaddr, 0, address, stream, format,
deref_ref, recurse, pretty);
}
gdb_flush (stream);
return (0);
}
/* Mutually recursive subroutines of cplus_print_value and c_val_print to
print out a structure's fields: cp_print_value_fields and cplus_print_value.
TYPE, VALADDR, STREAM, RECURSE, and PRETTY have the
same meanings as in cplus_print_value and c_val_print.
DONT_PRINT is an array of baseclass types that we
should not print, or zero if called from top level. */
static void
chill_print_value_fields (type, valaddr, stream, format, recurse, pretty,
dont_print)
struct type *type;
char *valaddr;
GDB_FILE *stream;
int format;
int recurse;
enum val_prettyprint pretty;
struct type **dont_print;
{
int i, len;
int fields_seen = 0;
CHECK_TYPEDEF (type);
fprintf_filtered (stream, "[");
len = TYPE_NFIELDS (type);
if (len == 0)
{
fprintf_filtered (stream, "<No data fields>");
}
else
{
for (i = 0; i < len; i++)
{
if (fields_seen)
{
fprintf_filtered (stream, ", ");
}
fields_seen = 1;
if (pretty)
{
fprintf_filtered (stream, "\n");
print_spaces_filtered (2 + 2 * recurse, stream);
}
else
{
wrap_here (n_spaces (2 + 2 * recurse));
}
fputs_filtered (".", stream);
fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i),
language_chill, DMGL_NO_OPTS);
fputs_filtered (": ", stream);
if (TYPE_FIELD_PACKED (type, i))
{
value_ptr v;
/* Bitfields require special handling, especially due to byte
order problems. */
v = value_from_longest (TYPE_FIELD_TYPE (type, i),
unpack_field_as_long (type, valaddr, i));
chill_val_print (TYPE_FIELD_TYPE (type, i), VALUE_CONTENTS (v), 0, 0,
stream, format, 0, recurse + 1, pretty);
}
else
{
chill_val_print (TYPE_FIELD_TYPE (type, i),
valaddr + TYPE_FIELD_BITPOS (type, i) / 8, 0,
0, stream, format, 0, recurse + 1, pretty);
}
}
if (pretty)
{
fprintf_filtered (stream, "\n");
print_spaces_filtered (2 * recurse, stream);
}
}
fprintf_filtered (stream, "]");
}
int
chill_value_print (val, stream, format, pretty)
value_ptr val;
GDB_FILE *stream;
int format;
enum val_prettyprint pretty;
{
struct type *type = VALUE_TYPE (val);
struct type *real_type = check_typedef (type);
/* If it is a pointer, indicate what it points to.
Print type also if it is a reference. */
if (TYPE_CODE (real_type) == TYPE_CODE_PTR ||
TYPE_CODE (real_type) == TYPE_CODE_REF)
{
char *valaddr = VALUE_CONTENTS (val);
CORE_ADDR addr = unpack_pointer (type, valaddr);
if (TYPE_CODE (type) != TYPE_CODE_PTR || addr != 0)
{
int i;
char *name = TYPE_NAME (type);
if (name)
fputs_filtered (name, stream);
else if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_VOID)
fputs_filtered ("PTR", stream);
else
{
fprintf_filtered (stream, "(");
type_print (type, "", stream, -1);
fprintf_filtered (stream, ")");
}
fprintf_filtered (stream, "(");
i = val_print (type, valaddr, 0, VALUE_ADDRESS (val),
stream, format, 1, 0, pretty);
fprintf_filtered (stream, ")");
return i;
}
}
return (val_print (type, VALUE_CONTENTS (val), 0,
VALUE_ADDRESS (val), stream, format, 1, 0, pretty));
}

134
gdb/coff-solib.c Normal file
View File

@ -0,0 +1,134 @@
/* Handle COFF SVR3 shared libraries for GDB, the GNU Debugger.
Copyright 1993 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "frame.h"
#include "bfd.h"
#include "gdbcore.h"
#include "symtab.h"
/*
GLOBAL FUNCTION
coff_solib_add -- add a shared library files to the symtab list. We
examine the `.lib' section of the exec file and determine the names of
the shared libraries.
This function is responsible for discovering those names and
addresses, and saving sufficient information about them to allow
their symbols to be read at a later time.
SYNOPSIS
void coff_solib_add (char *arg_string, int from_tty,
struct target_ops *target)
DESCRIPTION
*/
void
coff_solib_add (arg_string, from_tty, target)
char *arg_string;
int from_tty;
struct target_ops *target;
{
asection *libsect;
libsect = bfd_get_section_by_name (exec_bfd, ".lib");
if (libsect)
{
int libsize;
unsigned char *lib;
struct libent
{
bfd_byte len[4];
bfd_byte nameoffset[4];
};
libsize = bfd_section_size (exec_bfd, libsect);
lib = (unsigned char *) alloca (libsize);
bfd_get_section_contents (exec_bfd, libsect, lib, 0, libsize);
while (libsize > 0)
{
struct libent *ent;
struct objfile *objfile;
int len, nameoffset;
char *filename;
ent = (struct libent *)lib;
len = bfd_get_32 (exec_bfd, ent->len);
nameoffset = bfd_get_32 (exec_bfd, ent->nameoffset);
if (len <= 0)
break;
filename = (char *)ent + nameoffset * 4;
objfile = symbol_file_add (filename, from_tty,
0, /* addr */
0, /* not mainline */
0, /* not mapped */
0, /* Not readnow */
0, /* Not user loaded */
1); /* Is a solib */
libsize -= len * 4;
lib += len * 4;
}
/* Getting new symbols may change our opinion about what is
frameless. */
reinit_frame_cache ();
}
}
/*
GLOBAL FUNCTION
coff_solib_create_inferior_hook -- shared library startup support
SYNOPSIS
void coff_solib_create_inferior_hook()
DESCRIPTION
When gdb starts up the inferior, the kernel maps in the shared
libraries. We get here with the target stopped at it's first
instruction, and the libraries already mapped. At this point, this
function gets called via expansion of the macro
SOLIB_CREATE_INFERIOR_HOOK.
*/
void
coff_solib_create_inferior_hook()
{
coff_solib_add ((char *) 0, 0, (struct target_ops *) 0);
}

190
gdb/coff-solib.h Normal file
View File

@ -0,0 +1,190 @@
/* COFF (SVR3) Shared library declarations for GDB, the GNU Debugger.
Copyright (C) 1992 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifdef __STDC__ /* Forward decl's for prototypes */
struct target_ops;
#endif
/* Called when we free all symtabs, to free the shared library information
as well. */
#if 0
#define CLEAR_SOLIB coff_clear_solib
extern void
coff_clear_solib PARAMS ((void));
#endif
/* Called to add symbols from a shared library to gdb's symbol table. */
#define SOLIB_ADD(filename, from_tty, targ) \
coff_solib_add (filename, from_tty, targ)
extern void
coff_solib_add PARAMS ((char *, int, struct target_ops *));
/* Function to be called when the inferior starts up, to discover the names
of shared libraries that are dynamically linked, the base addresses to
which they are linked, and sufficient information to read in their symbols
at a later time. */
#define SOLIB_CREATE_INFERIOR_HOOK(PID) coff_solib_create_inferior_hook()
extern void
coff_solib_create_inferior_hook PARAMS((void)); /* solib.c */
/* Function to be called to remove the connection between debugger and
dynamic linker that was established by SOLIB_CREATE_INFERIOR_HOOK.
(This operation does not remove shared library information from
the debugger, as CLEAR_SOLIB does.)
This functionality is presently not implemented for this target.
*/
#define SOLIB_REMOVE_INFERIOR_HOOK(PID) (0)
/* This function is called by the "catch load" command. It allows
the debugger to be notified by the dynamic linker when a specified
library file (or any library file, if filename is NULL) is loaded.
Presently, this functionality is not implemented.
*/
#define SOLIB_CREATE_CATCH_LOAD_HOOK(pid,tempflag,filename,cond_string) \
error("catch of library loads/unloads not yet implemented on this platform")
/* This function is called by the "catch unload" command. It allows
the debugger to be notified by the dynamic linker when a specified
library file (or any library file, if filename is NULL) is unloaded.
Presently, this functionality is not implemented.
*/
#define SOLIB_CREATE_CATCH_UNLOAD_HOOK(pid,tempflag,filename,cond_string) \
error("catch of library loads/unloads not yet implemented on this platform")
/* This function returns TRUE if the dynamic linker has just reported
a load of a library.
This function must be used only when the inferior has stopped in
the dynamic linker hook, or undefined results are guaranteed.
Presently, this functionality is not implemented.
*/
/*
#define SOLIB_HAVE_LOAD_EVENT(pid) \
error("catch of library loads/unloads not yet implemented on this platform")
*/
#define SOLIB_HAVE_LOAD_EVENT(pid) \
(0)
/* This function returns a pointer to the string representation of the
pathname of the dynamically-linked library that has just been loaded.
This function must be used only when SOLIB_HAVE_LOAD_EVENT is TRUE,
or undefined results are guaranteed.
This string's contents are only valid immediately after the inferior
has stopped in the dynamic linker hook, and becomes invalid as soon
as the inferior is continued. Clients should make a copy of this
string if they wish to continue the inferior and then access the string.
Presently, this functionality is not implemented.
*/
/*
#define SOLIB_LOADED_LIBRARY_PATHNAME(pid) \
error("catch of library loads/unloads not yet implemented on this platform")
*/
#define SOLIB_LOADED_LIBRARY_PATHNAME(pid) \
(0)
/* This function returns TRUE if the dynamic linker has just reported
an unload of a library.
This function must be used only when the inferior has stopped in
the dynamic linker hook, or undefined results are guaranteed.
Presently, this functionality is not implemented.
*/
/*
#define SOLIB_HAVE_UNLOAD_EVENT(pid) \
error("catch of library loads/unloads not yet implemented on this platform")
*/
#define SOLIB_HAVE_UNLOAD_EVENT(pid) \
(0)
/* This function returns a pointer to the string representation of the
pathname of the dynamically-linked library that has just been unloaded.
This function must be used only when SOLIB_HAVE_UNLOAD_EVENT is TRUE,
or undefined results are guaranteed.
This string's contents are only valid immediately after the inferior
has stopped in the dynamic linker hook, and becomes invalid as soon
as the inferior is continued. Clients should make a copy of this
string if they wish to continue the inferior and then access the string.
Presently, this functionality is not implemented.
*/
/*
#define SOLIB_UNLOADED_LIBRARY_PATHNAME(pid) \
error("catch of library loads/unloads not yet implemented on this platform")
*/
#define SOLIB_UNLOADED_LIBRARY_PATHNAME(pid) \
(0)
/* This function returns TRUE if pc is the address of an instruction that
lies within the dynamic linker (such as the event hook, or the dld
itself).
This function must be used only when a dynamic linker event has been
caught, and the inferior is being stepped out of the hook, or undefined
results are guaranteed.
Presently, this functionality is not implemented.
*/
/*
#define SOLIB_IN_DYNAMIC_LINKER(pid,pc) \
error("catch of library loads/unloads not yet implemented on this platform")
*/
#define SOLIB_IN_DYNAMIC_LINKER(pid,pc) \
(0)
/* This function must be called when the inferior is killed, and the program
restarted. This is not the same as CLEAR_SOLIB, in that it doesn't discard
any symbol tables.
Presently, this functionality is not implemented.
*/
#define SOLIB_RESTART() \
(0)
/* If we can't set a breakpoint, and it's in a shared library, just
disable it. */
#if 0
#define DISABLE_UNSETTABLE_BREAK(addr) coff_solib_address(addr)
extern int
solib_address PARAMS ((CORE_ADDR)); /* solib.c */
#endif

2255
gdb/coffread.c Normal file

File diff suppressed because it is too large Load Diff

1564
gdb/command.c Normal file

File diff suppressed because it is too large Load Diff

259
gdb/command.h Normal file
View File

@ -0,0 +1,259 @@
/* Header file for command-reading library command.c.
Copyright (C) 1986, 1989, 1990 Free Software Foundation, Inc.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if !defined (COMMAND_H)
#define COMMAND_H 1
/* Not a set/show command. Note that some commands which begin with
"set" or "show" might be in this category, if their syntax does
not fall into one of the following categories. */
typedef enum cmd_types {
not_set_cmd,
set_cmd,
show_cmd
} cmd_types;
/* Types of "set" or "show" command. */
typedef enum var_types {
/* "on" or "off". *VAR is an integer which is nonzero for on,
zero for off. */
var_boolean,
/* Unsigned Integer. *VAR is an unsigned int. The user can type 0
to mean "unlimited", which is stored in *VAR as UINT_MAX. */
var_uinteger,
/* Like var_uinteger but signed. *VAR is an int. The user can type 0
to mean "unlimited", which is stored in *VAR as INT_MAX. */
var_integer,
/* String which the user enters with escapes (e.g. the user types \n and
it is a real newline in the stored string).
*VAR is a malloc'd string, or NULL if the string is empty. */
var_string,
/* String which stores what the user types verbatim.
*VAR is a malloc'd string, or NULL if the string is empty. */
var_string_noescape,
/* String which stores a filename.
*VAR is a malloc'd string, or NULL if the string is empty. */
var_filename,
/* ZeroableInteger. *VAR is an int. Like Unsigned Integer except
that zero really means zero. */
var_zinteger,
/* Enumerated type. Can only have one of the specified values. *VAR is a
char pointer to the name of the element that we find. */
var_enum
} var_types;
/* This structure records one command'd definition. */
struct cmd_list_element
{
/* Points to next command in this list. */
struct cmd_list_element *next;
/* Name of this command. */
char *name;
/* Command class; class values are chosen by application program. */
enum command_class class;
/* Function definition of this command.
NO_FUNCTION for command class names and for help topics that
are not really commands. */
union
{
/* If type is not_set_cmd, call it like this: */
void (*cfunc) PARAMS ((char *args, int from_tty));
/* If type is cmd_set or show_cmd, first set the variables, and
then call this. */
void (*sfunc) PARAMS ((char *args, int from_tty,
struct cmd_list_element *c));
} function;
# define NO_FUNCTION ((void (*) PARAMS((char *args, int from_tty))) 0)
/* Documentation of this command (or help topic).
First line is brief documentation; remaining lines form, with it,
the full documentation. First line should end with a period.
Entire string should also end with a period, not a newline. */
char *doc;
/* Hook for another command to be executed before this command. */
struct cmd_list_element *hook;
/* Nonzero identifies a prefix command. For them, the address
of the variable containing the list of subcommands. */
struct cmd_list_element **prefixlist;
/* For prefix commands only:
String containing prefix commands to get here: this one
plus any others needed to get to it. Should end in a space.
It is used before the word "command" in describing the
commands reached through this prefix. */
char *prefixname;
/* For prefix commands only:
nonzero means do not get an error if subcommand is not
recognized; call the prefix's own function in that case. */
char allow_unknown;
/* Nonzero says this is an abbreviation, and should not
be mentioned in lists of commands.
This allows "br<tab>" to complete to "break", which it
otherwise wouldn't. */
char abbrev_flag;
/* Completion routine for this command. TEXT is the text beyond
what was matched for the command itself (leading whitespace is
skipped). It stops where we are supposed to stop completing
(rl_point) and is '\0' terminated.
Return value is a malloc'd vector of pointers to possible completions
terminated with NULL. If there are no completions, returning a pointer
to a NULL would work but returning NULL itself is also valid.
WORD points in the same buffer as TEXT, and completions should be
returned relative to this position. For example, suppose TEXT is "foo"
and we want to complete to "foobar". If WORD is "oo", return
"oobar"; if WORD is "baz/foo", return "baz/foobar". */
char ** (*completer) PARAMS ((char *text, char *word));
/* Type of "set" or "show" command (or SET_NOT_SET if not "set"
or "show"). */
cmd_types type;
/* Pointer to variable affected by "set" and "show". Doesn't matter
if type is not_set. */
char *var;
/* What kind of variable is *VAR? */
var_types var_type;
/* Pointer to NULL terminated list of enumerated values (like argv). */
char **enums;
/* Pointer to command strings of user-defined commands */
struct command_line *user_commands;
/* Pointer to command that is hooked by this one,
so the hook can be removed when this one is deleted. */
struct cmd_list_element *hookee;
/* Pointer to command that is aliased by this one, so the
aliased command can be located in case it has been hooked. */
struct cmd_list_element *cmd_pointer;
};
/* Forward-declarations of the entry-points of command.c. */
extern struct cmd_list_element *
add_cmd PARAMS ((char *, enum command_class, void (*fun) (char *, int),
char *, struct cmd_list_element **));
extern struct cmd_list_element *
add_alias_cmd PARAMS ((char *, char *, enum command_class, int,
struct cmd_list_element **));
extern struct cmd_list_element *
add_prefix_cmd PARAMS ((char *, enum command_class, void (*fun) (char *, int),
char *, struct cmd_list_element **, char *, int,
struct cmd_list_element **));
extern struct cmd_list_element *
add_abbrev_prefix_cmd PARAMS ((char *, enum command_class,
void (*fun) (char *, int), char *,
struct cmd_list_element **, char *, int,
struct cmd_list_element **));
extern struct cmd_list_element *
lookup_cmd PARAMS ((char **, struct cmd_list_element *, char *, int, int));
extern struct cmd_list_element *
lookup_cmd_1 PARAMS ((char **, struct cmd_list_element *,
struct cmd_list_element **, int));
extern void
add_com PARAMS ((char *, enum command_class, void (*fun)(char *, int),
char *));
extern void
add_com_alias PARAMS ((char *, char *, enum command_class, int));
extern void
add_info PARAMS ((char *, void (*fun) (char *, int), char *));
extern void
add_info_alias PARAMS ((char *, char *, int));
extern char **
complete_on_cmdlist PARAMS ((struct cmd_list_element *, char *, char *));
extern char **
complete_on_enum PARAMS ((char **enumlist, char *, char *));
extern void
delete_cmd PARAMS ((char *, struct cmd_list_element **));
extern void
help_cmd PARAMS ((char *, GDB_FILE *));
extern void
help_list PARAMS ((struct cmd_list_element *, char *, enum command_class,
GDB_FILE *));
extern void
help_cmd_list PARAMS ((struct cmd_list_element *, enum command_class, char *,
int, GDB_FILE *));
extern struct cmd_list_element *
add_set_cmd PARAMS ((char *, enum command_class, var_types, char *, char *,
struct cmd_list_element **));
extern struct cmd_list_element *
add_set_enum_cmd PARAMS ((char *name, enum command_class, char *list[],
char *var, char *doc, struct cmd_list_element **c));
extern struct cmd_list_element *
add_show_from_set PARAMS ((struct cmd_list_element *,
struct cmd_list_element **));
/* Do a "set" or "show" command. ARG is NULL if no argument, or the text
of the argument, and FROM_TTY is nonzero if this command is being entered
directly by the user (i.e. these are just like any other
command). C is the command list element for the command. */
extern void
do_setshow_command PARAMS ((char *, int, struct cmd_list_element *));
/* Do a "show" command for each thing on a command list. */
extern void
cmd_show_list PARAMS ((struct cmd_list_element *, int, char *));
extern void
error_no_arg PARAMS ((char *));
extern void
dont_repeat PARAMS ((void));
/* Used to mark commands that don't do anything. If we just leave the
function field NULL, the command is interpreted as a help topic, or
as a class of commands. */
extern void
not_just_help_class_command PARAMS ((char *, int));
#endif /* !defined (COMMAND_H) */

166
gdb/complaints.c Normal file
View File

@ -0,0 +1,166 @@
/* Support for complaint handling during symbol reading in GDB.
Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "complaints.h"
#include "gdbcmd.h"
/* Structure to manage complaints about symbol file contents. */
struct complaint complaint_root[1] = {
{
(char *) NULL, /* Complaint message */
0, /* Complaint counter */
complaint_root /* Next complaint. */
}
};
/* How many complaints about a particular thing should be printed before
we stop whining about it? Default is no whining at all, since so many
systems have ill-constructed symbol files. */
static unsigned int stop_whining = 0;
/* Should each complaint be self explanatory, or should we assume that
a series of complaints is being produced?
case 0: self explanatory message.
case 1: First message of a series that must start off with explanation.
case 2: Subsequent message, when user already knows we are reading
symbols and we can just state our piece. */
static int complaint_series = 0;
/* External variables and functions referenced. */
extern int info_verbose;
/* Functions to handle complaints during symbol reading. */
/* Print a complaint about the input symbols, and link the complaint block
into a chain for later handling. */
/* VARARGS */
void
#ifdef ANSI_PROTOTYPES
complain (struct complaint *complaint, ...)
#else
complain (va_alist)
va_dcl
#endif
{
va_list args;
#ifdef ANSI_PROTOTYPES
va_start (args, complaint);
#else
struct complaint *complaint;
va_start (args);
complaint = va_arg (args, struct complaint *);
#endif
complaint -> counter++;
if (complaint -> next == NULL)
{
complaint -> next = complaint_root -> next;
complaint_root -> next = complaint;
}
if (complaint -> counter > stop_whining)
{
return;
}
wrap_here ("");
switch (complaint_series + (info_verbose << 1))
{
/* Isolated messages, must be self-explanatory. */
case 0:
begin_line ();
puts_filtered ("During symbol reading, ");
wrap_here ("");
vprintf_filtered (complaint -> message, args);
puts_filtered (".\n");
break;
/* First of a series, without `set verbose'. */
case 1:
begin_line ();
puts_filtered ("During symbol reading...");
vprintf_filtered (complaint -> message, args);
puts_filtered ("...");
wrap_here ("");
complaint_series++;
break;
/* Subsequent messages of a series, or messages under `set verbose'.
(We'll already have produced a "Reading in symbols for XXX..."
message and will clean up at the end with a newline.) */
default:
vprintf_filtered (complaint -> message, args);
puts_filtered ("...");
wrap_here ("");
}
/* If GDB dumps core, we'd like to see the complaints first. Presumably
GDB will not be sending so many complaints that this becomes a
performance hog. */
gdb_flush (gdb_stdout);
va_end (args);
}
/* Clear out all complaint counters that have ever been incremented.
If sym_reading is 1, be less verbose about successive complaints,
since the messages are appearing all together during a command that
reads symbols (rather than scattered around as psymtabs get fleshed
out into symtabs at random times). If noisy is 1, we are in a
noisy symbol reading command, and our caller will print enough
context for the user to figure it out. */
void
clear_complaints (sym_reading, noisy)
int sym_reading;
int noisy;
{
struct complaint *p;
for (p = complaint_root -> next; p != complaint_root; p = p -> next)
{
p -> counter = 0;
}
if (!sym_reading && !noisy && complaint_series > 1)
{
/* Terminate previous series, since caller won't. */
puts_filtered ("\n");
}
complaint_series = sym_reading ? 1 + noisy : 0;
}
void
_initialize_complaints ()
{
add_show_from_set
(add_set_cmd ("complaints", class_support, var_zinteger,
(char *) &stop_whining,
"Set max number of complaints about incorrect symbols.",
&setlist),
&showlist);
}

53
gdb/complaints.h Normal file
View File

@ -0,0 +1,53 @@
/* Definitions for complaint handling during symbol reading in GDB.
Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if !defined (COMPLAINTS_H)
#define COMPLAINTS_H
/* Support for complaining about things in the symbol file that aren't
catastrophic.
Each such thing gets a counter. The first time we have the problem,
during a symbol read, we report it. At the end of symbol reading,
if verbose, we report how many of each problem we had. */
struct complaint
{
char *message;
unsigned counter;
struct complaint *next;
};
/* Root of the chain of complaints that have at some point been issued.
This is used to reset the counters, and/or report the total counts. */
extern struct complaint complaint_root[1];
/* Functions that handle complaints. (in complaints.c) */
extern void
complain PARAMS ((struct complaint *, ...));
extern void
clear_complaints PARAMS ((int, int));
#endif /* !defined (COMPLAINTS_H) */

325
gdb/config.in Normal file
View File

@ -0,0 +1,325 @@
/* config.in. Generated automatically from configure.in by autoheader. */
/* Whether malloc must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_MALLOC
/* Whether realloc must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_REALLOC
/* Whether free must be declared even if <stdlib.h> is included. */
#undef NEED_DECLARATION_FREE
/* Whether strerror must be declared even if <string.h> is included. */
#undef NEED_DECLARATION_STRERROR
/* Define if on AIX 3.
System headers sometimes define this.
We just want to avoid a redefinition error message. */
#ifndef _ALL_SOURCE
#undef _ALL_SOURCE
#endif
/* Define if using alloca.c. */
#undef C_ALLOCA
/* Define to empty if the keyword does not work. */
#undef const
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
This function is required for alloca.c support on those systems. */
#undef CRAY_STACKSEG_END
/* Define if you have alloca, as a function or macro. */
#undef HAVE_ALLOCA
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
#undef HAVE_ALLOCA_H
/* Define if the `long double' type works. */
#undef HAVE_LONG_DOUBLE
/* Define if you have a working `mmap' system call. */
#undef HAVE_MMAP
/* Define as __inline if that's what the C compiler calls it. */
#undef inline
/* Define to `long' if <sys/types.h> doesn't define. */
#undef off_t
/* Define if you need to in order for stat and other things to work. */
#undef _POSIX_SOURCE
/* Define as the return type of signal handlers (int or void). */
#undef RETSIGTYPE
/* Define to `unsigned' if <sys/types.h> doesn't define. */
#undef size_t
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown
*/
#undef STACK_DIRECTION
/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly. */
#undef STAT_MACROS_BROKEN
/* Define if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define if ioctl argument PIOCSET is available. */
#undef HAVE_PROCFS_PIOCSET
/* /proc PID entries are directories containing the files
ctl as map status */
#undef HAVE_MULTIPLE_PROC_FDS
/* Define if the `long long' type works. */
#undef CC_HAS_LONG_LONG
/* Define if the "ll" format works to print long long ints. */
#undef PRINTF_HAS_LONG_LONG
/* Define if the "%Lg" format works to print long doubles. */
#undef PRINTF_HAS_LONG_DOUBLE
/* Define if the "%Lg" format works to scan long doubles. */
#undef SCANF_HAS_LONG_DOUBLE
/* Define if using Solaris thread debugging. */
#undef HAVE_THREAD_DB_LIB
/* Define on a GNU/Linux system to work around problems in sys/procfs.h. */
#undef START_INFERIOR_TRAPS_EXPECTED
#undef sys_quotactl
/* Define if you have HPUX threads */
#undef HAVE_HPUX_THREAD_SUPPORT
/* Define if you want to use the memory mapped malloc package (mmalloc). */
#undef USE_MMALLOC
/* Define if the runtime uses a routine from mmalloc before gdb has a chance
to initialize mmalloc, and we want to force checking to be used anyway.
This may cause spurious memory corruption messages if the runtime tries
to explicitly deallocate that memory when gdb calls exit. */
#undef MMCHECK_FORCE
/* Define if you want to use the full-screen terminal user interface. */
#undef TUI
/* Define if <proc_service.h> on solaris uses int instead of
size_t, and assorted other type changes. */
#undef PROC_SERVICE_IS_OLD
/* Set to true if the save_state_t structure is present */
#define HAVE_STRUCT_SAVE_STATE_T 0
/* Set to true if the save_state_t structure has the ss_wide member */
#define HAVE_STRUCT_MEMBER_SS_WIDE 0
/* Define if you have the __argz_count function. */
#undef HAVE___ARGZ_COUNT
/* Define if you have the __argz_next function. */
#undef HAVE___ARGZ_NEXT
/* Define if you have the __argz_stringify function. */
#undef HAVE___ARGZ_STRINGIFY
/* Define if you have the bcopy function. */
#undef HAVE_BCOPY
/* Define if you have the btowc function. */
#undef HAVE_BTOWC
/* Define if you have the bzero function. */
#undef HAVE_BZERO
/* Define if you have the dcgettext function. */
#undef HAVE_DCGETTEXT
/* Define if you have the getcwd function. */
#undef HAVE_GETCWD
/* Define if you have the getpagesize function. */
#undef HAVE_GETPAGESIZE
/* Define if you have the isascii function. */
#undef HAVE_ISASCII
/* Define if you have the munmap function. */
#undef HAVE_MUNMAP
/* Define if you have the putenv function. */
#undef HAVE_PUTENV
/* Define if you have the sbrk function. */
#undef HAVE_SBRK
/* Define if you have the setenv function. */
#undef HAVE_SETENV
/* Define if you have the setlocale function. */
#undef HAVE_SETLOCALE
/* Define if you have the setpgid function. */
#undef HAVE_SETPGID
/* Define if you have the sigaction function. */
#undef HAVE_SIGACTION
/* Define if you have the stpcpy function. */
#undef HAVE_STPCPY
/* Define if you have the strcasecmp function. */
#undef HAVE_STRCASECMP
/* Define if you have the strchr function. */
#undef HAVE_STRCHR
/* Define if you have the <argz.h> header file. */
#undef HAVE_ARGZ_H
/* Define if you have the <asm/debugreg.h> header file. */
#undef HAVE_ASM_DEBUGREG_H
/* Define if you have the <ctype.h> header file. */
#undef HAVE_CTYPE_H
/* Define if you have the <curses.h> header file. */
#undef HAVE_CURSES_H
/* Define if you have the <endian.h> header file. */
#undef HAVE_ENDIAN_H
/* Define if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
/* Define if you have the <link.h> header file. */
#undef HAVE_LINK_H
/* Define if you have the <locale.h> header file. */
#undef HAVE_LOCALE_H
/* Define if you have the <malloc.h> header file. */
#undef HAVE_MALLOC_H
/* Define if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define if you have the <nl_types.h> header file. */
#undef HAVE_NL_TYPES_H
/* Define if you have the <objlist.h> header file. */
#undef HAVE_OBJLIST_H
/* Define if you have the <ptrace.h> header file. */
#undef HAVE_PTRACE_H
/* Define if you have the <sgtty.h> header file. */
#undef HAVE_SGTTY_H
/* Define if you have the <stddef.h> header file. */
#undef HAVE_STDDEF_H
/* Define if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define if you have the <sys/debugreg.h> header file. */
#undef HAVE_SYS_DEBUGREG_H
/* Define if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
/* Define if you have the <sys/procfs.h> header file. */
#undef HAVE_SYS_PROCFS_H
/* Define if you have the <sys/ptrace.h> header file. */
#undef HAVE_SYS_PTRACE_H
/* Define if you have the <sys/reg.h> header file. */
#undef HAVE_SYS_REG_H
/* Define if you have the <sys/wait.h> header file. */
#undef HAVE_SYS_WAIT_H
/* Define if you have the <term.h> header file. */
#undef HAVE_TERM_H
/* Define if you have the <termio.h> header file. */
#undef HAVE_TERMIO_H
/* Define if you have the <termios.h> header file. */
#undef HAVE_TERMIOS_H
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define if you have the <values.h> header file. */
#undef HAVE_VALUES_H
/* Define if you have the <wait.h> header file. */
#undef HAVE_WAIT_H
/* Define if you have the <wchar.h> header file. */
#undef HAVE_WCHAR_H
/* Define if you have the <wctype.h> header file. */
#undef HAVE_WCTYPE_H
/* Define if you have the dl library (-ldl). */
#undef HAVE_LIBDL
/* Define if you have the m library (-lm). */
#undef HAVE_LIBM
/* Define if you have the w library (-lw). */
#undef HAVE_LIBW
/* Define if you have the stpcpy function */
#undef HAVE_STPCPY
/* Define if your locale.h file contains LC_MESSAGES. */
#undef HAVE_LC_MESSAGES
/* Define to 1 if NLS is requested */
#undef ENABLE_NLS
/* Define as 1 if you have gettext and don't want to use GNU gettext. */
#undef HAVE_GETTEXT
/* Define if malloc is not declared in system header files. */
#undef NEED_DECLARATION_MALLOC
/* Define if realloc is not declared in system header files. */
#undef NEED_DECLARATION_REALLOC
/* Define if free is not declared in system header files. */
#undef NEED_DECLARATION_FREE
/* Define if strerror is not declared in system header files. */
#undef NEED_DECLARATION_STRERROR
/* Define if strdup is not declared in system header files. */
#undef NEED_DECLARATION_STRDUP
/* Define if <sys/procfs.h> has pstatus_t. */
#undef HAVE_PSTATUS_T
/* Define if <sys/procfs.h> has prrun_t. */
#undef HAVE_PRRUN_T
/* Define if <sys/procfs.h> has gregset_t. */
#undef HAVE_GREGSET_T
/* Define if <sys/procfs.h> has fpregset_t. */
#undef HAVE_FPREGSET_T

View File

@ -0,0 +1,13 @@
# Target: Remote AMD 29000 that runs Unix kernel on NYU Ultra3 processor board
# This builds a gdb that should run on a host (we use sun3os4) that
# then communicates over the serial line to either an Adapt or MiniMon,
# for use in debugging Unix kernels.
# As compared to ordinary remote 29K debugging, this changes the register
# numbering a bit, to hold kernel regs, and adds support for looking at
# the upage.
TDEPFILES= a29k-tdep.o remote-mm.o remote-adapt.o
TM_FILE= tm-ultra3.h
MT_CFLAGS = -DKERNEL_DEBUGGING -DNO_HIF_SUPPORT

View File

@ -0,0 +1,5 @@
# Target: AMD 29000 on EB29K board over a serial line
TDEPFILES= a29k-tdep.o remote-udi.o udip2soc.o udr.o udi2go32.o
TM_FILE= tm-a29k.h
MT_CFLAGS = $(HOST_IPC)

5
gdb/config/a29k/a29k.mt Normal file
View File

@ -0,0 +1,5 @@
# Target: AMD 29000
TDEPFILES= a29k-tdep.o remote-eb.o remote-adapt.o
TM_FILE= tm-a29k.h
MT_CFLAGS = -DNO_HIF_SUPPORT

View File

@ -0,0 +1,26 @@
/* Host definitions for GDB running on an a29k NYU Ultracomputer
Copyright (C) 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
Contributed by David Wood (wood@lab.ultra.nyu.edu).
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* If we ever *do* end up using the standard fetch_inferior_registers,
this is the right value for U_REGS_OFFSET. */
#define U_REGS_OFFSET 0
/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
#define FETCH_INFERIOR_REGISTERS

707
gdb/config/a29k/tm-a29k.h Normal file
View File

@ -0,0 +1,707 @@
/* Parameters for target machine AMD 29000, for GDB, the GNU debugger.
Copyright 1990, 1991, 1993, 1994 Free Software Foundation, Inc.
Contributed by Cygnus Support. Written by Jim Kingdon.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Parameters for an EB29K (a board which plugs into a PC and is
accessed through EBMON software running on the PC, which we
use as we'd use a remote stub (see remote-eb.c).
If gdb is ported to other a29k machines/systems, the
machine/system-specific parts should be removed from this file (a
la tm-m68k.h). */
/* Byte order is configurable, but this machine runs big-endian. */
#define TARGET_BYTE_ORDER BIG_ENDIAN
/* Floating point uses IEEE representations. */
#define IEEE_FLOAT
/* Recognize our magic number. */
#define BADMAG(x) ((x).f_magic != 0572)
/* Offset from address of function to start of its code.
Zero on most machines. */
#define FUNCTION_START_OFFSET 0
/* Advance PC across any function entry prologue instructions
to reach some "real" code. */
#define SKIP_PROLOGUE(pc) \
{ pc = skip_prologue (pc); }
CORE_ADDR skip_prologue ();
/* Immediately after a function call, return the saved pc.
Can't go through the frames for this because on some machines
the new frame is not set up until the new function executes
some instructions. */
#define SAVED_PC_AFTER_CALL(frame) ((frame->flags & TRANSPARENT_FRAME) \
? read_register (TPC_REGNUM) \
: read_register (LR0_REGNUM))
/* Stack grows downward. */
#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
/* Stack must be aligned on 32-bit boundaries when synthesizing
function calls. */
#define STACK_ALIGN(ADDR) (((ADDR) + 3) & ~3)
/* Sequence of bytes for breakpoint instruction. */
/* ASNEQ 0x50, gr1, gr1
The trap number 0x50 is chosen arbitrarily.
We let the command line (or previously included files) override this
setting. */
#ifndef BREAKPOINT
#if TARGET_BYTE_ORDER == BIG_ENDIAN
#define BREAKPOINT {0x72, 0x50, 0x01, 0x01}
#else /* Target is little-endian. */
#define BREAKPOINT {0x01, 0x01, 0x50, 0x72}
#endif /* Target is little-endian. */
#endif /* BREAKPOINT */
/* Amount PC must be decremented by after a breakpoint.
This is often the number of bytes in BREAKPOINT
but not always. */
#define DECR_PC_AFTER_BREAK 0
/* Say how long (ordinary) registers are. This is a piece of bogosity
used in push_word and a few other places; REGISTER_RAW_SIZE is the
real way to know how big a register is. */
#define REGISTER_SIZE 4
/* Allow the register declarations here to be overridden for remote
kernel debugging. */
#if !defined (REGISTER_NAMES)
/* Number of machine registers */
#define NUM_REGS 205
/* Initializer for an array of names of registers.
There should be NUM_REGS strings in this initializer.
FIXME, add floating point registers and support here.
Also note that this list does not attempt to deal with kernel
debugging (in which the first 32 registers are gr64-gr95). */
#define REGISTER_NAMES \
{"gr96", "gr97", "gr98", "gr99", "gr100", "gr101", "gr102", "gr103", "gr104", \
"gr105", "gr106", "gr107", "gr108", "gr109", "gr110", "gr111", "gr112", \
"gr113", "gr114", "gr115", "gr116", "gr117", "gr118", "gr119", "gr120", \
"gr121", "gr122", "gr123", "gr124", "gr125", "gr126", "gr127", \
"lr0", "lr1", "lr2", "lr3", "lr4", "lr5", "lr6", "lr7", "lr8", "lr9", \
"lr10", "lr11", "lr12", "lr13", "lr14", "lr15", "lr16", "lr17", "lr18", \
"lr19", "lr20", "lr21", "lr22", "lr23", "lr24", "lr25", "lr26", "lr27", \
"lr28", "lr29", "lr30", "lr31", "lr32", "lr33", "lr34", "lr35", "lr36", \
"lr37", "lr38", "lr39", "lr40", "lr41", "lr42", "lr43", "lr44", "lr45", \
"lr46", "lr47", "lr48", "lr49", "lr50", "lr51", "lr52", "lr53", "lr54", \
"lr55", "lr56", "lr57", "lr58", "lr59", "lr60", "lr61", "lr62", "lr63", \
"lr64", "lr65", "lr66", "lr67", "lr68", "lr69", "lr70", "lr71", "lr72", \
"lr73", "lr74", "lr75", "lr76", "lr77", "lr78", "lr79", "lr80", "lr81", \
"lr82", "lr83", "lr84", "lr85", "lr86", "lr87", "lr88", "lr89", "lr90", \
"lr91", "lr92", "lr93", "lr94", "lr95", "lr96", "lr97", "lr98", "lr99", \
"lr100", "lr101", "lr102", "lr103", "lr104", "lr105", "lr106", "lr107", \
"lr108", "lr109", "lr110", "lr111", "lr112", "lr113", "lr114", "lr115", \
"lr116", "lr117", "lr118", "lr119", "lr120", "lr121", "lr122", "lr123", \
"lr124", "lr125", "lr126", "lr127", \
"AI0", "AI1", "AI2", "AI3", "AI4", "AI5", "AI6", "AI7", "AI8", "AI9", \
"AI10", "AI11", "AI12", "AI13", "AI14", "AI15", "FP", \
"bp", "fc", "cr", "q", \
"vab", "ops", "cps", "cfg", "cha", "chd", "chc", "rbp", "tmc", "tmr", \
"pc0", "pc1", "pc2", "mmu", "lru", "fpe", "inte", "fps", "exo", "gr1", \
"alu", "ipc", "ipa", "ipb" }
/*
* Converts an sdb register number to an internal gdb register number.
* Currently under epi, gr96->0...gr127->31...lr0->32...lr127->159, or...
* gr64->0...gr95->31, lr0->32...lr127->159.
*/
#define SDB_REG_TO_REGNUM(value) \
(((value) >= 96 && (value) <= 127) ? ((value) - 96) : \
((value) >= 128 && (value) <= 255) ? ((value) - 128 + LR0_REGNUM) : \
(value))
/*
* Provide the processor register numbers of some registers that are
* expected/written in instructions that might change under different
* register sets. Namely, gcc can compile (-mkernel-registers) so that
* it uses gr64-gr95 in stead of gr96-gr127.
*/
#define MSP_HW_REGNUM 125 /* gr125 */
#define RAB_HW_REGNUM 126 /* gr126 */
/* Convert Processor Special register #x to REGISTER_NAMES register # */
#define SR_REGNUM(x) \
((x) < 15 ? VAB_REGNUM + (x) \
: (x) >= 128 && (x) < 131 ? IPC_REGNUM + (x) - 128 \
: (x) == 131 ? Q_REGNUM \
: (x) == 132 ? ALU_REGNUM \
: (x) >= 133 && (x) < 136 ? BP_REGNUM + (x) - 133 \
: (x) >= 160 && (x) < 163 ? FPE_REGNUM + (x) - 160 \
: (x) == 164 ? EXO_REGNUM \
: (error ("Internal error in SR_REGNUM"), 0))
#define GR96_REGNUM 0
/* Define the return register separately, so it can be overridden for
kernel procedure calling conventions. */
#define RETURN_REGNUM GR96_REGNUM
#define GR1_REGNUM 200
/* This needs to be the memory stack pointer, not the register stack pointer,
to make call_function work right. */
#define SP_REGNUM MSP_REGNUM
#define FP_REGNUM 33 /* lr1 */
/* Return register for transparent calling convention (gr122). */
#define TPC_REGNUM (122 - 96 + GR96_REGNUM)
/* Large Return Pointer (gr123). */
#define LRP_REGNUM (123 - 96 + GR96_REGNUM)
/* Static link pointer (gr124). */
#define SLP_REGNUM (124 - 96 + GR96_REGNUM)
/* Memory Stack Pointer (gr125). */
#define MSP_REGNUM (125 - 96 + GR96_REGNUM)
/* Register allocate bound (gr126). */
#define RAB_REGNUM (126 - 96 + GR96_REGNUM)
/* Register Free Bound (gr127). */
#define RFB_REGNUM (127 - 96 + GR96_REGNUM)
/* Register Stack Pointer. */
#define RSP_REGNUM GR1_REGNUM
#define LR0_REGNUM 32
#define BP_REGNUM 177
#define FC_REGNUM 178
#define CR_REGNUM 179
#define Q_REGNUM 180
#define VAB_REGNUM 181
#define OPS_REGNUM (VAB_REGNUM + 1)
#define CPS_REGNUM (VAB_REGNUM + 2)
#define CFG_REGNUM (VAB_REGNUM + 3)
#define CHA_REGNUM (VAB_REGNUM + 4)
#define CHD_REGNUM (VAB_REGNUM + 5)
#define CHC_REGNUM (VAB_REGNUM + 6)
#define RBP_REGNUM (VAB_REGNUM + 7)
#define TMC_REGNUM (VAB_REGNUM + 8)
#define TMR_REGNUM (VAB_REGNUM + 9)
#define NPC_REGNUM (VAB_REGNUM + 10) /* pc0 */
#define PC_REGNUM (VAB_REGNUM + 11) /* pc1 */
#define PC2_REGNUM (VAB_REGNUM + 12)
#define MMU_REGNUM (VAB_REGNUM + 13)
#define LRU_REGNUM (VAB_REGNUM + 14)
#define FPE_REGNUM (VAB_REGNUM + 15)
#define INTE_REGNUM (VAB_REGNUM + 16)
#define FPS_REGNUM (VAB_REGNUM + 17)
#define EXO_REGNUM (VAB_REGNUM + 18)
/* gr1 is defined above as 200 = VAB_REGNUM + 19 */
#define ALU_REGNUM (VAB_REGNUM + 20)
#define PS_REGNUM ALU_REGNUM
#define IPC_REGNUM (VAB_REGNUM + 21)
#define IPA_REGNUM (VAB_REGNUM + 22)
#define IPB_REGNUM (VAB_REGNUM + 23)
#endif /* !defined(REGISTER_NAMES) */
/* Total amount of space needed to store our copies of the machine's
register state, the array `registers'. */
#define REGISTER_BYTES (NUM_REGS * 4)
/* Index within `registers' of the first byte of the space for
register N. */
#define REGISTER_BYTE(N) ((N)*4)
/* Number of bytes of storage in the actual machine representation
for register N. */
/* All regs are 4 bytes. */
#define REGISTER_RAW_SIZE(N) (4)
/* Number of bytes of storage in the program's representation
for register N. */
/* All regs are 4 bytes. */
#define REGISTER_VIRTUAL_SIZE(N) (4)
/* Largest value REGISTER_RAW_SIZE can have. */
#define MAX_REGISTER_RAW_SIZE (4)
/* Largest value REGISTER_VIRTUAL_SIZE can have. */
#define MAX_REGISTER_VIRTUAL_SIZE (4)
/* Return the GDB type object for the "standard" data type
of data in register N. */
#define REGISTER_VIRTUAL_TYPE(N) \
(((N) == PC_REGNUM || (N) == LRP_REGNUM || (N) == SLP_REGNUM \
|| (N) == MSP_REGNUM || (N) == RAB_REGNUM || (N) == RFB_REGNUM \
|| (N) == GR1_REGNUM || (N) == FP_REGNUM || (N) == LR0_REGNUM \
|| (N) == NPC_REGNUM || (N) == PC2_REGNUM) \
? lookup_pointer_type (builtin_type_void) : builtin_type_int)
/* Store the address of the place in which to copy the structure the
subroutine will return. This is called from call_function. */
/* On the a29k the LRP points to the part of the structure beyond the first
16 words. */
#define STORE_STRUCT_RETURN(ADDR, SP) \
write_register (LRP_REGNUM, (ADDR) + 16 * 4);
/* Should call_function allocate stack space for a struct return? */
/* On the a29k objects over 16 words require the caller to allocate space. */
extern use_struct_convention_fn a29k_use_struct_convention;
#define USE_STRUCT_CONVENTION(gcc_p, type) a29k_use_struct_convention (gcc_p, type)
/* Extract from an array REGBUF containing the (raw) register state
a function return value of type TYPE, and copy that, in virtual format,
into VALBUF. */
#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
{ \
int reg_length = TYPE_LENGTH (TYPE); \
if (reg_length > 16 * 4) \
{ \
reg_length = 16 * 4; \
read_memory (*((int *)(REGBUF) + LRP_REGNUM), (VALBUF) + 16 * 4, \
TYPE_LENGTH (TYPE) - 16 * 4); \
} \
memcpy ((VALBUF), ((int *)(REGBUF))+RETURN_REGNUM, reg_length); \
}
/* Write into appropriate registers a function return value
of type TYPE, given in virtual format. */
#define STORE_RETURN_VALUE(TYPE,VALBUF) \
{ \
int reg_length = TYPE_LENGTH (TYPE); \
if (reg_length > 16 * 4) \
{ \
reg_length = 16 * 4; \
write_memory (read_register (LRP_REGNUM), \
(char *)(VALBUF) + 16 * 4, \
TYPE_LENGTH (TYPE) - 16 * 4); \
} \
write_register_bytes (REGISTER_BYTE (RETURN_REGNUM), (char *)(VALBUF), \
TYPE_LENGTH (TYPE)); \
}
/* The a29k user's guide documents well what the stacks look like.
But what isn't so clear there is how this interracts with the
symbols, or with GDB.
In the following saved_msp, saved memory stack pointer (which functions
as a memory frame pointer), means either
a register containing the memory frame pointer or, in the case of
functions with fixed size memory frames (i.e. those who don't use
alloca()), the result of the calculation msp + msize.
LOC_ARG, LOC_LOCAL - For GCC, these are relative to saved_msp.
For high C, these are relative to msp (making alloca impossible).
LOC_REGISTER, LOC_REGPARM - The register number is the number at the
time the function is running (after the prologue), or in the case
of LOC_REGPARM, may be a register number in the range 160-175.
The compilers do things like store an argument into memory, and then put out
a LOC_ARG for it, or put it into global registers and put out a
LOC_REGPARM. Thus is it important to execute the first line of
code (i.e. the line of the open brace, i.e. the prologue) of a function
before trying to print arguments or anything.
The following diagram attempts to depict what is going on in memory
(see also the _a29k user's guide_) and also how that interacts with
GDB frames. We arbitrarily pick fci->frame to point the same place
as the register stack pointer; since we set it ourself in
INIT_EXTRA_FRAME_INFO, and access it only through the FRAME_*
macros, it doesn't really matter exactly how we
do it. However, note that FRAME_FP is used in two ways in GDB:
(1) as a "magic cookie" which uniquely identifies frames (even over
calls to the inferior), (2) (in PC_IN_CALL_DUMMY [ON_STACK])
as the value of SP_REGNUM before the dummy frame was pushed. These
two meanings would be incompatible for the a29k if we defined
CALL_DUMMY_LOCATION == ON_STACK (but we don't, so don't worry about it).
Also note that "lr1" below, while called a frame pointer
in the user's guide, has only one function: To determine whether
registers need to be filled in the function epilogue.
Consider the code:
< call bar>
loc1: . . .
bar: sub gr1,gr1,rsize_b
. . .
add mfp,msp,0
sub msp,msp,msize_b
. . .
< call foo >
loc2: . . .
foo: sub gr1,gr1,rsize_f
. . .
add mfp,msp,0
sub msp,msp,msize_f
. . .
loc3: < suppose the inferior stops here >
memory stack register stack
| | |____________|
| | |____loc1____|
+------->|___________| | | ^
| | ^ | | locals_b | |
| | | | |____________| |
| | | | | | | rsize_b
| | | msize_b | | args_to_f | |
| | | | |____________| |
| | | | |____lr1_____| V
| | V | |____loc2____|<----------------+
| +--->|___________|<---------mfp | ^ |
| | | ^ | | locals_f | | |
| | | | msize_f | |____________| | |
| | | | | | | | rsize_f |
| | | V | | args | | |
| | |___________|<msp |____________| | |
| | |_____lr1____| V |
| | |___garbage__| <- gr1 <----+ |
| | | |
| | | |
| | pc=loc3 | |
| | | |
| | | |
| | frame cache | |
| | |_________________| | |
| | |rsize=rsize_b | | |
| | |msize=msize_b | | |
+---|--------saved_msp | | |
| |frame------------------------------------|---+
| |pc=loc2 | |
| |_________________| |
| |rsize=rsize_f | |
| |msize=msize_f | |
+--------saved_msp | |
|frame------------------------------------+
|pc=loc3 |
|_________________|
So, is that sufficiently confusing? Welcome to the 29000.
Notes:
* The frame for foo uses a memory frame pointer but the frame for
bar does not. In the latter case the saved_msp is
computed by adding msize to the saved_msp of the
next frame.
* msize is in the frame cache only for high C's sake. */
void read_register_stack ();
long read_register_stack_integer ();
#define FRAME_INIT_SAVED_REGS(fi) /*no-op*/
#define EXTRA_FRAME_INFO \
CORE_ADDR saved_msp; \
unsigned int rsize; \
unsigned int msize; \
unsigned char flags;
/* Bits for flags in EXTRA_FRAME_INFO */
#define TRANSPARENT_FRAME 0x1 /* This is a transparent frame */
#define MFP_USED 0x2 /* A memory frame pointer is used */
/* Because INIT_FRAME_PC gets passed fromleaf, that's where we init
not only ->pc and ->frame, but all the extra stuff, when called from
get_prev_frame_info, that is. */
#define INIT_EXTRA_FRAME_INFO(fromleaf, fci) init_extra_frame_info(fci)
void init_extra_frame_info ();
#define INIT_FRAME_PC(fromleaf, fci) init_frame_pc(fromleaf, fci)
void init_frame_pc ();
/* FRAME_CHAIN takes a FRAME
and produces the frame's chain-pointer.
However, if FRAME_CHAIN_VALID returns zero,
it means the given frame is the outermost one and has no caller. */
/* On the a29k, the nominal address of a frame is the address on the
register stack of the return address (the one next to the incoming
arguments, not down at the bottom so nominal address == stack pointer).
GDB expects "nominal address" to equal contents of FP_REGNUM,
at least when it comes time to create the innermost frame.
However, that doesn't work for us, so when creating the innermost
frame we set ->frame ourselves in INIT_EXTRA_FRAME_INFO. */
/* These are mostly dummies for the a29k because INIT_FRAME_PC
sets prev->frame instead. */
/* If rsize is zero, we must be at end of stack (or otherwise hosed).
If we don't check rsize, we loop forever if we see rsize == 0. */
#define FRAME_CHAIN(thisframe) \
((thisframe)->rsize == 0 \
? 0 \
: (thisframe)->frame + (thisframe)->rsize)
/* Determine if the frame has a 'previous' and back-traceable frame. */
#define FRAME_IS_UNCHAINED(frame) ((frame)->flags & TRANSPARENT_FRAME)
/* Find the previous frame of a transparent routine.
* For now lets not try and trace through a transparent routine (we might
* have to assume that all transparent routines are traps).
*/
#define FIND_PREV_UNCHAINED_FRAME(frame) 0
/* Define other aspects of the stack frame. */
/* A macro that tells us whether the function invocation represented
by FI does not have a frame on the stack associated with it. If it
does not, FRAMELESS is set to 1, else 0. */
#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
(FRAMELESS) = frameless_look_for_prologue(FI)
/* Saved pc (i.e. return address). */
#define FRAME_SAVED_PC(fraim) \
(read_register_stack_integer ((fraim)->frame + (fraim)->rsize, 4))
/* Local variables (i.e. LOC_LOCAL) are on the memory stack, with their
offsets being relative to the memory stack pointer (high C) or
saved_msp (gcc). */
#define FRAME_LOCALS_ADDRESS(fi) frame_locals_address (fi)
extern CORE_ADDR frame_locals_address ();
/* Return number of args passed to a frame.
Can return -1, meaning no way to tell. */
/* We tried going to the effort of finding the tags word and getting
the argcount field from it, to support debugging assembler code.
Problem was, the "argcount" field never did hold the argument
count. */
#define FRAME_NUM_ARGS(numargs, fi) ((numargs) = -1)
#define FRAME_ARGS_ADDRESS(fi) FRAME_LOCALS_ADDRESS (fi)
/* Return number of bytes at start of arglist that are not really args. */
#define FRAME_ARGS_SKIP 0
/* Provide our own get_saved_register. HAVE_REGISTER_WINDOWS is insufficient
because registers get renumbered on the a29k without getting saved. */
#define GET_SAVED_REGISTER
/* Call function stuff. */
/* The dummy frame looks like this (see also the general frame picture
above):
register stack
| | frame for function
| locals_sproc | executing at time
|________________| of call_function.
| | We must not disturb
| args_out_sproc | it.
memory stack |________________|
|____lr1_sproc___|<-+
| | |__retaddr_sproc_| | <-- gr1 (at start)
|____________|<-msp 0 <-----------mfp_dummy_____| |
| | (at start) | save regs | |
| arg_slop | | pc0,pc1 | |
| | | pc2,lr0 sproc | |
| (16 words) | | gr96-gr124 | |
|____________|<-msp 1--after | sr160-sr162 | |
| | PUSH_DUMMY_FRAME| sr128-sr135 | |
| struct ret | |________________| |
| 17+ | | | |
|____________|<- lrp | args_out_dummy | |
| struct ret | | (16 words) | |
| 16 | |________________| |
| (16 words) | |____lr1_dummy___|--+
|____________|<- msp 2--after |_retaddr_dummy__|<- gr1 after
| | struct ret | | PUSH_DUMMY_FRAME
| margs17+ | area allocated | locals_inf |
| | |________________| called
|____________|<- msp 4--when | | function's
| | inf called | args_out_inf | frame (set up
| margs16 | |________________| by called
| (16 words) | |_____lr1_inf____| function).
|____________|<- msp 3--after | . |
| | args pushed | . |
| | | . |
| |
arg_slop: This area is so that when the call dummy adds 16 words to
the msp, it won't end up larger than mfp_dummy (it is needed in the
case where margs and struct_ret do not add up to at least 16 words).
struct ret: This area is allocated by GDB if the return value is more
than 16 words. struct ret_16 is not used on the a29k.
margs: Pushed by GDB. The call dummy copies the first 16 words to
args_out_dummy.
retaddr_sproc: Contains the PC at the time we call the function.
set by PUSH_DUMMY_FRAME and read by POP_FRAME.
retaddr_dummy: This points to a breakpoint instruction in the dummy. */
/* Rsize for dummy frame, in bytes. */
/* Bytes for outgoing args, lr1, and retaddr. */
#define DUMMY_ARG (2 * 4 + 16 * 4)
/* Number of special registers (sr128-) to save. */
#define DUMMY_SAVE_SR128 8
/* Number of special registers (sr160-) to save. */
#define DUMMY_SAVE_SR160 3
/* Number of general (gr96- or gr64-) registers to save. */
#define DUMMY_SAVE_GREGS 29
#define DUMMY_FRAME_RSIZE \
(4 /* mfp_dummy */ \
+ 4 * 4 /* pc0, pc1, pc2, lr0 */ \
+ DUMMY_SAVE_GREGS * 4 \
+ DUMMY_SAVE_SR160 * 4 \
+ DUMMY_SAVE_SR128 * 4 \
+ DUMMY_ARG \
+ 4 /* pad to doubleword */ )
/* Push an empty stack frame, to record the current PC, etc. */
#define PUSH_DUMMY_FRAME push_dummy_frame()
extern void push_dummy_frame ();
/* Discard from the stack the innermost frame,
restoring all saved registers. */
#define POP_FRAME pop_frame()
extern void pop_frame ();
/* This sequence of words is the instructions
mtsrim cr, 15
loadm 0, 0, lr2, msp ; load first 16 words of arguments into registers
add msp, msp, 16 * 4 ; point to the remaining arguments
CONST_INSN:
const lr0,inf ; (replaced by half of target addr)
consth lr0,inf ; (replaced by other half of target addr)
calli lr0, lr0
aseq 0x40,gr1,gr1 ; nop
BREAKPT_INSN:
asneq 0x50,gr1,gr1 ; breakpoint (replaced by local breakpoint insn)
*/
#if TARGET_BYTE_ORDER == HOST_BYTE_ORDER
#define BS(const) const
#else
#define BS(const) (((const) & 0xff) << 24) | \
(((const) & 0xff00) << 8) | \
(((const) & 0xff0000) >> 8) | \
(((const) & 0xff000000) >> 24)
#endif
/* Position of the "const" and blkt instructions within CALL_DUMMY in bytes. */
#define CONST_INSN (3 * 4)
#define BREAKPT_INSN (7 * 4)
#define CALL_DUMMY { \
BS(0x0400870f),\
BS(0x36008200|(MSP_HW_REGNUM)), \
BS(0x15000040|(MSP_HW_REGNUM<<8)|(MSP_HW_REGNUM<<16)), \
BS(0x03ff80ff), \
BS(0x02ff80ff), \
BS(0xc8008080), \
BS(0x70400101), \
BS(0x72500101)}
#define CALL_DUMMY_LENGTH (8 * 4)
#define CALL_DUMMY_START_OFFSET 0 /* Start execution at beginning of dummy */
/* Helper macro for FIX_CALL_DUMMY. WORDP is a long * which points to a
word in target byte order; bits 0-7 and 16-23 of *WORDP are replaced with
bits 0-7 and 8-15 of DATA (which is in host byte order). */
#if TARGET_BYTE_ORDER == BIG_ENDIAN
#define STUFF_I16(WORDP, DATA) \
{ \
*((char *)(WORDP) + 3) = ((DATA) & 0xff);\
*((char *)(WORDP) + 1) = (((DATA) >> 8) & 0xff);\
}
#else /* Target is little endian. */
#define STUFF_I16(WORDP, DATA) \
{
*(char *)(WORDP) = ((DATA) & 0xff);
*((char *)(WORDP) + 2) = (((DATA) >> 8) & 0xff);
}
#endif /* Target is little endian. */
/* Insert the specified number of args and function address
into a call sequence of the above form stored at DUMMYNAME. */
/* Currently this stuffs in the address of the function that we are calling.
Since different a29k systems use different breakpoint instructions, it
also stuffs BREAKPOINT in the right place (to avoid having to
duplicate CALL_DUMMY in each tm-*.h file). */
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
{\
STUFF_I16((char *)dummyname + CONST_INSN, fun); \
STUFF_I16((char *)dummyname + CONST_INSN + 4, fun >> 16); \
/* FIXME memcpy ((char *)(dummyname) + BREAKPT_INSN, break_insn, 4); */ \
}
/* a29k architecture has separate data & instruction memories -- wired to
different pins on the chip -- and can't execute the data memory.
Also, there should be space after text_end;
we won't get a SIGSEGV or scribble on data space. */
#define CALL_DUMMY_LOCATION AFTER_TEXT_END
/* Because of this, we need (as a kludge) to know the addresses of the
text section. */
#define NEED_TEXT_START_END 1
/* How to translate register numbers in the .stab's into gdb's internal register
numbers. We don't translate them, but we warn if an invalid register
number is seen. Note that FIXME, we use the value "sym" as an implicit
argument in printing the error message. It happens to be available where
this macro is used. (This macro definition appeared in a late revision
of gdb-3.91.6 and is not well tested. Also, it should be a "complaint".) */
#define STAB_REG_TO_REGNUM(num) \
(((num) > LR0_REGNUM + 127) \
? fprintf(stderr, \
"Invalid register number %d in symbol table entry for %s\n", \
(num), SYMBOL_SOURCE_NAME (sym)), (num) \
: (num))
extern enum a29k_processor_types {
a29k_unknown,
/* Bit 0x400 of the CPS does *not* identify freeze mode, i.e. 29000,
29030, etc. */
a29k_no_freeze_mode,
/* Bit 0x400 of the CPS does identify freeze mode, i.e. 29050. */
a29k_freeze_mode
} processor_type;
/* We need three arguments for a general frame specification for the
"frame" or "info frame" command. */
#define SETUP_ARBITRARY_FRAME(argc, argv) setup_arbitrary_frame (argc, argv)
extern struct frame_info *setup_arbitrary_frame PARAMS ((int, CORE_ADDR *));

226
gdb/config/a29k/tm-ultra3.h Normal file
View File

@ -0,0 +1,226 @@
/* Parameters for NYU Ultracomputer 29000 target, for GDB, the GNU debugger.
Copyright 1990, 1991 Free Software Foundation, Inc.
Contributed by David Wood @ New York University (wood@nyu.edu).
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* This file includes tm-a29k.h, but predefines REGISTER_NAMES and
related macros. The file supports a a29k running our flavor of
Unix on our Ultra3 PE Boards. */
/* Byte order is configurable, but this machine runs big-endian. */
#define TARGET_BYTE_ORDER BIG_ENDIAN
/* Initializer for an array of names of registers.
There should be NUM_REGS strings in this initializer.
*/
#define NUM_REGS (EXO_REGNUM + 1)
#define REGISTER_NAMES { \
"gr1", \
"gr64", "gr65", "gr66", "gr67", "gr68", "gr69", "gr70", "gr71", "gr72", \
"gr73", "gr74", "gr75", "gr76", "gr77", "gr78", "gr79", "gr80", "gr81", \
"gr82", "gr83", "gr84", "gr85", "gr86", "gr87", "gr88", "gr89", "gr90", \
"gr91", "gr92", "gr93", "gr94", "gr95", \
"gr96", "gr97", "gr98", "gr99", "gr100", "gr101", "gr102", "gr103", "gr104", \
"gr105", "gr106", "gr107", "gr108", "gr109", "gr110", "gr111", "gr112", \
"gr113", "gr114", "gr115", "gr116", "gr117", "gr118", "gr119", "gr120", \
"gr121", "gr122", "gr123", "gr124", "gr125", "gr126", "gr127", \
"lr0", "lr1", "lr2", "lr3", "lr4", "lr5", "lr6", "lr7", "lr8", "lr9", \
"lr10", "lr11", "lr12", "lr13", "lr14", "lr15", "lr16", "lr17", "lr18", \
"lr19", "lr20", "lr21", "lr22", "lr23", "lr24", "lr25", "lr26", "lr27", \
"lr28", "lr29", "lr30", "lr31", "lr32", "lr33", "lr34", "lr35", "lr36", \
"lr37", "lr38", "lr39", "lr40", "lr41", "lr42", "lr43", "lr44", "lr45", \
"lr46", "lr47", "lr48", "lr49", "lr50", "lr51", "lr52", "lr53", "lr54", \
"lr55", "lr56", "lr57", "lr58", "lr59", "lr60", "lr61", "lr62", "lr63", \
"lr64", "lr65", "lr66", "lr67", "lr68", "lr69", "lr70", "lr71", "lr72", \
"lr73", "lr74", "lr75", "lr76", "lr77", "lr78", "lr79", "lr80", "lr81", \
"lr82", "lr83", "lr84", "lr85", "lr86", "lr87", "lr88", "lr89", "lr90", \
"lr91", "lr92", "lr93", "lr94", "lr95", "lr96", "lr97", "lr98", "lr99", \
"lr100", "lr101", "lr102", "lr103", "lr104", "lr105", "lr106", "lr107", \
"lr108", "lr109", "lr110", "lr111", "lr112", "lr113", "lr114", "lr115", \
"lr116", "lr117", "lr118", "lr119", "lr120", "lr121", "lr122", "lr123", \
"lr124", "lr125", "lr126", "lr127", \
"vab", "ops", "cps", "cfg", "cha", "chd", "chc", "rbp", "tmc", "tmr", \
"pc0", "pc1", "pc2", "mmu", "lru", \
"ipc", "ipa", "ipb", "q", "alu", "bp", "fc", "cr", \
"fpe", "int", "fps", "exo" }
#ifdef KERNEL_DEBUGGING
# define PADDR_U_REGNUM 22 /* gr86 */
# define RETURN_REGNUM GR64_REGNUM
#else
# define RETURN_REGNUM GR96_REGNUM
#endif /* KERNEL_DEBUGGING */
/* Should rename all GR96_REGNUM to RETURN_REGNUM */
#define GR1_REGNUM (0)
#define GR64_REGNUM 1
#define GR96_REGNUM (GR64_REGNUM + 32)
/* This needs to be the memory stack pointer, not the register stack pointer,
to make call_function work right. */
#define SP_REGNUM MSP_REGNUM
#define FP_REGNUM (LR0_REGNUM + 1) /* lr1 */
/* Large Return Pointer */
#define LRP_REGNUM (123 - 96 + RETURN_REGNUM)
/* Static link pointer */
#define SLP_REGNUM (124 - 96 + RETURN_REGNUM)
/* Memory Stack Pointer. */
#define MSP_REGNUM (125 - 96 + RETURN_REGNUM)
/* Register allocate bound. */
#define RAB_REGNUM (126 - 96 + RETURN_REGNUM)
/* Register Free Bound. */
#define RFB_REGNUM (127 - 96 + RETURN_REGNUM)
/* Register Stack Pointer. */
#define RSP_REGNUM GR1_REGNUM
#define LR0_REGNUM ( 32 + GR96_REGNUM)
/* Protected Special registers */
#define VAB_REGNUM (LR0_REGNUM + 128)
#define OPS_REGNUM (VAB_REGNUM + 1)
#define CPS_REGNUM (VAB_REGNUM + 2)
#define CFG_REGNUM (VAB_REGNUM + 3)
#define CHA_REGNUM (VAB_REGNUM + 4)
#define CHD_REGNUM (VAB_REGNUM + 5)
#define CHC_REGNUM (VAB_REGNUM + 6)
#define RBP_REGNUM (VAB_REGNUM + 7)
#define TMC_REGNUM (VAB_REGNUM + 8)
#define TMR_REGNUM (VAB_REGNUM + 9)
#define NPC_REGNUM (VAB_REGNUM + 10) /* pc0 */
#define PC_REGNUM (VAB_REGNUM + 11) /* pc1 */
#define PC2_REGNUM (VAB_REGNUM + 12) /* pc2 */
#define MMU_REGNUM (VAB_REGNUM + 13)
#define LRU_REGNUM (VAB_REGNUM + 14)
/* Register sequence gap */
/* Unprotected Special registers */
#define IPC_REGNUM (LRU_REGNUM + 1)
#define IPA_REGNUM (IPC_REGNUM + 1)
#define IPB_REGNUM (IPC_REGNUM + 2)
#define Q_REGNUM (IPC_REGNUM + 3)
#define ALU_REGNUM (IPC_REGNUM + 4)
#define PS_REGNUM ALU_REGNUM
#define BP_REGNUM (IPC_REGNUM + 5)
#define FC_REGNUM (IPC_REGNUM + 6)
#define CR_REGNUM (IPC_REGNUM + 7)
/* Register sequence gap */
#define FPE_REGNUM (CR_REGNUM + 1)
#define INT_REGNUM (FPE_REGNUM + 1)
#define FPS_REGNUM (FPE_REGNUM + 2)
/* Register sequence gap */
#define EXO_REGNUM (FPS_REGNUM + 1)
/* Special register #x. */
#define SR_REGNUM(x) \
((x) < 15 ? VAB_REGNUM + (x) \
: (x) >= 128 && (x) < 136 ? IPC_REGNUM + (x-128) \
: (x) >= 160 && (x) < 163 ? FPE_REGNUM + (x-160) \
: (x) == 164 ? EXO_REGNUM \
: (error ("Internal error in SR_REGNUM"), 0))
#ifndef KERNEL_DEBUGGING
/*
* This macro defines the register numbers (from REGISTER_NAMES) that
* are effectively unavailable to the user through ptrace(). It allows
* us to include the whole register set in REGISTER_NAMES (inorder to
* better support remote debugging). If it is used in
* fetch/store_inferior_registers() gdb will not complain about I/O errors
* on fetching these registers. If all registers in REGISTER_NAMES
* are available, then return false (0).
*/
#define CANNOT_STORE_REGISTER(regno) \
(((regno)>=GR64_REGNUM && (regno)<GR64_REGNUM+32) || \
((regno)==VAB_REGNUM) || \
((regno)==OPS_REGNUM) || \
((regno)>=CFG_REGNUM && (regno)<=TMR_REGNUM) || \
((regno)==MMU_REGNUM) || \
((regno)==LRU_REGNUM) || \
((regno)>=ALU_REGNUM) || \
((regno)==CR_REGNUM) || \
((regno)==EXO_REGNUM))
#define CANNOT_FETCH_REGISTER(regno) CANNOT_STORE_REGISTER(regno)
#endif /* KERNEL_DEBUGGING */
/*
* Converts an sdb register number to an internal gdb register number.
* Currently under gcc, gr96->0...gr128->31...lr0->32...lr127->159, or...
* gr64->0...gr95->31, lr0->32...lr127->159.
*/
#define SDB_REG_TO_REGNUM(value) (((value)<32) ? ((value)+RETURN_REGNUM) : \
((value)-32+LR0_REGNUM))
#ifdef KERNEL_DEBUGGING
/* ublock virtual address as defined in our sys/param.h */
/* FIXME: Should get this from sys/param.h */
# define UVADDR ((32*0x100000)-8192)
#endif
/*
* Are we in sigtramp(), needed in infrun.c. Specific to ultra3, because
* we take off the leading '_'.
*/
#if !defined(KERNEL_DEBUGGING)
#ifdef SYM1
# define IN_SIGTRAMP(pc, name) (name && STREQ ("sigtramp", name))
#else
Need to define IN_SIGTRAMP() for sym2.
#endif
#endif /* !KERNEL_DEBUGGING */
#include "a29k/tm-a29k.h"
/**** The following are definitions that override those in tm-a29k.h ****/
/* This sequence of words is the instructions
mtsrim cr, 15
loadm 0, 0, lr2, msp ; load first 16 words of arguments into registers
add msp, msp, 16 * 4 ; point to the remaining arguments
CONST_INSN:
const gr96,inf
consth gr96,inf
calli lr0, gr96
aseq 0x40,gr1,gr1 ; nop
asneq 0x50,gr1,gr1 ; breakpoint
When KERNEL_DEBUGGIN is defined, msp -> gr93, gr96 -> gr64,
7d -> 5d, 60 -> 40
*/
/* Position of the "const" instruction within CALL_DUMMY in bytes. */
#undef CALL_DUMMY
#if TARGET_BYTE_ORDER == HOST_BYTE_ORDER
#ifdef KERNEL_DEBUGGING /* gr96 -> gr64 */
# define CALL_DUMMY {0x0400870f, 0x3600825d, 0x155d5d40, 0x03ff40ff, \
0x02ff40ff, 0xc8008040, 0x70400101, 0x72500101}
#else
# define CALL_DUMMY {0x0400870f, 0x3600827d, 0x157d7d40, 0x03ff60ff, \
0x02ff60ff, 0xc8008060, 0x70400101, 0x72500101}
#endif /* KERNEL_DEBUGGING */
#else /* Byte order differs. */
you lose
#endif /* Byte order differs. */
#if !defined(KERNEL_DEBUGGING)
# ifdef SYM1
# undef DECR_PC_AFTER_BREAK
# define DECR_PC_AFTER_BREAK 0 /* Sym1 kernel does the decrement */
# else
->"ULTRA3 running other than sym1 OS"!;
# endif
#endif /* !KERNEL_DEBUGGING */

229
gdb/config/a29k/tm-vx29k.h Normal file
View File

@ -0,0 +1,229 @@
/* Target machine description for VxWorks on the 29k, for GDB, the GNU debugger.
Copyright 1994 Free Software Foundation, Inc.
Contributed by Cygnus Support.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "a29k/tm-a29k.h"
#define GDBINIT_FILENAME ".vxgdbinit"
#define DEFAULT_PROMPT "(vxgdb) "
/* Number of registers in a ptrace_getregs call. */
#define VX_NUM_REGS (NUM_REGS)
/* Number of registers in a ptrace_getfpregs call. */
/* #define VX_SIZE_FPREGS */
/* This is almost certainly the wrong place for this: */
#define LR2_REGNUM 34
/* Vxworks has its own CALL_DUMMY since it manages breakpoints in the kernel */
#undef CALL_DUMMY
/* Replace the breakpoint instruction in the CALL_DUMMY with a nop.
For Vxworks, the breakpoint is set and deleted by calls to
CALL_DUMMY_BREAK_SET and CALL_DUMMY_BREAK_DELETE. */
#if TARGET_BYTE_ORDER == HOST_BYTE_ORDER
#define CALL_DUMMY {0x0400870f,\
0x36008200|(MSP_HW_REGNUM), \
0x15000040|(MSP_HW_REGNUM<<8)|(MSP_HW_REGNUM<<16), \
0x03ff80ff, 0x02ff80ff, 0xc8008080, 0x70400101, 0x70400101}
#else /* Byte order differs. */
#define CALL_DUMMY {0x0f870004,\
0x00820036|(MSP_HW_REGNUM << 24), \
0x40000015|(MSP_HW_REGNUM<<8)|(MSP_HW_REGNUM<<16), \
0xff80ff03, 0xff80ff02, 0x808000c8, 0x01014070, 0x01014070}
#endif /* Byte order differs. */
/* For the basic CALL_DUMMY definitions, see "tm-29k.h." We use the
same CALL_DUMMY code, but define FIX_CALL_DUMMY (and related macros)
locally to handle remote debugging of VxWorks targets. The difference
is in the setting and clearing of the breakpoint at the end of the
CALL_DUMMY code fragment; under VxWorks, we can't simply insert a
breakpoint instruction into the code, since that would interfere with
the breakpoint management mechanism on the target.
Note that CALL_DUMMY is a piece of code that is used to call any C function
thru VxGDB */
/* The offset of the instruction within the CALL_DUMMY code where we
want the inferior to stop after the function call has completed.
call_function_by_hand () sets a breakpoint here (via CALL_DUMMY_BREAK_SET),
which POP_FRAME later deletes (via CALL_DUMMY_BREAK_DELETE). */
#define CALL_DUMMY_STOP_OFFSET (7 * 4)
/* The offset of the first instruction of the CALL_DUMMY code fragment
relative to the frame pointer for a dummy frame. This is equal to
the size of the CALL_DUMMY plus the arg_slop area size (see the diagram
in "tm-29k.h"). */
/* PAD : the arg_slop area size doesn't appear to me to be useful since, the
call dummy code no longer modify the msp. See below. This must be checked. */
#define CALL_DUMMY_OFFSET_IN_FRAME (CALL_DUMMY_LENGTH + 16 * 4)
/* Insert the specified number of args and function address
into a CALL_DUMMY sequence stored at DUMMYNAME, replace the third
instruction (add msp, msp, 16*4) with a nop, and leave the final nop.
We can't keep using a CALL_DUMMY that modify the msp since, for VxWorks,
CALL_DUMMY is stored in the Memory Stack. Adding 16 words to the msp
would then make possible for the inferior to overwrite the CALL_DUMMY code,
thus creating a lot of trouble when exiting the inferior to come back in
a CALL_DUMMY code that no longer exists... Furthermore, ESF are also stored
from the msp in the memory stack. If msp is set higher than the dummy code,
an ESF may clobber this code. */
#if TARGET_BYTE_ORDER == BIG_ENDIAN
#define NOP_INSTR 0x70400101
#else /* Target is little endian */
#define NOP_INSTR 0x01014070
#endif
#undef FIX_CALL_DUMMY
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
{ \
*(int *)((char *)dummyname + 8) = NOP_INSTR; \
STUFF_I16((char *)dummyname + CONST_INSN, fun); \
STUFF_I16((char *)dummyname + CONST_INSN + 4, fun >> 16); \
}
/* For VxWorks, CALL_DUMMY must be stored in the stack of the task that is
being debugged and executed "in the context of" this task */
#undef CALL_DUMMY_LOCATION
#define CALL_DUMMY_LOCATION ON_STACK
/* Set or delete a breakpoint at the location within a CALL_DUMMY code
fragment where we want the target program to stop after the function
call is complete. CALL_DUMMY_ADDR is the address of the first
instruction in the CALL_DUMMY. DUMMY_FRAME_ADDR is the value of the
frame pointer in the dummy frame.
NOTE: in the both of the following definitions, we take advantage of
knowledge of the implementation of the target breakpoint operation,
in that we pass a null pointer as the second argument. It seems
reasonable to assume that any target requiring the use of
CALL_DUMMY_BREAK_{SET,DELETE} will not store the breakpoint
shadow contents in GDB; in any case, this assumption is vaild
for all VxWorks-related targets. */
#define CALL_DUMMY_BREAK_SET(call_dummy_addr) \
target_insert_breakpoint ((call_dummy_addr) + CALL_DUMMY_STOP_OFFSET, \
(char *) 0)
#define CALL_DUMMY_BREAK_DELETE(dummy_frame_addr) \
target_remove_breakpoint ((dummy_frame_addr) - (CALL_DUMMY_OFFSET_IN_FRAME \
- CALL_DUMMY_STOP_OFFSET), \
(char *) 0)
/* Return nonzero if the pc is executing within a CALL_DUMMY frame. */
#define PC_IN_CALL_DUMMY(pc, sp, frame_address) \
((pc) >= (sp) \
&& (pc) <= (sp) + CALL_DUMMY_OFFSET_IN_FRAME + CALL_DUMMY_LENGTH)
/* Defining this prevents us from trying to pass a structure-valued argument
to a function called via the CALL_DUMMY mechanism. This is not handled
properly in call_function_by_hand (), and the fix might require re-writing
the CALL_DUMMY handling for all targets (at least, a clean solution
would probably require this). Arguably, this should go in "tm-29k.h"
rather than here. */
#define STRUCT_VAL_ARGS_UNSUPPORTED
#define BKPT_OFFSET (7 * 4)
#define BKPT_INSTR 0x72500101
#undef FIX_CALL_DUMMY
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
{\
STUFF_I16((char *)dummyname + CONST_INSN, fun);\
STUFF_I16((char *)dummyname + CONST_INSN + 4, fun >> 16);\
*(int *)((char *)dummyname + BKPT_OFFSET) = BKPT_INSTR;\
}
/* Offsets into jmp_buf. They are derived from VxWorks' REG_SET struct
(see VxWorks' setjmp.h). Note that Sun2, Sun3 and SunOS4 and VxWorks have
different REG_SET structs, hence different layouts for the jmp_buf struct.
Only JB_PC is needed for getting the saved PC value. */
#define JB_ELEMENT_SIZE 4 /* size of each element in jmp_buf */
#define JB_PC 3 /* offset of pc (pc1) in jmp_buf */
/* Figure out where the longjmp will land. We expect that we have just entered
longjmp and haven't yet setup the stack frame, so the args are still in the
output regs. lr2 (LR2_REGNUM) points at the jmp_buf structure from which we
extract the pc (JB_PC) that we will land at. The pc is copied into ADDR.
This routine returns true on success */
#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
extern int get_longjmp_target PARAMS ((CORE_ADDR *));
/* VxWorks adjusts the PC after a breakpoint has been hit. */
#undef DECR_PC_AFTER_BREAK
#define DECR_PC_AFTER_BREAK 0
/* Do whatever promotions are appropriate on a value being returned
from a function. VAL is the user-supplied value, and FUNC_TYPE
is the return type of the function if known, else 0.
For the Am29k, as far as I understand, if the function return type is known,
cast the value to that type; otherwise, ensure that integer return values
fill all of gr96.
This definition really belongs in "tm-29k.h", since it applies
to most Am29K-based systems; but once moved into that file, it might
need to be redefined for all Am29K-based targets that also redefine
STORE_RETURN_VALUE. For now, to be safe, we define it here. */
#define PROMOTE_RETURN_VALUE(val, func_type) \
do { \
if (func_type) \
val = value_cast (func_type, val); \
if ((TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_INT \
|| TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_ENUM) \
&& TYPE_LENGTH (VALUE_TYPE (val)) < REGISTER_RAW_SIZE (0)) \
val = value_cast (builtin_type_int, val); \
} while (0)
extern int vx29k_frame_chain_valid PARAMS ((CORE_ADDR, struct frame_info *));
#define FRAME_CHAIN_VALID(chain, thisframe) vx29k_frame_chain_valid (chain, thisframe)
extern CORE_ADDR frame_saved_call_site ();
#undef PREPARE_TO_INIT_FRAME_INFO
#define PREPARE_TO_INIT_FRAME_INFO(fci) do { \
long current_msp = read_register (MSP_REGNUM); \
if (PC_IN_CALL_DUMMY (fci->pc, current_msp, 0)) \
{ \
fci->rsize = DUMMY_FRAME_RSIZE; \
fci->msize = 0; \
fci->saved_msp = \
read_register_stack_integer (fci->frame + DUMMY_FRAME_RSIZE - 4, 4); \
fci->flags |= (TRANSPARENT|MFP_USED); \
return; \
} \
} while (0)

13
gdb/config/a29k/ultra3.mh Normal file
View File

@ -0,0 +1,13 @@
# Host: NYU Ultracomputer (AMD 29000 running Unix)
CC=u3cc
XM_FILE= xm-ultra3.h
XDEPFILES= ultra3-xdep.o
MH_CFLAGS = -DSYM1
XM_CLIBS = -lsysv -ljobs -ltermlib
NAT_FILE= nm-ultra3.h
NATDEPFILES= infptrace.o inftarg.o fork-child.o ultra3-nat.o

View File

@ -0,0 +1,6 @@
# Target: AMD 29000 running Unix on New York University processor board
TDEPFILES= a29k-tdep.o
TM_FILE= tm-ultra3.h
# SYM1 is some OS they have.
MT_CFLAGS = -DSYM1

4
gdb/config/a29k/vx29k.mt Normal file
View File

@ -0,0 +1,4 @@
# Target: AMD 29k running VxWorks
TDEPFILES= a29k-tdep.o remote-vx.o remote-vx29k.o xdr_ld.o xdr_ptrace.o xdr_rdb.o
TM_FILE= tm-vx29k.h
MT_CFLAGS = -DNO_HIF_SUPPORT

View File

@ -0,0 +1,52 @@
/* Host definitions for GDB running on an a29k NYU Ultracomputer
Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
Contributed by David Wood (wood@lab.ultra.nyu.edu).
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Here at NYU we have what we call an ULTRA3 PE board. So
ifdefs for ULTRA3 are my doing. At this point in time,
I don't know of any other Unixi running on the a29k. */
#define HOST_BYTE_ORDER BIG_ENDIAN
#define HAVE_WAIT_STRUCT
#ifndef L_SET
# define L_SET 0 /* set the seek pointer */
# define L_INCR 1 /* increment the seek pointer */
# define L_XTND 2 /* extend the file size */
#endif
#ifndef O_RDONLY
# define O_RDONLY 0
# define O_WRONLY 1
# define O_RDWR 2
#endif
#ifndef F_OK
# define R_OK 4
# define W_OK 2
# define X_OK 1
# define F_OK 0
#endif
/* System doesn't provide siginterrupt(). */
#define NO_SIGINTERRUPT
/* System uses a `short' to hold a process group ID. */
#define SHORT_PGRP

View File

@ -0,0 +1,9 @@
# Host: Little-endian Alpha running Linux
XDEPFILES= ser-tcp.o
XM_FILE= xm-alphalinux.h
NAT_FILE= nm-linux.h
NATDEPFILES= infptrace.o inftarg.o corelow.o core-regset.o alpha-nat.o \
fork-child.o solib.o
MMALLOC =
MMALLOC_CFLAGS = -DNO_MMALLOC

View File

@ -0,0 +1,3 @@
# Target: Little-endian Alpha
TDEPFILES= alpha-tdep.o
TM_FILE= tm-alphalinux.h

View File

@ -0,0 +1,5 @@
# Host: Little-endian Alpha running OSF/1-1.x
XDEPFILES=
XM_FILE= xm-alphaosf.h
NAT_FILE= nm-osf.h
NATDEPFILES= infptrace.o inftarg.o corelow.o alpha-nat.o fork-child.o osfsolib.o

View File

@ -0,0 +1,3 @@
# Target: Little-endian Alpha
TDEPFILES= alpha-tdep.o
TM_FILE= tm-alpha.h

View File

@ -0,0 +1,5 @@
# Host: Little-endian Alpha running OSF/1-2.x using procfs
XDEPFILES=
XM_FILE= xm-alphaosf.h
NAT_FILE= nm-osf2.h
NATDEPFILES= infptrace.o inftarg.o corelow.o alpha-nat.o fork-child.o osfsolib.o procfs.o

View File

@ -0,0 +1,5 @@
# Host: Little-endian Alpha running OSF/1-3.x and higher using procfs
XDEPFILES=
XM_FILE= xm-alphaosf.h
NAT_FILE= nm-osf3.h
NATDEPFILES= infptrace.o inftarg.o corelow.o alpha-nat.o fork-child.o osfsolib.o procfs.o

View File

@ -0,0 +1,66 @@
/* Native definitions for alpha running Linux.
Copyright (C) 1993, 1994 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Figure out where the longjmp will land. We expect that we have just entered
longjmp and haven't yet setup the stack frame, so the args are still in the
argument regs. A0_REGNUM points at the jmp_buf structure from which we
extract the pc (JB_PC) that we will land at. The pc is copied into ADDR.
This routine returns true on success */
#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
extern int
get_longjmp_target PARAMS ((CORE_ADDR *));
/* Tell gdb that we can attach and detach other processes */
#define ATTACH_DETACH
/* ptrace register ``addresses'' are absolute. */
#define U_REGS_OFFSET 0
#define PTRACE_ARG3_TYPE long
/* ptrace transfers longs, the ptrace man page is lying. */
#define PTRACE_XFER_TYPE long
/* The alpha does not step over a breakpoint, the manpage is lying again. */
#define CANNOT_STEP_BREAKPOINT
/* Linux has shared libraries. */
#define GDB_TARGET_HAS_SHARED_LIBS
/* Support for shared libraries. */
#include "solib.h"
#ifdef __ELF__
#define SVR4_SHARED_LIBS
#define TARGET_ELF64
#endif
/* This is a lie. It's actually in stdio.h. */
#define PSIGNAL_IN_SIGNAL_H
/* Given a pointer to either a gregset_t or fpregset_t, return a
pointer to the first register. */
#define ALPHA_REGSET_BASE(regsetp) ((long *) (regsetp))

56
gdb/config/alpha/nm-osf.h Normal file
View File

@ -0,0 +1,56 @@
/* Native definitions for alpha running OSF/1.
Copyright (C) 1993, 1994 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Figure out where the longjmp will land. We expect that we have just entered
longjmp and haven't yet setup the stack frame, so the args are still in the
argument regs. A0_REGNUM points at the jmp_buf structure from which we
extract the pc (JB_PC) that we will land at. The pc is copied into ADDR.
This routine returns true on success */
#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
extern int
get_longjmp_target PARAMS ((CORE_ADDR *));
/* ptrace register ``addresses'' are absolute. */
#define U_REGS_OFFSET 0
/* FIXME: Shouldn't the default definition in inferior.h be int* ? */
#define PTRACE_ARG3_TYPE int*
/* ptrace transfers longs, the ptrace man page is lying. */
#define PTRACE_XFER_TYPE long
/* The alpha does not step over a breakpoint, the manpage is lying again. */
#define CANNOT_STEP_BREAKPOINT
/* OSF/1 has shared libraries. */
#define GDB_TARGET_HAS_SHARED_LIBS
/* Support for shared libraries. */
#include "solib.h"
/* Given a pointer to either a gregset_t or fpregset_t, return a
pointer to the first register. */
#define ALPHA_REGSET_BASE(regsetp) ((regsetp)->regs)

View File

@ -0,0 +1,54 @@
/* Native definitions for alpha running OSF/1-2.x, using procfs.
Copyright (C) 1995 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Get generic OSF/1 definitions. */
#include "alpha/nm-osf.h"
/* OSF/1-2.x has optional /proc support, try to use it instead of ptrace. */
#define USE_PROC_FS
#define HAVE_OPTIONAL_PROC_FS
/* OSF/1 doesn't provide the standard fault definitions, so don't use them. */
#define FAULTED_USE_SIGINFO
/* Don't trace faults under OSF/1, rely on the posting of the appropriate
signal if fault tracing is disabled.
Tracing T_IFAULT under Alpha OSF/1 causes a `floating point enable'
fault from which we cannot continue (except by disabling the
tracing).
And as OSF/1 doesn't provide the standard fault definitions, the
mapping of faults to appropriate signals in procfs_wait is difficult. */
#define PROCFS_DONT_TRACE_FAULTS
/* Work around some peculiarities in the OSF/1 procfs implementation. */
#define PROCFS_SIGPEND_OFFSET
#define PROCFS_NEED_PIOCSSIG_FOR_KILL
#define PROCFS_DONT_PIOCSSIG_CURSIG
/* Return sizeof user struct to callers in less machine dependent routines */
#define KERNEL_U_SIZE kernel_u_size()
extern int kernel_u_size PARAMS ((void));
/* poll() doesn't seem to work properly for /proc in this version of the OS.
If we only specify POLLPRI, things hang. It seems to get better when we set
POLLOUT, but that always returns POLLNVAL!!! Also, POLLOUT causes problems
on other OSes. */
#define LOSING_POLL

View File

@ -0,0 +1,26 @@
/* Native definitions for alpha running OSF/1-3.x and higher, using procfs.
Copyright (C) 1995 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* OSF/1-3.x fixes some OSF/1-2.x procfs peculiarities and adds
a new one. */
#include "alpha/nm-osf2.h"
#undef PROCFS_NEED_PIOCSSIG_FOR_KILL
#undef PROCFS_DONT_PIOCSSIG_CURSIG
#define PROCFS_NEED_CLEAR_CURSIG_FOR_KILL

479
gdb/config/alpha/tm-alpha.h Normal file
View File

@ -0,0 +1,479 @@
/* Definitions to make GDB run on an Alpha box under OSF1. This is
also used by the Alpha/Netware and Alpha/Linux targets.
Copyright 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef TM_ALPHA_H
#define TM_ALPHA_H
#include "bfd.h"
#include "coff/sym.h" /* Needed for PDR below. */
#include "coff/symconst.h"
#ifdef __STDC__
struct frame_info;
struct type;
struct value;
struct symbol;
#endif
#if !defined (TARGET_BYTE_ORDER)
#define TARGET_BYTE_ORDER LITTLE_ENDIAN
#endif
/* Redefine some target bit sizes from the default. */
#define TARGET_LONG_BIT 64
#define TARGET_LONG_LONG_BIT 64
#define TARGET_PTR_BIT 64
/* Floating point is IEEE compliant */
#define IEEE_FLOAT
/* Number of traps that happen between exec'ing the shell
* to run an inferior, and when we finally get to
* the inferior code. This is 2 on most implementations.
*/
#define START_INFERIOR_TRAPS_EXPECTED 3
/* Offset from address of function to start of its code.
Zero on most machines. */
#define FUNCTION_START_OFFSET 0
/* Advance PC across any function entry prologue instructions
to reach some "real" code. */
#define SKIP_PROLOGUE(pc) pc = alpha_skip_prologue(pc, 0)
extern CORE_ADDR alpha_skip_prologue PARAMS ((CORE_ADDR addr, int lenient));
/* Immediately after a function call, return the saved pc.
Can't always go through the frames for this because on some machines
the new frame is not set up until the new function executes
some instructions. */
#define SAVED_PC_AFTER_CALL(frame) alpha_saved_pc_after_call(frame)
extern CORE_ADDR
alpha_saved_pc_after_call PARAMS ((struct frame_info *));
/* Are we currently handling a signal ? */
#define IN_SIGTRAMP(pc, name) ((name) && STREQ ("__sigtramp", (name)))
/* Stack grows downward. */
#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
#define BREAKPOINT {0x80, 0, 0, 0} /* call_pal bpt */
/* Amount PC must be decremented by after a breakpoint.
This is often the number of bytes in BREAKPOINT
but not always. */
#ifndef DECR_PC_AFTER_BREAK
#define DECR_PC_AFTER_BREAK 4
#endif
/* Say how long (ordinary) registers are. This is a piece of bogosity
used in push_word and a few other places; REGISTER_RAW_SIZE is the
real way to know how big a register is. */
#define REGISTER_SIZE 8
/* Number of machine registers */
#define NUM_REGS 66
/* Initializer for an array of names of registers.
There should be NUM_REGS strings in this initializer. */
#define REGISTER_NAMES \
{ "v0", "t0", "t1", "t2", "t3", "t4", "t5", "t6", \
"t7", "s0", "s1", "s2", "s3", "s4", "s5", "fp", \
"a0", "a1", "a2", "a3", "a4", "a5", "t8", "t9", \
"t10", "t11", "ra", "t12", "at", "gp", "sp", "zero", \
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",\
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",\
"pc", "vfp", \
}
/* Register numbers of various important registers.
Note that most of these values are "real" register numbers,
and correspond to the general registers of the machine,
and FP_REGNUM is a "phony" register number which is too large
to be an actual register number as far as the user is concerned
but serves to get the desired value when passed to read_register. */
#define V0_REGNUM 0 /* Function integer return value */
#define T7_REGNUM 8 /* Return address register for OSF/1 __add* */
#define GCC_FP_REGNUM 15 /* Used by gcc as frame register */
#define A0_REGNUM 16 /* Loc of first arg during a subr call */
#define T9_REGNUM 23 /* Return address register for OSF/1 __div* */
#define T12_REGNUM 27 /* Contains start addr of current proc */
#define SP_REGNUM 30 /* Contains address of top of stack */
#define RA_REGNUM 26 /* Contains return address value */
#define ZERO_REGNUM 31 /* Read-only register, always 0 */
#define FP0_REGNUM 32 /* Floating point register 0 */
#define FPA0_REGNUM 48 /* First float arg during a subr call */
#define PC_REGNUM 64 /* Contains program counter */
#define FP_REGNUM 65 /* Virtual frame pointer */
#define CANNOT_FETCH_REGISTER(regno) \
((regno) == FP_REGNUM || (regno) == ZERO_REGNUM)
#define CANNOT_STORE_REGISTER(regno) \
((regno) == FP_REGNUM || (regno) == ZERO_REGNUM)
/* Total amount of space needed to store our copies of the machine's
register state, the array `registers'. */
#define REGISTER_BYTES (NUM_REGS * 8)
/* Index within `registers' of the first byte of the space for
register N. */
#define REGISTER_BYTE(N) ((N) * 8)
/* Number of bytes of storage in the actual machine representation
for register N. On Alphas, all regs are 8 bytes. */
#define REGISTER_RAW_SIZE(N) 8
/* Number of bytes of storage in the program's representation
for register N. On Alphas, all regs are 8 bytes. */
#define REGISTER_VIRTUAL_SIZE(N) 8
/* Largest value REGISTER_RAW_SIZE can have. */
#define MAX_REGISTER_RAW_SIZE 8
/* Largest value REGISTER_VIRTUAL_SIZE can have. */
#define MAX_REGISTER_VIRTUAL_SIZE 8
/* Nonzero if register N requires conversion
from raw format to virtual format.
The alpha needs a conversion between register and memory format if
the register is a floating point register and
memory format is float, as the register format must be double
or
memory format is an integer with 4 bytes or less, as the representation
of integers in floating point registers is different. */
#define REGISTER_CONVERTIBLE(N) ((N) >= FP0_REGNUM && (N) < FP0_REGNUM + 32)
/* Convert data from raw format for register REGNUM in buffer FROM
to virtual format with type TYPE in buffer TO. */
#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM, TYPE, FROM, TO) \
alpha_register_convert_to_virtual (REGNUM, TYPE, FROM, TO)
extern void
alpha_register_convert_to_virtual PARAMS ((int, struct type *, char *, char *));
/* Convert data from virtual format with type TYPE in buffer FROM
to raw format for register REGNUM in buffer TO. */
#define REGISTER_CONVERT_TO_RAW(TYPE, REGNUM, FROM, TO) \
alpha_register_convert_to_raw (TYPE, REGNUM, FROM, TO)
extern void
alpha_register_convert_to_raw PARAMS ((struct type *, int, char *, char *));
/* Return the GDB type object for the "standard" data type
of data in register N. */
#define REGISTER_VIRTUAL_TYPE(N) \
(((N) >= FP0_REGNUM && (N) < FP0_REGNUM+32) \
? builtin_type_double : builtin_type_long) \
/* Store the address of the place in which to copy the structure the
subroutine will return. Handled by alpha_push_arguments. */
#define STORE_STRUCT_RETURN(addr, sp) /**/
/* Extract from an array REGBUF containing the (raw) register state
a function return value of type TYPE, and copy that, in virtual format,
into VALBUF. */
#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
alpha_extract_return_value(TYPE, REGBUF, VALBUF)
extern void
alpha_extract_return_value PARAMS ((struct type *, char *, char *));
/* Write into appropriate registers a function return value
of type TYPE, given in virtual format. */
#define STORE_RETURN_VALUE(TYPE,VALBUF) \
alpha_store_return_value(TYPE, VALBUF)
extern void
alpha_store_return_value PARAMS ((struct type *, char *));
/* Extract from an array REGBUF containing the (raw) register state
the address in which a function should return its structure value,
as a CORE_ADDR (or an expression that can be used as one). */
/* The address is passed in a0 upon entry to the function, but when
the function exits, the compiler has copied the value to v0. This
convention is specified by the System V ABI, so I think we can rely
on it. */
#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
(extract_address (REGBUF + REGISTER_BYTE (V0_REGNUM), \
REGISTER_RAW_SIZE (V0_REGNUM)))
/* Structures are returned by ref in extra arg0 */
#define USE_STRUCT_CONVENTION(gcc_p, type) 1
/* Describe the pointer in each stack frame to the previous stack frame
(its caller). */
/* FRAME_CHAIN takes a frame's nominal address
and produces the frame's chain-pointer. */
#define FRAME_CHAIN(thisframe) (CORE_ADDR) alpha_frame_chain (thisframe)
extern CORE_ADDR alpha_frame_chain PARAMS ((struct frame_info *));
/* Define other aspects of the stack frame. */
/* A macro that tells us whether the function invocation represented
by FI does not have a frame on the stack associated with it. If it
does not, FRAMELESS is set to 1, else 0. */
/* We handle this differently for alpha, and maybe we should not */
#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) {(FRAMELESS) = 0;}
/* Saved Pc. */
#define FRAME_SAVED_PC(FRAME) (alpha_frame_saved_pc(FRAME))
extern CORE_ADDR
alpha_frame_saved_pc PARAMS ((struct frame_info *));
/* The alpha has two different virtual pointers for arguments and locals.
The virtual argument pointer is pointing to the bottom of the argument
transfer area, which is located immediately below the virtual frame
pointer. Its size is fixed for the native compiler, it is either zero
(for the no arguments case) or large enough to hold all argument registers.
gcc uses a variable sized argument transfer area. As it has
to stay compatible with the native debugging tools it has to use the same
virtual argument pointer and adjust the argument offsets accordingly.
The virtual local pointer is localoff bytes below the virtual frame
pointer, the value of localoff is obtained from the PDR. */
#define ALPHA_NUM_ARG_REGS 6
#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame - (ALPHA_NUM_ARG_REGS * 8))
#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame - (fi)->localoff)
/* Return number of args passed to a frame.
Can return -1, meaning no way to tell. */
#define FRAME_NUM_ARGS(num, fi) ((num) = -1)
/* Return number of bytes at start of arglist that are not really args. */
#define FRAME_ARGS_SKIP 0
/* Put here the code to store, into a struct frame_saved_regs,
the addresses of the saved registers of frame described by FRAME_INFO.
This includes special registers such as pc and fp saved in special
ways in the stack frame. sp is even more special:
the address we return for it IS the sp for the next frame. */
extern void alpha_find_saved_regs PARAMS ((struct frame_info *));
#define FRAME_INIT_SAVED_REGS(frame_info) \
do { \
if ((frame_info)->saved_regs == NULL) \
alpha_find_saved_regs (frame_info); \
(frame_info)->saved_regs[SP_REGNUM] = (frame_info)->frame; \
} while (0)
/* Things needed for making the inferior call functions. */
#define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \
sp = alpha_push_arguments((nargs), (args), (sp), (struct_return), (struct_addr))
extern CORE_ADDR
alpha_push_arguments PARAMS ((int, struct value **, CORE_ADDR, int, CORE_ADDR));
/* Push an empty stack frame, to record the current PC, etc. */
#define PUSH_DUMMY_FRAME alpha_push_dummy_frame()
extern void
alpha_push_dummy_frame PARAMS ((void));
/* Discard from the stack the innermost frame, restoring all registers. */
#define POP_FRAME alpha_pop_frame()
extern void
alpha_pop_frame PARAMS ((void));
/* Alpha OSF/1 inhibits execution of code on the stack.
But there is no need for a dummy on the alpha. PUSH_ARGUMENTS
takes care of all argument handling and bp_call_dummy takes care
of stopping the dummy. */
#define CALL_DUMMY_LOCATION AT_ENTRY_POINT
/* On the Alpha the call dummy code is never copied to user space,
stopping the user call is achieved via a bp_call_dummy breakpoint.
But we need a fake CALL_DUMMY definition to enable the proper
call_function_by_hand and to avoid zero length array warnings
in valops.c */
#define CALL_DUMMY { 0 } /* Content doesn't matter. */
#define CALL_DUMMY_START_OFFSET (0)
#define CALL_DUMMY_BREAKPOINT_OFFSET (0)
extern CORE_ADDR alpha_call_dummy_address PARAMS ((void));
#define CALL_DUMMY_ADDRESS() alpha_call_dummy_address()
/* Insert the specified number of args and function address
into a call sequence of the above form stored at DUMMYNAME.
We only have to set RA_REGNUM to the dummy breakpoint address
and T12_REGNUM (the `procedure value register') to the function address. */
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
{ \
CORE_ADDR bp_address = CALL_DUMMY_ADDRESS (); \
if (bp_address == 0) \
error ("no place to put call"); \
write_register (RA_REGNUM, bp_address); \
write_register (T12_REGNUM, fun); \
}
/* There's a mess in stack frame creation. See comments in blockframe.c
near reference to INIT_FRAME_PC_FIRST. */
#define INIT_FRAME_PC(fromleaf, prev) /* nada */
#define INIT_FRAME_PC_FIRST(fromleaf, prev) \
(prev)->pc = ((fromleaf) ? SAVED_PC_AFTER_CALL ((prev)->next) : \
(prev)->next ? FRAME_SAVED_PC ((prev)->next) : read_pc ());
/* Special symbol found in blocks associated with routines. We can hang
alpha_extra_func_info_t's off of this. */
#define MIPS_EFI_SYMBOL_NAME "__GDB_EFI_INFO__"
extern void ecoff_relocate_efi PARAMS ((struct symbol *, CORE_ADDR));
/* Specific information about a procedure.
This overlays the ALPHA's PDR records,
alpharead.c (ab)uses this to save memory */
typedef struct alpha_extra_func_info {
long numargs; /* number of args to procedure (was iopt) */
PDR pdr; /* Procedure descriptor record */
} *alpha_extra_func_info_t;
/* Define the extra_func_info that mipsread.c needs.
FIXME: We should define our own PDR interface, perhaps in a separate
header file. This would get rid of the <bfd.h> inclusion in all sources
and would abstract the mips/alpha interface from ecoff. */
#define mips_extra_func_info alpha_extra_func_info
#define mips_extra_func_info_t alpha_extra_func_info_t
#define EXTRA_FRAME_INFO \
int localoff; \
int pc_reg; \
alpha_extra_func_info_t proc_desc;
#define INIT_EXTRA_FRAME_INFO(fromleaf, fci) init_extra_frame_info(fci)
extern void
init_extra_frame_info PARAMS ((struct frame_info *));
#define PRINT_EXTRA_FRAME_INFO(fi) \
{ \
if (fi && fi->proc_desc && fi->proc_desc->pdr.framereg < NUM_REGS) \
printf_filtered (" frame pointer is at %s+%d\n", \
REGISTER_NAME (fi->proc_desc->pdr.framereg), \
fi->proc_desc->pdr.frameoffset); \
}
/* It takes two values to specify a frame on the ALPHA. Sigh.
In fact, at the moment, the *PC* is the primary value that sets up
a frame. The PC is looked up to see what function it's in; symbol
information from that function tells us which register is the frame
pointer base, and what offset from there is the "virtual frame pointer".
(This is usually an offset from SP.) FIXME -- this should be cleaned
up so that the primary value is the SP, and the PC is used to disambiguate
multiple functions with the same SP that are at different stack levels. */
#define SETUP_ARBITRARY_FRAME(argc, argv) setup_arbitrary_frame (argc, argv)
extern struct frame_info *setup_arbitrary_frame PARAMS ((int, CORE_ADDR *));
/* This is used by heuristic_proc_start. It should be shot it the head. */
#ifndef VM_MIN_ADDRESS
#define VM_MIN_ADDRESS (CORE_ADDR)0x120000000
#endif
/* If PC is in a shared library trampoline code, return the PC
where the function itself actually starts. If not, return 0. */
#define SKIP_TRAMPOLINE_CODE(pc) find_solib_trampoline_target (pc)
/* If the current gcc for for this target does not produce correct debugging
information for float parameters, both prototyped and unprototyped, then
define this macro. This forces gdb to always assume that floats are
passed as doubles and then converted in the callee.
For the alpha, it appears that the debug info marks the parameters as
floats regardless of whether the function is prototyped, but the actual
values are always passed in as doubles. Thus by setting this to 1, both
types of calls will work. */
#define COERCE_FLOAT_TO_DOUBLE 1
/* Return TRUE if procedure descriptor PROC is a procedure descriptor
that refers to a dynamically generated sigtramp function.
OSF/1 doesn't use dynamic sigtramp functions, so this is always
FALSE. */
#define PROC_DESC_IS_DYN_SIGTRAMP(proc) (0)
#define SET_PROC_DESC_IS_DYN_SIGTRAMP(proc)
/* If PC is inside a dynamically generated sigtramp function, return
how many bytes the program counter is beyond the start of that
function. Otherwise, return a negative value.
OSF/1 doesn't use dynamic sigtramp functions, so this always
returns -1. */
#define DYNAMIC_SIGTRAMP_OFFSET(pc) (-1)
/* Translate a signal handler frame into the address of the sigcontext
structure. */
#define SIGCONTEXT_ADDR(frame) \
(read_memory_integer ((frame)->next ? frame->next->frame : frame->frame, 8))
/* If FRAME refers to a sigtramp frame, return the address of the next
frame. */
#define FRAME_PAST_SIGTRAMP_FRAME(frame, pc) \
(alpha_osf_skip_sigtramp_frame (frame, pc))
extern CORE_ADDR alpha_osf_skip_sigtramp_frame PARAMS ((struct frame_info *, CORE_ADDR));
#endif /* TM_ALPHA_H */

View File

@ -0,0 +1,80 @@
/* Definitions to make GDB run on an Alpha box under Linux. The
definitions here are used when the _target_ system is running Linux.
Copyright 1996 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#ifndef TM_LINUXALPHA_H
#define TM_LINUXALPHA_H
#include "alpha/tm-alpha.h"
/* Are we currently handling a signal ? */
extern long alpha_linux_sigtramp_offset PARAMS ((CORE_ADDR));
#undef IN_SIGTRAMP
#define IN_SIGTRAMP(pc, name) (alpha_linux_sigtramp_offset (pc) >= 0)
/* Get start and end address of sigtramp handler. */
#define SIGTRAMP_START(pc) (pc - alpha_linux_sigtramp_offset (pc))
#define SIGTRAMP_END(pc) (SIGTRAMP_START(pc) + 3*4)
/* Number of traps that happen between exec'ing the shell to run an
inferior, and when we finally get to the inferior code. This is 2
on Linux and most implementations. */
#undef START_INFERIOR_TRAPS_EXPECTED
#define START_INFERIOR_TRAPS_EXPECTED 2
/* Return TRUE if procedure descriptor PROC is a procedure descriptor
that refers to a dynamically generated sigtramp function. */
#undef PROC_DESC_IS_DYN_SIGTRAMP
#define PROC_SIGTRAMP_MAGIC 0x0e0f0f0f
#define PROC_DESC_IS_DYN_SIGTRAMP(proc) ((proc)->pdr.isym \
== PROC_SIGTRAMP_MAGIC)
#undef SET_PROC_DESC_IS_DYN_SIGTRAMP
#define SET_PROC_DESC_IS_DYN_SIGTRAMP(proc) ((proc)->pdr.isym \
= PROC_SIGTRAMP_MAGIC)
/* If PC is inside a dynamically generated sigtramp function, return
how many bytes the program counter is beyond the start of that
function. Otherwise, return a negative value. */
#undef DYNAMIC_SIGTRAMP_OFFSET
#define DYNAMIC_SIGTRAMP_OFFSET(pc) (alpha_linux_sigtramp_offset (pc))
/* Translate a signal handler frame into the address of the sigcontext
structure. */
#undef SIGCONTEXT_ADDR
#define SIGCONTEXT_ADDR(frame) ((frame)->frame - 0x298)
/* If FRAME refers to a sigtramp frame, return the address of the next frame.
Under Linux, sigtramp handlers have dynamically generated procedure
descriptors that make this hack unnecessary. */
#undef FRAME_PAST_SIGTRAMP_FRAME
#define FRAME_PAST_SIGTRAMP_FRAME(frame, pc) (0)
/* We need this for the SOLIB_TRAMPOLINE stuff. */
#include "tm-sysv4.h"
#endif /* TM_LINUXALPHA_H */

View File

@ -0,0 +1,29 @@
/* Host definitions for GDB running on an Alpha under Linux
Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#if !defined (HOST_BYTE_ORDER)
#define HOST_BYTE_ORDER LITTLE_ENDIAN
#endif
/* The alpha has no siginterrupt routine. */
#define NO_SIGINTERRUPT
#define HAVE_TERMIOS
#define HAVE_SIGSETMASK 1
#define USG

View File

@ -0,0 +1,27 @@
/* Host definitions for GDB running on an alpha under OSF/1
Copyright (C) 1992, 1993 Free Software Foundation, Inc.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#if !defined (HOST_BYTE_ORDER)
#define HOST_BYTE_ORDER LITTLE_ENDIAN
#endif
/* The alpha has no siginterrupt routine. */
#define NO_SIGINTERRUPT
#define HAVE_TERMIOS

3
gdb/config/arc/arc.mt Normal file
View File

@ -0,0 +1,3 @@
# Target: ARC processor
TDEPFILES = arc-tdep.o
TM_FILE = tm-arc.h

347
gdb/config/arc/tm-arc.h Normal file
View File

@ -0,0 +1,347 @@
/* Parameters for target machine ARC, for GDB, the GNU debugger.
Copyright (C) 1995 Free Software Foundation, Inc.
Contributed by Cygnus Support.
This file is part of GDB.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Used by arc-tdep.c to set the default cpu type. */
#define DEFAULT_ARC_CPU_TYPE "base"
/* Byte order is selectable. */
#define TARGET_BYTE_ORDER_SELECTABLE
/* We have IEEE floating point, if we have any float at all. */
#define IEEE_FLOAT
/* Offset from address of function to start of its code.
Zero on most machines. */
#define FUNCTION_START_OFFSET 0
/* Advance PC across any function entry prologue instructions
to reach some "real" code. SKIP_PROLOGUE_FRAMELESS_P advances
the PC past some of the prologue, but stops as soon as it
knows that the function has a frame. Its result is equal
to its input PC if the function is frameless, unequal otherwise. */
#define SKIP_PROLOGUE(pc) \
{ pc = skip_prologue (pc, 0); }
#define SKIP_PROLOGUE_FRAMELESS_P(pc) \
{ pc = skip_prologue (pc, 1); }
extern CORE_ADDR skip_prologue PARAMS ((CORE_ADDR, int));
/* Sequence of bytes for breakpoint instruction.
??? The current value is "sr -1,[-1]" and is for the simulator only.
The simulator watches for this and does the right thing.
The hardware version will have to associate with each breakpoint
the sequence "flag 1; nop; nop; nop". IE: The breakpoint insn will not
be a fixed set of bits but instead will be a branch to a semi-random
address. Presumably this will be cleaned up for "second silicon". */
#define BIG_BREAKPOINT { 0x12, 0x1f, 0xff, 0xff }
#define LITTLE_BREAKPOINT { 0xff, 0xff, 0x1f, 0x12 }
/* Given the exposed pipeline, there isn't any one correct value.
However, this value must be 4. GDB can't handle any other value (other than
zero). See for example infrun.c:
"prev_pc != stop_pc - DECR_PC_AFTER_BREAK" */
/* FIXME */
#define DECR_PC_AFTER_BREAK 8
/* We don't have a reliable single step facility.
??? We do have a cycle single step facility, but that won't work. */
#define SOFTWARE_SINGLE_STEP_P 1
extern void arc_software_single_step PARAMS ((unsigned int, int));
#define SOFTWARE_SINGLE_STEP(sig,bp_p) arc_software_single_step (sig, bp_p)
/* FIXME: Need to set STEP_SKIPS_DELAY. */
/* Given a pc value as defined by the hardware, return the real address.
Remember that on the ARC blink contains that status register which
includes PC + flags (so we have to mask out the flags). */
#define ARC_PC_TO_REAL_ADDRESS(pc) (((pc) & 0xffffff) << 2)
/* Immediately after a function call, return the saved pc.
Can't always go through the frames for this because on some machines
the new frame is not set up until the new function
executes some instructions. */
#define SAVED_PC_AFTER_CALL(frame) \
(ARC_PC_TO_REAL_ADDRESS (read_register (BLINK_REGNUM)))
/* Stack grows upward */
#define INNER_THAN(lhs,rhs) ((lhs) < (rhs))
/* Say how long (ordinary) registers are. This is a piece of bogosity
used in push_word and a few other places; REGISTER_RAW_SIZE is the
real way to know how big a register is. */
#define REGISTER_SIZE 4
/* Number of machine registers */
#define NUM_REGS 92
/* Initializer for an array of names of registers.
There should be NUM_REGS strings in this initializer. */
#define REGISTER_NAMES \
{ \
/* 0 */ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
/* 8 */ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \
/* 16 */ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \
/* 24 */ "r24", "r25", "r26", "fp", "sp", "ilink1", "ilink2", "blink", \
/* 32 */ "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", \
/* 40 */ "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47", \
/* 48 */ "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55", \
/* 56 */ "r56", "mlo", "mmid", "mhi", "lp_count", \
/* 61 */ "status", "sema", "lp_start", "lp_end", "identity", "debug", \
/* 67 */ "aux10", "aux11", "aux12", "aux13", "aux14", \
/* 72 */ "aux15", "aux16", "aux17", "aux18", "aux19", \
/* 77 */ "aux1a", "aux1b", "aux1c", "aux1d", "aux1e", \
/* 82 */ "aux1f", "aux20", "aux21", "aux22", \
/* 86 */ "aux30", "aux31", "aux32", "aux33", "aux40", \
/* 91 */ "pc" \
}
/* Register numbers of various important registers (used to index
into arrays of register names and register values). */
#define R0_REGNUM 0 /* First local register */
#define R59_REGNUM 59 /* Last local register */
#define FP_REGNUM 27 /* Contains address of executing stack frame */
#define SP_REGNUM 28 /* stack pointer */
#define BLINK_REGNUM 31 /* link register */
#define STA_REGNUM 61 /* processor status word */
#define PC_REGNUM 91 /* instruction pointer */
#define AUX_BEG_REGNUM 61 /* aux reg begins */
#define AUX_END_REGNUM 90 /* aux reg ends, pc not real aux reg */
/* Fake registers used to mark immediate data. */
#define SHIMM_FLAG_REGNUM 61
#define LIMM_REGNUM 62
#define SHIMM_REGNUM 63
#define AUX_REG_MAP \
{ \
{ 0, 1, 2, 3, 4, 5, \
16, -1, -1, -1, -1, \
-1, -1, -1, -1, -1, \
-1, -1, -1, -1, 30, \
-1, 32, 33, -1, \
48, 49, 50, 51, 64, \
0 \
}, \
{ 0, 1, 2, 3, 4, 5, \
16, -1, -1, -1, -1, \
-1, -1, -1, -1, -1, \
-1, -1, -1, -1, 30, \
31, 32, 33, -1, \
-1, -1, -1, -1, -1, \
0 \
}, \
{ 0, 1, 2, 3, 4, 5, \
16, 17, 18, 19, 20, \
21, 22, 23, 24, 25, \
26, 27, 28, 29, 30, \
31, 32, 33, 34, \
-1, -1, -1, -1, -1, \
0 \
} \
}
#define PFP_REGNUM R0_REGNUM /* Previous frame pointer */
/* Total amount of space needed to store our copies of the machine's
register state, the array `registers'. */
#define REGISTER_BYTES (NUM_REGS * 4)
/* Index within `registers' of the first byte of the space for register N. */
#define REGISTER_BYTE(N) (4*(N))
/* Number of bytes of storage in the actual machine representation
for register N. */
#define REGISTER_RAW_SIZE(N) 4
/* Number of bytes of storage in the program's representation for register N. */
#define REGISTER_VIRTUAL_SIZE(N) 4
/* Largest value REGISTER_RAW_SIZE can have. */
#define MAX_REGISTER_RAW_SIZE 4
/* Largest value REGISTER_VIRTUAL_SIZE can have. */
#define MAX_REGISTER_VIRTUAL_SIZE 4
/* Return the GDB type object for the "standard" data type
of data in register N. */
#define REGISTER_VIRTUAL_TYPE(N) (builtin_type_int)
/* Macros for understanding function return values... */
/* Does the specified function use the "struct returning" convention
or the "value returning" convention? The "value returning" convention
almost invariably returns the entire value in registers. The
"struct returning" convention often returns the entire value in
memory, and passes a pointer (out of or into the function) saying
where the value (is or should go).
Since this sometimes depends on whether it was compiled with GCC,
this is also an argument. This is used in call_function to build a
stack, and in value_being_returned to print return values.
On arc, a structure is always retunred with pointer in r0. */
#define USE_STRUCT_CONVENTION(gcc_p, type) 1
/* Extract from an array REGBUF containing the (raw) register state
a function return value of type TYPE, and copy that, in virtual format,
into VALBUF. This is only called if USE_STRUCT_CONVENTION for this
type is 0.
*/
#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
memcpy(VALBUF, REGBUF+REGISTER_BYTE(R0_REGNUM), TYPE_LENGTH (TYPE))
/* If USE_STRUCT_CONVENTION produces a 1,
extract from an array REGBUF containing the (raw) register state
the address in which a function should return its structure value,
as a CORE_ADDR (or an expression that can be used as one). */
#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) \
(error("Don't know where large structure is returned on arc"), 0)
/* Write into appropriate registers a function return value
of type TYPE, given in virtual format, for "value returning" functions.
For 'return' command: not (yet) implemented for arc. */
#define STORE_RETURN_VALUE(TYPE,VALBUF) \
error ("Returning values from functions is not implemented in arc gdb")
/* Store the address of the place in which to copy the structure the
subroutine will return. This is called from call_function. */
#define STORE_STRUCT_RETURN(ADDR, SP) \
error ("Returning values from functions is not implemented in arc gdb")
/* Describe the pointer in each stack frame to the previous stack frame
(its caller). */
/* We cache information about saved registers in the frame structure,
to save us from having to re-scan function prologues every time
a register in a non-current frame is accessed. */
#define EXTRA_FRAME_INFO \
struct frame_saved_regs *fsr; \
CORE_ADDR arg_pointer;
/* Zero the frame_saved_regs pointer when the frame is initialized,
so that FRAME_FIND_SAVED_REGS () will know to allocate and
initialize a frame_saved_regs struct the first time it is called.
Set the arg_pointer to -1, which is not valid; 0 and other values
indicate real, cached values. */
#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) \
((fi)->fsr = 0, (fi)->arg_pointer = -1)
/* FRAME_CHAIN takes a frame's nominal address
and produces the frame's chain-pointer.
However, if FRAME_CHAIN_VALID returns zero,
it means the given frame is the outermost one and has no caller. */
/* On the arc, we get the chain pointer by reading the PFP saved
on the stack. */
/* The PFP and RPC is in fp and fp+4. */
#define FRAME_CHAIN(thisframe) \
(read_memory_integer (FRAME_FP (thisframe), 4))
/* FRAME_CHAIN_VALID returns zero if the given frame is the outermost one
and has no caller. */
#define FRAME_CHAIN_VALID(chain, thisframe) nonnull_frame_chain_valid (chain, thisframe)
/* A macro that tells us whether the function invocation represented
by FI does not have a frame on the stack associated with it. If it
does not, FRAMELESS is set to 1, else 0. */
#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
do { \
if ((FI)->signal_handler_caller) \
(FRAMELESS) = 0; \
else \
(FRAMELESS) = frameless_look_for_prologue (FI); \
} while (0)
/* Where is the PC for a specific frame.
A leaf function may never save blink, so we have to check for that here. */
#define FRAME_SAVED_PC(frame) (arc_frame_saved_pc (frame))
struct frame_info; /* in case frame.h not included yet */
CORE_ADDR arc_frame_saved_pc PARAMS ((struct frame_info *));
/* If the argument is on the stack, it will be here.
We cache this value in the frame info if we've already looked it up. */
/* ??? Is the arg_pointer check necessary? */
#define FRAME_ARGS_ADDRESS(fi) \
(((fi)->arg_pointer != -1) ? (fi)->arg_pointer : (fi)->frame)
/* This is the same except it should return 0 when
it does not really know where the args are, rather than guessing.
This value is not cached since it is only used infrequently. */
#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
/* Set NUMARGS to the number of args passed to a frame.
Can return -1, meaning no way to tell. */
#define FRAME_NUM_ARGS(numargs, fi) (numargs = -1)
/* Return number of bytes at start of arglist that are not really args. */
#define FRAME_ARGS_SKIP 0
/* Produce the positions of the saved registers in a stack frame. */
#define FRAME_FIND_SAVED_REGS(frame_info_addr, sr) \
frame_find_saved_regs (frame_info_addr, &sr)
extern void frame_find_saved_regs(); /* See arc-tdep.c */
/* Things needed for making calls to functions in the inferior process */
#define PUSH_DUMMY_FRAME \
push_dummy_frame ()
/* Discard from the stack the innermost frame, restoring all registers. */
#define POP_FRAME \
pop_frame ()
/* This sequence of words is the instructions bl xxxx, flag 1 */
#define CALL_DUMMY { 0x28000000, 0x1fbe8001 }
#define CALL_DUMMY_LENGTH 8
/* Start execution at beginning of dummy */
#define CALL_DUMMY_START_OFFSET 0
/* Insert the specified number of args and function address
into a call sequence of the above form stored at 'dummyname'.*/
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
{ \
int from, to, delta, loc; \
loc = (int)(read_register (SP_REGNUM) - CALL_DUMMY_LENGTH); \
from = loc + 4; \
to = (int)(fun); \
delta = (to - from) >> 2; \
*((char *)(dummyname) + 1) = (delta & 0x1); \
*((char *)(dummyname) + 2) = ((delta >> 1) & 0xff); \
*((char *)(dummyname) + 3) = ((delta >> 9) & 0xff); \
*((char *)(dummyname) + 4) = ((delta >> 17) & 0x7); \
}

5
gdb/config/arm/arm.mh Normal file
View File

@ -0,0 +1,5 @@
# Host: Acorn RISC machine running RISCiX (4.3bsd)
XDEPFILES= infptrace.o inftarg.o fork-child.o arm-xdep.o arm-convert.o
XM_FILE= xm-arm.h
NAT_FILE= nm-arm.h

Some files were not shown because too many files have changed in this diff Show More