⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 debug.c

📁 ARM入门的好帮手.包含了从简单到相对较复杂的程序.
💻 C
字号:
/*> debug.c < *//*---------------------------------------------------------------------------*//* This file provides the main debug agent support for Angel. It deals * with certain messages, and with routing certain messages to * specific handlers. i.e. certain CPU related messages are sent to * the debug-hardware module, whilst O/S specific messages are passed * up through Angel to the environment executing on top of Angel. * * $Revision: 1.6.6.2 $ *   $Author: rivimey $ *     $Date: 1997/12/19 15:54:36 $ * * Copyright Advanced RISC Machines Limited, 1995. * All Rights Reserved. *//*---------------------------------------------------------------------------*/#include <stdarg.h>             /* Standard varargs processing */#include "angel.h"              /* Generic Angel definitions */#include "adp.h"                /* ADP protocol */#include "arm.h"                /* ARM processor definitions */#include "debug.h"              /* header for this file */#include "endian.h"             /* For target independant endianness access */#include "debughwi.h"           /* Hardware debugging functions interface. */#include "channels.h"           /* Channels stuff */#include "msgbuild.h"           /* unpack_message(), etc. */#include "logging.h"            /* LogError() etc. */#include "serlock.h"            /* Angel_Yield() */#include "devconf.h"/*---------------------------------------------------------------------------*//* Global (single-threaded) data. Certain parts of the debug agent are * single-threaded, so we can have some globally allocated Angel * variables. If multi-threaded code needs to manipulate these * variables, then suitable synchronisation should be provided in the * code to ensure atomic access. *//* The "debug_Status" variable holds the current debug agent state: */unsigned32 debug_Status = 0x00000000;/* The "debug_VectorCatch" value is a bitmask of ARM exception vectors * and Angel vectors that will raise pseudo-breakpoints to the host * when taken. */unsigned32 debug_VectorCatch = 0x00000000;int boot_completed = 0;/*---------------------------------------------------------------------------*//* * .. Software breakpoints .. *  * .. Those where the breakpoint is set within 2^26 of the breakpoint entry routine * .. a direct branch instruction can be used .. can breakpoint in any mode * .. requires run-time support to enter SVC mode * .. limits placing of breakpoints and address of handler * .. requires each breakpoint to have a stub entry, that can be used to uniquely identify the breakpoint *  * .. Those where a direct PC instruction can be used to load the breakpoint entry routine address * .. direct breakpoint entry, can be entered in any mode * .. requires run-time support to enter SVC mode * .. requires each breakpoint to have a stub entry, that can be used to uniquely identify the breakpoint * .. Handler entry stubs at a fixed low address, but breakpoints can be anywhere * MOV     pc,#<address> *  * .. Those where an undefined instruction is required * .. Cannot be used to safely breakpoint code executing in UNDef mode * .. Does *NOT* require run-time support to enter SVC mode * .. Does *NOT* require a seperate entry stub for each breakpoint * .. Breakpoint and breakpoint handling code can live at any address *//* The last of these options is the one chosen for the default Angel * implementation. However, if soft-breakpoints are required to debug * UNDefined mode code then one of the previous two schemes must be * used. These options are left as alternative Angel implementations * to be provided as conditional build systems. *//* TODO: .. possible mutex on asynchronous event code .. * .. to avoid eating all the free buffers .. * .. e.g. wait until current breakpoint message sent before sending another .. *//*---------------------------------------------------------------------------*//* ADP message vectoring * --------------------- * The indirection tables used by the debug world are defined in * assembler. This allows *ALL* of the handler functions to be * imported WEAK. If the developer then does not include a sub-section * (e.g. breakpoint support), then the table will have zero slots for * those functions. The vectoring code can then check for these, and * perform suitable error message generation if there is no handler. * * This is better than having a lot of conditionals in the 'C' source, * since now all that is required to remove handler functions is * simply to build an Angel with the relevant object files (or AREAs) * missing. */static void debugHandler(DeviceID devid, ChannelID chanid,             p_Buffer buffer, unsigned int length,             void *stateptr){    unsigned int reason;    int err;    IGNORE(devid);        if (length < 4)    {        LogWarning(LOG_DEBUG, ("debugHandler: buffer 0x%08X too small (%d bytes)\n",                     (unsigned int)buffer, length));        angel_ChannelReleaseBuffer(buffer);        return;    }    unpack_message(BUFFERDATA(buffer), "%w", &reason);    LogInfo(LOG_BOOT, ("debugHandler: message received: reason 0x%08x (%s), chanid %d\n",                         reason, log_adpname(reason), chanid));    /* Check to make sure booting is finished. */    if (boot_completed == 0)    {        p_Buffer rbuff;        LogError(LOG_DEBUG, ( "Entered debugHandler before boot has completed."));        angel_ChannelReleaseBuffer(buffer);        rbuff = angel_ChannelAllocBuffer(Angel_ChanBuffSize);        if (rbuff != NULL)        {            int count;            count = msgbuild(BUFFERDATA(rbuff), "%w%w%w%w%w", reason | TtoH,                             0, ADP_HandleUnknown, ADP_HandleUnknown,                             RDIError_NotInitialised);            angel_ChannelSend(CH_DEFAULT_DEV, CI_HADP, rbuff, count);        }        else            LogError(LOG_DEBUG, ( "Couldn't allocate buffer in debugHandler"));        return;    }    if (reason & TtoH)    {        LogWarning(LOG_DEBUG, ( "Warning: debugHandler has received TtoH msg - ignoring \n"));    }    else    {        if (chanid == CI_HADP)        {               /* Range check reason code. */            if ((reason & 0xFFFF) < hfptr_max)            {                LogInfo(LOG_DEBUG, ( "Jumping to vector table entry (reason code): 0x%x\n", reason & 0xFFFF));                err = hfptr[reason & 0xFFFF] (&buffer, stateptr);            }            else                err = -1;            if (err == -1)            {                /* Message isn't implemented so return a ADP_Unrecognised message. */                p_Buffer rbuff;                LogWarning(LOG_DEBUG, ( "debugHandler: Message not implemented, "                                          "reason 0x%x\n", reason & 0xffff));                rbuff = angel_ChannelAllocBuffer(Angel_ChanBuffSize);                if (rbuff != NULL)                {                    int count;                    count = msgbuild(BUFFERDATA(rbuff), "%w%w%w%w%w",                                     ADP_HADPUnrecognised | TtoH, 0, ADP_HandleUnknown,                                     ADP_HandleUnknown, reason);                    angel_ChannelSend(CH_DEFAULT_DEV, CI_HADP, rbuff, count);                }                else                {                    LogError(LOG_DEBUG, ( "ERROR: Couldn't allocate buffer in function debugH..."));                }            }        }        else        {                        LogWarning(LOG_DEBUG, ( "Warning: debugHandler received message for channel %d\n", chanid));        }    }    /* if the buffer is passed to a vector table entry, it may get freed there */    if (buffer != NULL)    {        LogInfo(LOG_DEBUG, ("debugHandler: freeing request buffer\n"));        angel_ChannelReleaseBuffer(buffer);    }        /* Always return OK, buffer excepted even if contents are ignored. */    return;}/* * .. Message handling *  * .. Direct action (immediate bounded effect) * .. Angel debug must be in control in single-threaded world * .. Angel multi-threaded debug must exist in multi-threaded world * .. Host-to-Target message * .. Target performs action * .. Target returns ACK (with any required data) * .. Debug agent still has control of the target *  * .. In-direct action (unbounded effect) * .. Angel debug must be in control in single-threaded world * .. Angel multi-threaded debug must exist in multi-threaded world * .. Host-to-Target message * .. Target schedules some action * .. Target returns ACK * .. Target performs action (e.g. Execute) * .. Debug agent no longer has control of the target *  *//* * .. single-threaded debugging * .. for debugging OSs, and the multi-threaded debugging system *  * .. multi-threaded debugging * .. when the OS is active, and we are debugging threads within it *  * .. interaction (through a defined API) with the hardware debugging features (e.g. Breakpoints, Watchpoints, etc.) *//*---------------------------------------------------------------------------*//* debug_ThreadStopped * ------------------_ * This routine deals with notifying the host of asynchronous target * events. It raises an "ADP_Stopped" message with the relevant * parameters. * * NOTE: This is a varargs function, to cope with the fact that some * messages have arguments to be passed. This code does not perform * any argument checking or verification, and it is assumed that the * caller of this function has passed the correct number and type of * arguments. */static volatile int stopping;typedef struct{    ChanRx_CB_Fn fn;    void *state_ptr;}debug_stophandlerargs;/* Handler to receive ack. for stopped message. */static void stoppedHandler(DeviceID devid, ChannelID chanid,               p_Buffer buffer, unsigned int length,               void *stateptr){    word reason, debugID, OSinfo1, OSinfo2, status;    IGNORE(devid);    IGNORE(chanid);    IGNORE(stateptr);    LogInfo(LOG_DEBUG, ( "DEBUG: Entered stoppedHandler."));    if (length < 20)    {        LogWarning(LOG_DEBUG, ("Message shorter than expected!!!"));    }    unpack_message(BUFFERDATA(buffer), "%w%w%w%w%w", &reason, &debugID,                   &OSinfo1, &OSinfo2, &status);    angel_ChannelReleaseBuffer(buffer);    if (reason != (ADP_Stopped | HtoT))    {        LogInfo(LOG_DEBUG, ( "Unexpected reason code in stoppedHandler: %x\n", reason));        return;    }    if (status != RDIError_NoError)    {        LogWarning(LOG_DEBUG, ( "Bad status in stopped ACK"));        return;    }    LogInfo(LOG_DEBUG, ( "got stopped ACK"));    stopping = FALSE;    return;}void debug_ThreadStopped(word OSinfo1, word OSinfo2, unsigned int event,                    unsigned int subcode){    /*     * Called from except.s as a callback,     * also from debughwi.c:gendbg_interruptrequest()     */    IGNORE(subcode);    IGNORE(OSinfo1);    IGNORE(OSinfo2);    if (debug_Status & debug_Status_Init)    {        p_Buffer pbuff;        word status = 0;        LogInfo(LOG_DEBUG, ( "Entered function debug_ThreadStopped.\n"));        LogInfo(LOG_DEBUG, ( "Reason no. for stopping = %x\n", event));        switch (event)        {            case ADP_Stopped_BreakPoint:                LogInfo(LOG_DEBUG, ( "ADP_Stopped_BreakPoint."));                break;        }        /* Send an ADP_Stopped. */        pbuff = angel_ChannelAllocBuffer(Angel_ChanBuffSize);        if (pbuff != NULL)        {            int count;            ChanError err;            count = msgbuild(BUFFERDATA(pbuff), "%w%w%w%w%w%w",                             (ADP_Stopped | TtoH), 0, ADP_HandleUnknown,                             ADP_HandleUnknown, event, status);            /* Register a special handler to receive the reply. */            LogInfo(LOG_DEBUG, ( "Registering stoppedHandler."));            err = angel_ChannelReadAsync(CH_DEFAULT_DEV, CI_TADP,                                         stoppedHandler,                                         NULL);            if (err != RDIError_NoError)                LogError(LOG_DEBUG, ( "Register failed."));            LogInfo(LOG_DEBUG, ( "Transmitting stopped message."));            stopping = TRUE;            err = angel_ChannelSend(CH_DEFAULT_DEV, CI_TADP, pbuff, count);            if (err != RDIError_NoError)                LogWarning(LOG_DEBUG, ( "Transmit failed."));            LogInfo(LOG_DEBUG, ( "Waiting for stopped ack..."));            while (stopping)                Angel_Yield();            LogInfo(LOG_DEBUG, ( "Unregistering stoppedHandler."));            err = angel_ChannelReadAsync(CH_DEFAULT_DEV, CI_TADP,                                         NULL, NULL);            if (err != RDIError_NoError)                LogError(LOG_DEBUG, ( "Unregister failed."));            LogInfo(LOG_DEBUG, ( "Returning..."));        }        else        {            LogError(LOG_DEBUG, ( "ERROR: Couldn't allocate buffer in debug_ThreadStopped."));            return;        }    }    /* Else return to the caller. */    return;}/*---------------------------------------------------------------------------*//* angel_DebugInit * --------------- * This is the starting point for attaching the Angel debug agent. At * the moment this single entry point must deal with setting up both * the single- and multi-threaded debugging handlers. */void angel_DebugInit(void){    LogInfo(LOG_BOOT, ( "angel_DebugInit: entered\n"));    /* Open the channel for single-threaded debugging messages */    {        if (angel_ChannelReadAsync(CH_DEFAULT_DEV, CI_HADP, debugHandler,                                   NULL) < 0)        {            LogError(LOG_DEBUG, ( "angel_DebugInit: Failed to attach handler for CI_HADP"));        }    }    /*     * TODO: Comments about preserving break-points on     * application initialisation (rom ROM initialisation)     */    /*     * .. NOTE: We will need magic here to deal with automatically     * .. setting a breakpoint on "main" when building ROM applications.     * .. Similarly we have the problem of the application being downloaded     * .. using the boot monitor, the user then setting a breakpoint on     * .. main, the application being started, which then provides a new     * .. breakpoint handler (as part of its Angel initialisation). We need     * .. to ensure that breakpoints are passed through so that the     * .. application library based Angel will still stop when main is     * .. reached.     */    /* NOTE: We explicitly set the single "Init"ialised flag, to clear     * the rest of the debug agent state bits:     */    debug_Status = (debug_Status_Init);    return;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -