On Thu, Mar 01, 2012 at 19:02:14 +0100, Denys Vlasenko wrote:
> The libunwind-based coredump-level backtrace generator is ready
> for first review.
I compiled the code and briefly tested it and it seems to be OK.
Building it on x86_64 required some modifications of libunwind -- the
patch is attached, but I don't really know what the code does, I just
imitated the i386 version and it seems to work. Few changes were needed
in the attached source as well, but I suppose it's still
work-in-progress.
> On my test problem directory, old one was generating this
> core_backtrace:
>
> ec1fd70dbee0db36eff9527254d9d2bbfd260f13 0x34a7 - [exe] -
> ec1fd70dbee0db36eff9527254d9d2bbfd260f13 0x3dd8 - [exe] -
> ec1fd70dbee0db36eff9527254d9d2bbfd260f13 0x2093 - [exe] -
> ec1fd70dbee0db36eff9527254d9d2bbfd260f13 0x1659 - [exe] -
>
> And new one generates this:
>
> ec1fd70dbee0db36eff9527254d9d2bbfd260f13 0x34a7 close_stdout /usr/bin/md5sum -
> ec1fd70dbee0db36eff9527254d9d2bbfd260f13 0x3dd8 close_stdout /usr/bin/md5sum -
> ec1fd70dbee0db36eff9527254d9d2bbfd260f13 0x2093 - /usr/bin/md5sum -
> ec1fd70dbee0db36eff9527254d9d2bbfd260f13 0x1659 - /usr/bin/md5sum -
> 879571cf1e8dd31736d0f24b55e0daffc1591278 0x196b3 __libc_start_main
> /lib/libc-2.14.90.so -
> ec1fd70dbee0db36eff9527254d9d2bbfd260f13 0x1f99 - /usr/bin/md5sum -
Good -- I guess the filename is more useful information than the
"module name" used earlier. Old version also discarded everything below
__libc_start_main, but that can be added later.
The symbol names (close_stdout), however, are incorrect as can be seen
when you generate the backtrace in gdb. This is due to unw_get_proc_name
returning the closest symbol available (which happens to be
close_stdout) when the correct symbol in question is stripped from the
binary. This behavior is documented in the unw_get_proc_name man page.
We will need to determine start and end addresses of functions for the
fingerprinting functionality so maybe we can just check if the address
of the symbol belongs to the address range and if not then just ignore
it? This is already implemented in the old version.
> It does not use gdb or eu-unstrip: search for build-ids
> is implemented in the tool itself, backtracing is provided
> by (patched) libunwind.
Great;)
> Segmentation faults are rather likely when libunwind tries to access missing
> parts of coredump. Therefore the tool has SIGSEGV handler, which needs
> to be extended so that we can survive it and continue extracting useful data,
> if possible.
This sounds scary, but I suppose it stems from the design of libunwind
and cannot be easily done otherwise?
Martin
> New abrt-action-generate-core-backtrace.c is below.
>
> (Note: so far it prints results to stdout instead of saving them
> in core_backtrace element.)
>
> --
> vda
diff -ur libunwind.t4/src/coredump/_UCD_access_reg.c
libunwind.t4.modified/src/coredump/_UCD_access_reg.c
--- libunwind.t4/src/coredump/_UCD_access_reg.c 2012-02-27 16:09:34.000000000
+0100
+++ libunwind.t4.modified/src/coredump/_UCD_access_reg.c 2012-03-06
14:48:24.069950505 +0100
@@ -55,17 +55,23 @@
#elif defined(UNW_TARGET_X86_64)
static const int8_t remap_regs[] =
{
- [UNW_X86_RAX] = offsetof(struct user_regs_struct, rax) / sizeof(long),
- [UNW_X86_RDX] = offsetof(struct user_regs_struct, rdx) / sizeof(long),
- [UNW_X86_RCX] = offsetof(struct user_regs_struct, rcx) / sizeof(long),
- [UNW_X86_RBX] = offsetof(struct user_regs_struct, rbx) / sizeof(long),
- [UNW_X86_RSI] = offsetof(struct user_regs_struct, rsi) / sizeof(long),
- [UNW_X86_RDI] = offsetof(struct user_regs_struct, rdi) / sizeof(long),
- [UNW_X86_RBP] = offsetof(struct user_regs_struct, rbp) / sizeof(long),
- [UNW_X86_RSP] = offsetof(struct user_regs_struct, rsp) / sizeof(long),
- [UNW_X86_RIP] = offsetof(struct user_regs_struct, rip) / sizeof(long),
- [UNW_X86_RFLAGS] = offsetof(struct user_regs_struct, rflags) /
sizeof(long),
- [UNW_X86_TRAPNO] = offsetof(struct user_regs_struct, orig_rax) /
sizeof(long),
+ [UNW_X86_64_RAX] = offsetof(struct user_regs_struct, rax) /
sizeof(long),
+ [UNW_X86_64_RDX] = offsetof(struct user_regs_struct, rdx) /
sizeof(long),
+ [UNW_X86_64_RCX] = offsetof(struct user_regs_struct, rcx) /
sizeof(long),
+ [UNW_X86_64_RBX] = offsetof(struct user_regs_struct, rbx) /
sizeof(long),
+ [UNW_X86_64_RSI] = offsetof(struct user_regs_struct, rsi) /
sizeof(long),
+ [UNW_X86_64_RDI] = offsetof(struct user_regs_struct, rdi) /
sizeof(long),
+ [UNW_X86_64_RBP] = offsetof(struct user_regs_struct, rbp) /
sizeof(long),
+ [UNW_X86_64_RSP] = offsetof(struct user_regs_struct, rsp) /
sizeof(long),
+ [UNW_X86_64_R8] = offsetof(struct user_regs_struct, r8) /
sizeof(long),
+ [UNW_X86_64_R9] = offsetof(struct user_regs_struct, r9) /
sizeof(long),
+ [UNW_X86_64_R10] = offsetof(struct user_regs_struct, r10) /
sizeof(long),
+ [UNW_X86_64_R11] = offsetof(struct user_regs_struct, r11) /
sizeof(long),
+ [UNW_X86_64_R12] = offsetof(struct user_regs_struct, r12) /
sizeof(long),
+ [UNW_X86_64_R13] = offsetof(struct user_regs_struct, r13) /
sizeof(long),
+ [UNW_X86_64_R14] = offsetof(struct user_regs_struct, r14) /
sizeof(long),
+ [UNW_X86_64_R15] = offsetof(struct user_regs_struct, r15) /
sizeof(long),
+ [UNW_X86_64_RIP] = offsetof(struct user_regs_struct, rip) /
sizeof(long),
};
#else
#error Port me