selph
selph
Published on 2023-12-28 / 229 Visits
0
0

【附自动化脚本】编译可进行源码级调试的libc库

编译可进行源码级调试的libc库

手动操作过程

  1. 下载对应版本的libc源码:Index of /gnu/glibc,解压

  2. 创建两个目录:glibc-2.xx_build,glibc-2.xx_out

  3. 进入glibc-2.xx_build目录

  4. 执行:

    ../glibc-2.xx/configure --prefix=/home/selph/glibcs/glibc-2.xx_out CFLAGS="-Og -g -g3 -ggdb -gdwarf-4" CXXFLAGS="-Og -g -g3 -ggdb -gdwarf-4" --disable-werror
    
    • 为了调试,加了"-g -g3 -ggdb"调试选项,
    • -Og是必须得,因为C库必须要指定,否则会报libc/config.h:4:3: error: #error "glibc cannot be compiled without optimization"错误(具体原因可以参考这里:gcc - GLibc optimizations required - Stack Overflow)。
    • 最后的--disable-werror也是必须的,否则会将编译过程中的很多警告信息归为错误,那么就没法继续编译了。
    • 参考../glibc-2.35/configure --help的提示帮助。
  5. 执行make​,make install

  6. 在out文件夹的lib目录下就是我们编译的libc

参考资料:


遇到的问题

如果configure出错了:

configure: WARNING:
*** These auxiliary programs are missing or incompatible versions: msgfmt makeinfo
*** some features or tests will be disabled.
*** Check the INSTALL file for required versions.

可能需要装几个包:

sudo apt install gettext texinfo

检查安装好了没:

msgfmt --version
makeinfo --version

自动化下载编译脚本

#!/bin/sh

# a function to show usage info
usage() {
    # highlight print the usage and author
    echo "\033[31mUsage:    $0 [version]\033[0m"
    echo "Example:  $0 2.35"
    echo "Author:   selph"
    exit 1
}
# param check 
if [ $# -ne 1 ]; then
    usage
fi

# if param is -h or --help, show usage info
if [ $1 = "-h" ] || [ $1 = "--help" ]; then
    usage
fi

# check if install, if not install it
# texinfo
if [ ! -x "$(command -v texinfo)" ]; then
    sudo apt install texinfo
fi
# gettext
if [ ! -x "$(command -v gettext)" ]; then
    sudo apt install gettext
fi
# wget
if [ ! -x "$(command -v wget)" ]; then
    sudo apt install wget
fi

# recvice a param named version
version=$1

# split version to url
url="https://ftp.gnu.org/gnu/glibc/glibc-${version}.tar.gz"

# judge the file is exist or not, if not download it
if [ ! -f "glibc-${version}.tar.gz" ]; then
    wget $url
fi

# uncompress the file
tar -zxvf glibc-${version}.tar.gz

# create build and out dir
mkdir glibc-${version}_build
mkdir glibc-${version}_out

# get prefix path
prefix=$(pwd)/glibc-${version}_out
# enter build dir and compile
cd glibc-${version}_build
../glibc-${version}/configure --prefix=$prefix CFLAGS="-Og -g -g3 -ggdb -gdwarf-4" CXXFLAGS="-Og -g -g3 -ggdb -gdwarf-4" --disable-werror
make -j12
# make install

# exit build dir
cd ..

# check glibcs dir is exist or not, if not create it
if [ ! -d "glibcs" ]; then
    mkdir glibcs
fi

# make a another dir to store all libc's libc.so and ld.so
#cp glibc-${version}_out/lib/libc.so.6 glibcs/libc-${version}.so
#cp glibc-${version}_out/lib/ld-linux-x86-64.so.2 glibcs/ld-${version}.so
 
# libc.so 就在glibc-2.xx_build目录下
# ld.so 就在glibc-2.xx_build/elf 目录下
# copy libc.so and ld.so to glibcs dir
cp glibc-${version}_build/libc.so glibcs/libc-${version}.so
cp glibc-${version}_build/elf/ld.so glibcs/ld-${version}.so

# check if have trash-cli ,if not using rm command
if [ ! -x "$(command -v trash)" ]; then
    rm -rf glibc-${version}_build
else
    # remove build dir
    trash glibc-${version}_build
    # clear trash
    trash-empty
fi

自动切换目标程序的libc和ld链接

#!/bin/sh

# This script is used to change the default libc library to the one specified using patchelf
# libc and ld file in glibcs/ld-${version}.so

# param1: filename
# param2: version of libc

# root directary using store libc and ld
root_dir=/home/selph/glibc-self-compile/glibcs



# if param is not 2, print help
if [ $# -ne 2 ]; then
    # print banner and help and author selph
    echo "Change libc to the specified version"
    echo "Usage: $0 [filename] [version]"
    echo "Example: $0 a.out 2.35"
    echo "Author: selph"  
    exit 1
fi

# recvice a param named filename and version
filename=$1
version=$2

# patchelf change file's ld 
patchelf --set-interpreter ${root_dir}/ld-${version}.so $filename
# patchelf change file's libc
patchelf --replace-needed libc.so.6 ${root_dir}/libc-${version}.so $filename

Comment