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

Commit 88628e2b authored by Christopher Ferris's avatar Christopher Ferris Committed by Gerrit Code Review
Browse files

Merge "Discards frames for code within library."

parents 7ab2c78e ca09ce90
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -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) {
+3 −0
Original line number Diff line number Diff line
@@ -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);

+22 −17
Original line number Diff line number Diff line
@@ -99,7 +99,6 @@ 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;
@@ -107,18 +106,24 @@ bool UnwindCurrent::UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucon
    frame->sp = static_cast<uintptr_t>(sp);
    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) {
          // 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;
        }

      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);

+18 −0
Original line number Diff line number Diff line
@@ -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);
}