Using NuMega SoftICE

"Symbol Table" - the most important thing for source level debugging with SoftICE.

SoftICE is capable of disassembling instructions at any given address (assuming that address actually points to a valid byte stream of instructions). With just this capability, an assembly language programmer could use SoftICE quite effectively. However, most modern programs, both applications and even drivers, are written in high-level languages, and it becomes quickly unrealistic to try to debug a program without source files.

To setup for a source level debugging, you MUST load symbol table (and of course associated source files), and the symbol table must be correctly mapped to the load address of the target module.

The figure below demonstrate this concept of "mapping a symbol table at load address".

Suppose you want to debug a DLL, "MyDll.dll" which is dynamically loaded by an client application, "Client.exe". First thing you have to do is to "pre-load" the symbol table for your DLL. Remember that DLL cannot be started by itself. It needs a "process space" to which DLL is loaded into. When symbol table of "MyDll.dll" is pre-loaded into memory, and even after the client program, "Client.exe" is loaded, the symbol table for "MyDll" remains "logical" - meaning that symbols point to nowhere.

You see a process space created for an application, "Client.exe", and symbol table for "Client.exe" is already mapped to the load address of "Client.exe". SoftICE does this mapping automatically when "Client.exe" is loaded.

If you look at the output of "SYM" command while "MyDll[NM32]" is selected as the current symbol table, you notice that ".text" section is mapped to address 0001:00000000. If you issue SoftICE GDT command, you will learn that the selector value of 0001 is invalid. In other words, "MyDll[NM32]" symbol table is not mapped to anywhere.

Now, after "Client.exe" calls Win32 API LoadLibrary to load "MyDll.dll", SoftICE automatically "maps" the symbol table by setting the base address of the symbol table to the "load address" of "MyDll" - in this case, it is 0x10000000.

Once this mapping occur, you can symbolically debug "MyDll" at source level.

Common problem

Sometimes, you experience breakpoint not going off, even if symbol table and associated source files are loaded. If this happens, first, make sure that symbol table is "mapped" to the load address using "SYM" command. If "SYM" command list address like "0001:00000000" or "0002:00000000", then you know that it is not mapped correctly. No breakpoint will triger since execution never occur at that address.

This could be caused by a number of reasons including "limitations" of SoftICE (see below). However, there is a workaround for this situation: use SoftICE command "SYMLOC" to do the "mapping" by hand. Syntax of SYMLOC asks you for (1) section, (2) selector, and (3) base address. (1) section is almost always value=1 because most programs have CODE section as the first section. (2) is almost always either 0x08 or 0x1B. If your program is "user-mode" application, then use 0x1B, if its a "kernel-mode" driver, then use 0x08. You can find out the base address of a module using either "MOD", "QUERY", or "DRIER" command.


Unfortunately, there exists a limitation with the current symbol table architecture of SoftICE: SoftICE cannot distinguish two modules by thier file extensions. For instance, if you have "test.exe" and "test.dll" and "test.sys" with all modules loaded at the same time. Only one symbol table named "test[NM32]" is allowed to be loaded. Furthermore, the "load address" is determined by the order of loading - SoftICE uses the address of whatever loaded at last for mapping.


 contact guestbook | control panel 
1998-2000 Tsuyoshi Watanabe. All rights reserved.