mirror of
git://sourceware.org/git/lvm2.git
synced 2025-01-03 05:18:29 +03:00
Initial revision
This commit is contained in:
commit
838ae13dc4
9
gdb/29k-share/README
Normal file
9
gdb/29k-share/README
Normal 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.
|
607
gdb/29k-share/udi/udi2go32.c
Normal file
607
gdb/29k-share/udi/udi2go32.c
Normal 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__ */
|
48
gdb/29k-share/udi/udiids.h
Normal file
48
gdb/29k-share/udi/udiids.h
Normal 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
1250
gdb/29k-share/udi/udip2soc.c
Normal file
File diff suppressed because it is too large
Load Diff
44
gdb/29k-share/udi/udiphcfg.h
Normal file
44
gdb/29k-share/udi/udiphcfg.h
Normal 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
|
81
gdb/29k-share/udi/udiphunix.h
Normal file
81
gdb/29k-share/udi/udiphunix.h
Normal 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
308
gdb/29k-share/udi/udiproc.h
Normal 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 */
|
||||||
|
));
|
87
gdb/29k-share/udi/udipt29k.h
Normal file
87
gdb/29k-share/udi/udipt29k.h
Normal 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;
|
19
gdb/29k-share/udi/udiptcfg.h
Normal file
19
gdb/29k-share/udi/udiptcfg.h
Normal 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
184
gdb/29k-share/udi/udisoc.h
Normal 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
427
gdb/29k-share/udi/udr.c
Normal 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
9
gdb/29k-share/udi_soc
Normal 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
340
gdb/COPYING
Normal 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
1116
gdb/ChangeLog
Normal file
File diff suppressed because it is too large
Load Diff
4838
gdb/ChangeLog-3.x
Normal file
4838
gdb/ChangeLog-3.x
Normal file
File diff suppressed because it is too large
Load Diff
8322
gdb/ChangeLog-9091
Normal file
8322
gdb/ChangeLog-9091
Normal file
File diff suppressed because it is too large
Load Diff
6285
gdb/ChangeLog-92
Normal file
6285
gdb/ChangeLog-92
Normal file
File diff suppressed because it is too large
Load Diff
7597
gdb/ChangeLog-93
Normal file
7597
gdb/ChangeLog-93
Normal file
File diff suppressed because it is too large
Load Diff
5705
gdb/ChangeLog-94
Normal file
5705
gdb/ChangeLog-94
Normal file
File diff suppressed because it is too large
Load Diff
4915
gdb/ChangeLog-95
Normal file
4915
gdb/ChangeLog-95
Normal file
File diff suppressed because it is too large
Load Diff
5116
gdb/ChangeLog-96
Normal file
5116
gdb/ChangeLog-96
Normal file
File diff suppressed because it is too large
Load Diff
2855
gdb/ChangeLog-97
Normal file
2855
gdb/ChangeLog-97
Normal file
File diff suppressed because it is too large
Load Diff
7122
gdb/ChangeLog-98
Normal file
7122
gdb/ChangeLog-98
Normal file
File diff suppressed because it is too large
Load Diff
1619
gdb/Makefile.in
Normal file
1619
gdb/Makefile.in
Normal file
File diff suppressed because it is too large
Load Diff
618
gdb/README
Normal file
618
gdb/README
Normal 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
471
gdb/TODO
Normal 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
1040
gdb/a29k-tdep.c
Normal file
File diff suppressed because it is too large
Load Diff
123
gdb/a68v-nat.c
Normal file
123
gdb/a68v-nat.c
Normal 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, ®isters[REGISTER_BYTE (FP0_REGNUM)],
|
||||||
|
sizeof inferior_fp_registers.regs);
|
||||||
|
*(int *)®isters[REGISTER_BYTE (PS_REGNUM)] = inferior_control_registers.sr;
|
||||||
|
*(int *)®isters[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 (®isters[REGISTER_BYTE (FP0_REGNUM)], inferior_fp_registers.regs,
|
||||||
|
sizeof inferior_fp_registers.regs);
|
||||||
|
|
||||||
|
inferior_control_registers.sr = *(int *)®isters[REGISTER_BYTE (PS_REGNUM)];
|
||||||
|
inferior_control_registers.pc = *(int *)®isters[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
169
gdb/abug-rom.c
Normal 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
95
gdb/acconfig.h
Normal 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
861
gdb/acinclude.m4
Normal 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
1307
gdb/aclocal.m4
vendored
Normal file
File diff suppressed because it is too large
Load Diff
297
gdb/alpha-nat.c
Normal file
297
gdb/alpha-nat.c
Normal 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 (®isters[REGISTER_BYTE (FP0_REGNUM)], core_reg_sect, 31*8);
|
||||||
|
memset (®isters[REGISTER_BYTE (FP0_REGNUM+31)], 0, 8);
|
||||||
|
memset (®ister_valid[FP0_REGNUM], 1, 32);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The General Registers. */
|
||||||
|
memcpy (®isters[REGISTER_BYTE (V0_REGNUM)], core_reg_sect, 31*8);
|
||||||
|
memcpy (®isters[REGISTER_BYTE (PC_REGNUM)], core_reg_sect+31*8, 8);
|
||||||
|
memset (®isters[REGISTER_BYTE (ZERO_REGNUM)], 0, 8);
|
||||||
|
memset (®ister_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 *) ®isters[REGISTER_BYTE (regi)];
|
||||||
|
|
||||||
|
if ((regno == -1) || (regno == PC_REGNUM))
|
||||||
|
*(regp + 31) = *(long *) ®isters[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 *) ®isters[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
1410
gdb/alpha-tdep.c
Normal file
File diff suppressed because it is too large
Load Diff
164
gdb/altos-xdep.c
Normal file
164
gdb/altos-xdep.c
Normal 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
577
gdb/annotate.c
Normal 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
104
gdb/annotate.h
Normal 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
733
gdb/arc-tdep.c
Normal 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
16
gdb/arm-convert.s
Normal 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
1626
gdb/arm-tdep.c
Normal file
File diff suppressed because it is too large
Load Diff
559
gdb/arm-xdep.c
Normal file
559
gdb/arm-xdep.c
Normal 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
1942
gdb/ax-gdb.c
Normal file
File diff suppressed because it is too large
Load Diff
111
gdb/ax-gdb.h
Normal file
111
gdb/ax-gdb.h
Normal 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
552
gdb/ax-general.c
Normal 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
285
gdb/ax.h
Normal 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
219
gdb/bcache.c
Normal 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
72
gdb/bcache.h
Normal 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
1301
gdb/blockframe.c
Normal file
File diff suppressed because it is too large
Load Diff
6686
gdb/breakpoint.c
Normal file
6686
gdb/breakpoint.c
Normal file
File diff suppressed because it is too large
Load Diff
604
gdb/breakpoint.h
Normal file
604
gdb/breakpoint.h
Normal 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
1130
gdb/buildsym.c
Normal file
File diff suppressed because it is too large
Load Diff
297
gdb/buildsym.h
Normal file
297
gdb/buildsym.h
Normal 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) */
|
2796
gdb/c-exp.tab.c
Normal file
2796
gdb/c-exp.tab.c
Normal file
File diff suppressed because it is too large
Load Diff
1740
gdb/c-exp.y
Normal file
1740
gdb/c-exp.y
Normal file
File diff suppressed because it is too large
Load Diff
527
gdb/c-lang.c
Normal file
527
gdb/c-lang.c
Normal 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
87
gdb/c-lang.h
Normal 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
1089
gdb/c-typeprint.c
Normal file
File diff suppressed because it is too large
Load Diff
535
gdb/c-valprint.c
Normal file
535
gdb/c-valprint.c
Normal 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
28
gdb/call-cmds.h
Normal 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
2169
gdb/ch-exp.c
Normal file
File diff suppressed because it is too large
Load Diff
675
gdb/ch-lang.c
Normal file
675
gdb/ch-lang.c
Normal 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
42
gdb/ch-lang.h
Normal 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
346
gdb/ch-typeprint.c
Normal 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
630
gdb/ch-valprint.c
Normal 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
134
gdb/coff-solib.c
Normal 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
190
gdb/coff-solib.h
Normal 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
2255
gdb/coffread.c
Normal file
File diff suppressed because it is too large
Load Diff
1564
gdb/command.c
Normal file
1564
gdb/command.c
Normal file
File diff suppressed because it is too large
Load Diff
259
gdb/command.h
Normal file
259
gdb/command.h
Normal 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
166
gdb/complaints.c
Normal 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
53
gdb/complaints.h
Normal 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
325
gdb/config.in
Normal 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
|
||||||
|
|
13
gdb/config/a29k/a29k-kern.mt
Normal file
13
gdb/config/a29k/a29k-kern.mt
Normal 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
|
5
gdb/config/a29k/a29k-udi.mt
Normal file
5
gdb/config/a29k/a29k-udi.mt
Normal 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
5
gdb/config/a29k/a29k.mt
Normal 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
|
26
gdb/config/a29k/nm-ultra3.h
Normal file
26
gdb/config/a29k/nm-ultra3.h
Normal 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
707
gdb/config/a29k/tm-a29k.h
Normal 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
226
gdb/config/a29k/tm-ultra3.h
Normal 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
229
gdb/config/a29k/tm-vx29k.h
Normal 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
13
gdb/config/a29k/ultra3.mh
Normal 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
|
||||||
|
|
6
gdb/config/a29k/ultra3.mt
Normal file
6
gdb/config/a29k/ultra3.mt
Normal 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
4
gdb/config/a29k/vx29k.mt
Normal 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
|
52
gdb/config/a29k/xm-ultra3.h
Normal file
52
gdb/config/a29k/xm-ultra3.h
Normal 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
|
9
gdb/config/alpha/alpha-linux.mh
Normal file
9
gdb/config/alpha/alpha-linux.mh
Normal 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
|
3
gdb/config/alpha/alpha-linux.mt
Normal file
3
gdb/config/alpha/alpha-linux.mt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Target: Little-endian Alpha
|
||||||
|
TDEPFILES= alpha-tdep.o
|
||||||
|
TM_FILE= tm-alphalinux.h
|
5
gdb/config/alpha/alpha-osf1.mh
Normal file
5
gdb/config/alpha/alpha-osf1.mh
Normal 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
|
3
gdb/config/alpha/alpha-osf1.mt
Normal file
3
gdb/config/alpha/alpha-osf1.mt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Target: Little-endian Alpha
|
||||||
|
TDEPFILES= alpha-tdep.o
|
||||||
|
TM_FILE= tm-alpha.h
|
5
gdb/config/alpha/alpha-osf2.mh
Normal file
5
gdb/config/alpha/alpha-osf2.mh
Normal 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
|
5
gdb/config/alpha/alpha-osf3.mh
Normal file
5
gdb/config/alpha/alpha-osf3.mh
Normal 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
|
66
gdb/config/alpha/nm-linux.h
Normal file
66
gdb/config/alpha/nm-linux.h
Normal 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
56
gdb/config/alpha/nm-osf.h
Normal 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)
|
54
gdb/config/alpha/nm-osf2.h
Normal file
54
gdb/config/alpha/nm-osf2.h
Normal 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
|
26
gdb/config/alpha/nm-osf3.h
Normal file
26
gdb/config/alpha/nm-osf3.h
Normal 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
479
gdb/config/alpha/tm-alpha.h
Normal 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 */
|
80
gdb/config/alpha/tm-alphalinux.h
Normal file
80
gdb/config/alpha/tm-alphalinux.h
Normal 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 */
|
29
gdb/config/alpha/xm-alphalinux.h
Normal file
29
gdb/config/alpha/xm-alphalinux.h
Normal 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
|
27
gdb/config/alpha/xm-alphaosf.h
Normal file
27
gdb/config/alpha/xm-alphaosf.h
Normal 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
3
gdb/config/arc/arc.mt
Normal 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
347
gdb/config/arc/tm-arc.h
Normal 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); \
|
||||||
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user