diff options
author | Yabin Cui | 2018-02-22 19:11:31 -0600 |
---|---|---|
committer | Christopher Ferris | 2018-03-21 19:23:54 -0500 |
commit | d5b22c5f048c3aae950d48a7681c156fe52cad24 (patch) | |
tree | 223634bb9f3992004a5394e9c742a021af964d2a /libunwindstack | |
parent | 5ea2c4baf1d60915b4a75f2ea8347afbcecef98f (diff) | |
download | platform-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.bp | 1 | ||||
-rw-r--r-- | libunwindstack/Maps.cpp | 6 | ||||
-rw-r--r-- | libunwindstack/Unwinder.cpp | 16 | ||||
-rw-r--r-- | libunwindstack/include/unwindstack/Maps.h | 6 | ||||
-rw-r--r-- | libunwindstack/tests/UnwindOfflineTest.cpp | 41 | ||||
-rw-r--r-- | libunwindstack/tests/files/offline/jit_map_arm/jit_map0.so | bin | 0 -> 616 bytes | |||
-rw-r--r-- | libunwindstack/tests/files/offline/jit_map_arm/jit_map1.so | bin | 0 -> 604 bytes | |||
-rw-r--r-- | libunwindstack/tests/files/offline/jit_map_arm/libart.so | bin | 0 -> 6095540 bytes | |||
-rw-r--r-- | libunwindstack/tests/files/offline/jit_map_arm/libc.so | bin | 0 -> 841140 bytes | |||
-rw-r--r-- | libunwindstack/tests/files/offline/jit_map_arm/maps.txt | 2 | ||||
-rw-r--r-- | libunwindstack/tests/files/offline/jit_map_arm/regs.txt | 16 | ||||
-rw-r--r-- | libunwindstack/tests/files/offline/jit_map_arm/stack.data | bin | 0 -> 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 | ||
213 | void Maps::Sort() { | ||
214 | std::sort(maps_.begin(), maps_.end(), | ||
215 | [](const MapInfo* a, const MapInfo* b) { return a->start < b->start; }); | ||
216 | } | ||
217 | |||
212 | Maps::~Maps() { | 218 | Maps::~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. |
32 | static constexpr int MAPS_FLAGS_DEVICE_MAP = 0x8000; | 32 | static 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. | ||
36 | static constexpr int MAPS_FLAGS_JIT_SYMFILE_MAP = 0x4000; | ||
33 | 37 | ||
34 | class Maps { | 38 | class 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 | ||
1074 | TEST_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 @@ | |||
1 | e466e000-e4ae8000 r-xp 0 00:00 0 libart.so | ||
2 | e7d91000-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 @@ | |||
1 | r0: e814103c | ||
2 | r1: 12dcf218 | ||
3 | r2: 1a90df75 | ||
4 | r3: ffffffbf | ||
5 | r4: 0 | ||
6 | r5: 12dc0800 | ||
7 | r6: 12dcf218 | ||
8 | r7: 1a90df75 | ||
9 | r8: 0 | ||
10 | r9: dd23cc00 | ||
11 | r10: 1c | ||
12 | r11: cd4ff16c | ||
13 | ip: 0 | ||
14 | sp: cd4ff140 | ||
15 | lr: d025cdd7 | ||
16 | pc: 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 | |||