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