在google breakpad中没有来自剥离二进制文件的符号痕迹



从文档来看,google breakpad是:

一个库和工具套件,允许您分发应用程序向用户提供编译器提供的调试信息删除

为了证明上述报价,我们将尝试使用这个最小的c++17样本:

#include <thread>
#include <filesystem>
#include <client/linux/handler/exception_handler.h>
namespace breakpad = google_breakpad;
static bool DumpCallback(const breakpad::MinidumpDescriptor& md,
void* context,
bool success) {
(void)md;
(void)context;
return success;
}
static void fault(unsigned after) {
std::this_thread::sleep_for(std::chrono::seconds{after});
delete reinterpret_cast<std::string*>(0xFEE1DEAD);
}
int32_t main(int argc, char** argv) {
(void)argc;
(void)argv;
auto pwd = std::filesystem::current_path();
const auto dumpDir = pwd.string() + "/dumps";
std::filesystem::create_directory(dumpDir);
breakpad::MinidumpDescriptor md(dumpDir);
new google_breakpad::ExceptionHandler(
md,
/* FilterCallback */ nullptr,
DumpCallback,
/* callback_context */ nullptr,
true,
-1
);
fault(1U);
return EXIT_SUCCESS;
}

在普通的Debug构建中,它是预期的,所以如果我们尝试运行它,并处理生成的小型转储文件(在dump_symsminidump_stackwalk等主要实用程序的帮助下(,结果是一个很好的符号跟踪:

Operating system: Linux
0.0.0 Linux 4.19.0-16-amd64 #1 SMP Debian 4.19.181-1 (2021-03-19) x86_64
CPU: amd64
family 6 model 58 stepping 9
1 CPU
GPU: UNKNOWN
Crash reason:  SIGSEGV /SEGV_MAPERR
Crash address: 0xfee1dead
Process uptime: not available
Thread 0 (crashed)
0  core!std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_data() const [basic_string.h : 176 + 0x4]
rax = 0x00000000fee1dead   rdx = 0x00007ffc12803cc0
rcx = 0x00007fc328087bc1   rbx = 0x000055cdac272940
rsi = 0x00007ffc12803cc0   rdi = 0x00000000fee1dead
rbp = 0x00007ffc12803c80   rsp = 0x00007ffc12803c80
r8 = 0x0000000000000000    r9 = 0x000055cdac276bd8
r10 = 0x0000000000000000   r11 = 0x0000000000000246
r12 = 0x000055cdabc1af40   r13 = 0x00007ffc12803f80
r14 = 0x0000000000000000   r15 = 0x0000000000000000
rip = 0x000055cdabc1bc20
Found by: given as instruction pointer in context
1  core!std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_is_local() const [basic_string.h : 211 + 0xc]
rbx = 0x000055cdac272940   rbp = 0x00007ffc12803cb0
rsp = 0x00007ffc12803c90   r12 = 0x000055cdabc1af40
r13 = 0x00007ffc12803f80   r14 = 0x0000000000000000
r15 = 0x0000000000000000   rip = 0x000055cdabc1bf0b
Found by: call frame info
2  core!std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_dispose() [basic_string.h : 220 + 0xc]
rbx = 0x000055cdac272940   rbp = 0x00007ffc12803cd0
rsp = 0x00007ffc12803cc0   r12 = 0x000055cdabc1af40
r13 = 0x00007ffc12803f80   r14 = 0x0000000000000000
r15 = 0x0000000000000000   rip = 0x000055cdabc1bc3e
Found by: call frame info
3  core!std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() [basic_string.h : 657 + 0xc]
rbx = 0x000055cdac272940   rbp = 0x00007ffc12803cf0
rsp = 0x00007ffc12803ce0   r12 = 0x000055cdabc1af40
r13 = 0x00007ffc12803f80   r14 = 0x0000000000000000
r15 = 0x0000000000000000   rip = 0x000055cdabc1b5b6
Found by: call frame info
4  core!fault [main.cpp : 18 + 0xa]
rbx = 0x000055cdac272940   rbp = 0x00007ffc12803d20
rsp = 0x00007ffc12803d00   r12 = 0x000055cdabc1af40
r13 = 0x00007ffc12803f80   r14 = 0x0000000000000000
r15 = 0x0000000000000000   rip = 0x000055cdabc1b070
Found by: call frame info
5  core!main [main.cpp : 38 + 0xa]
rbx = 0x000055cdac272940   rbp = 0x00007ffc12803ea0
rsp = 0x00007ffc12803d30   r12 = 0x000055cdabc1af40
r13 = 0x00007ffc12803f80   r14 = 0x0000000000000000
r15 = 0x0000000000000000   rip = 0x000055cdabc1b182
Found by: call frame info
6  libc.so.6 + 0x2409b
rbx = 0x0000000000000000   rbp = 0x000055cdabc43ec0
rsp = 0x00007ffc12803eb0   r12 = 0x000055cdabc1af40
r13 = 0x00007ffc12803f80   r14 = 0x0000000000000000
r15 = 0x0000000000000000   rip = 0x00007fc327ed909b
Found by: call frame info
7  core!fault [main.cpp : 19 + 0x3]
rsp = 0x00007ffc12803ed0   rip = 0x000055cdabc1b082
Found by: stack scanning
8  core!google_breakpad::FileID::ElfFileIdentifier(google_breakpad::wasteful_vector<unsigned char>&) [file_id.cc : 158 + 0x10]
rsp = 0x00007ffc12803ee8   rip = 0x000055cdabc1af40
Found by: stack scanning
9  ld-linux-x86-64.so.2 + 0xf476
rsp = 0x00007ffc12803f40   rip = 0x00007fc3283ef476
Found by: stack scanning
10  core!google_breakpad::FileID::ElfFileIdentifier(google_breakpad::wasteful_vector<unsigned char>&) [file_id.cc : 158 + 0x10]
rsp = 0x00007ffc12803f58   rip = 0x000055cdabc1af40
Found by: stack scanning
Loaded modules:
0x55cdabc08000 - 0x55cdabc43fff  core  ???  (main)
0x7fc327eb5000 - 0x7fc32801efff  libc.so.6  ???  (WARNING: No symbols, libc.so.6, A8A9B91823C5CFE5E5B5D946D605D0920)
0x7fc328076000 - 0x7fc32808afff  libpthread.so.0  ???
0x7fc328097000 - 0x7fc3280aafff  libgcc_s.so.1  ???
0x7fc3280b1000 - 0x7fc32815cfff  libm.so.6  ???
0x7fc328234000 - 0x7fc328368fff  libstdc++.so.6  ???
0x7fc3283e0000 - 0x7fc3283fefff  ld-linux-x86-64.so.2  ???  (WARNING: No symbols, ld-linux-x86-64.so.2, 7BFD5DF2BE95A34B86FD71080ACCAE8C0)
0x7ffc12932000 - 0x7ffc12933fff  linux-gate.so  ???

但在部署中,典型的情况是有两个版本,一个是普通的Release,另一个是RelWithDebInfo(相同的版本,但带有调试符号(。因此,如果您尝试与上面完全相同的例程,但使用从正常版本二进制文件(部署到客户端(生成的转储文件和RelWithDebInfo二进制文件中的符号,则会得到以下跟踪,警告您有关主二进制文件的符号:

Operating system: Linux
0.0.0 Linux 4.19.0-16-amd64 #1 SMP Debian 4.19.181-1 (2021-03-19) x86_64
CPU: amd64
family 6 model 58 stepping 9
1 CPU
GPU: UNKNOWN
Crash reason:  SIGSEGV /SEGV_MAPERR
Crash address: 0xfee1dead
Process uptime: not available
Thread 0 (crashed)
0  core + 0xf26a
rax = 0x0000000000000000   rdx = 0x00005604fdc66209
rcx = 0x00007f77d9bcfbc1   rbx = 0x00007fffbc001120
rsi = 0x00007fffbc0010b0   rdi = 0x00007fffbc0010b0
rbp = 0x00007fffbc0011e0   rsp = 0x00007fffbc0010a0
r8 = 0x0000000000000000    r9 = 0x00005604ff997be8
r10 = 0x0000000000000000   r11 = 0x0000000000000246
r12 = 0x00007fffbc0010e0   r13 = 0x00007fffbc0010c0
r14 = 0x00007fffbc0010b0   r15 = 0x00005604ff993940
rip = 0x00005604fdc6626a
Found by: given as instruction pointer in context
1  core + 0x36995
rbp = 0x00007fffbc0011e0   rsp = 0x00007fffbc0011b0
rip = 0x00005604fdc8d995
Found by: stack scanning
2  ld-linux-x86-64.so.2 + 0xf530
rbp = 0x00007fffbc0011e0   rsp = 0x00007fffbc0011b8
rip = 0x00007f77d9f37530
Found by: stack scanning
3  core + 0xf520
rbp = 0x00007fffbc0011e0   rsp = 0x00007fffbc0011c8
rip = 0x00005604fdc66520
Found by: stack scanning
4  core + 0x36950
rsp = 0x00007fffbc0011e8   rip = 0x00005604fdc8d950
Found by: stack scanning
5  libc.so.6 + 0x2409b
rsp = 0x00007fffbc0011f0   rip = 0x00007f77d9a2109b
Found by: stack scanning
6  core + 0xef90
rsp = 0x00007fffbc001210   rip = 0x00005604fdc65f90
Found by: stack scanning
7  core + 0xf520
rsp = 0x00007fffbc001228   rip = 0x00005604fdc66520
Found by: stack scanning
8  ld-linux-x86-64.so.2 + 0xf476
rsp = 0x00007fffbc001280   rip = 0x00007f77d9f37476
Found by: stack scanning
9  core + 0xf520
rsp = 0x00007fffbc001298   rip = 0x00005604fdc66520
Found by: stack scanning
10  core + 0xf54a
rsp = 0x00007fffbc0012b0   rip = 0x00005604fdc6654a
Found by: stack scanning
Loaded modules:
0x5604fdc57000 - 0x5604fdc8dfff  core  ???  (main)  (WARNING: No symbols, core, C33015040F685CBAD56AEFBFD7109D4C0)
0x7f77d99fd000 - 0x7f77d9b66fff  libc.so.6  ???  (WARNING: No symbols, libc.so.6, A8A9B91823C5CFE5E5B5D946D605D0920)
0x7f77d9bbe000 - 0x7f77d9bd2fff  libpthread.so.0  ???
0x7f77d9bdf000 - 0x7f77d9bf2fff  libgcc_s.so.1  ???
0x7f77d9bf9000 - 0x7f77d9ca4fff  libm.so.6  ???
0x7f77d9d7c000 - 0x7f77d9eb0fff  libstdc++.so.6  ???
0x7f77d9f28000 - 0x7f77d9f46fff  ld-linux-x86-64.so.2  ???  (WARNING: No symbols, ld-linux-x86-64.so.2, 7BFD5DF2BE95A34B86FD71080ACCAE8C0)
0x7fffbc1ad000 - 0x7fffbc1aefff  linux-gate.so  ???

我们还有什么需要考虑的吗?

更新日期:2001年5月21日

我们用于符号生成的实际脚本:

#!/bin/bash
#
# e.g ./dump.sh ./exec $PWD/dumps
#
set -e
set -u
DBG_INFO=$(realpath ${1})
DUMPS_DIR=$(realpath ${2:-$PWD/dumps})
DUMP_SYMS=${3:-~/WorkSpace/libraries/breakpad/src/tools/linux/dump_syms/dump_syms}
STAK_WALK=${4:-~/WorkSpace/libraries/breakpad/src/processor/minidump_stackwalk}
#
# Generate debug symbols
#
base=$(basename $DBG_INFO)
$DUMP_SYMS $DBG_INFO > $DUMPS_DIR/$base.sym
#
# Create dump dir structure
#
list=($(head -n1 $DUMPS_DIR/$base.sym))
hash=${list[3]}
mkdir -p $DUMPS_DIR/symbols/$base/$hash
mv $DUMPS_DIR/$base.sym $DUMPS_DIR/symbols/$base/$hash
#
# Produce stack trace
#
RED='33[0;36m'
NC='33[0m' # No Color
tree $DUMPS_DIR
for dmp in $DUMPS_DIR/*.dmp ; do
filename=$(basename -- "${dmp}")
filename="${filename%.*}"
echo -e "generating stack trace for -> ${RED}${dmp}${NC}"
$STAK_WALK ${dmp} $DUMPS_DIR/symbols > $DUMPS_DIR/${filename}.txt 2>/dev/null
done

在尝试将minidump_stackwalk用于应用程序的发布版本时,我也遇到了同样的问题。我使用的是qmake,并使用qmake的CONFIG标志force_debug_infoseparate_debug_info解决了这个问题。在构建之后,将在构建文件夹中显示appName.debug可执行文件(。要转储符号,只需将appName.debug文件复制到某个位置(例如,在构建文件夹中创建子文件夹debug(,然后将其重命名为appName。最后,调用dump_syms build_folder/debug/appName > appName.sym,您将能够在应用程序的发布版本上进行minidump_stackwalk。

PS:对于基于CMake的项目和其他项目,也有类似的解决方案。

您发送的二进制文件与调试符号不匹配

我认为符号生成本身很好。但是,在为RelWithDebinfo构建生成符号时,您正在发送Release构建。

如果您从RelWithDebInfo构建中提取二进制文件并对其进行剥离(即在其上使用strip(,那么您最终应该得到一个剥离的二进制文件,该二进制文件可以发货,并且与提取的调试符号相匹配。

小型转储没有符号。

breakpad文档告诉开发人员,将使用附带的dump_syms或symupload工具或其他合适的工具创建供breakpad使用的符号文件,并将符号文件放置在处理器的符号供应商能够找到的位置。

因此,使用dump_syms生成符号文件,例如'/dump_sys/我的二进制>我的.sym’.

然后,在使用minidump_stackwalk之前,将符号文件放在文件第一行指定的目录中。请参阅Mozilla存储库中的symbolstore.py。https://github.com/MozillaReality/symbolgenerator

最后,生成一个跟踪堆栈,使用minidump_stackwalk,这个命令生成跟踪堆栈并打印它

相关内容

  • 没有找到相关文章

最新更新