#include <debugapi.h>
#include <process.h>
-/************************************************************************/
-/*****************************************************************************
- *
- * (C) Copyright 1988-1993 Novell, Inc.
- * All Rights Reserved.
- *
- * This program is an unpublished copyrighted work which is proprietary
- * to Novell, Inc. and contains confidential information that is not
- * to be reproduced or disclosed to any other person or entity without
- * prior written consent from Novell, Inc. in each and every instance.
- *
- * WARNING: Unauthorized reproduction of this program as well as
- * unauthorized preparation of derivative works based upon the
- * program or distribution of copies by sale, rental, lease or
- * lending are violations of federal copyright laws and state trade
- * secret laws, punishable by civil and criminal penalties.
- *
- * $release$
- * $modname: loadstuff.h$
- * $version: 1.37$
- * $date: Fri, Jan 15, 1993$
- *
- ****************************************************************************/
+/****************************************************/
+/* This information is from Novell. It is not in any of the standard
+ NetWare header files. */
-
-/* WARNING: THIS IS NOT A COMPLETE OS HEADER FILE - DON'T GET CONFUSED
- ***********************************************************************
- * The information is this file is a subset of the OS LOADER.H.
- * This file was created to reveal the LoadDefinitionStrucutre and some
- * associated information to Cygnus Support to assist them in their
- * efforts to develop GNU netware utilities. Don't confuse this file
- * with LOADER.H or any other actually supported NetWare header.
-
-************************************************************************/
-
-struct LoadDefinitionStructure
+struct DBG_LoadDefinitionStructure
{
- struct LoadDefinitionStructure *LDLink;
- struct LoadDefinitionStructure *LDKillLink;
- struct LoadDefinitionStructure *LDScanLink;
- struct ResourceTagStructure *LDResourceList;
- LONG LDIdentificationNumber;
+ void *reserved1[4];
+ LONG reserved5;
LONG LDCodeImageOffset;
LONG LDCodeImageLength;
LONG LDDataImageOffset;
LONG LDUninitializedDataLength;
LONG LDCustomDataOffset;
LONG LDCustomDataSize;
- LONG LDFlags;
- LONG LDType;
- LONG (*LDInitializationProcedure)(
- struct LoadDefinitionStructure *LoadRecord,
- struct ScreenStruct *screenID,
- BYTE *CommandLine,
- BYTE *loadDirectoryPath,
- LONG uninitializedDataLength,
- LONG fileHandle,
- LONG (*ReadRoutine)(
- LONG fileHandle,
- LONG offset,
- void *buffer,
- LONG numberOfBytes),
- LONG customDataOffset,
- LONG customDataSize);
- void (*LDExitProcedure)(void);
- LONG (*LDCheckUnloadProcedure)(
- struct ScreenStruct *screenID);
- struct ExternalPublicDefinitionStructure *LDPublics;
- BYTE LDFileName[36];
- BYTE LDName[128];
- LONG *LDCLIBLoadStructure;
- LONG *LDNLMDebugger;
- LONG LDParentID;
- LONG LDReservedForCLIB;
- LONG Reserved0;
- LONG Reserved1;
- void *LDModuleObjectHandle; /* If Instrumented BEW 10/16/90 */
- LONG LDMajorVersion;
- LONG LDMinorVersion;
- LONG LDRevision;
- LONG LDYear;
- LONG LDMonth;
- LONG LDDay;
- BYTE *LDCopyright;
- LONG LDAllocAvailBytes;
- LONG LDAllocFreeCount;
- LONG LDLastGarbCollect;
- LONG LDAlloc16Lists[64];
- LONG LDAlloc256Lists[12];
- LONG LDAlloc4kList;
- struct DomainStructure *LDDomainID; /* This must be non-zero for the Alloc Hunt code to work right. */
- /* It also points to the domain structure. */
- struct LoadDefinitionStructure *LDEnvLink;
- void *LDAllocPagesListHead;
- struct ExternalPublicDefinitionStructure *LDTempPublicList;
- LONG LDMessageLanguage; /* for enabling */
- BYTE **LDMessages; /* for enabling */
- LONG LDMessageCount; /* for enabling */
- BYTE *LDHelpFile; /* for enabling */
- LONG LDMessageBufferSize; /* for enabling */
- LONG LDHelpBufferSize; /* for enabling */
- LONG LDSharedCodeOffset; /* for protection */
- LONG LDSharedCodeLength; /* for protection */
- LONG LDSharedDataOffset; /* for protection */
- LONG LDSharedDataLength; /* for protection */
- LONG (*LDSharedInitProcedure)(
- struct LoadDefinitionStructure *LoadRecord,
- struct ScreenStruct *screenID,
- BYTE *CommandLine);
- void (*LDSharedExitProcedure)(void);
- LONG LDRPCDataTable;
- LONG LDRealRPCDataTable;
- LONG LDRPCDataTableSize;
- LONG LDNumberOfReferencedPublics;
- struct ExternalPublicDefinitionStructure **LDReferencedPublics;
- LONG LDNumberOfReferencedExports;
+ LONG reserved6[2];
+ LONG (*LDInitializationProcedure)(void);
};
-
-/* define the LDFlags. */
-
-#define LDModuleIsReEntrantBit 0x00000001
-#define LDModuleCanBeMultiplyLoadedBit 0x00000002
-#define LDSynchronizeStart 0x00000004
-#define LDPseudoPreemptionBit 0x00000008
-#define LDLoadInOSDomain 0x00000010
-#define LDDontUnloadBit 0x20000000
-#define LDModuleIsBeingDebugged 0x40000000
-#define LDMemoryOn4KBoundriesBit 0x80000000
-
-/* LoadModule load options */
-#define LO_NORMAL 0x0000
-#define LO_STARTUP 0x0001
-#define LO_PROTECT 0x0002
-#define LO_DEBUG 0x0004
-#define LO_AUTO_LOAD 0x0008
-#define LO_DONT_PROMPT 0x0010
-#define LO_LOAD_LOW 0x0020
-#define LO_RETURN_HANDLE 0x0040
-#define LO_LOAD_SILENT 0x0080
+#define LO_NORMAL 0x0000
+#define LO_STARTUP 0x0001
+#define LO_PROTECT 0x0002
+#define LO_DEBUG 0x0004
+#define LO_AUTO_LOAD 0x0008
/* Loader returned error codes */
-#define LOAD_COULD_NOT_FIND_FILE 1
-#define LOAD_ERROR_READING_FILE 2
-#define LOAD_NOT_NLM_FILE_FORMAT 3
+#define LOAD_COULD_NOT_FIND_FILE 1
+#define LOAD_ERROR_READING_FILE 2
+#define LOAD_NOT_NLM_FILE_FORMAT 3
#define LOAD_WRONG_NLM_FILE_VERSION 4
#define LOAD_REENTRANT_INITIALIZE_FAILURE 5
#define LOAD_CAN_NOT_LOAD_MULTIPLE_COPIES 6
-#define LOAD_ALREADY_IN_PROGRESS 7
+#define LOAD_ALREADY_IN_PROGRESS 7
#define LOAD_NOT_ENOUGH_MEMORY 8
-#define LOAD_INITIALIZE_FAILURE 9
+#define LOAD_INITIALIZE_FAILURE 9
#define LOAD_INCONSISTENT_FILE_FORMAT 10
#define LOAD_CAN_NOT_LOAD_AT_STARTUP 11
#define LOAD_AUTO_LOAD_MODULES_NOT_LOADED 12
-#define LOAD_UNRESOLVED_EXTERNAL 13
+#define LOAD_UNRESOLVED_EXTERNAL 13
#define LOAD_PUBLIC_ALREADY_DEFINED 14
-#define LOAD_XDC_DATA_ERROR 15
-#define LOAD_NOT_OS_DOMAIN 16
-
-/****************************************************************************/
+/****************************************************/
/* The main thread ID. */
static int mainthread;
/* The LoadDefinitionStructure of the NLM being debugged. */
-static struct LoadDefinitionStructure *handle;
+static struct DBG_LoadDefinitionStructure *handle;
/* Whether we have connected to gdb. */
static int talking;
}
while (checksum != xmitcsum);
+ if (remote_debug)
+ ConsolePrintf ("Received packet \"%s\"\r\n", buffer);
+
return 1;
}
int count;
int ch;
+ if (remote_debug)
+ ConsolePrintf ("Sending packet \"%s\"\r\n", buffer);
+
/* $<packet info>#<checksum>. */
do
{
char *parm;
{
if (remote_debug)
- fprintf (stderr, format, parm);
+ {
+ fprintf (stderr, format, parm);
+ fprintf (stderr, "\n");
+ }
}
-/* Address of a routine to RTE to if we get a memory fault. */
-static volatile void (*mem_fault_routine)() = NULL;
+/* This is set if we could get a memory access fault. */
+static int mem_may_fault;
/* Indicate to caller of mem2hex or hex2mem that there has been an
error. */
static volatile int mem_err = 0;
-static void
-set_mem_err ()
-{
- mem_err = 1;
-}
-
/* These are separate functions so that they are so short and sweet
that the compiler won't save any registers (if there is a fault
to mem_fault, they won't get restored, so there better not be any
*addr = val;
}
+/* This bit of assembly language just returns from a function. If a
+ memory error occurs within get_char or set_char, the debugger
+ handler points EIP at these instructions to get out. */
+
+extern void just_return ();
+asm (".globl just_return");
+asm (".globl _just_return");
+asm ("just_return:");
+asm ("_just_return:");
+asm ("leave");
+asm ("ret");
+
/* convert the memory pointed to by mem into hex, placing result in buf */
/* return a pointer to the last char put in buf (null) */
/* If MAY_FAULT is non-zero, then we should set mem_err in response to
int i;
unsigned char ch;
- if (may_fault)
- mem_fault_routine = set_mem_err;
+ mem_may_fault = may_fault;
for (i = 0; i < count; i++)
{
ch = get_char (mem++);
*buf++ = hexchars[ch % 16];
}
*buf = 0;
- if (may_fault)
- mem_fault_routine = NULL;
+ mem_may_fault = 0;
return(buf);
}
int i;
unsigned char ch;
- if (may_fault)
- mem_fault_routine = set_mem_err;
+ mem_may_fault = may_fault;
for (i=0;i<count;i++)
{
ch = hex(*buf++) << 4;
if (may_fault && mem_err)
return (mem);
}
- if (may_fault)
- mem_fault_routine = NULL;
+ mem_may_fault = 0;
return(mem);
}
handle_exception (T_StackFrame *old_frame)
{
T_TSS_StackFrame *frame = (T_TSS_StackFrame *) old_frame;
- int first = 0;
int sigval;
int addr, length;
char * ptr;
if (frame->ExceptionNumber == START_NLM_EVENT
&& handle == NULL)
{
- handle = (struct LoadDefinitionStructure *) frame->ExceptionErrorCode;
+ handle = ((struct DBG_LoadDefinitionStructure *)
+ frame->ExceptionErrorCode);
first_insn = *(char *) handle->LDInitializationProcedure;
*(unsigned char *) handle->LDInitializationProcedure = 0xcc;
return RETURN_TO_PROGRAM;
}
+ /* After we've reached the initial breakpoint, reset it. */
+ if (frame->ExceptionEIP == (LONG) handle->LDInitializationProcedure + 1
+ && *(unsigned char *) handle->LDInitializationProcedure == 0xcc)
+ {
+ *(char *) handle->LDInitializationProcedure = first_insn;
+ frame->ExceptionEIP = (LONG) handle->LDInitializationProcedure;
+ }
+
/* Pass some events on to the next debugger, in case it will handle
them. */
if (frame->ExceptionNumber == ENTER_DEBUGGER_EVENT
&& frame->ExceptionNumber > 31)
return RETURN_TO_PROGRAM;
- /* Reset the initial breakpoint if necessary. */
- if (frame->ExceptionNumber == 3
- && frame->ExceptionEIP == (LONG) handle->LDInitializationProcedure + 1
- && *(unsigned char *) handle->LDInitializationProcedure == 0xcc)
+ /* If we get a GP fault, and mem_may_fault is set, and the
+ instruction pointer is near set_char or get_char, then we caused
+ the fault ourselves accessing an illegal memory location. */
+ if (mem_may_fault
+ && (frame->ExceptionNumber == 11
+ || frame->ExceptionNumber == 13
+ || frame->ExceptionNumber == 14)
+ && ((frame->ExceptionEIP >= (long) &set_char
+ && frame->ExceptionEIP < (long) &set_char + 50)
+ || (frame->ExceptionEIP >= (long) &get_char
+ && frame->ExceptionEIP < (long) &get_char + 50)))
{
- *(char *) handle->LDInitializationProcedure = first_insn;
- frame->ExceptionEIP = (LONG) handle->LDInitializationProcedure;
- first = 1;
+ mem_err = 1;
+ /* Point the instruction pointer at an assembly language stub
+ which just returns from the function. */
+ frame->ExceptionEIP = (long) &just_return;
+ /* Keep going. This will act as though it returned from
+ set_char or get_char. The calling routine will check
+ mem_err, and do the right thing. */
+ return RETURN_TO_PROGRAM;
}
/* FIXME: How do we know that this exception has anything to do with
else
{
sigval = computeSignal (frame->ExceptionNumber);
- remcomOutBuffer[0] = 'S';
+ remcomOutBuffer[0] = 'N';
remcomOutBuffer[1] = hexchars[sigval >> 4];
remcomOutBuffer[2] = hexchars[sigval % 16];
- remcomOutBuffer[3] = 0;
- if (first)
- {
- remcomOutBuffer[0] = 'N';
- sprintf (remcomOutBuffer + 3, "0x%x;0x%x;0x%x",
- handle->LDCodeImageOffset,
- handle->LDDataImageOffset,
- handle->LDDataImageOffset + handle->LDDataImageLength);
- }
+ sprintf (remcomOutBuffer + 3, "0x%x;0x%x;0x%x",
+ handle->LDCodeImageOffset,
+ handle->LDDataImageOffset,
+ handle->LDDataImageOffset + handle->LDDataImageLength);
}
if (! putpacket(remcomOutBuffer))
{
case '?':
sigval = computeSignal (frame->ExceptionNumber);
- remcomOutBuffer[0] = 'S';
+ remcomOutBuffer[0] = 'N';
remcomOutBuffer[1] = hexchars[sigval >> 4];
remcomOutBuffer[2] = hexchars[sigval % 16];
- remcomOutBuffer[3] = 0;
- if (first)
- {
- remcomOutBuffer[0] = 'N';
- sprintf (remcomOutBuffer + 3, "0x%x;0x%x;0x%x",
- handle->LDCodeImageOffset,
- handle->LDDataImageOffset,
- (handle->LDDataImageOffset
- + handle->LDDataImageLength));
- }
+ sprintf (remcomOutBuffer + 3, "0x%x;0x%x;0x%x",
+ handle->LDCodeImageOffset,
+ handle->LDDataImageOffset,
+ handle->LDDataImageOffset + handle->LDDataImageLength);
break;
case 'd':
remote_debug = !(remote_debug); /* toggle debug flag */