Posts tagged ‘debug’

How to debug a portion of FreeBSD code using gdb from a shell? (Using Sysinstall code as an example)

Well, in my last FreeBSD Friday post, I talked about How to compile a portion of FreeBSD code with debugging? (Sysinstall for this example). The next step is to learn to step through the code. There is a debugging tool included with FreeBSD called gdb.

A good start for gdb is to read this document from the FreeBSD Developers’ Handbook.
http://www.freebsd.org/doc/en/books/developers-handbook/debugging.html

To really get good at gdb though, you should read the gdb documenation here:
http://sourceware.org/gdb/current/onlinedocs/gdb/

Well, lets get started.

Step 1 – Compile a portion of FreeBSD code with debugging enabled
How to compile a portion of FreeBSD code with debugging? (Sysinstall for this example)

Step 2 – Start gdb
As a user (not root) launch gdb with the name of the executable as the only parameter.

$ gdb sysinstall
GNU gdb 6.1.1 [FreeBSD]
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type “show copying” to see the conditions.
There is absolutely no warranty for GDB. Type “show warranty” for details.
This GDB was configured as “amd64-marcel-freebsd”…
(gdb)

Step 3 – Set a break point
At the gdb prompt, type break main.

(gdb) break main
Breakpoint 1 at 0x416b00: file main.c, line 55.
(gdb)

Step 4 – Start the program
To start the program type run and hit enter.

(gdb) run
Starting program: /usr/home/jared/Devel/FreeBSD/head/usr.sbin/sysinstall/sysinstall

Breakpoint 1, main (argc=1, argv=0x7fffffffe998) at main.c:55
55 {
(gdb)

Step 5 – Step through the code
Ok, to step through the code you simply type ‘s’.

(gdb) s
Breakpoint 1 at 0x416b00: file main.c, line 55.
(gdb)

Once you have typed ‘s’ once, you can just hit enter and it will keep stepping through. You could keep typing ‘s’ but you don’t need to.

Step through the code until it terminates because you are not root.

Here is the entire run through in one screen.

$ gdb sysinstall
GNU gdb 6.1.1 [FreeBSD]
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type “show copying” to see the conditions.
There is absolutely no warranty for GDB. Type “show warranty” for details.
This GDB was configured as “amd64-marcel-freebsd”…
(gdb) break main
Breakpoint 1 at 0x416b00: file main.c, line 55.
(gdb) run
Starting program: /usr/home/jared/Devel/FreeBSD/head/usr.sbin/sysinstall/sysinstall

Breakpoint 1, main (argc=1, argv=0x7fffffffe998) at main.c:55
55 {
(gdb) s
61 StartName = argv[0];
(gdb)
64 if (getpid() == 1) {
(gdb)
68 signal(SIGPIPE, SIG_IGN);
(gdb)
71 if (geteuid() != 0) {
(gdb)
72 fprintf(stderr, “Error: This utility should only be run as root.\n”);
(gdb)
Error: This utility should only be run as root.
204 }
(gdb)
0x0000000000404d9e in _start ()
(gdb)
Single stepping until exit from function _start,
which has no line number information.

Program exited with code 01.
(gdb)

Ok, you now have done some basic debugging with gdb and you have learned that you cannot run sysinstall as root.

Step 6 – Debug as root
Ok, this shouldn’t be hard for you by now. Sudo to root and repeat the above steps only this time the program will continue past the check for whether it is running as root because it will be. Stop just after you pass the line that checks if you are root.

One you get so far, you will actually get to the sysinstall gui and you can choose to exit.

Step 7 – Set a break point based on line number
Type the following to set a break point based on line number.

(gdb) break main.c:103
Breakpoint 2 at 0x416bd6: file main.c, line 103.
(gdb)

Step 8 – Continuing to the next break point
So now instead of stepping to line 110, we will just continue the program with the command “continue”. By the way, the following three commands will continue and all are really the exact same command. You might ask, “Why are there three ways to do the same thing?” I have to answer, “I don’t know, I didn’t write gdb.” But hey, I am not complaining.

  • continue
  • c
  • fg

So yes to continue you can type any of the three commands at the gdb prompt and your program will continue until the next break point or until the program terminates.

(gdb) c
Continuing.

Breakpoint 2, main (argc=1, argv=0x7fffffffe8c8) at main.c:103
103 systemInitialize(argc, argv);
(gdb)

Note on finding development code or development features
Often while developing, a developer adds code to help them develop. This is development code, development features, debug code, or whatever you want to call it. This code is not really meant to be used in production, but it sure helps the developer write and test and debug the production code. Most large applications have such hidden development features. When stepping through code, you should look for these.

As I was looking through the sysinstall code, I noticed a section of code starting at line 110 (obviously this is subject to change but you should be able to find the line number in the same area) that checks for a parameter called -fake.

    if (argc > 1 && !strcmp(argv[1], "-fake")) {
        variable_set2(VAR_DEBUG, "YES", 0);
        Fake = TRUE;
        msgConfirm("I'll be just faking it from here on out, OK?");
    }

This hidden switch is never mentioned in the man page. It appears to be one of those development only features that we can take advantage of to help us code Sysinstall. It also suggests that you can step through Sysinstall without having anything actually happen, which might be useful in debugging.

Making our first code change
Ok, so if I am going to use the -fake switch, I would assume that I could do so without running as root. Since we are “faking it” anyway, we might as well not be running as root at all.

So here is a code change I have made that will allow me to run as a normal user if I pass the -fake parameter. I am going to change line 73 (again this may not be the exact line for you as this is subject to change) where sysinstall checks if it is running as root and add an additional check to see if a parameter was passed and if so see if the parameter was -fake and if so, continue even though it is not root.

Here is what the code was originally.

    if (geteuid() != 0) {
        fprintf(stderr, "Error: This utility should only be run as root.\n");
        return 1;
    }

Here is what I changed the code to. Notice that I didn’t delete or add to the existing line just yet. Instead, I commented it out and added a new line because that makes it easier to switch back and forth when testing this new code out.

    //if (geteuid() != 0) {
    if (geteuid() != 0 && (argc < 2 || strcmp(argv[1], "-fake"))) {
        fprintf(stderr, "Error: This utility should only be run as root.\n");
        return 1;
    }

Ok, so save and exit. No go ahead and exit your root shell so you are just logged in as your user again.

Recompile to apply your changes. In case you forgot, you recompile with this command:

$ make DEBUG_FLAGS=-g

Go ahead and debug again. Repeat the steps above again, however, this time, in the gdb prompt, before you execute the command “run”, go ahead and set the arguments to pass to your application so that the -fake argument is passed.

(gdb) set args -fake
(gdb)

Just to make sure, lets show the arguments to make sure that we properly set them.

(gdb) show args
Argument list to give program being debugged when it is started is “-fake”.
(gdb)

Now you can run your program in gdb and continue debugging sysinstall as a regular user. I think I am going to send this change in because maybe it should be a permanent change. What do you think?


Copyright ® Rhyous.com – Linking to this article is allowed without permission and as many as ten lines of this article can be used along with this link. Any other use of this article is allowed only by permission of Rhyous.com.

How to compile a portion of FreeBSD code with debugging? (Sysinstall for this example)

Ok, so maybe you want to work on fixing something in a portion of FreeBSD code, but you lack the knowledge to get started. That is what this document is for, to get you started.

For this example, I am going to use Sysinstall, which is a pretty old installer but still in use and functional. Let’s be honest, when the developers write in the code that Sysinstall needs to be completely rewritten and those notes are almost a decade old, you can guess that the installer is living far past its days. However, I don’t mind Sysinstall and many others don’t mind it either, which is probably why it is not updated yet. So lets at least see if we can inspire some contributors to start working on it. Sysinstall is actually on the Project Ideas page for a couple reasons, though I am surprised that “complete rewrite” is not one of them.

So lets get started.

Step 1 – Install FreeBSD
You need a FreeBSD Environment, so install one. Following one of these documents:
How do I install FreeBSD?
or if you want a FreeBSD install with a desktop as well:
How to install and configure a FreeBSD 8 Desktop with Xorg and KDE?

Step 2 – Download the FreeBSD Source
Follow this guide to make sure you have the source you need.
How to download FreeBSD-Current or FreeBSD-Stable using svn?

Now that you have read that post and have the source, you should understand what I mean when I say for this example I checked out head.

Step 3 – Find the location of the portion of source you wish to compile (Sysinstall in this example)

  1. Change to the directory where your source is stored.
    $ cd /usr/home/jared/Devel/FreeBSD/head
  2. It is probably a good idea to browse the folders and get an understanding of what code is where. But this is a task you should perform over time. For now, lets search for exactly what we want: sysinstall.
    $ find ./ -name sysinstall

    You will see that sysinstall is here: ./usr.sbin/sysinstall

  3. Change to that directory.
    $ cd usr.sbin/sysinstall

Step 4 – Compile with debugging.
FreeBSD uses make to manage the compiling of the code, so it is really easy to compile it all.

  1. Run this command to compile Syinstall with debugging.
    $ make DEBUG_FLAGS=-g

You should now see all the .o libraries and the sysinstall libraries. You have just compiled a portion of FreeBSD.


Copyright ® Rhyous.com – Linking to this article is allowed without permission and as many as ten lines of this article can be used along with this link. Any other use of this article is allowed only by permission of Rhyous.com.