To enable debugging of an application using the Snapshot Viewer, you must have the following
If you are unable to provide all of this data, then the level of
debug that is available is compromised. Capturing this data is specific to your
application, and no tools are provided to help with this. You might have to install
exception or signal handlers to catch erroneous situations in your application and
dump the required data out.
You must also consider how to get the dumped data from your device
onto a workstation that is accessible by the debugger. Some suggestions on how to do
this are to:
Write the data to a file on the host workstation using
Send the data over a UART to a terminal.
Send the data over a socket using TCP/IP.
Register values are used to emulate the state of the original system at a particular point in time. The most important registers are those in the current processor mode. For example, on an ARMv4 architecture processor these registers are R0-R15 and also the Program Status Registers (PSRs):
Current Program Status Register (CPSR)
Application Program Status Register (APSR)
Saved Program Status Register (SPSR).
Be aware that on many ARM® processors, an
exception, a data abort, causes a switch to a different processor mode. In this
case, you must ensure that the register values you use reflect the correct mode in
which the exception occurred, rather than the register values within your exception
If your application uses floating-point data and your device contains vector
floating-point hardware, then you must also provide the Snapshot
Viewer with the contents of the vector floating-point registers. The
important registers to capture are:
Floating-point Status and Control Register (FPSCR)
Floating-Point EXCeption register (FPEXC)
Single precision registers (S
Double precision registers (D
Quad precision registers (Q
The majority of the application state is usually stored in memory in the form
of global variables, the heap and the stack. Due to size constraints, it is often
difficult to provide the Snapshot Viewer with a copy of the
entire contents of memory. In this case, you must carefully consider the areas of
memory that are of particular importance.
If you are debugging a crash, the most useful information to find out is often
the call stack, because this shows the calling sequence of each function prior to
the exception and the values of all the respective function parameters. To show the
call stack, the debugger must know the current stack pointer and have access to the
contents of the memory that contains the stack. By default, on ARM processors, the
stack grows downwards, you must provide the memory starting from the current stack
pointer and going up in memory until the beginning of the stack is reached. If you
are unable to provide the entire contents of the stack, then a smaller portion
starting at the current stack pointer is still useful because it provides the most
recent function calls.
If your application uses global (
extern or file
static) data, then providing the corresponding memory values enables you to view the variables within the debugger.
If you have local or global variables that point to heap data, then you might
want to follow the relevant pointers in the debugger to examine the data. To do this
you must have provided the contents of the heap to the Snapshot Viewer. Be aware that heap can often occupy a large memory
range, so it might not be possible to capture the entire heap. The layout of the
heap in memory and the data structures that control heap allocation are often
specific to the application or the C library, see the relevant documentation for
To debug at the disassembly level, the debugger must have access to the memory values where the application code is located. It is often not necessary to capture the contents of the memory containing the code, because identical data can often be extracted directly from the image using
processing tools such as
fromelf. However, some complications to be aware of are:
The debugger requires debug information to display high-level information
about your application, for example:
This information is stored by the compiler and linker within the application
image, so you must ensure that you have a local debug copy of the same image that
you are running on your device. The amount of debug information that is stored in
the image, and therefore the resulting quality of your debug session, can be
affected by the debug and optimization settings passed to the compiler and
It is common to strip out as much of the debug information as possible when running an image on an embedded device. In such cases, try to use the original unstripped image for debugging purposes.