|Non-Confidential||PDF version||ARM DUI0446Z|
|Home > Working with the Snapshot Viewer > About the Snapshot Viewer|
Use the Snapshot Viewer to analyze a snapshot representation of the application state of one or more processors in scenarios where interactive debugging is not possible.
To enable debugging of an application using the Snapshot Viewer, you must have the following data:
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 semihosting.
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 handler.
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 more information.
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:
Self-modifying code where the values in the image and memory can vary.
Dynamic relocation of the memory address within the image at runtime.
The debugger requires debug information to display high-level information about your application, for example:
Variable values and types
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 linker.
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.