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

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

Merge "Move dex pc frame creation into libunwindstack."

parents 5e041a4f d70ea5ea
Loading
Loading
Loading
Loading
+2 −6
Original line number Diff line number Diff line
@@ -50,7 +50,6 @@ libbacktrace_sources = [
    "BacktracePtrace.cpp",
    "thread_utils.c",
    "ThreadEntry.cpp",
    "UnwindDexFile.cpp",
    "UnwindStack.cpp",
    "UnwindStackMap.cpp",
]
@@ -110,10 +109,9 @@ cc_library {
            static_libs: ["libasync_safe"],
        },
        vendor: {
            cflags: ["-DNO_LIBDEXFILE"],
            exclude_srcs: ["UnwindDexFile.cpp"],
            cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
            exclude_shared_libs: ["libdexfile"],
        },
        }
    },
    whole_static_libs: ["libdemangle"],
}
@@ -145,8 +143,6 @@ cc_test {
        "backtrace_test.cpp",
        "GetPss.cpp",
        "thread_utils.c",

        "unwind_dex_test.cpp",
    ],

    cflags: [
+9 −84
Original line number Diff line number Diff line
@@ -36,70 +36,15 @@
#include <unwindstack/Regs.h>
#include <unwindstack/RegsGetLocal.h>

#if !defined(NO_LIBDEXFILE_SUPPORT)
#include <unwindstack/DexFiles.h>
#endif
#include <unwindstack/Unwinder.h>

#include "BacktraceLog.h"
#ifndef NO_LIBDEXFILE
#include "UnwindDexFile.h"
#endif
#include "UnwindStack.h"
#include "UnwindStackMap.h"

static void FillInDexFrame(UnwindStackMap* stack_map, uint64_t dex_pc,
                           backtrace_frame_data_t* frame) {
  // The DEX PC points into the .dex section within an ELF file.
  // However, this is a BBS section manually mmaped to a .vdex file,
  // so we need to get the following map to find the ELF data.
  unwindstack::Maps* maps = stack_map->stack_maps();
  auto it = maps->begin();
  uint64_t rel_dex_pc;
  unwindstack::MapInfo* info;
  for (; it != maps->end(); ++it) {
    auto entry = *it;
    if (dex_pc >= entry->start && dex_pc < entry->end) {
      info = entry;
      rel_dex_pc = dex_pc - entry->start;
      frame->map.start = entry->start;
      frame->map.end = entry->end;
      frame->map.offset = entry->offset;
      frame->map.load_bias = entry->load_bias;
      frame->map.flags = entry->flags;
      frame->map.name = entry->name;
      frame->rel_pc = rel_dex_pc;
      break;
    }
  }
  if (it == maps->end() || ++it == maps->end()) {
    return;
  }

  auto entry = *it;
  auto process_memory = stack_map->process_memory();
  unwindstack::Elf* elf = entry->GetElf(process_memory, true);
  if (!elf->valid()) {
    return;
  }

  // Adjust the relative dex by the offset.
  rel_dex_pc += entry->elf_offset;

  uint64_t dex_offset;
  if (!elf->GetFunctionName(rel_dex_pc, &frame->func_name, &dex_offset)) {
    return;
  }
  frame->func_offset = dex_offset;
  if (frame->func_name != "$dexfile") {
    return;
  }

#ifndef NO_LIBDEXFILE
  UnwindDexFile* dex_file = stack_map->GetDexFile(dex_pc - dex_offset, info);
  if (dex_file != nullptr) {
    dex_file->GetMethodInformation(dex_offset, &frame->func_name, &frame->func_offset);
  }
#endif
}

bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
                       std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames,
                       std::vector<std::string>* skip_names, BacktraceUnwindError* error) {
@@ -110,6 +55,11 @@ bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
  if (stack_map->GetJitDebug() != nullptr) {
    unwinder.SetJitDebug(stack_map->GetJitDebug(), regs->Arch());
  }
#if !defined(NO_LIBDEXFILE_SUPPORT)
  if (stack_map->GetDexFiles() != nullptr) {
    unwinder.SetDexFiles(stack_map->GetDexFiles(), regs->Arch());
  }
#endif
  unwinder.Unwind(skip_names, &stack_map->GetSuffixesToIgnore());
  if (error != nullptr) {
    switch (unwinder.LastErrorCode()) {
@@ -150,36 +100,11 @@ bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
  }

  auto unwinder_frames = unwinder.frames();
  // Get the real number of frames we'll need.
  size_t total_frames = 0;
  for (size_t i = num_ignore_frames; i < unwinder.NumFrames(); i++, total_frames++) {
    if (unwinder_frames[i].dex_pc != 0) {
      total_frames++;
    }
  }
  frames->resize(total_frames);
  frames->resize(unwinder.NumFrames() - num_ignore_frames);
  size_t cur_frame = 0;
  for (size_t i = num_ignore_frames; i < unwinder.NumFrames(); i++) {
    auto frame = &unwinder_frames[i];

    // Inject extra 'virtual' frame that represents the dex pc data.
    // The dex pc is magic register defined in the Mterp interpreter,
    // and thus it will be restored/observed in the frame after it.
    // Adding the dex frame first here will create something like:
    //   #7 pc 006b1ba1 libartd.so  ExecuteMterpImpl+14625
    //   #8 pc 0015fa20 core.vdex   java.util.Arrays.binarySearch+8
    //   #9 pc 0039a1ef libartd.so  art::interpreter::Execute+719
    if (frame->dex_pc != 0) {
      backtrace_frame_data_t* dex_frame = &frames->at(cur_frame);
      dex_frame->num = cur_frame++;
      dex_frame->pc = frame->dex_pc;
      dex_frame->rel_pc = frame->dex_pc;
      dex_frame->sp = frame->sp;
      dex_frame->stack_size = 0;
      dex_frame->func_offset = 0;
      FillInDexFrame(stack_map, frame->dex_pc, dex_frame);
    }

    backtrace_frame_data_t* back_frame = &frames->at(cur_frame);

    back_frame->num = cur_frame++;
+3 −29
Original line number Diff line number Diff line
@@ -26,20 +26,11 @@
#include <unwindstack/MapInfo.h>
#include <unwindstack/Maps.h>

#include "UnwindDexFile.h"
#include "UnwindStackMap.h"

//-------------------------------------------------------------------------
UnwindStackMap::UnwindStackMap(pid_t pid) : BacktraceMap(pid) {}

UnwindStackMap::~UnwindStackMap() {
#ifndef NO_LIBDEXFILE
  for (auto& entry : dex_files_) {
    delete entry.second;
  }
#endif
}

bool UnwindStackMap::Build() {
  if (pid_ == 0) {
    pid_ = getpid();
@@ -54,6 +45,9 @@ bool UnwindStackMap::Build() {
  // Create a JitDebug object for getting jit unwind information.
  std::vector<std::string> search_libs_{"libart.so", "libartd.so"};
  jit_debug_.reset(new unwindstack::JitDebug(process_memory_, search_libs_));
#if !defined(NO_LIBDEXFILE_SUPPORT)
  dex_files_.reset(new unwindstack::DexFiles(process_memory_));
#endif

  if (!stack_maps_->Parse()) {
    return false;
@@ -127,26 +121,6 @@ std::shared_ptr<unwindstack::Memory> UnwindStackMap::GetProcessMemory() {
  return process_memory_;
}

#ifdef NO_LIBDEXFILE
UnwindDexFile* UnwindStackMap::GetDexFile(uint64_t, unwindstack::MapInfo*) {
  return nullptr;
}
#else
UnwindDexFile* UnwindStackMap::GetDexFile(uint64_t dex_file_offset, unwindstack::MapInfo* info) {
  // Lock while we get the data.
  std::lock_guard<std::mutex> guard(dex_lock_);
  UnwindDexFile* dex_file;
  auto entry = dex_files_.find(dex_file_offset);
  if (entry == dex_files_.end()) {
    dex_file = UnwindDexFile::Create(dex_file_offset, process_memory_.get(), info);
    dex_files_[dex_file_offset] = dex_file;
  } else {
    dex_file = entry->second;
  }
  return dex_file;
}
#endif

UnwindStackOfflineMap::UnwindStackOfflineMap(pid_t pid) : UnwindStackMap(pid) {}

bool UnwindStackOfflineMap::Build() {
+9 −5
Original line number Diff line number Diff line
@@ -27,6 +27,9 @@

#include <backtrace/Backtrace.h>
#include <backtrace/BacktraceMap.h>
#if !defined(NO_LIBDEXFILE_SUPPORT)
#include <unwindstack/DexFiles.h>
#endif
#include <unwindstack/JitDebug.h>
#include <unwindstack/Maps.h>

@@ -36,7 +39,7 @@ class UnwindDexFile;
class UnwindStackMap : public BacktraceMap {
 public:
  explicit UnwindStackMap(pid_t pid);
  ~UnwindStackMap();
  ~UnwindStackMap() = default;

  bool Build() override;

@@ -51,7 +54,9 @@ class UnwindStackMap : public BacktraceMap {

  unwindstack::JitDebug* GetJitDebug() { return jit_debug_.get(); }

  UnwindDexFile* GetDexFile(uint64_t dex_file_offset, unwindstack::MapInfo* info);
#if !defined(NO_LIBDEXFILE_SUPPORT)
  unwindstack::DexFiles* GetDexFiles() { return dex_files_.get(); }
#endif

 protected:
  uint64_t GetLoadBias(size_t index) override;
@@ -59,9 +64,8 @@ class UnwindStackMap : public BacktraceMap {
  std::unique_ptr<unwindstack::Maps> stack_maps_;
  std::shared_ptr<unwindstack::Memory> process_memory_;
  std::unique_ptr<unwindstack::JitDebug> jit_debug_;
#ifndef NO_LIBDEXFILE
  std::mutex dex_lock_;
  std::unordered_map<uint64_t, UnwindDexFile*> dex_files_;
#if !defined(NO_LIBDEXFILE_SUPPORT)
  std::unique_ptr<unwindstack::DexFiles> dex_files_;
#endif
};

+64 −0
Original line number Diff line number Diff line
@@ -80,7 +80,13 @@ cc_library {
        host: {
            cflags: ["-O0", "-g"],
        },
        vendor: {
            cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
            exclude_static_libs: ["libunwindstack_dex"],
            exclude_shared_libs: ["libdexfile"],
        },
    },
    whole_static_libs: ["libunwindstack_dex"],

    arch: {
        x86: {
@@ -99,14 +105,70 @@ cc_library {

    shared_libs: [
        "libbase",
        "libdexfile",
        "liblog",
        "liblzma",
    ],
}

// Isolate the dex file processing into a separate library. Currently,
// it is necessary to add art include directories directly, which also
// adds the art elf.h file in the include path, overriding the system one.
// Work to isolate libdexfile is b/72216369.
cc_library_static {
    name: "libunwindstack_dex",
    vendor_available: false,
    defaults: ["libunwindstack_flags"],

    cflags: [
        "-Wexit-time-destructors",
    ],

    srcs: [
        "DexFile.cpp",
        "DexFiles.cpp",
    ],

    shared_libs: [
        "libbase",
        "libdexfile",
    ],
    local_include_dirs: ["include"],
    allow_undefined_symbols: true,

    // libdexfile will eventually properly export headers, for now include
    // these directly.
    include_dirs: [
        "art/runtime",
    ],
}

//-------------------------------------------------------------------------
// Unit Tests
//-------------------------------------------------------------------------
cc_test_library {
    name: "libunwindstack_dex_test",
    vendor_available: false,
    defaults: ["libunwindstack_flags"],

    srcs: [
        "tests/DexFileTest.cpp",
    ],
    local_include_dirs: ["include"],
    allow_undefined_symbols: true,

    shared_libs: [
        "libbase",
        "libunwindstack",
    ],

    // libdexfile will eventually properly export headers, for now include
    // these directly.
    include_dirs: [
        "art/runtime",
    ],
}

cc_test {
    name: "libunwindstack_test",
    defaults: ["libunwindstack_flags"],
@@ -168,6 +230,8 @@ cc_test {
        "libgmock",
    ],

    whole_static_libs: ["libunwindstack_dex_test"],

    data: [
        "tests/files/elf32.xz",
        "tests/files/elf64.xz",
Loading