Difference between revisions of "Development/Debugging"

From Syslinux Wiki
Jump to: navigation, search
m (How to invoke: Minor rewording.)
(Minor rewording, typos. Wiki formatting.)
 
Line 1: Line 1:
''' NOTE '''
+
'''Please note, <!--
 +
-->this page may be incomplete or outdated or possibly use incorrect terminology.'''
  
Please note, this page is under development at the moment and may be incomplete or possibly use incorrect terminology
+
<!-- == Overview == -->
  
= Overview =
+
When testing, a "bug", or behavior contrary to design or expectation, may be found. 
 +
Debugging is the process of finding the source of the bug in order to remove it.
  
When testing, a "bug", or behavior contrary to design or expectation, may be found.  Debugging is the process of finding the source of the bug in order to remove it.
+
As always, there are multiple means by which to debug a program, varying, among other things,
 +
in their level of complexity and detail by which information may be examined.
  
As always, there are multiple means by which to debug a program that vary, among other things, in their level of complexity and detail by which information may be examined.
+
== In Source ==
  
= In Source =
+
Inserting statements like printf() and puts() to watch the progress
 +
and/or data of the program is the least technical method.
  
Inserting statements like printf() and puts() to watch the progress and/or data of the program is the least technical method
+
== Debugger 32-bit ==
  
= Debugger 32-bit =
+
<!--Insert stuff here about using a debugger with a 32/64b program.-->
 +
Both qemu and bochs have the capability of a gdbstub, allowing you to connect
 +
the GNU Debugger (gdb) to the qemu/bochs process and examine what the VM sees.
  
--Insert stuff here about using a debugger with a 32/64b program.
+
== Debugger 16-bit Segmented ==
  
Both qemu and bochs have the capability of a gdbstub, which allow you to connect gdb, the GNU Debugger, to the qemu/bochs process and examine what the VM sees.
+
(Or the real reason I built this page.  --Gene)<br/>
  
= Debugger 16-bit Segmented =
+
<!-- === Intro === -->
  
(Or the real reason I built this page.  --Gene)
+
16-bit segmented mode, also known as [http://en.wikipedia.org/wiki/Real_mode Real Mode],
 +
is recognized as addressing with 2 registers, a segment and an offset, each 16 bits long,
 +
and staggered to form a 20 bit address {{nowrap|1=(segment * 10h + offset = address).}}  
 +
This is the operating mode of the boot sector, the secondary loader
 +
(for disk-based variants in {{nowrap|Syslinux-4.00}} as of {{nowrap|2010-06-21),}}
 +
most (but I believe all) of the Syslinux core assembly code and COMBOOT modules.
  
== Intro ==
+
=== Background and Caveats ===
  
16-bit segmented mode, also known as [http://en.wikipedia.org/wiki/Real_mode Real Mode], is recognize as addressing with 2 registers, a segment and an offset, each 16 bits long, and staggered to form a 20 bit address (segment * 10h + offset = address).  This is the operating mode of the boot sector, the secondary loader (for disk-based variants in Syslinux-4.00 as of 2010-06-21), most (but I believe all) of the Syslinux core assembly code and COMBOOT modules.
+
Unfortunately, gdb is not effective at debugging 16-bit segmented code.
 +
Attempting to utilize qemu or bochs with gdb will only lead to frustration.
  
== Background/Caveats ==
+
However, bochs has an internal debugger available. 
 +
Unfortunately, it's mutually exclusive of the gdbstub at compile time and most distributions
 +
compile in the gdbstub instead of the internal debugger
 +
(which is probably a good choice _most_ of the time).
  
Unfortunately, gdb is not effective at debugging 16-bit segmented code.  Attempting to utilize qemu or bochs with gdb will only lead to frustration.
+
=== Use the source ===
  
However, bochs has an internal debugger availableUnfortunately, it's mutually exclusive of the gdbstub at compile time and most distributions compile in the gdbstub instead of the internal debugger (which is probably a good choice _most_ of the time).
+
Quite literallyGrab the source for bochs (on {{nowrap|2010-06-21}},  
 +
{{nowrap|2.4.5}} is the current stable),
 +
the needed development libraries
 +
(the configure script will warn you nicely; if it says libraries are missing,
 +
it means development libraries of course). 
 +
You'll want to configure using
 +
{{nowrap|1='<code>./configure --enable-debugger --enable-disasm</code>'}}
 +
to enable the debugger and disassembler. 
 +
{{nowrap|1='<code>--enable-readline</code>'}}
 +
is helpful in the debugger for editing the command line and history. 
 +
You can also add
 +
{{nowrap|1='<code>--enable-ne2000</code>'}} and
 +
{{nowrap|1='<code>--enable-pnic</code>'}}
 +
if you're interested in PXELINUX. 
 +
Next, compile it {{nowrap|('<code>make all</code>').}} 
 +
See also [[Development/SettingUpBochs|Setting Up Bochs]].
  
== Use the source ==
+
I've tried to build bfe (bochs debugger front end)
 +
but at this time have not figured out what I'm missing.
  
Quite literally.  Grab the source for bochs (on 2010-06-21, 2.4.5 is the current stable), the needed development libraries (the configure script will warn you nicely; if it says libraries are missing, it means development libraries of course).  You'll want to configure using './configure --enable-debugger --enable-disasm' to enable the debugger and disassembler.  '--enable-readline' is helpful in the debugger for editing the command line and history.  You can also add '--enable-ne2000' and '--enable-pnic' if you're interested in PXELINUX.  Next, compile it ('make all').  See also [[Development/SettingUpBochs|Setting Up Bochs]].
+
=== Configuration ===
  
I've tried to build bfe (bochs debugger front end) but at this time have not figured out what I'm missing.
+
Build a configuration file (aka bochsrc) as needed. 
 +
You'll of course need a boot device (floppy, cdrom, hard disk, PXE, etc). 
 +
See also [[Development/Testing|Testing]] and [[Development/SettingUpBochs|Setting Up Bochs]].
  
== Configuration ==
+
=== Usage hints ===
  
Build a configuration file (aka bochsrc) as needed.  You'll of course need a boot device (floppy, cdrom, hard disk, PXE, etc).  See also [[Development/Testing|Testing]] and [[Development/SettingUpBochs|Setting Up Bochs]].
+
==== Start ====
  
== Usage hints ==
+
After launching, it will come up to the "start menu" (unless {{nowrap|<tt>-q</tt>}}
 +
is specified). 
 +
If it's fully configured, "Begin Simulation". 
 +
At this point, it will dump you to the debugger prompt. 
 +
Your first friend here is 'help' (also as 'h') to list the possible commands. 
 +
{{nowrap|<tt>'h b'</tt>}} will list help information for 'b' (breakpoint).
  
=== Start ===
+
See also the official manual
 +
[http://bochs.sourceforge.net/doc/docbook/user/internal-debugger.html here]
 +
(although as of {{nowrap|2010-08-01}}, it appears to be out of date
 +
and the internal help is current).
  
After launching, it will come up to the "start menu" (unless -q is specified).  If it's fully configured, "Begin Simulation".  At this point, it will dump you to the debugger prompt.  Your first friend here is 'help' (also as 'h') to list the possible commands.  'h b' will list help information for 'b' (breakpoint).
+
==== Breaking ====
  
See also the official manual [http://bochs.sourceforge.net/doc/docbook/user/internal-debugger.html here] (although as of 2010-08-01, it appears to be out of date and the internal help is current).
+
Breakpoints are a way to stop the debugger at an exact code point.
 +
The first one to be aware of is 0x7c00 ('<tt>b 0x7c00</tt>').
 +
This is the code entry point for all variants. 
 +
If you're debugging a boot sector (for a disk-based variant or for ISOLINUX),  
 +
this is a great starting breakpoint. 
 +
This makes it execute through all of the BIOS related initialization code without stopping.
  
=== Breaking ===
+
If you don't want to look at the code in an interrupt,
 +
try setting a breakpoint at the return point.
  
Breakpoints are a way to stop the debugger at an exact code point.  The first one to be aware of is 0x7c00 ('b 0x7c00'). This is the code entry point for all variants.  If you're debugging a boot sector (for a disk-based variant or ISOLINUX), this is a great starting breakpoint.  This makes it execute through all of the BIOS related initialization code without stopping.
+
As of 2010-06-21, Syslinux {{nowrap|4.00-pre55}} disk-based variants  
 +
used a boot loader to a secondary loader (starting at address 0x8000).
  
If you don't want to look at the code in an interrupt, try setting a breakpoint at the return point.
+
For additional addresses within the Syslinux core, look at the .lst file
 +
for the variant you are examining as it has the correct addresses. 
 +
Please note this requires currently that you compile Syslinux yourself at this time.
  
As of 2010-06-21, Syslinux 4.00-pre55 disk-based variants used a boot loader to a secondary loader (starting at address 0x8000).
+
For the loading and entry into a COM32 module,  
 +
search for call <tt>com32_entry</tt> in the .lst file of the variant you are using.
  
For additional addresses within the Syslinux core, look at the .lst file for the variant you are examining as it has the correct addresses.  Please note this requires currently that you compile Syslinux yourself at this time.
+
==== Continuing ====
 
+
For the loading and entry into a COM32 module, search for call com32_entry in the .lst file of the variant you are using.
+
 
+
=== Continuing ===
+
  
 
'c' will tell it to continue on if it's been interrupted (including the initial prompt).
 
'c' will tell it to continue on if it's been interrupted (including the initial prompt).
  
=== Stepping ===
+
==== Stepping ====
 
+
's' or 's #' will step forward a certain number of instructions (default 1).  This will include the code you're examining and any interrupt calls.
+
 
+
=== Disassembly ===
+
 
+
'u' or 'disasm' will disassemble the current instruction.  'u /count' disassembles count instructions
+
 
+
'u start' will disassemble the instruction at the location start.  'u start end' will disassemble instructions from location start inclusive to end exclusive.
+
  
=== Registers ===
+
's' or 's #' will step forward a certain number of instructions (default 1). 
 +
This will include the code you're examining and any interrupt calls.
  
'r' will dump the state of all of the "standard" registers, eax, ecx, edx, ebx, esp, ebp, esi, edi, eip, eflags.
+
==== Disassembly ====
  
'sreg' will dump the segment registers es, cs, ss, ds, fs, gs (and information about those segments)
+
'u' or 'disasm' will disassemble the current instruction. 
 +
{{nowrap|'u /count'}} disassembles ''count'' instructions.
  
'set reg = expr' will set the register reg to the value of the expression expr (as of 2010-08-01, the manual states it only works on general purpose integer registers but it does also work on the segment registers).
+
'u start' will disassemble the instruction at the location ''start''. 
 +
{{nowrap|'u start end'}} will disassemble instructions
 +
from location ''start'' inclusive to ''end'' exclusive.
  
=== Memory ===
+
==== Registers ====
  
'xp /nuf addr' is a way to examine the contents of memory.  'xp /4wx 0x7c00' will dump 4 "words" (32b) in heXidecimal starting at 0x7c00.
+
'r' will dump the state of all of the "standard" registers,
 +
eax, ecx, edx, ebx, esp, ebp, esi, edi, eip, eflags.
  
= Syslinux Dynamic Debugger =
+
'sreg' will dump the segment registers
 +
es, cs, ss, ds, fs, gs (and information about those segments).
  
From Syslinux-5.11-pre8 and Syslinux-6.02-pre1, all prereleases contain a debugging utility in the form of a COM32 file - debug.c32. This utility can be used to enable and disable debug code at runtime and is especially useful for debugging an existing installation when it isn't possible to build Syslinux from source.
+
{{nowrap|1='set reg = expr'}} will set the register ''reg''
 +
to the value of the expression ''expr''.  
 +
As of {{nowrap|2010-08-01}},  
 +
bochs' manual states it only works on general purpose integer registers,
 +
but it does also work on the segment registers.
  
== Arguments ==
+
==== Memory ====
The arguments to debug.c32 look like,
+
  
  debug.c32 [-e|-d] func1[,func2,func3,...]
+
{{nowrap|'xp /nuf addr'}} is a way to examine the contents of memory.
 +
{{nowrap|'xp /4wx 0x7c00'}}
 +
will dump ''4'' "''W''ords" (32b) in he''X''adecimal starting at ''0x7c00''.
  
-e and -d are used to (e)nable and (d)isable debug code, respectively. "func1" is the name of a function inside which you want to configure debug code. For example, to enable the dprintf() statements inside open_file(),
+
<br/>
  
  debug.c32 -e open_file
+
----
  
== How to invoke ==
+
== Dynamic Debug ==
 +
<span id="Syslinux_Dynamic_Debugger"></span>
 +
From Syslinux-5.11-pre8 and Syslinux-6.02-pre1,
 +
all (pre)releases contain a debugging utility in the form of a COM32 file - debug.c32.
 +
This utility can be used to enable and disable debug code at runtime
 +
and is especially useful for debugging an existing installation
 +
when it isn't possible to build Syslinux from source.
  
debug.c32 can be invoked either from the boot: prompt or from within a configuration file,
+
=== Arguments ===
 +
The arguments to debug.c32 look like:
  
  DEFAULT dbg
+
debug.c32 [-e|-d] func1[,func2,func3,...]
  LABEL dbg
+
    COM32 debug.c32
+
    APPEND -e <func>
+
  
If using a config file to enable debug, it would be recommended to make the above 'dbg' label the DEFAULT.
+
<tt>-e</tt> and <tt>-d</tt> are used to (e)nable and (d)isable debug code, respectively.
 +
"''func1''" is the name of a function inside which you want to configure debug code.  
 +
For example, to enable the dprintf() statements inside open_file():
  
== Useful functions ==
+
debug.c32 -e open_file
  
If you suspect a bug in Syslinux some useful functions to debug-enable are,
+
=== Invoke ===
  
=== PXELINUX ===
+
debug.c32 can be invoked either from the "boot:" prompt or from within a configuration file,
  
  o pxe_call
+
DEFAULT dbg
    
+
LABEL dbg
=== Loading kernels ===
+
   COM32 debug.c32
 +
  APPEND -e <func>
  
  o new_linux_kernel
+
If using a config file to enable debug,
  o syslinux_boot_linux (or bios_boot_linux/efi_boot_linux in 6.0x)
+
it would be recommended to make the above ''dbg'' label the DEFAULT.
  
=== Memory corruption ===
+
=== Useful functions ===
  
  o malloc
+
If you suspect a bug in Syslinux, some useful functions to enable for debug are:
  o free
+
  
= References =
+
* PXELINUX
 +
** <tt>pxe_call</tt>
 +
* Loading kernels
 +
** <tt>new_linux_kernel</tt>
 +
** <tt>syslinux_boot_linux</tt>
 +
** <tt>bios_boot_linux</tt>
 +
** <tt>efi_boot_linux</tt>
 +
* Memory corruption
 +
** <tt>malloc</tt>
 +
** <tt>free</tt>

Latest revision as of 06:31, 25 May 2019

Please note, this page may be incomplete or outdated or possibly use incorrect terminology.


When testing, a "bug", or behavior contrary to design or expectation, may be found. Debugging is the process of finding the source of the bug in order to remove it.

As always, there are multiple means by which to debug a program, varying, among other things, in their level of complexity and detail by which information may be examined.

In Source

Inserting statements like printf() and puts() to watch the progress and/or data of the program is the least technical method.

Debugger 32-bit

Both qemu and bochs have the capability of a gdbstub, allowing you to connect the GNU Debugger (gdb) to the qemu/bochs process and examine what the VM sees.

Debugger 16-bit Segmented

(Or the real reason I built this page. --Gene)


16-bit segmented mode, also known as Real Mode, is recognized as addressing with 2 registers, a segment and an offset, each 16 bits long, and staggered to form a 20 bit address (segment * 10h + offset = address). This is the operating mode of the boot sector, the secondary loader (for disk-based variants in Syslinux-4.00 as of 2010-06-21), most (but I believe all) of the Syslinux core assembly code and COMBOOT modules.

Background and Caveats

Unfortunately, gdb is not effective at debugging 16-bit segmented code. Attempting to utilize qemu or bochs with gdb will only lead to frustration.

However, bochs has an internal debugger available. Unfortunately, it's mutually exclusive of the gdbstub at compile time and most distributions compile in the gdbstub instead of the internal debugger (which is probably a good choice _most_ of the time).

Use the source

Quite literally. Grab the source for bochs (on 2010-06-21, 2.4.5 is the current stable), the needed development libraries (the configure script will warn you nicely; if it says libraries are missing, it means development libraries of course). You'll want to configure using './configure --enable-debugger --enable-disasm' to enable the debugger and disassembler. '--enable-readline' is helpful in the debugger for editing the command line and history. You can also add '--enable-ne2000' and '--enable-pnic' if you're interested in PXELINUX. Next, compile it ('make all'). See also Setting Up Bochs.

I've tried to build bfe (bochs debugger front end) but at this time have not figured out what I'm missing.

Configuration

Build a configuration file (aka bochsrc) as needed. You'll of course need a boot device (floppy, cdrom, hard disk, PXE, etc). See also Testing and Setting Up Bochs.

Usage hints

Start

After launching, it will come up to the "start menu" (unless -q is specified). If it's fully configured, "Begin Simulation". At this point, it will dump you to the debugger prompt. Your first friend here is 'help' (also as 'h') to list the possible commands. 'h b' will list help information for 'b' (breakpoint).

See also the official manual here (although as of 2010-08-01, it appears to be out of date and the internal help is current).

Breaking

Breakpoints are a way to stop the debugger at an exact code point. The first one to be aware of is 0x7c00 ('b 0x7c00'). This is the code entry point for all variants. If you're debugging a boot sector (for a disk-based variant or for ISOLINUX), this is a great starting breakpoint. This makes it execute through all of the BIOS related initialization code without stopping.

If you don't want to look at the code in an interrupt, try setting a breakpoint at the return point.

As of 2010-06-21, Syslinux 4.00-pre55 disk-based variants used a boot loader to a secondary loader (starting at address 0x8000).

For additional addresses within the Syslinux core, look at the .lst file for the variant you are examining as it has the correct addresses. Please note this requires currently that you compile Syslinux yourself at this time.

For the loading and entry into a COM32 module, search for call com32_entry in the .lst file of the variant you are using.

Continuing

'c' will tell it to continue on if it's been interrupted (including the initial prompt).

Stepping

's' or 's #' will step forward a certain number of instructions (default 1). This will include the code you're examining and any interrupt calls.

Disassembly

'u' or 'disasm' will disassemble the current instruction. 'u /count' disassembles count instructions.

'u start' will disassemble the instruction at the location start. 'u start end' will disassemble instructions from location start inclusive to end exclusive.

Registers

'r' will dump the state of all of the "standard" registers, eax, ecx, edx, ebx, esp, ebp, esi, edi, eip, eflags.

'sreg' will dump the segment registers es, cs, ss, ds, fs, gs (and information about those segments).

'set reg = expr' will set the register reg to the value of the expression expr. As of 2010-08-01, bochs' manual states it only works on general purpose integer registers, but it does also work on the segment registers.

Memory

'xp /nuf addr' is a way to examine the contents of memory. 'xp /4wx 0x7c00' will dump 4 "Words" (32b) in heXadecimal starting at 0x7c00.



Dynamic Debug

From Syslinux-5.11-pre8 and Syslinux-6.02-pre1, all (pre)releases contain a debugging utility in the form of a COM32 file - debug.c32. This utility can be used to enable and disable debug code at runtime and is especially useful for debugging an existing installation when it isn't possible to build Syslinux from source.

Arguments

The arguments to debug.c32 look like:

debug.c32 [-e|-d] func1[,func2,func3,...]

-e and -d are used to (e)nable and (d)isable debug code, respectively. "func1" is the name of a function inside which you want to configure debug code. For example, to enable the dprintf() statements inside open_file():

debug.c32 -e open_file

Invoke

debug.c32 can be invoked either from the "boot:" prompt or from within a configuration file,

DEFAULT dbg
LABEL dbg
 COM32 debug.c32
 APPEND -e <func>

If using a config file to enable debug, it would be recommended to make the above dbg label the DEFAULT.

Useful functions

If you suspect a bug in Syslinux, some useful functions to enable for debug are:

  • PXELINUX
    • pxe_call
  • Loading kernels
    • new_linux_kernel
    • syslinux_boot_linux
    • bios_boot_linux
    • efi_boot_linux
  • Memory corruption
    • malloc
    • free