INTERMISSION: Building a "vmlinux" file under Ubuntu (FREE LESSON)

Printer-friendly versionPrinter-friendly version

What's the big deal about a vmlinux file?

For the purposes of kernel debugging that will be covered later in this course, it's sometimes extremely useful to have on hand the raw, uncompressed vmlinux file that corresponds to the running kernel. More specifically, it's useful to have a vmlinux file that's been configured with the kernel settings CONFIG_PROC_KCORE and CONFIG_DEBUG_INFO.

Make sure you understand that, by vmlinux file, we're not talking about the vmlinuz-* file corresponding to the running kernel that you can find under /boot -- that's not the one you want. Some distros make it very easy to get your hands on the matching vmlinux file; Ubuntu makes you do a bit more work, but it's still feasible.

One last point -- if you have the freedom to configure, build and reboot a new kernel, then this whole issue is trivial since the vmlinux file is generated as part of the build process, and you can find it at the top of the kernel source tree once the build is done. This little tutorial is for those people who don't have the freedom to build and boot a new kernel, and therefore have to work with the kernel that's currently running.

Acknowledgements: Much of what follows is based on the Ubuntu kernel compilation page here, plus some very helpful people on the Ubuntu kernel mailing list.

Which kernel should you be running?

While it's not strictly necessary, it never hurts to be running the most up-to-date kernel available, so do the standard update and upgrade before going any further. If you want, you can check the current version with:

$ uname -r
2.6.32-23-generic
$

Installing the build tools

The Ubuntu folks have added an entire extra layer of build infrastructure to the standard kernel source tree, so you first need to install all the necessary utilities:

$ sudo apt-get build-dep linux-image-$(uname -r)

Getting the source tree

While there are a couple ways to get the appropriate kernel source tree, the simplest way appears to be using git, so pick a convenient location and:

$ git clone git://kernel.ubuntu.com/ubuntu/ubuntu-lucid.git 

whereupon you'll end up with a ubuntu-lucid directory that contains not just a standard kernel source tree, but quite a lot of Ubuntu additions.

Building the appropriate vmlinux file

Now that you have your local git clone, it's essential that you check out exactly the tag that corresponds to your running kernel. Get that information with:

$ uname -a
Linux lynx 2.6.32-23-generic #37-Ubuntu SMP ... snip ...
$

The above tells you that you should check out the tag:

$ git checkout Ubuntu-2.6.32-23.37

in order to have a source tree that corresponds to the one used to build your running kernel. Next, clean the source in preparation for the build:

$ fakeroot debian/rules clean

and start the build:

$ fakeroot debian/rules binary-generic

Once this is done, you should find your (sizable) vmlinux file here:

$ ls -l debian/build/build-generic/vmlinux
... 114276028 2010-07-01 15:31 debian/build/build-generic/vmlinux
$ file debian/build/build-generic/vmlinux
ELF 64-bit LSB executable, x86-64, version 1 (SYSV), \
  statically linked, not stripped
$

Don't bother doing anything with it, just remember how to get it since you'll be needing it down the road.

So ... will this vmlinux file actually work?

As in, will this built vmlinux file actually match exactly the running kernel? That's not at all clear -- there are all kinds of reasons why there might be subtle but sufficient differences that you can't use it for debugging, because the symbol table entries are slightly off.

The only way to guarantee compatibility is to configure and build your own kernel, then boot to that new kernel, knowing you have the original vmlinux file for it. Really, that's the only way to guarantee correctness.

Oh, about that config file ...

The whole reason for building a vmlinux file in the first place is to have an unstripped, uncompressed kernel image that you can use later for debugging your running kernel. And part of that value comes from configuring your kernel with the appropriate kernel config options -- specificially, CONFIG_PROC_KCORE and CONFIG_DEBUG_INFO -- for reasons that will become obvious in a later lesson.

When using Ubuntu's build infrastructure, the config file used is constructed hierarchically, based on the following files (at least, in my case on my 64-bit laptop and choosing to build a "generic" kernel)):

  • ./debian.master/config/config.common.ubuntu
  • ./debian.master/config/amd64/config.common.amd64
  • ./debian.master/config/amd64/config.flavour.generic

Unsurprisingly, the more specific file settings override the more generic ones.

In fact, it's easy to check that the config file used for the build is equivalent to the one you can see in /boot:

$ diff debian/build/build-generic/.config /boot/config-2.6.32-23-generic
4c4
< # Thu Jul  1 14:50:17 2010
---
> # Fri Jun 11 08:03:19 2010
$

That tells me that the only difference is the internal timestamp and the rest of the two files are identical. That's what you want to see.

Moving up to a newer kernel

If you update your Ubuntu system to a newer kernel, it should be easy to see how to rebuild your vmlinux file accordingly. Just clean the result of the current build with:

$ fakeroot debian/rules clean

then follow the same instructions for your newer kernel version.

Obligatory marketing

This tutorial is a free part of a larger, subscriber-only introductory course in Linux kernel programming that you can read about here.

Comments

Are the debug variables set by default

Are the variables CONFIG_PROC_KCORE and CONFIG_DEBUG_INFO set default when building vmlinux because it is not explicitly set in this tutorial?

Default Ubuntu kernel config settings.

If you build a default Ubuntu kernel, those settings are automatically configured. Take a look at the config file that's used for this build, it's in debian/build/build-generic/.config.

Kernel-wedge command not found...

I'm having issues at the

$ fakeroot debian/rules clean

I get the error above at line 127 of the script.

I had to run

sudo apt-get install kernel-wedge in order for the clean to work.

As an fyi...

Getting kernel-wedge

The kernel-wedge command (and a number of others) should have been installed when you ran:

$ sudo apt-get build-dep linux

whose job it is to install all packages necessary to build a linux kernel on Ubuntu. Did you actually run that command?

UPDATE: Whoops, hang on, you're right, the kernel-wedge utility doesn't get installed by that command. How odd. I will investigate further.

MORE UPDATE: OK, apparently the correct command is:

$ sudo apt-get build-dep linux-image-$(uname -r)

A quick way to check is to remove the kernel-wedge package, then run the above to verify that it gets re-installed. Sorry for the confusion. And I've already corrected this in the article.

Also missing

I found that makedumpfile, same solution.

sudo apt-get install makedumpfile

I'm guessing that is covered by your new command.

"makedumpfile" command

I believe it is. A simple way to confirm that would be to remove makedumpfile, then run the command I provided and see if makedumpfile gets re-installed. I'm fairly sure it will be. I'm still getting used to the Ubuntu software management commands.

I figured as much

..and the kernel is now built without problem.

(except mine is 2.6.32-22.36) - 32 bit ELF for my VM

do I need to do it as root

When I did it as a normal user on Ubuntu 9.04 32 bit

git clone git://kernel.ubuntu.com/ubuntu/ubuntu-lucid.git

Got following error

Initialized empty Git repository in /home/electricity/LKP/pandora/ubuntu-lucid/.git/
fatal: Unable to look up kernel.ubuntu.com (port 9418) (Name or service not known)

but when I logged in as root and did the same then I was able to see some activity started as counting remote objects etc etc.

No, you shouldn't need to be root.

I do this sort of git cloning all the time as a regular user, there's no reason to be root to do this. I just tried it now and it worked fine, so I don't know what your problem might be.

Ok

Ok

How Did the system know to build the 64 bit version?

Hi Robert,
I was perplexed by the fact the system built a 64 bit binary even though it doesn't appear to have been specified. And it wasn't clear to me that the currently running kernel was 64 bit which I presume it was.

Ivan.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <p> <br> <pre> <h1> <h2> <h3> <h4>
  • Lines and paragraphs break automatically.

More information about formatting options

By submitting this form, you accept the Mollom privacy policy.