Merge "Discards frames for code within library."
This commit is contained in:
commit
88628e2baf
|
@ -14,6 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE 1
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
@ -73,6 +74,16 @@ bool BacktraceCurrent::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) {
|
|||
return UnwindFromContext(num_ignore_frames, nullptr);
|
||||
}
|
||||
|
||||
bool BacktraceCurrent::DiscardFrame(const backtrace_frame_data_t& frame) {
|
||||
if (BacktraceMap::IsValid(frame.map)) {
|
||||
const std::string library = basename(frame.map.name.c_str());
|
||||
if (library == "libunwind.so" || library == "libbacktrace.so") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static pthread_mutex_t g_sigaction_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static void SignalHandler(int, siginfo_t*, void* sigcontext) {
|
||||
|
|
|
@ -46,6 +46,9 @@ public:
|
|||
|
||||
bool Unwind(size_t num_ignore_frames, ucontext_t* ucontext) override;
|
||||
|
||||
protected:
|
||||
bool DiscardFrame(const backtrace_frame_data_t& frame);
|
||||
|
||||
private:
|
||||
bool UnwindThread(size_t num_ignore_frames);
|
||||
|
||||
|
|
|
@ -99,25 +99,30 @@ bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucon
|
|||
break;
|
||||
}
|
||||
|
||||
if (num_ignore_frames == 0) {
|
||||
frames_.resize(num_frames+1);
|
||||
backtrace_frame_data_t* frame = &frames_.at(num_frames);
|
||||
frame->num = num_frames;
|
||||
frame->pc = static_cast<uintptr_t>(pc);
|
||||
frame->sp = static_cast<uintptr_t>(sp);
|
||||
frame->stack_size = 0;
|
||||
frames_.resize(num_frames+1);
|
||||
backtrace_frame_data_t* frame = &frames_.at(num_frames);
|
||||
frame->num = num_frames;
|
||||
frame->pc = static_cast<uintptr_t>(pc);
|
||||
frame->sp = static_cast<uintptr_t>(sp);
|
||||
frame->stack_size = 0;
|
||||
|
||||
if (num_frames > 0) {
|
||||
// Set the stack size for the previous frame.
|
||||
backtrace_frame_data_t* prev = &frames_.at(num_frames-1);
|
||||
prev->stack_size = frame->sp - prev->sp;
|
||||
FillInMap(frame->pc, &frame->map);
|
||||
// Check to see if we should skip this frame because it's coming
|
||||
// from within the library, and we are doing a local unwind.
|
||||
if (ucontext != nullptr || num_frames != 0 || !DiscardFrame(*frame)) {
|
||||
if (num_ignore_frames == 0) {
|
||||
// GetFunctionName is an expensive call, only do it if we are
|
||||
// keeping the frame.
|
||||
frame->func_name = GetFunctionName(frame->pc, &frame->func_offset);
|
||||
if (num_frames > 0) {
|
||||
// Set the stack size for the previous frame.
|
||||
backtrace_frame_data_t* prev = &frames_.at(num_frames-1);
|
||||
prev->stack_size = frame->sp - prev->sp;
|
||||
}
|
||||
num_frames++;
|
||||
} else {
|
||||
num_ignore_frames--;
|
||||
}
|
||||
|
||||
frame->func_name = GetFunctionName(frame->pc, &frame->func_offset);
|
||||
FillInMap(frame->pc, &frame->map);
|
||||
num_frames++;
|
||||
} else {
|
||||
num_ignore_frames--;
|
||||
}
|
||||
ret = unw_step (cursor.get());
|
||||
} while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE 1
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
|
@ -200,6 +201,23 @@ bool WaitForNonZero(int32_t* value, uint64_t seconds) {
|
|||
return false;
|
||||
}
|
||||
|
||||
TEST(libbacktrace, local_no_unwind_frames) {
|
||||
// Verify that a local unwind does not include any frames within
|
||||
// libunwind or libbacktrace.
|
||||
std::unique_ptr<Backtrace> backtrace(Backtrace::Create(getpid(), getpid()));
|
||||
ASSERT_TRUE(backtrace->Unwind(0));
|
||||
|
||||
ASSERT_TRUE(backtrace->NumFrames() != 0);
|
||||
for (const auto& frame : *backtrace ) {
|
||||
if (BacktraceMap::IsValid(frame.map)) {
|
||||
const std::string name = basename(frame.map.name.c_str());
|
||||
ASSERT_TRUE(name != "libunwind.so" && name != "libbacktrace.so")
|
||||
<< DumpFrames(backtrace.get());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(libbacktrace, local_trace) {
|
||||
ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelBacktrace, nullptr), 0);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue