Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ca09ce90 authored by Christopher Ferris's avatar Christopher Ferris
Browse files

Discards frames for code within library.

When doing a local unwind, do not include the frames that come
from either libunwind or libbacktrace.

Bug: 11518609
Change-Id: I0ec8d823aebbfa0903e61b16b7e5663f3fd65e78
parent 9dc41d5d
Loading
Loading
Loading
Loading
+11 −0
Original line number Original line Diff line number Diff line
@@ -14,6 +14,7 @@
 * limitations under the License.
 * limitations under the License.
 */
 */


#define _GNU_SOURCE 1
#include <errno.h>
#include <errno.h>
#include <stdint.h>
#include <stdint.h>
#include <string.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);
  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 pthread_mutex_t g_sigaction_mutex = PTHREAD_MUTEX_INITIALIZER;


static void SignalHandler(int, siginfo_t*, void* sigcontext) {
static void SignalHandler(int, siginfo_t*, void* sigcontext) {
+3 −0
Original line number Original line Diff line number Diff line
@@ -46,6 +46,9 @@ public:


  bool Unwind(size_t num_ignore_frames, ucontext_t* ucontext) override;
  bool Unwind(size_t num_ignore_frames, ucontext_t* ucontext) override;


protected:
  bool DiscardFrame(const backtrace_frame_data_t& frame);

private:
private:
  bool UnwindThread(size_t num_ignore_frames);
  bool UnwindThread(size_t num_ignore_frames);


+22 −17
Original line number Original line Diff line number Diff line
@@ -99,7 +99,6 @@ bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucon
      break;
      break;
    }
    }


    if (num_ignore_frames == 0) {
    frames_.resize(num_frames+1);
    frames_.resize(num_frames+1);
    backtrace_frame_data_t* frame = &frames_.at(num_frames);
    backtrace_frame_data_t* frame = &frames_.at(num_frames);
    frame->num = num_frames;
    frame->num = num_frames;
@@ -107,18 +106,24 @@ bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucon
    frame->sp = static_cast<uintptr_t>(sp);
    frame->sp = static_cast<uintptr_t>(sp);
    frame->stack_size = 0;
    frame->stack_size = 0;


    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) {
        if (num_frames > 0) {
          // Set the stack size for the previous frame.
          // Set the stack size for the previous frame.
          backtrace_frame_data_t* prev = &frames_.at(num_frames-1);
          backtrace_frame_data_t* prev = &frames_.at(num_frames-1);
          prev->stack_size = frame->sp - prev->sp;
          prev->stack_size = frame->sp - prev->sp;
        }
        }

      frame->func_name = GetFunctionName(frame->pc, &frame->func_offset);
      FillInMap(frame->pc, &frame->map);
        num_frames++;
        num_frames++;
      } else {
      } else {
        num_ignore_frames--;
        num_ignore_frames--;
      }
      }
    }
    ret = unw_step (cursor.get());
    ret = unw_step (cursor.get());
  } while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES);
  } while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES);


+18 −0
Original line number Original line Diff line number Diff line
@@ -14,6 +14,7 @@
 * limitations under the License.
 * limitations under the License.
 */
 */


#define _GNU_SOURCE 1
#include <dirent.h>
#include <dirent.h>
#include <errno.h>
#include <errno.h>
#include <inttypes.h>
#include <inttypes.h>
@@ -200,6 +201,23 @@ bool WaitForNonZero(int32_t* value, uint64_t seconds) {
  return false;
  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) {
TEST(libbacktrace, local_trace) {
  ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelBacktrace, nullptr), 0);
  ASSERT_NE(test_level_one(1, 2, 3, 4, VerifyLevelBacktrace, nullptr), 0);
}
}