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

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

Add support for UnwinderFromPid object.

This object is able to be easily used from other code and can be used
to replace the libbacktrace calls in other parts of the platform.

Also, demangle the function names when calling FormatFrame.

Bug: 120606663

Test: Unit tests pass, debuggerd using this code directly passes unit
Test: tests.
Change-Id: Ifd8cf9bdd89174c1736810711d20e9f37f29b1bf
parent 61f4ceb5
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -127,6 +127,10 @@ cc_library {
        },
    },

    whole_static_libs: [
        "libdemangle"
    ],

    static_libs: [
        "libprocinfo",
    ],
@@ -189,6 +193,7 @@ cc_test {
        "tests/MapInfoCreateMemoryTest.cpp",
        "tests/MapInfoGetElfTest.cpp",
        "tests/MapInfoGetLoadBiasTest.cpp",
        "tests/MapInfoTest.cpp",
        "tests/MapsTest.cpp",
        "tests/MemoryBufferTest.cpp",
        "tests/MemoryCacheTest.cpp",
+13 −0
Original line number Diff line number Diff line
@@ -221,6 +221,19 @@ Elf* MapInfo::GetElf(const std::shared_ptr<Memory>& process_memory, ArchEnum exp
  return elf.get();
}

bool MapInfo::GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) {
  {
    // Make sure no other thread is trying to update this elf object.
    std::lock_guard<std::mutex> guard(mutex_);
    if (elf == nullptr) {
      return false;
    }
  }
  // No longer need the lock, once the elf object is created, it is not deleted
  // until this object is deleted.
  return elf->GetFunctionName(addr, name, func_offset);
}

uint64_t MapInfo::GetLoadBias(const std::shared_ptr<Memory>& process_memory) {
  uint64_t cur_load_bias = load_bias.load();
  if (cur_load_bias != static_cast<uint64_t>(-1)) {
+29 −1
Original line number Diff line number Diff line
@@ -26,10 +26,13 @@

#include <android-base/stringprintf.h>

#include <demangle.h>

#include <unwindstack/Elf.h>
#include <unwindstack/JitDebug.h>
#include <unwindstack/MapInfo.h>
#include <unwindstack/Maps.h>
#include <unwindstack/Memory.h>
#include <unwindstack/Unwinder.h>

#if !defined(NO_LIBDEXFILE_SUPPORT)
@@ -306,7 +309,7 @@ std::string Unwinder::FormatFrame(const FrameData& frame, bool is32bit) {
  }

  if (!frame.function_name.empty()) {
    data += " (" + frame.function_name;
    data += " (" + demangle(frame.function_name.c_str());
    if (frame.function_offset != 0) {
      data += android::base::StringPrintf("+%" PRId64, frame.function_offset);
    }
@@ -327,4 +330,29 @@ void Unwinder::SetDexFiles(DexFiles* dex_files, ArchEnum arch) {
}
#endif

bool UnwinderFromPid::Init(ArchEnum arch) {
  if (pid_ == getpid()) {
    maps_ptr_.reset(new LocalMaps());
  } else {
    maps_ptr_.reset(new RemoteMaps(pid_));
  }
  if (!maps_ptr_->Parse()) {
    return false;
  }
  maps_ = maps_ptr_.get();

  process_memory_ = Memory::CreateProcessMemoryCached(pid_);

  jit_debug_ptr_.reset(new JitDebug(process_memory_));
  jit_debug_ = jit_debug_ptr_.get();
  SetJitDebug(jit_debug_, arch);
#if !defined(NO_LIBDEXFILE_SUPPORT)
  dex_files_ptr_.reset(new DexFiles(process_memory_));
  dex_files_ = dex_files_ptr_.get();
  SetDexFiles(dex_files_, arch);
#endif

  return true;
}

}  // namespace unwindstack
+2 −0
Original line number Diff line number Diff line
@@ -75,6 +75,8 @@ struct MapInfo {

  Memory* CreateMemory(const std::shared_ptr<Memory>& process_memory);

  bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset);

 private:
  MapInfo(const MapInfo&) = delete;
  void operator=(const MapInfo&) = delete;
+30 −3
Original line number Diff line number Diff line
@@ -24,7 +24,9 @@
#include <string>
#include <vector>

#include <unwindstack/DexFiles.h>
#include <unwindstack/Error.h>
#include <unwindstack/JitDebug.h>
#include <unwindstack/Maps.h>
#include <unwindstack/Memory.h>
#include <unwindstack/Regs.h>
@@ -32,9 +34,7 @@
namespace unwindstack {

// Forward declarations.
class DexFiles;
class Elf;
class JitDebug;
enum ArchEnum : uint8_t;

struct FrameData {
@@ -67,6 +67,11 @@ class Unwinder {
      : max_frames_(max_frames), maps_(maps), regs_(regs), process_memory_(process_memory) {
    frames_.reserve(max_frames);
  }
  Unwinder(size_t max_frames, Maps* maps, std::shared_ptr<Memory> process_memory)
      : max_frames_(max_frames), maps_(maps), process_memory_(process_memory) {
    frames_.reserve(max_frames);
  }

  ~Unwinder() = default;

  void Unwind(const std::vector<std::string>* initial_map_names_to_skip = nullptr,
@@ -81,6 +86,10 @@ class Unwinder {

  void SetJitDebug(JitDebug* jit_debug, ArchEnum arch);

  void SetRegs(Regs* regs) { regs_ = regs; }
  Maps* GetMaps() { return maps_; }
  std::shared_ptr<Memory>& GetProcessMemory() { return process_memory_; }

  // Disabling the resolving of names results in the function name being
  // set to an empty string and the function offset being set to zero.
  void SetResolveNames(bool resolve) { resolve_names_ = resolve; }
@@ -92,7 +101,9 @@ class Unwinder {
  ErrorCode LastErrorCode() { return last_error_.code; }
  uint64_t LastErrorAddress() { return last_error_.address; }

 private:
 protected:
  Unwinder(size_t max_frames) : max_frames_(max_frames) { frames_.reserve(max_frames); }

  void FillInDexFrame();
  void FillInFrame(MapInfo* map_info, Elf* elf, uint64_t rel_pc, uint64_t func_pc,
                   uint64_t pc_adjustment);
@@ -110,6 +121,22 @@ class Unwinder {
  ErrorData last_error_;
};

class UnwinderFromPid : public Unwinder {
 public:
  UnwinderFromPid(size_t max_frames, pid_t pid) : Unwinder(max_frames), pid_(pid) {}
  ~UnwinderFromPid() = default;

  bool Init(ArchEnum arch);

 private:
  pid_t pid_;
  std::unique_ptr<Maps> maps_ptr_;
  std::unique_ptr<JitDebug> jit_debug_ptr_;
#if !defined(NO_LIBDEXFILE_SUPPORT)
  std::unique_ptr<DexFiles> dex_files_ptr_;
#endif
};

}  // namespace unwindstack

#endif  // _LIBUNWINDSTACK_UNWINDER_H
Loading