[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Libunwind-devel] Request for help with libunwind-dynamic
From: |
Tim Holy |
Subject: |
[Libunwind-devel] Request for help with libunwind-dynamic |
Date: |
Fri, 12 Jul 2013 09:35:30 -0500 |
User-agent: |
KMail/4.8.5 (Linux/3.2.0-49-generic; KDE/4.8.5; x86_64; ; ) |
Hello,
I'm a user and contributor to a relatively new LLVM-based dynamic language,
Julia. We use libunwind for our backtraces, and I've also used libunwind to
develop a sampling profiler for Julia.
Occasionally I've seen "truncated" backtraces (more detail below), where
unw_step returns 0 when it shouldn't. My impression (which could, of course,
be entirely mistaken---I'm only recently self-educated on frames, registers,
etc.) is that these truncated backtraces may occur because we are not
providing sufficient unwind information, and I'm wondering whether we need to
be
explicitly using libunwind-dynamic. I am having a bit of trouble understanding
just how much I have to do to use it. In particular, the examples I've seen
almost all derive from Gtest-dyn1.c, in which "fake dynamic" code is generated
by memcpying a function, and the various parameters for interacting with
libunwind-dynamic are hard-coded.
The documentation on "dynamic unwind directives" seems to suggest that any
operation involving a register requires a directive? Wouldn't that mean I'd
have to go through the LLVM-produced assembly instruction-by-instruction and
check it? I've tried supplying just _U_dyn_op_stop or the alias/stop
combination that one finds in Gtest-dyn1.c; with either one, the best I've been
able to achieve is a segfault on program launch.
Here's my current best attempt, in case that's useful. The LLVM Function* is
f, and the address (returned by getPointerToFunction()) is fptr.
unw_dyn_region_info_t *region;
unw_dyn_info_t di;
region = (unw_dyn_region_info_t *) alloca(_U_dyn_region_info_size(2));
region->op_count = 2;
region->next = NULL;
// Count the number of instructions
int insn_count = 0;
for (Function::iterator i = f->begin(); i != f->end(); i++)
insn_count += i->size();
region->insn_count = insn_count+4; // +4 for prologue/epilogue
printf("%lx\n", fptr);
printf("nisn = %d\n", insn_count);
// _U_dyn_op_alias(®ion->op[0], 0, -1, fptr);
_U_dyn_op_stop(®ion->op[0]);
memset(&di, 0, sizeof(di));
di.start_ip = fptr;
di.end_ip = di.start_ip+16*region->insn_count/3;
di.format = UNW_INFO_FORMAT_DYNAMIC;
di.u.pi.name_ptr = (unw_word_t) "A test";
di.u.pi.regions = region;
_U_dyn_register (&di);
The segfault can be avoided by commenting out the U_dyn_register step.
Not sure whether you can help, but in any event thanks for taking the time to
read this.
Best,
--Tim
On the truncated backtraces: using a Julia function which is equivalent to the
C function:
int64_t unsafe_iceil(double x) {
ix = (int64_t) x;
return ix + (x > ix);
}
and which generated the following assembly:
Filename: /tmp/unrooted.jl
Source line: 4
push RBP
mov RBP, RSP
Source line: 4
cvttsd2si RCX, XMM0
Source line: 5
cvtsi2sd XMM1, RCX
ucomisd XMM0, XMM1
Source line: 6
seta AL
movzx EAX, AL
add RAX, RCX
pop RBP
ret
When calling this from a higher-level function, I got 2 types of backtraces,
ones of length 3 and 19. The length-3 backtraces are truncated (the first two
steps are generated by the signal handler and OS).
On one trial, the address of the function entry was 0x00007f3788531d90. For
truncated backtraces, the third frame pointer was always one of the following:
0x00007f3788531d99
0x00007f3788531d9e
0x00007f3788531da2
0x00007f3788531da5
0x00007f3788531da8
0x00007f3788531dab
The length-19 backtraces were always one of the following (note that some of
these may not have been inside unsafe_iceil):
0x00007f3788531d90
0x00007f3788531d91
0x00007f3788531dac
0x00007f378afc1bb0
0x00007f378afc1bba
Note that these are intermingled---the length-19 backtraces start at function
entry, and then there is a somewhat-curious gap of 9 bytes, followed by
truncated backtraces.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Libunwind-devel] Request for help with libunwind-dynamic,
Tim Holy <=