Building GDB on a freshly installed machine FAQ

So you just installed Fedora, RHEL or CentOS and now you want to build GDB from source.

  1. How do you make sure everything you need to build it is installed?
    # dnf builddep gdb
  2. Did it say, No such command: builddep? Do this, then try again:
    # dnf install dnf-plugins-core
  3. Did it say, dnf: command not found…? You’re using yum, try this:
    # yum-builddep gdb
  4. Did it say, yum-builddep: command not found…? Do this, then try again:
    # yum install yum-utils

Thank you, you’re welcome.

“Reformat the filesystem to enable support”

Apparently it’s been a while since I ran containers on my office computer—and by a while, I mean, since November 2016—because if your initial install was RHEL or CentOS 7.2 or older then neither Docker nor Podman will work:

# yum -q -y install podman skopeo buildah
# podman pull registry.access.redhat.com/ubi7/ubi
Error: could not get runtime: kernel does not support overlay fs: overlay: the backing xfs filesystem is formatted without d_type support, which leads to incorrect behavior. Reformat the filesystem with ftype=1 to enable d_type support. Running without d_type is not supported.: driver not supported

So… ugh. I didn’t have any disks it’d work on either:

# for i in $(awk '{ if ($3 == "xfs") print $2 }' /etc/mtab); do xfs_info $i; done | grep ftype
naming   =version 2              bsize=4096   ascii-ci=0 ftype=0
naming   =version 2              bsize=4096   ascii-ci=0 ftype=0
naming   =version 2              bsize=4096   ascii-ci=0 ftype=0
naming   =version 2              bsize=4096   ascii-ci=0 ftype=0

I didn’t reformat anything though. podman pull wants overlayFS on /var/run/containers/storage, and buildah bud wants it on /var/lib/containers/storage. I made loopback disks for both:

  1. Find/make space somewhere, then create a directory to put the images in:
    # mkdir -p /store/containers
  2. Create a big file, whatever size you want, for the disk image. I made mine 20GiB. It took a couple minutes, my disks are slow:
    # dd if=/dev/zero of=/store/containers/var_lib_containers.img bs=1M count=20K
  3. Find a free loop device and associate the file to it:
    # losetup -f /dev/loop1
    # losetup /dev/loop1 /store/containers/var_lib_containers.img 
    
  4. Format the “device”, then detach it from the file:
    # mkfs -t xfs -n ftype=1 /dev/loop1
    # losetup -d /dev/loop1
  5. Mount the “disk”, and see if it worked:
    # mount -oloop /store/containers/var_lib_containers.img /var/lib/containers
    # df -h /var/lib/containers
    Filesystem      Size  Used Avail Use% Mounted on
    /dev/loop1       20G   33M   20G   1% /var/lib/containers
  6. It worked? Make it permanent:
    # echo "/store/containers/var_lib_containers.img /var/lib/containers xfs defaults,loop 1 2" >> /etc/fstab

Rinse and repeat for the other drive it needed. Then try again:

# podman pull registry.access.redhat.com/ubi7/ubi
Trying to pull registry.access.redhat.com/ubi7/ubi...Getting image
source signatures
Copying blob bff3b73cbcc4 done
Copying blob 7b1c937e0f67 done
Copying config 6fecccc91c done
Writing manifest to image destination
Storing signatures
6fecccc91c83e11ae4fede6793e9410841221d4779520c2b9e9fb7f7b3830264

Resetting the root password on Fedora

Yesterday I made a Fedora 30 VM on my RHEL 7 box, and for some reason I couldn’t log in as root after the installation finished. Well, it’s been a while, so I had to look it up, and following the instructions didn’t work either—I finally managed to get a shell, but the terminal was corrupted. Because it was a VM? Because the instructions were out of date? I’ve no idea. Anyway, here’s what I did, with the stuff that wasn’t in the instructions kind of yellowish:

  1. Reboot and wait for the GRUB menu to appear. You may need to be pressing Shift for this to happen.
  2. In the menu, highlight any entry and press e to edit it.
  3. Find the line beginning with linux. Remove the rhgb and quiet options, then add init=/bin/sh at the end of the line.
  4. Press Ctrl-X to boot with those options. After a while you should get a root shell. The prompt was sh-5.0# on my system, not sh-4.2# like the instructions say, but it doesn’t matter.
  5. Run the commands in the instructions:
    /usr/sbin/load_policy -i
    mount -o remount,rw /
    passwd root
    mount -o remount,ro /
  6. The instructions say to reboot now, but none of the commands to reboot the system worked at this point. Probably they expected systemd. No problem, I hit “Force Reset” in Virtual Machine Manager. I probably should have run a sync or two beforehand, but I didn’t think to.

Ta-da, working system!

libiberty demangler fuzzer

I wrote a quick fuzzer for libiberty’s demangler this morning. Here’s how to get and use it:

$ mkdir workdir
$ cd workdir
$ git clone git@github.com:gbenson/binutils-gdb.git src
  ...
$ cd src
$ git co demangler
$ cd ..
$ mkdir build
$ cd build
$ CFLAGS="-g -O0" ../src/configure --with-separate-debug-dir=/usr/lib/debug
  ...
$ make
  ...
$ ../src/fuzzer.sh 
  ...
+ /home/gary/workdir/build/fuzzer
../src/fuzzer.sh: line 12: 22482 Segmentation fault      (core dumped) $fuzzer
# copy the executable and PID from the two lines above
$ gdb -batch /home/gary/workdir/build/fuzzer core.22482 -ex "bt"
...
Core was generated by `/home/gary/workdir/build/fuzzer'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x000000000040d5f2 in op_is_new_cast (op=0x7ffffac19930) at libiberty/cp-demangle.c:3064
3064	  const char *code = op->u.s_operator.op->code;
#0  0x000000000040d5f2 in op_is_new_cast (op=0x7ffffac19930) at libiberty/cp-demangle.c:3064
#1  0x000000000040dc6f in d_expression_1 (di=0x7ffffac19c90) at libiberty/cp-demangle.c:3232
#2  0x000000000040dfbc in d_expression (di=0x7ffffac19c90) at libiberty/cp-demangle.c:3315
#3  0x000000000040cff6 in d_array_type (di=0x7ffffac19c90) at libiberty/cp-demangle.c:2821
#4  0x000000000040c260 in cplus_demangle_type (di=0x7ffffac19c90) at libiberty/cp-demangle.c:2330
#5  0x000000000040cd70 in d_parmlist (di=0x7ffffac19c90) at libiberty/cp-demangle.c:2718
#6  0x000000000040ceb8 in d_bare_function_type (di=0x7ffffac19c90, has_return_type=0) at libiberty/cp-demangle.c:2772
#7  0x000000000040a9b2 in d_encoding (di=0x7ffffac19c90, top_level=1) at libiberty/cp-demangle.c:1287
#8  0x000000000040a6be in cplus_demangle_mangled_name (di=0x7ffffac19c90, top_level=1) at libiberty/cp-demangle.c:1164
#9  0x0000000000413131 in d_demangle_callback (mangled=0x7ffffac19ea0 "_Z1-Av23*;cG~Wo2Vu", options=259, callback=0x40ed11 , opaque=0x7ffffac19d70)
    at libiberty/cp-demangle.c:5862
#10 0x0000000000413267 in d_demangle (mangled=0x7ffffac19ea0 "_Z1-Av23*;cG~Wo2Vu", options=259, palc=0x7ffffac19dd8) at libiberty/cp-demangle.c:5913
#11 0x00000000004132d6 in cplus_demangle_v3 (mangled=0x7ffffac19ea0 "_Z1-Av23*;cG~Wo2Vu", options=259) at libiberty/cp-demangle.c:6070
#12 0x0000000000401a87 in cplus_demangle (mangled=0x7ffffac19ea0 "_Z1-Av23*;cG~Wo2Vu", options=259) at libiberty/cplus-dem.c:858
#13 0x0000000000400ea0 in main (argc=1, argv=0x7ffffac1a0a8) at /home/gary/workdir/src/fuzzer.c:26

The symbol that crashed it is one frame up from the bottom of the backtrace.

VM networking tip

If you are setting up VMs using libvirt then it’s a good idea to change the address of the virtual network to something other than the default. Why? Because if you don’t, and you create a guest which itself starts up libvirt and uses NetworkManager then at least some of the time your VM will start up with its networking hosed.

If the host is using the default network (192.168.122.0/24) and the guests also want to use that network then there is a race between NetworkManager bringing up eth0 and libvirt bringing up virbr0. libvirt checks for existing interfaces using the network it is configured for before starting up virbr0, so if NetworkManager brings up eth0 first then virbr0 will not be set up on the guest and everything will be fine. But, if eth0 is not set up by the time libvirt runs the check, then virbr0 will take 192.168.122.0/24, then eth0 will come up on 192.168.122.something, and you’ll have a VM with two separate interfaces connected to two separate networks that both have the same address range… and it won’t work!

The easy way to solve this is to not install libvirt on the guest, but you may not be able to change this until after the guest is running, and if libvirt starts up during a guest’s installer then you may need to complete parts of the installation with no networking. This may or may not be ok for you and your OS. I’m using VMs to set up clean test environments for GDB, and at the moment I’m setting up three or four new “machines” every day (and throwing them away when I’m done) so I want the process as streamlined as possible. If you only occasionally set up new VMs then some extra tasks during the installation may not be a problem, but it is pretty simple to change the network on the host and you only have to do it once:

  1. As root, run virsh net-edit default
  2. Change every occurence of 192.168.122 to something else
  3. Stop any running guests
  4. Run virsh net-destroy default
  5. Run virsh net-start default

It’s a shame this can’t be fixed more conclusively elsewhere, but NetworkManager brings up the interfaces asynchronously at boot time which makes it impossible to definitively schedule libvirt’s startup to happen after NetworkManager.

Thank you Laine Stump for helping me out with this.

Only dest dir longer than base dir not supported

Hello,

Have you experienced the mysterious error, “Only dest dir longer than base dir not supported”?

I have.

The Problem

When you build an rpm, the code is built in %{_builddir}, which usually evaluates as %{_topdir}/BUILD, which in turn evaluates as something like /home/you/rpmbuild/BUILD. The built code (if built with GCC) ends up with loads of /home/you/rpmbuild/BUILD paths embedded in it, and the script /usr/lib/rpm/debugedit rewrites these paths to /usr/src/debug so that the debuginfo rpms work. /usr/lib/rpm/debugedit cannot extend strings, it can only shrink them. If you are seeing “Only dest dir longer than base dir not supported” then, somewhere in your build system, %{_builddir} is defined as something that expands to a string shorter than /usr/src/debug.

Example

In my case, I was building a glibc rpm in a VM that turned out not to have enough disk. I created a new disk, mounted it on /mnt, and added the line %_topdir /mnt to my ~/.rpmmacros. The result? “Only dest dir longer than base dir not supported”. I fixed it by editing ~/.rpmmacros to say %_topdir /mnt/rpmbuild.

Briefly

/usr/src/debug       # the reference
/mnt/BUILD           # too short!
/mnt/rpmbuild/BUILD  # long enough

Thank you,
The Mgt.