Ubuntu下交叉编译ARMv7l下带符号表的release版并分析带剥离符号表的core文件

在Ubuntu下交叉编译ARMv7l下带符号表的release版并分析带剥离符号表的core文件

所谓交叉编译工具,就是让我们可以在Ubuntu或Windows上,通过交叉编译工具,生成其它系统下可执行的可执行文件。而这个交叉编译工具,就具备来交叉的功能属性,即输入口为Ubuntu或Widnows上,而生成的可执行文件,却可以在其它系统上执行。

该文档还描述了release下的崩溃,并分析core文件, 同时还描述了对release的可执行文件如何剥离符号文件的方法

1 配置环境

  1. 先参考gdb调试core dump文件文档,在Ubuntu上安装ARMv7下的交叉编译工具链arm-linux-gnueabihf(又说arm-linux-gnueabihf-toolchain)

  2. 获取安装路径

    由于当前的Ubuntu系统为16.04-32位系统,arm-linux-gnueabihf的安装路径为:

     /usr/local/ti-sdk-am335x-evm/linux-devkit/sysroots/i686-arago-linux/usr/bin/
    
  3. 配置环境变量

    将交叉编译工具的环境配置到~/.bashrc下,如下所示:

     export PATH="$PATH:/usr/local/ti-sdk-am335x-evm/linux-devkit/sysroots/i686-arago-linux/usr/bin/"
    
  4. 在当前shell中立马生效

     source ~/.bashrc
    

2 生成ARMv7l下的可执行文件

  • release下没有debugging info

    arm-linux-gnueabihf-g++ -O3 -DNDEBUG -o crash crash.cc
    
  • release下有debugging info

    arm-linux-gnueabihf-g++ -O3 -DNDEBUG -g -o crash crash.cc
    
  • -DNDEBUG:使用该编译选项,就是说定义来NDEBUG这个宏,它表示程序中的断言将被忽略,程序不会因为断言失败而终止。而编译器会在编译过程中将assert语句移除。

3 run program

将可执行文件拷贝到ARM系统上,取消core限制,是指core dump生成目录,之后再将core dump文件回传到Ubuntu系统上。

  • 将可执行文件拷贝到ARMv7系统下

    scp ./crash root@ip_address:/root/to/directory
    
  • 登录ARMv7系统

    ssh root@ip_address
    # 若有密码输入密码
    
  • 在ARM下取消core的限制:

    若是core文件收到限制,会返回0,不能生成core dump文件,那么要使用如下命令,解除显示额

    ulimit -c
    ulimit -c unlimited
    
  • 在ARM下指定core生成的路径:

    默认情况下,core文件会生成在程序运行所在的目录,可以修改此文件来指定core文件的存放位置和命名方式,可以修改如下文件:

    /proc/sys/kernel/core_pattern
    

    方法如下

    sudo echo "/tmp/core.%e-%p-%t-%s" > sudo /proc/sys/kernel/core_pattern
    sudo echo "core.%e" > sudo /proc/sys/kernel/core_pattern
    

    该命令改变code dump位置

    说明:

    • %e: 程序文件的完整路径(路径中的/会被!替换)
    • %p: 进程ID
    • %t: 进程崩溃的时间戳
    • %s: 哪个信号让程序崩溃

    当前的ARCS系统下,core_pattern中写着/home/**/log/core,记得测试完之后,恢复该值

    为了方便测试,就可改成与可执行文件的同一级目录,如下所示:

    • echo "core.%e">/proc/sys/kernel/core_pattern
  • 在ARM下运行可执行文件

    • ./crash: 在同一级的目录下产生崩溃文件core.crash;
    • ./crash_di: 在同一级的目录下产生崩溃文件core.crash_di;
  • 将该崩溃文件传会Ubuntu

    在Ubuntu上执行如下命令,将崩溃文件传回Ubuntu,并进行分析

    • scp root@ip_address:/root/test_crash/core.crash ./
    • scp root@ip_address:/root/test_crash/core.crash_di ./

3 分析core dump文件

di是指debugging information的缩写

  • gdb-multiarch ./crash ./core.crash: 没有符号文件
  • gdb-multiarch ./crash_di ./core.crash_di: 有符号文件

4 使用Ubuntu下的objcopy分离符号文件

4.1 编写并执行如下脚本

脚本名字为:strip_di.sh

记得加上可执行权限: sudo chmod 777 ./strip_di.sh

#!/bin/bash

#set -x

CURRENT_PATH=`pwd`

if [ $# != 2 ]; then
        echo "Command Format Error!"
        echo "1 usage: ./strip_di crash crash.debug"
fi

EXE_PATH="$CURRENT_PATH/$1"
if [ -f $EXE_PATH ]; then
        echo "$EXE_PATH exists."
else
        echo "$EXE_PATH does not exists."
        exit
fi

if [ $# == 2 ]; then
        objcopy --only-keep-debug $1 $2
        objcopy --strip-debug $1
        objcopy --add-gnu-debuglink=$2 $1
fi

4.2 结果

结果如下,从结果分析来看,ubuntu下的objcopy识别不了ARMv7下的可执行文件,所以执行失败

/home/chris/workspace/test/test_arm_crash/release_di/crash_di exists.
objcopy: Unable to recognise the format of the input file `crash_di'
objcopy: Unable to recognise the format of the input file `crash_di'  
objcopy: Unable to recognise the format of the input file `crash_di'

4.3 结果分析

  • 初步分析:该objcopy是适用于Ubuntu下的可执行文件,当然不适用于ARM下的可执行文件。
  • 思路:
    • 交叉编译工具是否有相应的objcopy文件; bingo,交叉编译工具下确实有该objcopy文件
      • arm-linux-gnueabihf-objcopy:需要使用该objcopy
    • 编译适合与ARM系统的objcopy文件;

4.4 使用交叉编译工具下的objcopy执行

ARM下的objcopy文件为arm-linux-gnueabihf-objcopy

结果如下所示

    chris@x:~/workspace/test/test_arm_crash/release_di$ ll -h
    总用量 296K
    drwxrwxr-x 2 chris chris 4.0K 7月  17 15:40 ./
    drwxrwxr-x 4 chris chris 4.0K 7月  17 14:45 ../
    -rw------- 1 chris chris 260K 7月  17 14:37 core.crash_di
    -rwxrwxr-x 1 chris chris  19K 7月  17 14:06 crash_di*
    -rwxrwxrwx 1 chris chris  452 7月  17 15:40 strip_di.sh*
    chris@x:~/workspace/test/test_arm_crash/release_di$ 
    chris@x:~/workspace/test/test_arm_crash/release_di$ 
    chris@x:~/workspace/test/test_arm_crash/release_di$ ./strip_di.sh crash_di ./crash_di.debug
    /home/chris/workspace/test/test_arm_crash/release_di/crash_di exists.
    chris@x:~/workspace/test/test_arm_crash/release_di$ ls
    core.crash_di  crash_di  crash_di.debug  strip_di.sh
    chris@x:~/workspace/test/test_arm_crash/release_di$ ll -h
    总用量 304K
    drwxrwxr-x 2 chris chris 4.0K 7月  17 15:41 ./
    drwxrwxr-x 4 chris chris 4.0K 7月  17 14:45 ../
    -rw------- 1 chris chris 260K 7月  17 14:37 core.crash_di
    -rwxrwxr-x 1 chris chris 6.5K 7月  17 15:41 crash_di*
    -rwxrwxr-x 1 chris chris  17K 7月  17 15:41 crash_di.debug*
    -rwxrwxrwx 1 chris chris  452 7月  17 15:40 strip_di.sh*
    chris@x:~/workspace/test/test_arm_crash/release_di$ 

说明执行成功,并且可执行文件crash_di19K缩写为6.5K,新增了crash_di.debug文件。

4.5 验证剥离符号文件的可执行文件crash_di

差考第3节 运行程序

4.4 objcopy参考

--only-keep-debug
Strip a file, removing contents of any sections that would not be stripped by --strip-debug and leaving the debugging sections intact. In ELF files, this preserves all note sections in the output.

Note - the section headers of the stripped sections are preserved, including their sizes, but the contents of the section are discarded. The section headers are preserved so that other tools can match up the debuginfo file with the real executable, even if that executable has been relocated to a different address space.

The intention is that this option will be used in conjunction with --add-gnu-debuglink to create a two part executable. One a stripped binary which will occupy less space in RAM and in a distribution and the second a debugging information file which is only needed if debugging abilities are required. The suggested procedure to create these files is as follows:

Link the executable as normal. Assuming that it is called foo then...
Run objcopy --only-keep-debug foo foo.dbg to create a file containing the debugging info.
Run objcopy --strip-debug foo to create a stripped executable.
Run objcopy --add-gnu-debuglink=foo.dbg foo to add a link to the debugging info into the stripped executable.

4 更好的方法

优化方案

  1. 直接使用CMake(这里是指CMakeLists.txt)来编写生成交叉编译;
  2. 直接在ARM上分析core文件;

5 教训

对于当前要分析的可执行文件,需要有所备份。因为分离之后,当前的可执行文件将会发生变化。

不仅仅是每一个操作需要备份,对于每一个操作的可执行文件也需要备份,以便将来有用。如比较文件大小。

posted @ 2024-07-17 16:23  绍荣  阅读(5)  评论(0编辑  收藏  举报