Install libstdc++ debug package on Ubuntu

When using pstack script to analyze the thread stacks of process on Ubuntu, there may be some unresolved symbols, like ??:

......
Thread 3 (Thread 0x7f71513f3700 (LWP 10049)):
#0  0x00007f716399cb13 in epoll_wait ()
#1  0x00007f71688569e5 in epoll_poll (
#2  0x00007f7168858c72 in ev_run (loop=0x7f71697e44e0 <default_loop_struct>,
#3  0x00007f716881cf16 in ev_loop ()
#4  0x00007f716881d680 in process::EventLoop::run ()
#5  0x00007f7168808141 in std::_Bind_simple<void (*())()>::_M_invoke<>(std::_Index_tuple<>) () from /home/nan/mesos-0.26.0/build/src/.libs/libmesos-0.26.0.so
#6  0x00007f716880809b in std::_Bind_simple<void (*())()>::operator()() ()
#7  0x00007f7168808034 in std::thread::_Impl<std::_Bind_simple<void (*())()> >::_M_run() () from /home/nan/mesos-0.26.0/build/src/.libs/libmesos-0.26.0.so
#8  0x00007f7164234a40 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#9  0x00007f716448f182 in start_thread (arg=0x7f71513f3700)
#10 0x00007f716399c47d in clone ()
......

To resolve this issue, firstly, you need to know the libstdc++6 version:

$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04)

Then search the debug files of the 4.8.4 version:

~$ sudo apt-cache search libstdc++ | grep 4.8
......
libstdc++6-4.8-dbg - GNU Standard C++ Library v3 (debugging files)
......

Install libstdc++6-4.8-dbg:

$ sudo apt-get install libstdc++6-4.8-dbg
Reading package lists... Done
Building dependency tree
Reading state information... Done
......

The symbols can be resolved now:

......
Thread 3 (Thread 0x7f71513f3700 (LWP 10049)):
#0  0x00007f716399cb13 in epoll_wait ()
#1  0x00007f71688569e5 in epoll_poll (
#2  0x00007f7168858c72 in ev_run (loop=0x7f71697e44e0 <default_loop_struct>,
#3  0x00007f716881cf16 in ev_loop ()
#4  0x00007f716881d680 in process::EventLoop::run ()
#5  0x00007f7168808141 in std::_Bind_simple<void (*())()>::_M_invoke<>(std::_Index_tuple<>) () from /home/nan/mesos-0.26.0/build/src/.libs/libmesos-0.26.0.so
#6  0x00007f716880809b in std::_Bind_simple<void (*())()>::operator()() ()
#7  0x00007f7168808034 in std::thread::_Impl<std::_Bind_simple<void (*())()> >::_M_run() () from /home/nan/mesos-0.26.0/build/src/.libs/libmesos-0.26.0.so
#8  0x00007f7164234a40 in std::(anonymous namespace)::execute_native_thread_routine (__p=<optimized out>)
#9  0x00007f716448f182 in start_thread (arg=0x7f71513f3700)
#10 0x00007f716399c47d in clone ()
......

 

Fix “Unable to install GRUB in /dev/sda” error during installing Ubuntu

Today, I met “Unable to install GRUB in /dev/sda” error during installing Ubuntu 14.04 server:

2

3 Suddenly, I remembered the OS was not installed on /dev/sda, but /dev/sdc:

1 So in “Install the GRUB boot loader on a hard disk” step, I should select No:

4

Then filled /dev/sdc as the right installation hard disk.

5

It worked!

 

 

Why doesn’t Linux device driver need to update file position in read/write functions?

From LDD3, “char drivers” section:

loff_t f_pos;

The current reading or writing position. loff_t is a 64-bit value on all platforms ( long long in gcc terminology). The driver can read this value if it needs to know the current position in the file but should not normally change it; read and write should update a position using the pointer they receive as the last argument instead of acting on filp->f_pos directly. The one exception to this rule is in the llseek method, the purpose of which is to change the file position.

Why “read and write should update a position using the pointer they receive as the last argument instead of acting on filp->f_pos directly“? After checking the kernel code(the version is 3.0), I get the answer.

Use read system call as an example, and others are similar. Firstly, check read code (fs/read_write.c):

SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
{
    struct file *file;
    ssize_t ret = -EBADF;
    int fput_needed;

    file = fget_light(fd, &fput_needed);
    if (file) {
        loff_t pos = file_pos_read(file);
        ret = vfs_read(file, buf, count, &pos);
        file_pos_write(file, pos);
        fput_light(file, fput_needed);
    }

    return ret;
}

The core part is the following part:

loff_t pos = file_pos_read(file);
ret = vfs_read(file, buf, count, &pos);
file_pos_write(file, pos);

file_pos_read is very simple, just one statement:

static inline loff_t file_pos_read(struct file *file)
{
    return file->f_pos;
}

It returns the current file position.

Then let we see the vfs_read:

ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{
    ssize_t ret;

    if (!(file->f_mode & FMODE_READ))
        return -EBADF;
    if (!file->f_op || (!file->f_op->read && !file->f_op->aio_read))
        return -EINVAL;
    if (unlikely(!access_ok(VERIFY_WRITE, buf, count)))
        return -EFAULT;

    ret = rw_verify_area(READ, file, pos, count);
    if (ret >= 0) {
        count = ret;
        if (file->f_op->read)
            ret = file->f_op->read(file, buf, count, pos);
        else
            ret = do_sync_read(file, buf, count, pos);
        if (ret > 0) {
            fsnotify_access(file);
            add_rchar(current, ret);
        }
        inc_syscr(current);
    }

    return ret;
}

Exclude a lot of condition checks, the skeleton is just like this:

if (file->f_op->read)
    ret = file->f_op->read(file, buf, count, pos);
else
    ret = do_sync_read(file, buf, count, pos);

If the driver provides theĀ read function, use it, else call do_sync_read. No matter which function is used, the new file position should be updated in the memory which pos points to.

Finally, it is file_pos_write‘s function to update the new position:

static inline void file_pos_write(struct file *file, loff_t pos)
{
    file->f_pos = pos;
}

From the above analysis, we can see that it’s no need for every device driver update the file position, and file_pos_read/write will do this uniformly.Other functions are similar, so we can answer the question posted at the beginning of the article now.

Fix “autoreconf: failed to run autopoint: No such file or directory” issue on Suse

On Suse, when executing “autoreconf -i” command in some repository, it prompts following error:

# autoreconf -i
Can't exec "autopoint": No such file or directory at /usr/share/autoconf/Autom4te/FileUtils.pm line 345.
autoreconf: failed to run autopoint: No such file or directory
autoreconf: autopoint is needed because this package uses Gettext

The solution is installing gettext-tools:

# zypper in gettext-tools
Loading repository data...
Reading installed packages...
Resolving package dependencies...

The following NEW package is going to be installed:
  gettext-tools

1 new package to install.
Overall download size: 1.8 MiB. Already cached: 0 B. After the operation, additional 7.9 MiB will be used.
Continue? [y/n/? shows all options] (y): y
Retrieving package gettext-tools-0.19.2-1.103.x86_64                                                   (1/1),   1.8 MiB (  7.9 MiB unpacked)
Checking for file conflicts: .........................................................................................................[done]
(1/1) Installing: gettext-tools-0.19.2-1.103 .........................................................................................[done] 

Then “autoreconf -i” works!