Skip to content

Commit 0f63959

Browse files
authored
Merge pull request #598 from Tencent/feature/dev
Fix arm32 exidx decode break.
2 parents 08b6965 + 7ae212c commit 0f63959

File tree

23 files changed

+212
-98
lines changed

23 files changed

+212
-98
lines changed

matrix/matrix-android/matrix-backtrace/src/main/cpp/libwechatbacktrace/Backtrace.cpp

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ namespace wechat_backtrace {
3434
QUT_EXTERN_C_BLOCK
3535

3636
static BacktraceMode backtrace_mode = FramePointer;
37+
static bool quicken_unwind_always_enabled = false;
3738

3839
#ifdef __aarch64__
3940
static const bool m_is_arm32 = false;
@@ -51,6 +52,11 @@ namespace wechat_backtrace {
5152
backtrace_mode = mode;
5253
}
5354

55+
BACKTRACE_EXPORT
56+
void set_quicken_always_enable(bool enable) {
57+
quicken_unwind_always_enabled = enable;
58+
}
59+
5460
BACKTRACE_EXPORT void
5561
BACKTRACE_FUNC_WRAPPER(restore_frame_detail)(const Frame *frames, const size_t frame_size,
5662
const std::function<void(
@@ -240,31 +246,24 @@ namespace wechat_backtrace {
240246
WeChatQuickenUnwind(CURRENT_ARCH, regs, frame_max_size, frames, frame_size);
241247
}
242248

243-
void
249+
inline void
244250
quicken_based_unwind_inlined(Frame *frames, const size_t max_frames,
245251
size_t &frame_size) {
246252
uptr regs[QUT_MINIMAL_REG_SIZE];
247253
GetQuickenMinimalRegs(regs);
248254
WeChatQuickenUnwind(CURRENT_ARCH, regs, max_frames, frames, frame_size);
249255
}
250256

251-
252-
BACKTRACE_EXPORT void
253-
BACKTRACE_FUNC_WRAPPER(quicken_based_unwind)(Frame *frames, const size_t max_frames,
254-
size_t &frame_size) {
255-
quicken_based_unwind_inlined(frames, max_frames, frame_size);
256-
}
257-
258-
BACKTRACE_EXPORT inline void
259-
BACKTRACE_FUNC_WRAPPER(fp_based_unwind)(Frame *frames, const size_t max_frames,
260-
size_t &frame_size) {
257+
inline void
258+
fp_based_unwind_inlined(Frame *frames, const size_t max_frames,
259+
size_t &frame_size) {
261260
uptr regs[FP_MINIMAL_REG_SIZE];
262261
GetFramePointerMinimalRegs(regs);
263262
FpUnwind(regs, frames, max_frames, frame_size);
264263
}
265264

266-
BACKTRACE_EXPORT inline void
267-
BACKTRACE_FUNC_WRAPPER(dwarf_based_unwind)(Frame *frames, const size_t max_frames,
265+
inline void
266+
dwarf_based_unwind_inlined(Frame *frames, const size_t max_frames,
268267
size_t &frame_size) {
269268
std::vector<unwindstack::FrameData> dst;
270269
unwindstack::RegsArm regs;
@@ -281,35 +280,48 @@ namespace wechat_backtrace {
281280
frame_size = dst.size();
282281
}
283282

283+
BACKTRACE_EXPORT void
284+
BACKTRACE_FUNC_WRAPPER(quicken_based_unwind)(Frame *frames, const size_t max_frames,
285+
size_t &frame_size) {
286+
quicken_based_unwind_inlined(frames, max_frames, frame_size);
287+
}
288+
289+
BACKTRACE_EXPORT void
290+
BACKTRACE_FUNC_WRAPPER(fp_based_unwind)(Frame *frames, const size_t max_frames,
291+
size_t &frame_size) {
292+
fp_based_unwind_inlined(frames, max_frames, frame_size);
293+
}
294+
295+
BACKTRACE_EXPORT void
296+
BACKTRACE_FUNC_WRAPPER(dwarf_based_unwind)(Frame *frames, const size_t max_frames,
297+
size_t &frame_size) {
298+
dwarf_based_unwind_inlined(frames, max_frames, frame_size);
299+
}
300+
284301
BACKTRACE_EXPORT void
285302
BACKTRACE_FUNC_WRAPPER(unwind_adapter)(Frame *frames, const size_t max_frames,
286303
size_t &frame_size) {
287304

288305
switch (get_backtrace_mode()) {
289306
case FramePointer:
290-
fp_based_unwind(frames, max_frames, frame_size);
307+
fp_based_unwind_inlined(frames, max_frames, frame_size);
291308
break;
292309
case Quicken:
293310
quicken_based_unwind_inlined(frames, max_frames, frame_size);
294311
break;
295312
case DwarfBased:
296-
dwarf_based_unwind(frames, max_frames, frame_size);
313+
dwarf_based_unwind_inlined(frames, max_frames, frame_size);
297314
break;
298315
}
299316
}
300317

301318
BACKTRACE_EXPORT void BACKTRACE_FUNC_WRAPPER(notify_maps_changed)() {
302-
303-
switch (backtrace_mode) {
304-
case DwarfBased:
305-
wechat_backtrace::UpdateLocalMaps();
306-
break;
307-
case Quicken:
308-
// Parse quicken maps
309-
wechat_backtrace::Maps::Parse();
310-
break;
311-
default:
312-
break;
319+
if (backtrace_mode == DwarfBased) {
320+
wechat_backtrace::UpdateLocalMaps();
321+
}
322+
if (quicken_unwind_always_enabled || backtrace_mode == Quicken) {
323+
// Parse quicken maps
324+
wechat_backtrace::Maps::Parse();
313325
}
314326
}
315327

matrix/matrix-android/matrix-backtrace/src/main/cpp/libwechatbacktrace/QuickenInMemory.cpp

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,22 @@ namespace wechat_backtrace {
4444
return false;
4545
}
4646

47+
QUT_LOG("ExidxDecoderHelper::FindEntry pc %llx, total_entries_ %llx, start_offset_ %llx",
48+
(ullint_t) pc, (ullint_t) total_entries_, (ullint_t) start_offset_);
4749
size_t first = 0;
4850
size_t last = total_entries_;
4951
uint32_t addr;
5052
while (first < last) {
5153
size_t current = (first + last) / 2;
52-
if (GetAddr(current, &addr)) {
54+
if (!GetAddr(current, &addr)) {
5355
return false;
5456
}
5557
if (pc == addr) {
5658
*entry_offset = start_offset_ + current * 8;
5759
*start_addr = addr;
5860
if (last >= total_entries_ || !GetAddr(current + 1, end_addr)) {
5961
*end_addr = INT32_MAX;
62+
return false;
6063
}
6164
return true;
6265
}
@@ -68,9 +71,18 @@ namespace wechat_backtrace {
6871
}
6972
if (last != 0) {
7073
*entry_offset = start_offset_ + (last - 1) * 8;
71-
*start_addr = addr;
74+
if (pc > addr) {
75+
*start_addr = addr;
76+
} else {
77+
if (!GetAddr(last - 1, start_addr)) {
78+
*start_addr = INT32_MAX;
79+
return false;
80+
}
81+
}
82+
7283
if (last >= total_entries_ || !GetAddr(last, end_addr)) {
7384
*end_addr = INT32_MAX;
85+
return false;
7486
}
7587
return true;
7688
}
@@ -109,13 +121,17 @@ namespace wechat_backtrace {
109121
uint32_t start_addr;
110122
uint32_t end_addr;
111123

112-
FindEntry(pc, &entry_offset, &start_addr, &end_addr);
124+
bool ret = FindEntry(pc, &entry_offset, &start_addr, &end_addr);
125+
126+
QUT_LOG("QuickenInMemory::DecodeEntry pc %llx, entry_offset %llx, "
127+
"start_addr %llx, end_addr %llx, ret: %d",
128+
(ullint_t) pc, (ullint_t) entry_offset,
129+
(ullint_t) start_addr, (ullint_t) end_addr, ret);
113130

114131
*pc_start = start_addr;
115132
*pc_end = end_addr;
116133

117134
ExidxDecoder decoder(memory_, process_memory_);
118-
119135
// Extract data, evaluate instructions and re-encode it.
120136
if (decoder.ExtractEntryData(entry_offset) && decoder.Eval()) {
121137
(*instructions)[start_addr] = std::make_pair(start_addr, move(decoder.instructions_));
@@ -155,9 +171,11 @@ namespace wechat_backtrace {
155171
FrameInfo eh_frame_info,
156172
std::unique_ptr<DwarfSectionDecoder<AddressType>> &eh_frame_) {
157173
{ // eh_frame & eh_frame_hdr
158-
QUT_LOG("QuickenInMemory::InitEhFrame memory %llx, eh_frame_hdr_info.size_ %llx "
174+
QUT_LOG("QuickenInMemory::InitEhFrame memory %llx, eh_frame_hdr_info.offset_ %llx, "
175+
"eh_frame_hdr_info.size_ %llx, eh_frame_info.offset_ %llx, "
159176
"eh_frame_info.size_ %llx",
160-
(ullint_t) memory, (ullint_t) eh_frame_hdr_info.size_,
177+
(ullint_t) memory, (ullint_t) eh_frame_hdr_info.offset_,
178+
(ullint_t) eh_frame_hdr_info.size_, (ullint_t) eh_frame_info.offset_,
161179
(ullint_t) eh_frame_info.size_);
162180
if (memory != nullptr && eh_frame_hdr_info.offset_ != 0) {
163181

@@ -224,10 +242,11 @@ namespace wechat_backtrace {
224242
eh_frame_from_gnu_debug_data_);
225243
}
226244

227-
QUT_LOG("QuickenInMemory::Init elf %s, %llx, %llx, %llx, %llx", elf_wrapper->GetSoname().c_str(),
245+
QUT_LOG("QuickenInMemory::Init elf %s, %llx, %llx, %llx, %llx, exidx %llx", elf_wrapper->GetSoname().c_str(),
228246
(ullint_t) debug_frame_.get(), (ullint_t) eh_frame_.get(),
229247
(ullint_t) debug_frame_from_gnu_debug_data_.get(),
230-
(ullint_t) eh_frame_from_gnu_debug_data_.get());
248+
(ullint_t) eh_frame_from_gnu_debug_data_.get(),
249+
(ullint_t) arm_exidx_info.size_);
231250

232251
if (arm_exidx_info.size_ > 0) {
233252
exidx_decoder_ = std::make_unique<ExidxDecoderHelper>(memory, process_memory.get());
@@ -246,7 +265,7 @@ namespace wechat_backtrace {
246265
for (const auto &it : qut_in_memory_) {
247266
(void) it;
248267
QUT_LOG("GetFutSectionsInMemory dump cache qut [%llx, %llx]",
249-
it.second->pc_start, it.second->pc_end);
268+
(ullint_t) it.second->pc_start, (ullint_t) it.second->pc_end);
250269
}
251270
}
252271

@@ -258,7 +277,7 @@ namespace wechat_backtrace {
258277
}
259278

260279
QUT_LOG("GetFutSectionsInMemory found cache qut pc %llx in range of fde[%llx, %llx]",
261-
pc, it->second->pc_start, it->second->pc_end);
280+
(ullint_t) pc, (ullint_t) it->second->pc_start, (ullint_t) it->second->pc_end);
262281
if (pc >= it->second->pc_start && pc <= it->second->pc_end) {
263282
fut_sections = it->second;
264283
return true;
@@ -276,7 +295,7 @@ namespace wechat_backtrace {
276295
if (log) {
277296
for (size_t i = 0; i < fut_sections->idx_size; i += 1) {
278297
QUT_LOG("GetFutSectionsInMemory dump fut sections -> %llx",
279-
fut_sections->quidx[i]);
298+
(ullint_t) fut_sections->quidx[i]);
280299
}
281300
}
282301

@@ -335,7 +354,7 @@ namespace wechat_backtrace {
335354

336355
if (ret) {
337356
QUT_LOG("GetFutSectionsInMemory found pc %llx in range of fde[%llx, %llx]", pc,
338-
fde->pc_start, fde->pc_end);
357+
(ullint_t) fde->pc_start, (ullint_t) fde->pc_end);
339358
fut_sections = fut_sections_sp;
340359
UpdateCache(fde->pc_start, fde->pc_end, fut_sections);
341360
return true;
@@ -352,7 +371,7 @@ namespace wechat_backtrace {
352371
return true;
353372
}
354373

355-
QUT_LOG("GetFutSectionsInMemory miss cache qut pc %llx", pc);
374+
QUT_LOG("GetFutSectionsInMemory miss cache qut pc %llx", (ullint_t) pc);
356375

357376
uint64_t pc_start = 0;
358377
uint64_t pc_end = 0;
@@ -391,11 +410,11 @@ namespace wechat_backtrace {
391410
}
392411
}
393412

394-
QUT_LOG("GetFutSectionsInMemory get fde -> %llx, pc -> %llx.", fde, pc);
413+
QUT_LOG("GetFutSectionsInMemory get fde -> %llx, pc -> %llx.", (ullint_t) fde, (ullint_t) pc);
395414

396415
if (fde) {
397416
if (UNLIKELY(decoder == nullptr)) {
398-
QUT_LOG("GetFutSectionsInMemory get null decoder, pc -> %llx.", pc);
417+
QUT_LOG("GetFutSectionsInMemory get null decoder, pc -> %llx.", (ullint_t) pc);
399418
return false;
400419
}
401420

@@ -417,14 +436,14 @@ namespace wechat_backtrace {
417436
ret = generator.PackEntriesToQutSections(instructions.get(),
418437
fut_sections_sp.get());
419438
} else {
420-
QUT_LOG("GetFutSectionsInMemory decode exidx failed, pc -> %llx.", pc);
439+
QUT_LOG("GetFutSectionsInMemory decode exidx failed, pc -> %llx.",(ullint_t) pc);
421440
}
422441
}
423442
}
424443

425444
if (ret) {
426-
QUT_LOG("GetFutSectionsInMemory found pc %llx in range of fde[%llx, %llx]", pc,
427-
pc_start, pc_end);
445+
QUT_LOG("GetFutSectionsInMemory found pc %llx in range of fde[%llx, %llx]",(ullint_t) pc,
446+
(ullint_t) pc_start, (ullint_t) pc_end);
428447
fut_sections = fut_sections_sp;
429448
UpdateCache(pc_start, pc_end, fut_sections);
430449
return true;

matrix/matrix-android/matrix-backtrace/src/main/cpp/libwechatbacktrace/QuickenInterface.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ namespace wechat_backtrace {
229229
}
230230
if (quicken_in_memory) {
231231
QUT_LOG("QuickenInterface::Step using quicken_in_memory_, elf: %s, frame: %llu",
232-
soname_.c_str(), frame_size);
232+
soname_.c_str(), (ullint_t) frame_size);
233233
std::shared_ptr<QutSectionsInMemory> qut_section_in_memory;
234234
bool ret = quicken_in_memory->GetFutSectionsInMemory(
235235
pc, /* out */ qut_section_in_memory);

matrix/matrix-android/matrix-backtrace/src/main/cpp/libwechatbacktrace/QuickenJNI.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,13 @@ namespace wechat_backtrace {
135135
set_backtrace_mode(static_cast<BacktraceMode>(mode));
136136
}
137137

138+
static void JNI_SetQuickenAlwaysOn(JNIEnv *env, jclass clazz, jboolean enable) {
139+
(void) env;
140+
(void) clazz;
141+
142+
set_quicken_always_enable(enable);
143+
}
144+
138145
static void JNI_SetImmediateGeneration(JNIEnv *env, jclass clazz, jboolean immediate) {
139146
(void) env;
140147
(void) clazz;
@@ -200,6 +207,7 @@ namespace wechat_backtrace {
200207
{"consumeRequestedQut", "()[Ljava/lang/String;", (void *) JNI_ConsumeRequestedQut},
201208
{"warmUp", "(Ljava/lang/String;IZ)Z", (void *) JNI_WarmUp},
202209
{"setBacktraceMode", "(I)V", (void *) JNI_SetBacktraceMode},
210+
{"setQuickenAlwaysOn", "(Z)V", (void *) JNI_SetQuickenAlwaysOn},
203211
{"statistic", "(Ljava/lang/String;)[I", (void *) JNI_Statistic},
204212
{"immediateGeneration", "(Z)V", (void *) JNI_SetImmediateGeneration},
205213
{"notifyWarmedUp", "(Ljava/lang/String;I)V", (void *) JNI_NotifyWarmedUp},

matrix/matrix-android/matrix-backtrace/src/main/cpp/libwechatbacktrace/QuickenMemory.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <unwindstack/Elf.h>
3333
#include <BacktraceDefine.h>
3434
#include "QuickenMemory.h"
35+
#include "MemoryLocal.h"
3536

3637
namespace wechat_backtrace {
3738

matrix/matrix-android/matrix-backtrace/src/main/cpp/libwechatbacktrace/QuickenUnwinder.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,15 @@
3030
#include <jni.h>
3131
#include <QuickenUtility.h>
3232
#include <QuickenMemory.h>
33-
#include "MemoryLocal.h"
3433
#include "QuickenUnwinder.h"
3534
#include "QuickenMaps.h"
3635

3736
#include "android-base/macros.h"
3837
#include "Log.h"
3938
#include "PthreadExt.h"
4039

40+
#include "MemoryLocal.h"
41+
4142
#define WECHAT_BACKTRACE_TAG "WeChatBacktrace"
4243

4344
namespace wechat_backtrace {
@@ -46,15 +47,19 @@ namespace wechat_backtrace {
4647
using namespace unwindstack;
4748

4849
QUT_EXTERN_C_BLOCK
49-
5050
DEFINE_STATIC_LOCAL(shared_ptr<Memory>, process_memory_, (new MemoryLocal));
51-
52-
DEFINE_STATIC_LOCAL(mutex, generate_lock_,);
51+
DEFINE_STATIC_LOCAL(shared_ptr<Memory>, process_memory_unsafe_, (new QuickenMemoryLocal));
5352

5453
BACKTRACE_EXPORT shared_ptr<Memory> &GetLocalProcessMemory() {
5554
return process_memory_;
5655
}
5756

57+
BACKTRACE_EXPORT shared_ptr<Memory> &GetUnsafeLocalProcessMemory() {
58+
return process_memory_unsafe_;
59+
}
60+
61+
DEFINE_STATIC_LOCAL(mutex, generate_lock_,);
62+
5863
void
5964
StatisticWeChatQuickenUnwindTable(const string &sopath, vector<uint32_t> &processed_result) {
6065

@@ -265,7 +270,7 @@ namespace wechat_backtrace {
265270
}
266271

267272
inline uint32_t
268-
GetPcAdjustment(Memory *process_memory, MapInfoPtr map_info, uint64_t pc, uint32_t rel_pc,
273+
GetPcAdjustment(MapInfoPtr map_info, uint64_t pc, uint32_t rel_pc,
269274
uint32_t load_bias) {
270275
if (UNLIKELY(rel_pc < load_bias)) {
271276
if (rel_pc < 2) {
@@ -285,10 +290,10 @@ namespace wechat_backtrace {
285290
// This is a thumb instruction, it could be 2 or 4 bytes.
286291
uint32_t value;
287292
uint64_t adjusted_pc = pc - 5;
288-
if (!(map_info->flags & PROT_READ) ||
293+
if (!(map_info->flags & PROT_READ || map_info->flags & PROT_EXEC) ||
289294
adjusted_pc < map_info->start ||
290295
(adjusted_pc + sizeof(value)) >= map_info->end ||
291-
!process_memory->ReadFully(adjusted_pc, &value, sizeof(value)) ||
296+
!process_memory_unsafe_->ReadFully(adjusted_pc, &value, sizeof(value)) ||
292297
(value & 0xe000f000) != 0xe000f000) {
293298
return 2;
294299
}
@@ -356,7 +361,7 @@ namespace wechat_backtrace {
356361
uint64_t step_pc = rel_pc;
357362

358363
if (adjust_pc) {
359-
pc_adjustment = GetPcAdjustment(process_memory_.get(), map_info, PC(regs), rel_pc,
364+
pc_adjustment = GetPcAdjustment(map_info, PC(regs), rel_pc,
360365
last_load_bias);
361366
} else {
362367
pc_adjustment = 0;

0 commit comments

Comments
 (0)