Gentoo Bug Reporting Guide Chris White This document shows the proper method of reporting bugs using Bugzilla. 1.0 2005-06-25 Introduction
Preface

Often one of the delaying factor in a bug being fixed is how it is reported. By creating this guide, I hope it will help improve the communication between developers and users in bug resolution. Getting bugs fixed is an important, if not crucial part of the quality assurance of any project. I hope this will help to make that a success.

Initial Finding

You're emerge-ing a package or working with a program, then suddenly the worst happens: you find a bug. Bugs come in many forms, whether it be emerge failures or segmentation faults. Whatever the cause, the fact still remains that such a bug must be fixed. Here's a few examples of bugs:

chris@localhost ~ $ ./bad_code `perl -e 'print Ax100'`
Segmentation fault
/usr/lib/gcc-lib/i686-pc-linux-gnu/3.3.2/include/g++-v3/backward/backward_warning.h:32:2:
warning: #warning This file includes at least one deprecated or antiquated
header. Please consider using one of the 32 headers found in section 17.4.1.2 of
the C++ standard. Examples include substituting the <X> header for the <X.h>
header for C++ includes, or <sstream> instead of the deprecated header
<strstream.h>. To disable this warning use -Wno-deprecated.
In file included from main.cc:40:
menudef.h:55: error: brace-enclosed initializer used to initialize `
OXPopupMenu*'
menudef.h:62: error: brace-enclosed initializer used to initialize `
OXPopupMenu*'
menudef.h:70: error: brace-enclosed initializer used to initialize `
OXPopupMenu*'
menudef.h:78: error: brace-enclosed initializer used to initialize `
OXPopupMenu*'
main.cc: In member function `void OXMain::DoOpen()':
main.cc:323: warning: unused variable `FILE*fp'
main.cc: In member function `void OXMain::DoSave(char*)':
main.cc:337: warning: unused variable `FILE*fp'
make[1]: *** [main.o] Error 1
make[1]: Leaving directory
`/var/tmp/portage/xclass-0.7.4/work/xclass-0.7.4/example-app'
make: *** [shared] Error 2

!!! ERROR: x11-libs/xclass-0.7.4 failed.
!!! Function src_compile, Line 29, Exitcode 2
!!! 'emake shared' failed

Collecting information on emerge errors will be described later on in the posting process. Right now, we'll look at runtime errors. In finding bugs, two tools are frequently utilized: gdb and strace.

Debugging Using gdb
Introduction

First off, let's take a look at what debugging entails. One of the main things you must do in order to debug a program is to emerge the program with FEATURES="nostrip". This prevents debug symbol stripping from occuring. Why are programs stripped by default? This is the same reason that manpages are gzipped, in order to save space. Here's an idea of a program with, and without debug symbol stripping:

-rwxr-xr-x  1 chris users 3140  6/28 13:11 bad_code
-rwxr-xr-x  1 chris users 6374  6/28 13:10 bad_code

Just for reference, bad_code is the program we'll be debugging with gdb later on. As you can see, the program without debugging symbols is 3140 bytes, while the program with them is 6374 bytes. That's close to double the size! Two more things can be done for debugging. The first is adding -g to your CFLAGS. This flag adds more debugging information than is generally included. We'll see what that means later on. Lastly, you can also add debug to the package's USE flags. This can be done with the package.use file:

echo "category/package debug" >> /etc/portage/package.use

If the package already has USE flags set in package.use, you will need to manually modify them in your favorite editor. Now that that's done, you will need to re-emerge your package to set the new debug settings into place. This can be done as follows:

FEATURES="nostrip" emerge package

Now that debug symbols are setup, we can continue with debugging the program.

Running The Program With GDB

GDB, or the (G)NU (D)e(B)ugger, is a program used to find runtime errors that normally involve memory corruption. Let's say we have a program here called "bad_code" (I know, it's sort of cheesy but..). Some person claims he can break the code and provides an example. You go ahead and test it out:

chris@localhost ~ $ ./bad_code `perl -e 'print Ax100'`
Segmentation fault

It seems this person was right. Since the program is obviously broken, we have a bug at hand. Now, it's time to use gdb to help solve this matter. First we run gdb with --args, then give it the full program with arguments like so:

chris@localhost ~ $ gdb --args ./bad_code `perl -e 'print Ax100'`
GNU gdb 6.3
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 "i686-pc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".

You should see a small terminal like setup after that which says "(gdb)" and waits for input. First, we have to run the program. We type in "run" at the command and recieve a notice like so:

(gdb) run
Starting program: /home/chris/bad_code

Program received signal SIGSEGV, Segmentation fault.
0xb7ec6dc0 in strcpy () from /lib/libc.so.6

Here we see the program starting, as well as a notification of SIGSEGV, or Segmantation Fault. This is GDB telling us that our program has crashed. It also gives the last run function it could trace when the program crashes. However, this isn't too usefull, as there could be multiple strcpy's in the program, making it hard for developers to find which one is causing the issue. In order to help them out, we do what's called a backtrace. A backtrace runs backwards through all the functions that occured upon program execution, to the function at fault. To get a backtrace, at the prompt "(gdb)", type in "bt". You will get something like this:

(gdb) bt
#0  0xb7ec6dc0 in strcpy () from /lib/libc.so.6
#1  0x0804838c in run_it ()
#2  0x080483ba in main ()

So as we see here, first main() was run, then run_it(), and somewhere in run_it lies the strcpy() at fault. Things such as this help developers narrow things down. Now, there are a few execptions to the output. First off is forgetting to disable debug symbols with FEATURES="nostrip". With debug symbols stripped, output looks something like this:

(gdb) bt
#0  0xb7e2cdc0 in strcpy () from /lib/libc.so.6
#1  0x0804838c in ?? ()
#2  0xbfd19510 in ?? ()
#3  0x00000000 in ?? ()
#4  0x00000000 in ?? ()
#5  0xb7eef148 in libgcc_s_personality () from /lib/libc.so.6
#6  0x080482ed in ?? ()
#7  0x080495b0 in ?? ()
#8  0xbfd19528 in ?? ()
#9  0xb7dd73b8 in __guard_setup () from /lib/libc.so.6
#10 0xb7dd742d in __guard_setup () from /lib/libc.so.6
#11 0x00000006 in ?? ()
#12 0xbfd19548 in ?? ()
#13 0x080483ba in ?? ()
#14 0x00000000 in ?? ()
#15 0x00000000 in ?? ()
#16 0xb7deebcc in __new_exitfn () from /lib/libc.so.6
#17 0x00000000 in ?? ()
#18 0xbfd19560 in ?? ()
#19 0xb7ef017c in nullserv () from /lib/libc.so.6
#20 0xb7dd6f37 in __libc_start_main () from /lib/libc.so.6
#21 0x00000001 in ?? ()
#22 0xbfd195d4 in ?? ()
#23 0xbfd195dc in ?? ()
#24 0x08048201 in ?? ()

This backtrace contains a large number of ??'s. This is because without debug symbols, gdb doesn't know how the program was ran. This is very important to remember! Now remember awhile ago I told you about the -g flag. Let's see what output looks like with that:

(gdb) bt
#0  0xb7e4bdc0 in strcpy () from /lib/libc.so.6
#1  0x0804838c in run_it (input=0x0) at bad_code.c:7
#2  0x080483ba in main (argc=1, argv=0xbfd3a434) at bad_code.c:12

Here we see a lot more information being avaliable for developers. Not only is variable information displayed, but even the exact line numbers of the sources files. This method is the most prefered if you can spare the extra space. Here's an example of the filesize differences between debug, strip, and -g programs.

-rwxr-xr-x  1 chris users 3140  6/28 13:11 bad_code
-rwxr-xr-x  1 chris users 6374  6/28 13:10 bad_code
-rwxr-xr-x  1 chris users 7366  6/28 13:11 bad_code

As you can see, -g adds about 1000 more bytes to the filesize, increasing even more than with debugging symbols. However, as shown above, this increase in filesize can be worth it if presenting debug information to developers. Now that we have obtained the backtrace, we can save it to a file by copy and pasting from the terminal (if it's a non-x based terminal, you can use gpm. To keep this doc simple, I recommend you readup on the documentation for gpm to see how to copy and paste with it). Now that we're done with gdb, we can quit gdb:

(gdb) quit
The program is running.  Exit anyway? (y or n) y
chris@localhost ~ $

This ends the walkthrough of gdb. Using gdb, it is my hope that you will be able to use it to create better bug reports. However, there are other types of errors that can cause a program to fail during runtime. One of the other ways is through improper file access. We can find those using a nifty little tool called strace.

Finding File Access Errors With strace
Introduction

Programs often use files to get configuration information, access hardware, or write logs. Often a program attempts to access such files incorrectly. A program called strace was made to help deal with this. Strace traces system calls (hence the name) which mainly include accessing memory and files. For our example, we're going to take a program foobar2. This is an updated version of foobar. However, during the changeover to foobar2, you notice all your configurations are missing! In foobar version 1, you had it setup to say "foo", but now it's using the default "bar"!:

chris@localhost ~ $ ./foobar2
Configuration says: bar

Our previous configuration specifically had it set to foo! Let's use strace to find out what's going on.

Using strace To Find The Issue

Let's have strace log the results of the system calls. To do this, we run strace with the -o[file] arguments. Let's use it on foobar2 like so:

strace -ostrace.log ./foobar2

This creates a file called strace.log in the current directory. We check the file, and here are the relevant parts:

open(".foobar2/config", O_RDONLY)       = 3
read(3, "bar", 3)                       = 3

Aha! There's the problem! They moved the configuration directory to .foobar2 instead of .foobar. We also see the program reading in "bar" as it should. In this case, we can recommend the ebuild maintainer to put a warning about it. For now though, we can copy over the config file from .foobar and modify it to produce the correct results.

Conclusion

Now that we've gathered the information we need to get up and running, let's go ahead and begin the bug reporting process.

Reporting Bugs
Introduction

Bugzilla is the Gentoo bug reporting system. Bugzilla is accessable by both https and http. https is avaliable for those on unsecure networks. For the sake of consistancy, I will be using the https version in the examples to follow. Let's go ahead and point our browser over to bugzilla.

So now we have to report our bug. Go ahead and click on "Report a Bug - Using the Guided format.

As you can see High emphasis has been put on putting your bug in the right place. Gentoo Linux is where a large majority of bugs go. However, despite this, some people will put ebuild bugs in portage development (assumption that portage team handles the portage tree) or infra (assumption that infra has access to mirrors and rsync and can fix it directly). This is simply not how things work. A note on this: We would rather see a non-Gentoo Linux bug filed in Gentoo Linux than a Gentoo Linux bug filed in non-Gentoo Linux components!. While neither is prefered, the former is more acceptable and understandable (except website bugs.. we might have an issue with that...). Our bug goes in Gentoo Linux, as it's an ebuild bug. We head over there and are presented with the multi-step bug reporting process. Let's take a look at step one:

The first step here is really important (as the red text tells you). This is where you search to see that someone else hasn't hit your bug yet. If you do skip this step, and a bug like yours already exists, it will be marked as a duplicated, wasting a large ammount of QA effort. To give you an idea, the numbers that are striked out are duplicate bugs. Now comes step 2, where we give the information.

Giving The Bug Report

We arrive at step 2, so let's look at the first few instructions

First we have the product. This is Gentoo Linux, which we selected earlier. Component is where the problem occurs. We use this to help us sort out the severity of the issue (ie. baselayout and core systems will be more important than new ebuilds or application bugs). Here we select Application, as it is an application at fault. Hardware platform is what architecture you're running. If you were running sparc, you would set it to sparc. For this example, we know this error can occur on multiple architectures, so we'll select All. Operating System is what Operating System you're using. Because Gentoo is considered a "Meta-distribution", it can run on other os's besides Linux. Examples are Gentoo on MacOS, Gentoo on FreeBSD, etc. For this example, we'll state that linux is what's being used. Build Identifier is what is being used to report the bugs (for logging purposes). You can just leave this as is. Let's see what we have so far:

Looking good so far. Now we'll begin with the actual report. In this instance, we'll use the foobar2 bug as our example. URL is used to point to errors on a site someplace (pastebin, etc.). However, doing it inside the bug lets developers be able to reference to it at any time and is prefered. Now we have the summary. For the summary, you should put the package category, name, and number. Not including the category really isn't too bad, but it's recommeneded. If you don't include the package name, however, we won't know what you're filling a bug for, and will have to ask you about it later. The version number is important for people searching for bugs. If 20 people filed bugs and not one put a version number, how would people looking for similiar bugs be able to tell if one was there's? They'd have to look through every single bug, which isn't too hard, but if there's, say, 200 bugs.. it's not that easy. After all the package information, you'll want to include a small description of the incident. Here's an example:

Just by those simple rules it can make handling bugs a lot easier. Next is the details. Here we put in the information about the bug. We'll give an example here:

So now the developer knows why we're filing the bug. Now we this person know what we did to reproduce it. Reproducibility tells us how often we were able to reproduce the problem. In this example, we can reproduce it any time simply by running foobar2. Let's put that information in:

So now we have explained how we reached the bug. Next we want to explain what the results were and what we think they should be:

Next we put additional information. This can be things such as stack traces, sections of strace logs, but most importantly, your emerge --info output. Here's an example:

Lastly we select the severity of the bug. Please look this over carefully. In most cases it's ok to leave it as is and someone will raise/lower it for you. However, if you raise the severity of the bug, please make sure you read it over carefully and make sure you're not making a mistake. Here we will set it to the default of normal:

Now we can submit the bug report by clicking on the Submit Bug Report box. You will now see your new bug come up. See this link for what the result looks like. We've reported our bug! Now let's see how it's dealt with.

Working With Your Bug

So, looking at the bug, we see the basic information we did earlier:

And our details are there too:

Now as you can see, right now it's filed under bug-wranglers@gentoo.org. This is the default location for Application component bugs. However, bug-wranglers (usually) won't fix our bugs, so we to reassign it to someone that can (you can also let bug-wranglers re-assign it for you as well). For this.. we use the package's metadata.xml. You can normally find them in /usr/portage/category/package/metadata.xml. Here's one I've made up for foobar2:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
<pkgmetadata>
<herd>chriswhite</herd>
<maintainer>
<email>chriswhite@gentoo.org</email>
<name>Chris White</name>
</maintainer>
<longdescription lang="en">
Foobar2 is a package that uses a configuration file to display a word.
</longdescription>
</pkgmetadata>

Notice the maintainer section. This lists the maintainer of the package, which in this case is myself, Chris White. The email listed is chriswhite@gentoo.org. We will use this to re-assign the bug to the proper person. To do this, click the bubble next to Reassign bug to, then fill in the email like so:

Then press the Commit button for the changes to take place. Now it's been reassigned to me. Shortly afterwards, you notice (by email usually) that I've responded to your bug. I've stated that I'd like to see an strace log to figure out how the program is trying to access your configuration file. You follow the previous instructions on using strace and obtain an strace log. Now you need to attach it to the bug. In order to do this, click on "Create A New Attachment":

Now we have to attach the log. We click on the "Browse..." button under "File" and select the strace log. For Description, we'll put "strace log". Content-Type is what kind of file we're attaching. A common mistake is to set it to auto. However, in most cases it's best to manually set it. Our log file is a plain text file, so we select "plain text (text/plain)". Obsoletes are for when you are attaching a revision to a previously attached file. You can simply click a checkbox next to the old file and it will cross it out in the bug. Reassignment means you want to take the bug yourself. I rarely tend to use this.. and I don't think you will need to at some point (unless you create great patches and we don't care about you taking our bugs ;). Comments are for leaving comments about the file you're posting. We'll put "Here is the strace file you requested". Now we have something like this:

We Submit the patch and we'll now see it on the bug report.

Now, while we're waiting another person notices your bug during step 1 of the Guided Format. This person wants to see the status of the bug as well. He or she may do so by putting their email in the Add CC field like so:

Email addresses must be registered with bugzilla. In order to CC multiple addresses, simply seperate them with commas or spaces.

Now shortly afterwards, I find the error in the strace log. I resolve the bug as RESOLVED FIXED and say that there was a change in the location of configuration files, and that I will update the ebuild with a warning about it. The bug now becomes resolved, and you are displayed with this:

Also note the section here:

This gives you the option of Reopening the bug if you wish to (ie. the developer thinks it's resolved but it's really not to your standards). Now our bug is fixed!

Conclusion

This concludes the howto on working with bugzilla. I hope this proved usefull. If you have any questions, comments, or ideas regarding this document, please send them to me at chriswhite@gentoo.org. Thanks!