diff options
author | Christopher Ferris | 2017-08-03 14:08:34 -0500 |
---|---|---|
committer | Gerrit Code Review | 2017-08-03 14:08:34 -0500 |
commit | 172b1d000844536bb4b268c2450211c97031d49d (patch) | |
tree | 5953d4f6b2318f210a422969313e2cce2310a71a | |
parent | 472808a5701515a7ce7180c625f4f5bcef0e792e (diff) | |
parent | 6f3981c181677830c33093411b51ad6b0bf2e337 (diff) | |
download | platform-system-core-172b1d000844536bb4b268c2450211c97031d49d.tar.gz platform-system-core-172b1d000844536bb4b268c2450211c97031d49d.tar.xz platform-system-core-172b1d000844536bb4b268c2450211c97031d49d.zip |
Merge "Add support for the new unwind method."
-rw-r--r-- | libbacktrace/Android.bp | 9 | ||||
-rw-r--r-- | libbacktrace/UnwindStack.cpp | 220 | ||||
-rw-r--r-- | libbacktrace/UnwindStack.h | 56 | ||||
-rw-r--r-- | libbacktrace/UnwindStackMap.cpp | 94 | ||||
-rw-r--r-- | libbacktrace/UnwindStackMap.h | 41 | ||||
-rw-r--r-- | libbacktrace/include/backtrace/Backtrace.h | 2 | ||||
-rw-r--r-- | libbacktrace/include/backtrace/BacktraceMap.h | 2 | ||||
-rw-r--r-- | libunwindstack/Android.bp | 1 | ||||
-rw-r--r-- | libunwindstack/include/unwindstack/MapInfo.h | 1 |
9 files changed, 426 insertions, 0 deletions
diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp index e02aaf216..c58d77733 100644 --- a/libbacktrace/Android.bp +++ b/libbacktrace/Android.bp | |||
@@ -53,6 +53,8 @@ libbacktrace_sources = [ | |||
53 | "UnwindCurrent.cpp", | 53 | "UnwindCurrent.cpp", |
54 | "UnwindMap.cpp", | 54 | "UnwindMap.cpp", |
55 | "UnwindPtrace.cpp", | 55 | "UnwindPtrace.cpp", |
56 | "UnwindStack.cpp", | ||
57 | "UnwindStackMap.cpp", | ||
56 | ] | 58 | ] |
57 | 59 | ||
58 | cc_library_headers { | 60 | cc_library_headers { |
@@ -84,6 +86,7 @@ cc_library { | |||
84 | "libbase", | 86 | "libbase", |
85 | "liblog", | 87 | "liblog", |
86 | "libunwind", | 88 | "libunwind", |
89 | "libunwindstack", | ||
87 | ], | 90 | ], |
88 | 91 | ||
89 | static_libs: ["libcutils"], | 92 | static_libs: ["libcutils"], |
@@ -97,6 +100,7 @@ cc_library { | |||
97 | "libbase", | 100 | "libbase", |
98 | "liblog", | 101 | "liblog", |
99 | "libunwind", | 102 | "libunwind", |
103 | "libunwindstack", | ||
100 | ], | 104 | ], |
101 | 105 | ||
102 | static_libs: ["libcutils"], | 106 | static_libs: ["libcutils"], |
@@ -108,6 +112,7 @@ cc_library { | |||
108 | "libbase", | 112 | "libbase", |
109 | "liblog", | 113 | "liblog", |
110 | "libunwind", | 114 | "libunwind", |
115 | "libunwindstack", | ||
111 | ], | 116 | ], |
112 | 117 | ||
113 | static_libs: ["libasync_safe", "libcutils"], | 118 | static_libs: ["libasync_safe", "libcutils"], |
@@ -130,11 +135,13 @@ cc_library_shared { | |||
130 | linux: { | 135 | linux: { |
131 | shared_libs: [ | 136 | shared_libs: [ |
132 | "libunwind", | 137 | "libunwind", |
138 | "libunwindstack", | ||
133 | ], | 139 | ], |
134 | }, | 140 | }, |
135 | android: { | 141 | android: { |
136 | shared_libs: [ | 142 | shared_libs: [ |
137 | "libunwind", | 143 | "libunwind", |
144 | "libunwindstack", | ||
138 | ], | 145 | ], |
139 | }, | 146 | }, |
140 | } | 147 | } |
@@ -161,6 +168,7 @@ cc_library_static { | |||
161 | shared_libs = [ | 168 | shared_libs = [ |
162 | "libbase", | 169 | "libbase", |
163 | "libunwind", | 170 | "libunwind", |
171 | "libunwindstack", | ||
164 | "libziparchive", | 172 | "libziparchive", |
165 | ], | 173 | ], |
166 | } | 174 | } |
@@ -192,6 +200,7 @@ cc_test { | |||
192 | "libcutils", | 200 | "libcutils", |
193 | "liblog", | 201 | "liblog", |
194 | "libunwind", | 202 | "libunwind", |
203 | "libunwindstack", | ||
195 | ], | 204 | ], |
196 | 205 | ||
197 | group_static_libs: true, | 206 | group_static_libs: true, |
diff --git a/libbacktrace/UnwindStack.cpp b/libbacktrace/UnwindStack.cpp new file mode 100644 index 000000000..baf0ada28 --- /dev/null +++ b/libbacktrace/UnwindStack.cpp | |||
@@ -0,0 +1,220 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #define _GNU_SOURCE 1 | ||
18 | #include <assert.h> | ||
19 | #include <stdint.h> | ||
20 | #include <stdlib.h> | ||
21 | #include <string.h> | ||
22 | #include <ucontext.h> | ||
23 | |||
24 | #include <memory> | ||
25 | #include <string> | ||
26 | |||
27 | #if !defined(__ANDROID__) | ||
28 | #include <cutils/threads.h> | ||
29 | #endif | ||
30 | |||
31 | #include <backtrace/Backtrace.h> | ||
32 | #include <unwindstack/Elf.h> | ||
33 | #include <unwindstack/MapInfo.h> | ||
34 | #include <unwindstack/Maps.h> | ||
35 | #include <unwindstack/Memory.h> | ||
36 | #include <unwindstack/Regs.h> | ||
37 | #include <unwindstack/RegsGetLocal.h> | ||
38 | |||
39 | #include "BacktraceLog.h" | ||
40 | #include "UnwindStack.h" | ||
41 | #include "UnwindStackMap.h" | ||
42 | |||
43 | static std::string GetFunctionName(pid_t pid, BacktraceMap* back_map, uintptr_t pc, | ||
44 | uintptr_t* offset) { | ||
45 | *offset = 0; | ||
46 | unwindstack::Maps* maps = reinterpret_cast<UnwindStackMap*>(back_map)->stack_maps(); | ||
47 | |||
48 | // Get the map for this | ||
49 | unwindstack::MapInfo* map_info = maps->Find(pc); | ||
50 | if (map_info == nullptr || map_info->flags & PROT_DEVICE_MAP) { | ||
51 | return ""; | ||
52 | } | ||
53 | |||
54 | unwindstack::Elf* elf = map_info->GetElf(pid, true); | ||
55 | |||
56 | std::string name; | ||
57 | uint64_t func_offset; | ||
58 | if (!elf->GetFunctionName(elf->GetRelPc(pc, map_info), &name, &func_offset)) { | ||
59 | return ""; | ||
60 | } | ||
61 | *offset = func_offset; | ||
62 | return name; | ||
63 | } | ||
64 | |||
65 | static bool IsUnwindLibrary(const std::string& map_name) { | ||
66 | const std::string library(basename(map_name.c_str())); | ||
67 | return library == "libunwindstack.so" || library == "libbacktrace.so"; | ||
68 | } | ||
69 | |||
70 | static bool Unwind(pid_t pid, unwindstack::Memory* memory, unwindstack::Regs* regs, | ||
71 | BacktraceMap* back_map, std::vector<backtrace_frame_data_t>* frames, | ||
72 | size_t num_ignore_frames) { | ||
73 | unwindstack::Maps* maps = reinterpret_cast<UnwindStackMap*>(back_map)->stack_maps(); | ||
74 | bool adjust_rel_pc = false; | ||
75 | size_t num_frames = 0; | ||
76 | frames->clear(); | ||
77 | while (num_frames < MAX_BACKTRACE_FRAMES) { | ||
78 | if (regs->pc() == 0) { | ||
79 | break; | ||
80 | } | ||
81 | unwindstack::MapInfo* map_info = maps->Find(regs->pc()); | ||
82 | if (map_info == nullptr) { | ||
83 | break; | ||
84 | } | ||
85 | |||
86 | unwindstack::Elf* elf = map_info->GetElf(pid, true); | ||
87 | uint64_t rel_pc = regs->pc(); | ||
88 | if (map_info != nullptr) { | ||
89 | rel_pc = elf->GetRelPc(regs->pc(), map_info); | ||
90 | } | ||
91 | |||
92 | bool skip_frame = num_frames == 0 && IsUnwindLibrary(map_info->name); | ||
93 | if (num_ignore_frames == 0 && !skip_frame) { | ||
94 | uint64_t adjusted_rel_pc = rel_pc; | ||
95 | if (map_info != nullptr && adjust_rel_pc) { | ||
96 | adjusted_rel_pc = regs->GetAdjustedPc(rel_pc, elf); | ||
97 | } | ||
98 | frames->resize(num_frames + 1); | ||
99 | backtrace_frame_data_t* frame = &frames->at(num_frames); | ||
100 | frame->num = num_frames; | ||
101 | if (map_info != nullptr) { | ||
102 | // This will point to the adjusted absolute pc. regs->pc() is | ||
103 | // unaltered. | ||
104 | frame->pc = map_info->start + adjusted_rel_pc; | ||
105 | } else { | ||
106 | frame->pc = rel_pc; | ||
107 | } | ||
108 | frame->sp = regs->sp(); | ||
109 | frame->rel_pc = adjusted_rel_pc; | ||
110 | frame->stack_size = 0; | ||
111 | |||
112 | frame->map.start = map_info->start; | ||
113 | frame->map.end = map_info->end; | ||
114 | frame->map.offset = map_info->offset; | ||
115 | frame->map.load_bias = elf->GetLoadBias(); | ||
116 | frame->map.flags = map_info->flags; | ||
117 | frame->map.name = map_info->name; | ||
118 | |||
119 | uint64_t func_offset = 0; | ||
120 | if (!elf->GetFunctionName(adjusted_rel_pc, &frame->func_name, &func_offset)) { | ||
121 | frame->func_name = ""; | ||
122 | } | ||
123 | frame->func_offset = func_offset; | ||
124 | if (num_frames > 0) { | ||
125 | // Set the stack size for the previous frame. | ||
126 | backtrace_frame_data_t* prev = &frames->at(num_frames - 1); | ||
127 | prev->stack_size = frame->sp - prev->sp; | ||
128 | } | ||
129 | num_frames++; | ||
130 | } else if (!skip_frame && num_ignore_frames > 0) { | ||
131 | num_ignore_frames--; | ||
132 | } | ||
133 | adjust_rel_pc = true; | ||
134 | |||
135 | // Do not unwind through a device map. | ||
136 | if (map_info->flags & PROT_DEVICE_MAP) { | ||
137 | break; | ||
138 | } | ||
139 | unwindstack::MapInfo* sp_info = maps->Find(regs->sp()); | ||
140 | if (sp_info->flags & PROT_DEVICE_MAP) { | ||
141 | break; | ||
142 | } | ||
143 | |||
144 | if (!elf->Step(rel_pc + map_info->elf_offset, regs, memory)) { | ||
145 | break; | ||
146 | } | ||
147 | } | ||
148 | |||
149 | return true; | ||
150 | } | ||
151 | |||
152 | UnwindStackCurrent::UnwindStackCurrent(pid_t pid, pid_t tid, BacktraceMap* map) | ||
153 | : BacktraceCurrent(pid, tid, map), memory_(new unwindstack::MemoryLocal) {} | ||
154 | |||
155 | std::string UnwindStackCurrent::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) { | ||
156 | return ::GetFunctionName(Pid(), GetMap(), pc, offset); | ||
157 | } | ||
158 | |||
159 | bool UnwindStackCurrent::UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucontext) { | ||
160 | std::unique_ptr<unwindstack::Regs> regs; | ||
161 | if (ucontext == nullptr) { | ||
162 | regs.reset(unwindstack::Regs::CreateFromLocal()); | ||
163 | // Fill in the registers from this function. Do it here to avoid | ||
164 | // one extra function call appearing in the unwind. | ||
165 | unwindstack::RegsGetLocal(regs.get()); | ||
166 | } else { | ||
167 | regs.reset(unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::GetMachineType(), ucontext)); | ||
168 | } | ||
169 | |||
170 | error_ = BACKTRACE_UNWIND_NO_ERROR; | ||
171 | return ::Unwind(getpid(), memory_.get(), regs.get(), GetMap(), &frames_, num_ignore_frames); | ||
172 | } | ||
173 | |||
174 | UnwindStackPtrace::UnwindStackPtrace(pid_t pid, pid_t tid, BacktraceMap* map) | ||
175 | : BacktracePtrace(pid, tid, map), memory_(new unwindstack::MemoryRemote(pid)) {} | ||
176 | |||
177 | std::string UnwindStackPtrace::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) { | ||
178 | return ::GetFunctionName(Pid(), GetMap(), pc, offset); | ||
179 | } | ||
180 | |||
181 | bool UnwindStackPtrace::Unwind(size_t num_ignore_frames, ucontext_t* context) { | ||
182 | std::unique_ptr<unwindstack::Regs> regs; | ||
183 | if (context == nullptr) { | ||
184 | uint32_t machine_type; | ||
185 | regs.reset(unwindstack::Regs::RemoteGet(Tid(), &machine_type)); | ||
186 | } else { | ||
187 | regs.reset(unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::GetMachineType(), context)); | ||
188 | } | ||
189 | |||
190 | error_ = BACKTRACE_UNWIND_NO_ERROR; | ||
191 | return ::Unwind(Pid(), memory_.get(), regs.get(), GetMap(), &frames_, num_ignore_frames); | ||
192 | } | ||
193 | |||
194 | Backtrace* Backtrace::CreateNew(pid_t pid, pid_t tid, BacktraceMap* map) { | ||
195 | if (pid == BACKTRACE_CURRENT_PROCESS) { | ||
196 | pid = getpid(); | ||
197 | if (tid == BACKTRACE_CURRENT_THREAD) { | ||
198 | tid = gettid(); | ||
199 | } | ||
200 | } else if (tid == BACKTRACE_CURRENT_THREAD) { | ||
201 | tid = pid; | ||
202 | } | ||
203 | |||
204 | if (map == nullptr) { | ||
205 | // This would cause the wrong type of map object to be created, so disallow. | ||
206 | #if defined(__ANDROID__) | ||
207 | __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, | ||
208 | "Backtrace::CreateNew() must be called with a real map pointer."); | ||
209 | #else | ||
210 | BACK_LOGE("Backtrace::CreateNew() must be called with a real map pointer."); | ||
211 | abort(); | ||
212 | #endif | ||
213 | } | ||
214 | |||
215 | if (pid == getpid()) { | ||
216 | return new UnwindStackCurrent(pid, tid, map); | ||
217 | } else { | ||
218 | return new UnwindStackPtrace(pid, tid, map); | ||
219 | } | ||
220 | } | ||
diff --git a/libbacktrace/UnwindStack.h b/libbacktrace/UnwindStack.h new file mode 100644 index 000000000..32d1f51ab --- /dev/null +++ b/libbacktrace/UnwindStack.h | |||
@@ -0,0 +1,56 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #ifndef _LIBBACKTRACE_UNWIND_STACK_H | ||
18 | #define _LIBBACKTRACE_UNWIND_STACK_H | ||
19 | |||
20 | #include <stdint.h> | ||
21 | |||
22 | #include <string> | ||
23 | |||
24 | #include <backtrace/BacktraceMap.h> | ||
25 | #include <unwindstack/Memory.h> | ||
26 | |||
27 | #include "BacktraceCurrent.h" | ||
28 | #include "BacktracePtrace.h" | ||
29 | |||
30 | class UnwindStackCurrent : public BacktraceCurrent { | ||
31 | public: | ||
32 | UnwindStackCurrent(pid_t pid, pid_t tid, BacktraceMap* map); | ||
33 | virtual ~UnwindStackCurrent() = default; | ||
34 | |||
35 | std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) override; | ||
36 | |||
37 | bool UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucontext) override; | ||
38 | |||
39 | private: | ||
40 | std::unique_ptr<unwindstack::Memory> memory_; | ||
41 | }; | ||
42 | |||
43 | class UnwindStackPtrace : public BacktracePtrace { | ||
44 | public: | ||
45 | UnwindStackPtrace(pid_t pid, pid_t tid, BacktraceMap* map); | ||
46 | virtual ~UnwindStackPtrace() = default; | ||
47 | |||
48 | bool Unwind(size_t num_ignore_frames, ucontext_t* context) override; | ||
49 | |||
50 | std::string GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset); | ||
51 | |||
52 | private: | ||
53 | std::unique_ptr<unwindstack::Memory> memory_; | ||
54 | }; | ||
55 | |||
56 | #endif // _LIBBACKTRACE_UNWIND_STACK_H | ||
diff --git a/libbacktrace/UnwindStackMap.cpp b/libbacktrace/UnwindStackMap.cpp new file mode 100644 index 000000000..ba9fd87d7 --- /dev/null +++ b/libbacktrace/UnwindStackMap.cpp | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #include <stdint.h> | ||
18 | #include <stdlib.h> | ||
19 | #include <sys/types.h> | ||
20 | |||
21 | #include <backtrace/BacktraceMap.h> | ||
22 | #include <unwindstack/Elf.h> | ||
23 | #include <unwindstack/MapInfo.h> | ||
24 | #include <unwindstack/Maps.h> | ||
25 | |||
26 | #include "UnwindStackMap.h" | ||
27 | |||
28 | //------------------------------------------------------------------------- | ||
29 | UnwindStackMap::UnwindStackMap(pid_t pid) : BacktraceMap(pid) {} | ||
30 | |||
31 | bool UnwindStackMap::Build() { | ||
32 | if (pid_ == 0) { | ||
33 | pid_ = getpid(); | ||
34 | stack_maps_.reset(new unwindstack::LocalMaps); | ||
35 | } else { | ||
36 | stack_maps_.reset(new unwindstack::RemoteMaps(pid_)); | ||
37 | } | ||
38 | |||
39 | if (!stack_maps_->Parse()) { | ||
40 | return false; | ||
41 | } | ||
42 | |||
43 | // Iterate through the maps and fill in the backtrace_map_t structure. | ||
44 | for (auto& map_info : *stack_maps_) { | ||
45 | backtrace_map_t map; | ||
46 | map.start = map_info.start; | ||
47 | map.end = map_info.end; | ||
48 | map.offset = map_info.offset; | ||
49 | // Set to -1 so that it is demand loaded. | ||
50 | map.load_bias = static_cast<uintptr_t>(-1); | ||
51 | map.flags = map_info.flags; | ||
52 | map.name = map_info.name; | ||
53 | |||
54 | maps_.push_back(map); | ||
55 | } | ||
56 | |||
57 | return true; | ||
58 | } | ||
59 | |||
60 | void UnwindStackMap::FillIn(uintptr_t addr, backtrace_map_t* map) { | ||
61 | BacktraceMap::FillIn(addr, map); | ||
62 | if (map->load_bias != static_cast<uintptr_t>(-1)) { | ||
63 | return; | ||
64 | } | ||
65 | |||
66 | // Fill in the load_bias. | ||
67 | unwindstack::MapInfo* map_info = stack_maps_->Find(addr); | ||
68 | if (map_info == nullptr) { | ||
69 | return; | ||
70 | } | ||
71 | unwindstack::Elf* elf = map_info->GetElf(pid_, true); | ||
72 | map->load_bias = elf->GetLoadBias(); | ||
73 | } | ||
74 | |||
75 | //------------------------------------------------------------------------- | ||
76 | // BacktraceMap create function. | ||
77 | //------------------------------------------------------------------------- | ||
78 | BacktraceMap* BacktraceMap::CreateNew(pid_t pid, bool uncached) { | ||
79 | BacktraceMap* map; | ||
80 | |||
81 | if (uncached) { | ||
82 | // Force use of the base class to parse the maps when this call is made. | ||
83 | map = new BacktraceMap(pid); | ||
84 | } else if (pid == getpid()) { | ||
85 | map = new UnwindStackMap(0); | ||
86 | } else { | ||
87 | map = new UnwindStackMap(pid); | ||
88 | } | ||
89 | if (!map->Build()) { | ||
90 | delete map; | ||
91 | return nullptr; | ||
92 | } | ||
93 | return map; | ||
94 | } | ||
diff --git a/libbacktrace/UnwindStackMap.h b/libbacktrace/UnwindStackMap.h new file mode 100644 index 000000000..7885b7428 --- /dev/null +++ b/libbacktrace/UnwindStackMap.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #ifndef _LIBBACKTRACE_UNWINDSTACK_MAP_H | ||
18 | #define _LIBBACKTRACE_UNWINDSTACK_MAP_H | ||
19 | |||
20 | #include <stdint.h> | ||
21 | #include <sys/types.h> | ||
22 | |||
23 | #include <backtrace/BacktraceMap.h> | ||
24 | #include <unwindstack/Maps.h> | ||
25 | |||
26 | class UnwindStackMap : public BacktraceMap { | ||
27 | public: | ||
28 | explicit UnwindStackMap(pid_t pid); | ||
29 | ~UnwindStackMap() = default; | ||
30 | |||
31 | bool Build() override; | ||
32 | |||
33 | void FillIn(uintptr_t addr, backtrace_map_t* map) override; | ||
34 | |||
35 | unwindstack::Maps* stack_maps() { return stack_maps_.get(); } | ||
36 | |||
37 | protected: | ||
38 | std::unique_ptr<unwindstack::Maps> stack_maps_; | ||
39 | }; | ||
40 | |||
41 | #endif // _LIBBACKTRACE_UNWINDSTACK_MAP_H | ||
diff --git a/libbacktrace/include/backtrace/Backtrace.h b/libbacktrace/include/backtrace/Backtrace.h index b919e81c6..d67ea50c9 100644 --- a/libbacktrace/include/backtrace/Backtrace.h +++ b/libbacktrace/include/backtrace/Backtrace.h | |||
@@ -90,6 +90,8 @@ public: | |||
90 | // If map is NULL, then create the map and manage it internally. | 90 | // If map is NULL, then create the map and manage it internally. |
91 | // If map is not NULL, the map is still owned by the caller. | 91 | // If map is not NULL, the map is still owned by the caller. |
92 | static Backtrace* Create(pid_t pid, pid_t tid, BacktraceMap* map = NULL); | 92 | static Backtrace* Create(pid_t pid, pid_t tid, BacktraceMap* map = NULL); |
93 | // Same as above, but uses a different underlying unwinder. | ||
94 | static Backtrace* CreateNew(pid_t pid, pid_t tid, BacktraceMap* map = NULL); | ||
93 | 95 | ||
94 | // Create an offline Backtrace object that can be used to do an unwind without a process | 96 | // Create an offline Backtrace object that can be used to do an unwind without a process |
95 | // that is still running. If cache_file is set to true, then elf information will be cached | 97 | // that is still running. If cache_file is set to true, then elf information will be cached |
diff --git a/libbacktrace/include/backtrace/BacktraceMap.h b/libbacktrace/include/backtrace/BacktraceMap.h index 02a50f738..963c34b64 100644 --- a/libbacktrace/include/backtrace/BacktraceMap.h +++ b/libbacktrace/include/backtrace/BacktraceMap.h | |||
@@ -52,6 +52,8 @@ public: | |||
52 | // Passing a map created with uncached set to true to Backtrace::Create() | 52 | // Passing a map created with uncached set to true to Backtrace::Create() |
53 | // is unsupported. | 53 | // is unsupported. |
54 | static BacktraceMap* Create(pid_t pid, bool uncached = false); | 54 | static BacktraceMap* Create(pid_t pid, bool uncached = false); |
55 | // Same as above, but is compatible with the new unwinder. | ||
56 | static BacktraceMap* CreateNew(pid_t pid, bool uncached = false); | ||
55 | 57 | ||
56 | static BacktraceMap* Create(pid_t pid, const std::vector<backtrace_map_t>& maps); | 58 | static BacktraceMap* Create(pid_t pid, const std::vector<backtrace_map_t>& maps); |
57 | 59 | ||
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp index 78ae40988..b971a9eda 100644 --- a/libunwindstack/Android.bp +++ b/libunwindstack/Android.bp | |||
@@ -34,6 +34,7 @@ cc_defaults { | |||
34 | 34 | ||
35 | cc_library { | 35 | cc_library { |
36 | name: "libunwindstack", | 36 | name: "libunwindstack", |
37 | vendor_available: true, | ||
37 | defaults: ["libunwindstack_flags"], | 38 | defaults: ["libunwindstack_flags"], |
38 | export_include_dirs: ["include"], | 39 | export_include_dirs: ["include"], |
39 | 40 | ||
diff --git a/libunwindstack/include/unwindstack/MapInfo.h b/libunwindstack/include/unwindstack/MapInfo.h index 2a97dde09..185476799 100644 --- a/libunwindstack/include/unwindstack/MapInfo.h +++ b/libunwindstack/include/unwindstack/MapInfo.h | |||
@@ -41,6 +41,7 @@ struct MapInfo { | |||
41 | uint64_t elf_offset; | 41 | uint64_t elf_offset; |
42 | 42 | ||
43 | Memory* CreateMemory(pid_t pid); | 43 | Memory* CreateMemory(pid_t pid); |
44 | // This function guarantees it will never return nullptr. | ||
44 | Elf* GetElf(pid_t pid, bool init_gnu_debugdata = false); | 45 | Elf* GetElf(pid_t pid, bool init_gnu_debugdata = false); |
45 | }; | 46 | }; |
46 | 47 | ||