Support a map that represents gdb jit elf data.

Changes:
- Add a new flag to the libbacktrace and libunwindstack map data.
- Modify the unwinder to handle this map to use the raw pc when stepping.
- Add new unit tests for this case.

Bug: http://b/73127105
Test: Run simpleperf to unwind through jit symfiles.
Test: Run new unit tests.
Test: Run 137-cfi test on host.
Change-Id: I10bc0410680accc6d35fe51e9f1098911f667e01
This commit is contained in:
Yabin Cui 2018-02-22 17:11:31 -08:00 committed by Christopher Ferris
parent 5ea2c4baf1
commit d5b22c5f04
13 changed files with 87 additions and 5 deletions

View File

@ -40,6 +40,10 @@ struct backtrace_stackinfo_t;
// Special flag to indicate a map is in /dev/. However, a map in
// /dev/ashmem/... does not set this flag.
static constexpr int PROT_DEVICE_MAP = 0x8000;
// Special flag to indicate that this map represents an elf file
// created by ART for use with the gdb jit debug interface.
// This should only ever appear in offline maps data.
static constexpr int PROT_JIT_SYMFILE_MAP = 0x4000;
struct backtrace_map_t {
uint64_t start = 0;

View File

@ -194,6 +194,7 @@ cc_test {
"tests/files/offline/eh_frame_hdr_begin_x86_64/*",
"tests/files/offline/jit_debug_arm/*",
"tests/files/offline/jit_debug_x86/*",
"tests/files/offline/jit_map_arm/*",
"tests/files/offline/gnu_debugdata_arm/*",
"tests/files/offline/straddle_arm/*",
"tests/files/offline/straddle_arm64/*",

View File

@ -25,6 +25,7 @@
#include <android-base/unique_fd.h>
#include <algorithm>
#include <cctype>
#include <memory>
#include <string>
@ -209,6 +210,11 @@ void Maps::Add(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
maps_.push_back(map_info);
}
void Maps::Sort() {
std::sort(maps_.begin(), maps_.end(),
[](const MapInfo* a, const MapInfo* b) { return a->start < b->start; });
}
Maps::~Maps() {
for (auto& map : maps_) {
delete map;

View File

@ -29,6 +29,7 @@
#include <unwindstack/Elf.h>
#include <unwindstack/JitDebug.h>
#include <unwindstack/MapInfo.h>
#include <unwindstack/Maps.h>
#include <unwindstack/Unwinder.h>
#if !defined(NO_LIBDEXFILE_SUPPORT)
@ -142,26 +143,31 @@ void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip,
uint64_t cur_sp = regs_->sp();
MapInfo* map_info = maps_->Find(regs_->pc());
uint64_t rel_pc;
uint64_t pc_adjustment = 0;
uint64_t step_pc;
uint64_t rel_pc;
Elf* elf;
if (map_info == nullptr) {
rel_pc = regs_->pc();
step_pc = rel_pc;
step_pc = regs_->pc();
rel_pc = step_pc;
last_error_.code = ERROR_INVALID_MAP;
} else {
if (ShouldStop(map_suffixes_to_ignore, map_info->name)) {
break;
}
elf = map_info->GetElf(process_memory_, true);
rel_pc = elf->GetRelPc(regs_->pc(), map_info);
step_pc = regs_->pc();
rel_pc = elf->GetRelPc(step_pc, map_info);
// Everyone except elf data in gdb jit debug maps uses the relative pc.
if (!(map_info->flags & MAPS_FLAGS_JIT_SYMFILE_MAP)) {
step_pc = rel_pc;
}
if (adjust_pc) {
pc_adjustment = regs_->GetPcAdjustment(rel_pc, elf);
} else {
pc_adjustment = 0;
}
step_pc = rel_pc - pc_adjustment;
step_pc -= pc_adjustment;
// If the pc is in an invalid elf file, try and get an Elf object
// using the jit debug information.

View File

@ -30,6 +30,10 @@ namespace unwindstack {
// Special flag to indicate a map is in /dev/. However, a map in
// /dev/ashmem/... does not set this flag.
static constexpr int MAPS_FLAGS_DEVICE_MAP = 0x8000;
// Special flag to indicate that this map represents an elf file
// created by ART for use with the gdb jit debug interface.
// This should only ever appear in offline maps data.
static constexpr int MAPS_FLAGS_JIT_SYMFILE_MAP = 0x4000;
class Maps {
public:
@ -45,6 +49,8 @@ class Maps {
void Add(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags, const std::string& name,
uint64_t load_bias);
void Sort();
typedef std::vector<MapInfo*>::iterator iterator;
iterator begin() { return maps_.begin(); }
iterator end() { return maps_.end(); }

View File

@ -18,6 +18,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
#include <gtest/gtest.h>
@ -1070,4 +1071,44 @@ TEST_F(UnwindOfflineTest, art_quick_osr_stub_arm) {
EXPECT_EQ(0xcd4ff960U, unwinder.frames()[24].sp);
}
TEST_F(UnwindOfflineTest, jit_map_arm) {
Init("jit_map_arm/", ARCH_ARM);
maps_->Add(0xd025c788, 0xd025c9f0, 0, PROT_READ | PROT_EXEC | MAPS_FLAGS_JIT_SYMFILE_MAP,
"jit_map0.so", 0);
maps_->Add(0xd025cd98, 0xd025cff4, 0, PROT_READ | PROT_EXEC | MAPS_FLAGS_JIT_SYMFILE_MAP,
"jit_map1.so", 0);
maps_->Sort();
Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
unwinder.Unwind();
std::string frame_info(DumpFrames(unwinder));
ASSERT_EQ(6U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
EXPECT_EQ(
" #00 pc 00000000 jit_map0.so "
"(com.example.simpleperf.simpleperfexamplewithnative.MixActivity.access$000)\n"
" #01 pc 0000003d jit_map1.so "
"(com.example.simpleperf.simpleperfexamplewithnative.MixActivity$1.run+60)\n"
" #02 pc 004135bb libart.so (art_quick_osr_stub+42)\n"
" #03 pc 003851dd libart.so (_ZN3art6Thread14CreateCallbackEPv+868)\n"
" #04 pc 00062925 libc.so (_ZL15__pthread_startPv+22)\n"
" #05 pc 0001de39 libc.so (__start_thread+24)\n",
frame_info);
EXPECT_EQ(0xd025c788U, unwinder.frames()[0].pc);
EXPECT_EQ(0xcd4ff140U, unwinder.frames()[0].sp);
EXPECT_EQ(0xd025cdd5U, unwinder.frames()[1].pc);
EXPECT_EQ(0xcd4ff140U, unwinder.frames()[1].sp);
EXPECT_EQ(0xe4a755bbU, unwinder.frames()[2].pc);
EXPECT_EQ(0xcd4ff160U, unwinder.frames()[2].sp);
EXPECT_EQ(0xe49e71ddU, unwinder.frames()[3].pc);
EXPECT_EQ(0xcd4ff8e8U, unwinder.frames()[3].sp);
EXPECT_EQ(0xe7df3925U, unwinder.frames()[4].pc);
EXPECT_EQ(0xcd4ff958U, unwinder.frames()[4].sp);
EXPECT_EQ(0xe7daee39U, unwinder.frames()[5].pc);
EXPECT_EQ(0xcd4ff960U, unwinder.frames()[5].sp);
}
} // namespace unwindstack

Binary file not shown.

View File

@ -0,0 +1,2 @@
e466e000-e4ae8000 r-xp 0 00:00 0 libart.so
e7d91000-e7e31000 r-xp 0 00:00 0 libc.so

View File

@ -0,0 +1,16 @@
r0: e814103c
r1: 12dcf218
r2: 1a90df75
r3: ffffffbf
r4: 0
r5: 12dc0800
r6: 12dcf218
r7: 1a90df75
r8: 0
r9: dd23cc00
r10: 1c
r11: cd4ff16c
ip: 0
sp: cd4ff140
lr: d025cdd7
pc: d025c788