uCdot
search uCdot:
 
Embedded Linux and uClinux Developer Forum
 
uCdot
- FAQ
- Dev Boards
- Submit Story
- Submit FAQ
- Submit Dev Board
- Topics
- Authors
- About

- Preferences
- Older Stuff
- Past Polls
- Discussions
- Journals
- Messages

Embedded Linux
Mailing Lists
uClinux-dev (search)
Coldfire (search)
MTD
Microblaze (search)
ELUG
BDM-devel
Blackfin

Embedded Linux
Sites
uClinux.org
uClinux-Dist
uClibc
uClinux Directory
LinuxDevices
ARMulator
uClinux-elf-tools
Colilo
Kernel Archives
H8-uClinux
TLDP
Microblaze uClinux
BDM Tools
SkyEye (emulator)
LOM
SETR live CD
Blackfin uClinux

Embedded Linux
Companies
SecureComputing
SDCS
CodePoet
Arcturus
Cadenux
ARMtwister
uClinux.net
Xiptech
senTec
embedded^cl
Cwlinux
emlix
TimeSys
eSpark Infotech
SSV Embedded Systems
Embedded Minds
PeerSec Networks
Vortech Consulting
swissEmbedded
Synertronixx
Mbedthis Software
.vantronix
Aday
GraceLabs
Pengutronix
metux ITS
Codito Technologies
Firmix Software
PetaLogix
NuDesign
Merritt Technologies
WindRiver
OpenGear
Rubico
Analog Devices
Artila Electronics
Vyatta
Embest Info&Tech
Katalix Systems
WorkWare Systems
Kdev
Intellimetrix
Virtual Cogs
SYSGO
coresystems
ExactCODE
KOAN
EzHomeTech
Linux4biz
Linkodas
Trego
EMBEST
Boardcon
HITEG
FemtoLinux
Prosoft World
Witech

 
Using m68k-bdm-elf-gdb with uClinux/Coldfire
FAQ This is a quick HOW-TO guide to using m68k-bdm-elf-gdb with uClinux/Coldfire platforms. It covers the basics of Kernel and Application debugging using the excellent BDM interface on the coldfire. It is not mean't to be a GDB tutorial.

Using m68k-bdm-elf-gdb with uClinux/Coldfire

By David McCullough
davidm@snapgear.com

Contents

  1. Compiling the tree
  2. Debugging the Kernel
  3. Debugging an Application
  4. Debugging Kernel and Applications together
  5. Cool GDB commands to remember
  6. Notes

1. Compiling the tree

The first thing to do if you want to get serious about debugging with GDB is to turn on the kernel/user options for symbolic debug. Just run:

  • make config, or make xconfig
  • be sure to enable "Customize kernel Settings"
  • be sure to enable "Customize Vendor/User Settings"
  • In the kernel settings, turn on "Full Symbolic/Source debugging support" under "Kernel hacking".
  • In the Vendor/User settings, turn on "build debugable libraries" and "build debugable applications" under the "Debug Builds" menu.
  • make clean; make dep; make

This builds all the source in the tree with full symbolic debug support and stack frames. You need the stack frames so that local variables and stack backtraces work.


2. Debugging the Kernel

To debug the kernel with gdb you will need a BDM cable, and a unix machine with the BDM driver installed. Once you have these you are ready to run gdb.

Firstly you need to boot the kernel you are going to debug. This may mean updating the flash before doing the following.

    cd linux-2.0.x or linux-2.4.x
    m68k-bdm-elf-gdb ./linux
    gdb> target bdm /dev/bdmcf0
    gdb> cont

If you are using a dev board just follow the steps your would normally use to get the kernel running on the board. If you are running from flash then the kernel will have started.

At this point you have kicked the kernel into life and it will boot. This is all fine and good if you can boot the kernel, you can now break into the debugger and add some break points to debug your code. If, however, you are crashing early in the boot, you will need to do some extra things before you can debug. The reason for this is that you cannot set break points until the kernel has been loaded into RAM.

The best way to break into the debugger early, before any runs, but after the code is loaded into ram is to put a "halt" instruction into the code at the appropriate point. A good spot for this is is just before we start the kernel. For example in the file:

    linux-2.X.Y/arch/m68knommu/platform/5307/NETtel/crt0_ram.S
Add the line marked with '***' to stop the CPU and drop into the debugger just before the 'C' code starts up.
        /*
         *  Assember start up done, start code proper.
         */
***     halt
        jsr start_kernel        /* Start Linux kernel */

    _exit:
        jmp _exit               /* Should never get here */

When the code hits this point, gdb will drop back to the prompt and you can set breakpoints or continue with whatever debugging you need. Once finished type "cont" to continue running and hit your breakpoints. NOTE once you put the "halt" in you will have to use the debugger to start the image, otherwise it will just halt and do nothing :-)


3. Debugging an Application

Debugging applications is fairly simple, you will need "gdbserver" in the romfs (or accessible via NFS) and a network.

To network debug an application you just need to start the application using gdbserver, instead of running it as you usually would. For example, on your uClinux target system run:

    /> gdbserver :3000 /bin/stty

This will load the application and stop it at the first instruction. You can then connect to it from your host system by running:

    m68k-bdm-elf-gdb user/stty/stty.gdb
    gdb> target remote 10.0.0.182:3000

Notice that on the host side you use the stty.gdb file. This file has the correct format for gdb to relocate it to match the binary that is already started in the target system. I usually set a break point on main and continue to there to get some 'C' code to look at.

    gdb> b main
    Breakpoint 1 main .....
    gdb> cont
    Hit breakpoint 1 ...
    gdb>

To debug an application using the BDM debugger is a little special. Check the Debugging Kernel and Applications together and Notes sections for more information on what can/can't be done.


4. Debugging Kernel and Applications together

If your system is crashing, and you are not sure if it is kernel or application, then you can setup to debug both at the same time. First recompile the whole tree with the symbolic debugging turned on as described above, then follow these steps.

  • Start the debugger as given above in Debugging the Kernel.

  • Let the kernel run (cont), then reproduce the crash/hang.

  • If the target system crashes it usually hangs. Go to your debugger and break into it with ^C (or your interrupt key). This will get you a debugger prompt.

  • Run "bt" to get a backtrace of where the code was when it died. If this gives you a list of function names then there is a good chance that you crashed in the kernel. Use this backtrace to begin finding the problem.

  • If the backtrace only contains numbers, then you probably died in an application. First lets find out which process is running. Do this by printing the name of the current process with:

    Kernel Version Command
    2.0.x
    p current_set[0]->comm
    2.4.x
    p _current_task->comm

    Lets say that this returned "sh". Then we know that process that crashed was the "sash" shell (if that is the shell you are using ;-).

  • The next step is to load the symbols for that process so we can find out where it died. For "sh" we would use:
        add-symbol-file user/sash/sh.gdb current_set[0]->mm->start_code
    
    If the above command asks you if you want to load the symbols at .text-addrs = 0, answer no. You will have to find out the start address and type it in manually -
        (gdb) p _current_task->mm->start_code
        1234566
        (gdb) add-symbol-file ../user/sash/sh.gdb 1234566
        
    This will automatically load the applications symbols at the correct location.

  • Re-run "bt" to get a new backtrace with symbols. Make sure it looks ok. If you have loaded the symbols for the wrong application is will look fairly obvious. You should now have a good idea what the app was doing when it died and can start tracking it from there.

There is all kinds of good information in the current_set structure to find out things about the current process. Try some of these to learn more:

Kernel Version Command
2.0.x
p *current_set[0]
p *current_set[0]->mm
2.4.x
p *_current_task
p *_current_task->mm


5. Cool GDB commands to remember

p or print
Print the value of something (or some expression). This is about the most used command. You can print any 'C' expression and it formats the output to suit that types of the fields. Some examples:
    gdb> p 1 << 10
    1024
    gdb> p /x 1 << 10
    0x400
    gdb> p my_array[0].name
    my_array[0].name = 0xNNNNNNNNN "my name is fred"
    gdb> p *my_name[0].name
    *my_array[0].name = 0xNNNNNNNNN 'm'

So you can see that the print command can tell you just about anything about anything. You can even cast values to help save time finding the offsets of fields.

    gdb> p * (struct stat *) 0x10000000
    ....

Remember you can change the format it prints with the '/' options, for example 'p /x' prints the values all in hex.

x
This is similar to 'hexdump' and is good for general memory dumping.

bt
Display a back trace (each function call gives you a frame number)

frame N
This allows you to select a frame from the back trace. You may then look at the local variables for that frame to see their values or set breakpoints in that function.

list [line number | function name]
list some source code. Good for looking at the source around the current line (ie list), checking other functions (ie., list main) or listing source from a line number in the current file (ie., list 20).

b (function name | line number)
set a break point on a function or a line number

step [count] or s
step one line of 'C' code, will step into function calls.

next [count] or n
step one line of 'C' code, do not step into functions.

stepi [count]
step one assembler instruction (best used with "display /i $pc").

display
Just like the "print" command, it allows you to have the value of an expression displayed every time you do something. As above, "display /i $pc" display the current assembler instruction, every time you stepi, the next instruction will be displayed.

delete [number]
Delete all breakpoints (or breakpoint number)

disable [number]
Disable all (or numbered) breakpoints.

enable [number]
Enable all (or numbered) breakpoints.

info breakpoints
List all your breakpoints and their status.

info reg
print the HW registers and their values. If this fails with a no-frame error then try running "frame 0" first, then doing it again.

sym filename
If you have loaded a new program or kernel then get the new symbols by running this command.
NOTE: make sure you remove or disable all break points before running this command or your system will crash.

set
Set allows you to change the value of variables or memory. For example, to set the program counter to address 0x400:
    set $pc = 0x400
To set the variable "i" to some new value (it can be quite complex):
    set i = 10 * 1024 + j * 2


help
I learn't everything I know about GDB through this command, you can use it too :-)
Don't forget the man page and the info pages as well.


6. Notes

The latest m68k-bdm-elf-gdb versions have hardware watchpoints. This is invaluable as you can break on a value being changed without affecting the speed of execution. If you know that a single 32 bit value is changed by someone at address 0x123456, but do not know who, try the following:

    (gdb) watch * (int *) 0x123456
    (gdb) cont

Once the debugger breaks, use the Debugging Kernel and Applications together method for finding out who it was, and better still, exactly which line it happened on ;-).

The only catch with HW watch points is that you only have one. After that you get SW watch points which are impossibly slow (step one instruction, check value, repeat).

You cannot set breakpoints in user programs from the BDM debugger. This is because it inserts "halt" instructions and these can only be executed by kernel code. You can set HW breakpoints in user code though using "hb". You can also "stepi" in user code. Both "step" and "next" should be avoided when running in user mode. It is possible to modify the BDM driver to allow the debugging of user applications via the BDM interface. You can see the original email on it here. Here is what you need to do:

  • This will only work if your app runs in RAM vs read only memory (ROM/Flash).
  • You need to rebuild the bdm driver for linux after modifying the bdm.c file that comes with Cybertec's latest linux BDM source archive, gdb-bdm-20020210.tar.gz (NOTE: this is very out of date and you may have to look around for ways to do all this).

    You can download it from here.

  • Before following the excellent instructions provided in the archive you need to mod the drivers/bdm.c file as follows (NOTE this information is quite out of date and the source has changed a lot). These mods were based on an old post by Mark Abbate:
    In cf_pe_read_sysreg:
          //self->cf_csr = ioc->value = (self->cf_csr & 0x0f000000) | ioc->value;
          self->cf_csr = ioc->value = (self->cf_csr & 0x0f000400) | ioc->value;
    
    In cf_pe_run_chip:
     //  csr_ioc.value   = 0x00000000;
      csr_ioc.value   = 0x00000400;
    
    In cf_pe_step_chip:
      //  csr_ioc.value   = 0x00000030;
      csr_ioc.value   = 0x00000430;
    
    and
    
      //  self->cf_csr     = 0x01000000;
      self->cf_csr     = 0x01000400;
    

Sometimes when your system locks up and you break into the debugger with ^C the "bt" command may give complete garbage. I have found that a "stepi" may pull you back to reality. It's worth a try at least ;-)

Is the Samsung 4510 Eval board for real? | uClinux port to the Apple iPod  >

 

 
uCdot Login
Nickname:

Password:

[ Create a new account ]

Related Links
  • Linux
  • SnapGear
  • Coldfire
  • uClinux
  • davidm@snapgear.com
  • Compiling the tree
  • Debugging the Kernel
  • Debugging an Application
  • Debugging Kernel and Applications together
  • Cool GDB commands to remember
  • Notes
  • Compiling the tree
  • Debugging the Kernel
  • Debugging an Application
  • Debugging Kernel and Applications together
  • Debugging Kernel and Applications together
  • Cool GDB commands to remember
  • Notes
  • here
  • here
  • More on FAQ
  • Also by davidm
  • This discussion has been archived. No new comments can be posted.
    Using m68k-bdm-elf-gdb with uClinux/Coldfire | Login/Create an Account | Top | Search Discussion
    Threshold:
    The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.

    The Embedded Linux and uClinux Developer Forum is hosted by: SnapGear A celebrity is a person who is known for his well-knownness.

    [ home | contribute story | older articles | past polls | faq | authors | preferences ]