summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYabin Cui2018-02-22 19:11:31 -0600
committerChristopher Ferris2018-03-21 19:23:54 -0500
commitd5b22c5f048c3aae950d48a7681c156fe52cad24 (patch)
tree223634bb9f3992004a5394e9c742a021af964d2a /libunwindstack
parent5ea2c4baf1d60915b4a75f2ea8347afbcecef98f (diff)
downloadplatform-system-core-d5b22c5f048c3aae950d48a7681c156fe52cad24.tar.gz
platform-system-core-d5b22c5f048c3aae950d48a7681c156fe52cad24.tar.xz
platform-system-core-d5b22c5f048c3aae950d48a7681c156fe52cad24.zip
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
Diffstat (limited to 'libunwindstack')
-rw-r--r--libunwindstack/Android.bp1
-rw-r--r--libunwindstack/Maps.cpp6
-rw-r--r--libunwindstack/Unwinder.cpp16
-rw-r--r--libunwindstack/include/unwindstack/Maps.h6
-rw-r--r--libunwindstack/tests/UnwindOfflineTest.cpp41
-rw-r--r--libunwindstack/tests/files/offline/jit_map_arm/jit_map0.sobin0 -> 616 bytes
-rw-r--r--libunwindstack/tests/files/offline/jit_map_arm/jit_map1.sobin0 -> 604 bytes
-rw-r--r--libunwindstack/tests/files/offline/jit_map_arm/libart.sobin0 -> 6095540 bytes
-rw-r--r--libunwindstack/tests/files/offline/jit_map_arm/libc.sobin0 -> 841140 bytes
-rw-r--r--libunwindstack/tests/files/offline/jit_map_arm/maps.txt2
-rw-r--r--libunwindstack/tests/files/offline/jit_map_arm/regs.txt16
-rw-r--r--libunwindstack/tests/files/offline/jit_map_arm/stack.databin0 -> 61080 bytes
12 files changed, 83 insertions, 5 deletions
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index 08dcf7724..0d43f8724 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -194,6 +194,7 @@ cc_test {
194 "tests/files/offline/eh_frame_hdr_begin_x86_64/*", 194 "tests/files/offline/eh_frame_hdr_begin_x86_64/*",
195 "tests/files/offline/jit_debug_arm/*", 195 "tests/files/offline/jit_debug_arm/*",
196 "tests/files/offline/jit_debug_x86/*", 196 "tests/files/offline/jit_debug_x86/*",
197 "tests/files/offline/jit_map_arm/*",
197 "tests/files/offline/gnu_debugdata_arm/*", 198 "tests/files/offline/gnu_debugdata_arm/*",
198 "tests/files/offline/straddle_arm/*", 199 "tests/files/offline/straddle_arm/*",
199 "tests/files/offline/straddle_arm64/*", 200 "tests/files/offline/straddle_arm64/*",
diff --git a/libunwindstack/Maps.cpp b/libunwindstack/Maps.cpp
index 4c1621284..e1a1a7144 100644
--- a/libunwindstack/Maps.cpp
+++ b/libunwindstack/Maps.cpp
@@ -25,6 +25,7 @@
25 25
26#include <android-base/unique_fd.h> 26#include <android-base/unique_fd.h>
27 27
28#include <algorithm>
28#include <cctype> 29#include <cctype>
29#include <memory> 30#include <memory>
30#include <string> 31#include <string>
@@ -209,6 +210,11 @@ void Maps::Add(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
209 maps_.push_back(map_info); 210 maps_.push_back(map_info);
210} 211}
211 212
213void Maps::Sort() {
214 std::sort(maps_.begin(), maps_.end(),
215 [](const MapInfo* a, const MapInfo* b) { return a->start < b->start; });
216}
217
212Maps::~Maps() { 218Maps::~Maps() {
213 for (auto& map : maps_) { 219 for (auto& map : maps_) {
214 delete map; 220 delete map;
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp
index 27262bd5b..9a6c6dfe2 100644
--- a/libunwindstack/Unwinder.cpp
+++ b/libunwindstack/Unwinder.cpp
@@ -29,6 +29,7 @@
29#include <unwindstack/Elf.h> 29#include <unwindstack/Elf.h>
30#include <unwindstack/JitDebug.h> 30#include <unwindstack/JitDebug.h>
31#include <unwindstack/MapInfo.h> 31#include <unwindstack/MapInfo.h>
32#include <unwindstack/Maps.h>
32#include <unwindstack/Unwinder.h> 33#include <unwindstack/Unwinder.h>
33 34
34#if !defined(NO_LIBDEXFILE_SUPPORT) 35#if !defined(NO_LIBDEXFILE_SUPPORT)
@@ -142,26 +143,31 @@ void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip,
142 uint64_t cur_sp = regs_->sp(); 143 uint64_t cur_sp = regs_->sp();
143 144
144 MapInfo* map_info = maps_->Find(regs_->pc()); 145 MapInfo* map_info = maps_->Find(regs_->pc());
145 uint64_t rel_pc;
146 uint64_t pc_adjustment = 0; 146 uint64_t pc_adjustment = 0;
147 uint64_t step_pc; 147 uint64_t step_pc;
148 uint64_t rel_pc;
148 Elf* elf; 149 Elf* elf;
149 if (map_info == nullptr) { 150 if (map_info == nullptr) {
150 rel_pc = regs_->pc(); 151 step_pc = regs_->pc();
151 step_pc = rel_pc; 152 rel_pc = step_pc;
152 last_error_.code = ERROR_INVALID_MAP; 153 last_error_.code = ERROR_INVALID_MAP;
153 } else { 154 } else {
154 if (ShouldStop(map_suffixes_to_ignore, map_info->name)) { 155 if (ShouldStop(map_suffixes_to_ignore, map_info->name)) {
155 break; 156 break;
156 } 157 }
157 elf = map_info->GetElf(process_memory_, true); 158 elf = map_info->GetElf(process_memory_, true);
158 rel_pc = elf->GetRelPc(regs_->pc(), map_info); 159 step_pc = regs_->pc();
160 rel_pc = elf->GetRelPc(step_pc, map_info);
161 // Everyone except elf data in gdb jit debug maps uses the relative pc.
162 if (!(map_info->flags & MAPS_FLAGS_JIT_SYMFILE_MAP)) {
163 step_pc = rel_pc;
164 }
159 if (adjust_pc) { 165 if (adjust_pc) {
160 pc_adjustment = regs_->GetPcAdjustment(rel_pc, elf); 166 pc_adjustment = regs_->GetPcAdjustment(rel_pc, elf);
161 } else { 167 } else {
162 pc_adjustment = 0; 168 pc_adjustment = 0;
163 } 169 }
164 step_pc = rel_pc - pc_adjustment; 170 step_pc -= pc_adjustment;
165 171
166 // If the pc is in an invalid elf file, try and get an Elf object 172 // If the pc is in an invalid elf file, try and get an Elf object
167 // using the jit debug information. 173 // using the jit debug information.
diff --git a/libunwindstack/include/unwindstack/Maps.h b/libunwindstack/include/unwindstack/Maps.h
index 17a2d28ae..74e5c4729 100644
--- a/libunwindstack/include/unwindstack/Maps.h
+++ b/libunwindstack/include/unwindstack/Maps.h
@@ -30,6 +30,10 @@ namespace unwindstack {
30// Special flag to indicate a map is in /dev/. However, a map in 30// Special flag to indicate a map is in /dev/. However, a map in
31// /dev/ashmem/... does not set this flag. 31// /dev/ashmem/... does not set this flag.
32static constexpr int MAPS_FLAGS_DEVICE_MAP = 0x8000; 32static constexpr int MAPS_FLAGS_DEVICE_MAP = 0x8000;
33// Special flag to indicate that this map represents an elf file
34// created by ART for use with the gdb jit debug interface.
35// This should only ever appear in offline maps data.
36static constexpr int MAPS_FLAGS_JIT_SYMFILE_MAP = 0x4000;
33 37
34class Maps { 38class Maps {
35 public: 39 public:
@@ -45,6 +49,8 @@ class Maps {
45 void Add(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags, const std::string& name, 49 void Add(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags, const std::string& name,
46 uint64_t load_bias); 50 uint64_t load_bias);
47 51
52 void Sort();
53
48 typedef std::vector<MapInfo*>::iterator iterator; 54 typedef std::vector<MapInfo*>::iterator iterator;
49 iterator begin() { return maps_.begin(); } 55 iterator begin() { return maps_.begin(); }
50 iterator end() { return maps_.end(); } 56 iterator end() { return maps_.end(); }
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
index 532640f38..6c242a5ab 100644
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -18,6 +18,7 @@
18#include <stdint.h> 18#include <stdint.h>
19#include <stdio.h> 19#include <stdio.h>
20#include <stdlib.h> 20#include <stdlib.h>
21#include <sys/mman.h>
21#include <unistd.h> 22#include <unistd.h>
22 23
23#include <gtest/gtest.h> 24#include <gtest/gtest.h>
@@ -1070,4 +1071,44 @@ TEST_F(UnwindOfflineTest, art_quick_osr_stub_arm) {
1070 EXPECT_EQ(0xcd4ff960U, unwinder.frames()[24].sp); 1071 EXPECT_EQ(0xcd4ff960U, unwinder.frames()[24].sp);
1071} 1072}
1072 1073
1074TEST_F(UnwindOfflineTest, jit_map_arm) {
1075 Init("jit_map_arm/", ARCH_ARM);
1076
1077 maps_->Add(0xd025c788, 0xd025c9f0, 0, PROT_READ | PROT_EXEC | MAPS_FLAGS_JIT_SYMFILE_MAP,
1078 "jit_map0.so", 0);
1079 maps_->Add(0xd025cd98, 0xd025cff4, 0, PROT_READ | PROT_EXEC | MAPS_FLAGS_JIT_SYMFILE_MAP,
1080 "jit_map1.so", 0);
1081 maps_->Sort();
1082
1083 Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
1084 unwinder.Unwind();
1085
1086 std::string frame_info(DumpFrames(unwinder));
1087 ASSERT_EQ(6U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
1088 EXPECT_EQ(
1089 " #00 pc 00000000 jit_map0.so "
1090 "(com.example.simpleperf.simpleperfexamplewithnative.MixActivity.access$000)\n"
1091 " #01 pc 0000003d jit_map1.so "
1092 "(com.example.simpleperf.simpleperfexamplewithnative.MixActivity$1.run+60)\n"
1093 " #02 pc 004135bb libart.so (art_quick_osr_stub+42)\n"
1094
1095 " #03 pc 003851dd libart.so (_ZN3art6Thread14CreateCallbackEPv+868)\n"
1096 " #04 pc 00062925 libc.so (_ZL15__pthread_startPv+22)\n"
1097 " #05 pc 0001de39 libc.so (__start_thread+24)\n",
1098 frame_info);
1099
1100 EXPECT_EQ(0xd025c788U, unwinder.frames()[0].pc);
1101 EXPECT_EQ(0xcd4ff140U, unwinder.frames()[0].sp);
1102 EXPECT_EQ(0xd025cdd5U, unwinder.frames()[1].pc);
1103 EXPECT_EQ(0xcd4ff140U, unwinder.frames()[1].sp);
1104 EXPECT_EQ(0xe4a755bbU, unwinder.frames()[2].pc);
1105 EXPECT_EQ(0xcd4ff160U, unwinder.frames()[2].sp);
1106 EXPECT_EQ(0xe49e71ddU, unwinder.frames()[3].pc);
1107 EXPECT_EQ(0xcd4ff8e8U, unwinder.frames()[3].sp);
1108 EXPECT_EQ(0xe7df3925U, unwinder.frames()[4].pc);
1109 EXPECT_EQ(0xcd4ff958U, unwinder.frames()[4].sp);
1110 EXPECT_EQ(0xe7daee39U, unwinder.frames()[5].pc);
1111 EXPECT_EQ(0xcd4ff960U, unwinder.frames()[5].sp);
1112}
1113
1073} // namespace unwindstack 1114} // namespace unwindstack
diff --git a/libunwindstack/tests/files/offline/jit_map_arm/jit_map0.so b/libunwindstack/tests/files/offline/jit_map_arm/jit_map0.so
new file mode 100644
index 000000000..e66788377
--- /dev/null
+++ b/libunwindstack/tests/files/offline/jit_map_arm/jit_map0.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_map_arm/jit_map1.so b/libunwindstack/tests/files/offline/jit_map_arm/jit_map1.so
new file mode 100644
index 000000000..9a1d71483
--- /dev/null
+++ b/libunwindstack/tests/files/offline/jit_map_arm/jit_map1.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_map_arm/libart.so b/libunwindstack/tests/files/offline/jit_map_arm/libart.so
new file mode 100644
index 000000000..09ba49532
--- /dev/null
+++ b/libunwindstack/tests/files/offline/jit_map_arm/libart.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_map_arm/libc.so b/libunwindstack/tests/files/offline/jit_map_arm/libc.so
new file mode 100644
index 000000000..39c9025db
--- /dev/null
+++ b/libunwindstack/tests/files/offline/jit_map_arm/libc.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/jit_map_arm/maps.txt b/libunwindstack/tests/files/offline/jit_map_arm/maps.txt
new file mode 100644
index 000000000..5aaec5420
--- /dev/null
+++ b/libunwindstack/tests/files/offline/jit_map_arm/maps.txt
@@ -0,0 +1,2 @@
1e466e000-e4ae8000 r-xp 0 00:00 0 libart.so
2e7d91000-e7e31000 r-xp 0 00:00 0 libc.so
diff --git a/libunwindstack/tests/files/offline/jit_map_arm/regs.txt b/libunwindstack/tests/files/offline/jit_map_arm/regs.txt
new file mode 100644
index 000000000..0b518143a
--- /dev/null
+++ b/libunwindstack/tests/files/offline/jit_map_arm/regs.txt
@@ -0,0 +1,16 @@
1r0: e814103c
2r1: 12dcf218
3r2: 1a90df75
4r3: ffffffbf
5r4: 0
6r5: 12dc0800
7r6: 12dcf218
8r7: 1a90df75
9r8: 0
10r9: dd23cc00
11r10: 1c
12r11: cd4ff16c
13ip: 0
14sp: cd4ff140
15lr: d025cdd7
16pc: d025c788
diff --git a/libunwindstack/tests/files/offline/jit_map_arm/stack.data b/libunwindstack/tests/files/offline/jit_map_arm/stack.data
new file mode 100644
index 000000000..fb8feebf1
--- /dev/null
+++ b/libunwindstack/tests/files/offline/jit_map_arm/stack.data
Binary files differ