Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: xpcom/threads/ThreadStackHelper.cpp

Issue 29334661: Issue 3406 - [Adblock Browser for Android] Crash after updating to Android 6.0.1 (Closed)
Left Patch Set: Created Jan. 27, 2016, 10:19 a.m.
Right Patch Set: Only removing native stack frame code now Created Jan. 27, 2016, 10:23 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « widget/android/AndroidBridge.cpp ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public 3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 6
7 #include "ThreadStackHelper.h" 7 #include "ThreadStackHelper.h"
8 #include "MainThreadUtils.h" 8 #include "MainThreadUtils.h"
9 #include "nsJSPrincipals.h" 9 #include "nsJSPrincipals.h"
10 #include "nsScriptSecurityManager.h" 10 #include "nsScriptSecurityManager.h"
11 #include "jsfriendapi.h" 11 #include "jsfriendapi.h"
12 #include "prprf.h"
12 #ifdef MOZ_THREADSTACKHELPER_NATIVE 13 #ifdef MOZ_THREADSTACKHELPER_NATIVE
13 #include "shared-libraries.h" 14 #include "shared-libraries.h"
14 #endif 15 #endif
15 16
16 #include "mozilla/Assertions.h" 17 #include "mozilla/Assertions.h"
17 #include "mozilla/Attributes.h" 18 #include "mozilla/Attributes.h"
18 #include "mozilla/IntegerPrintfMacros.h" 19 #include "mozilla/IntegerPrintfMacros.h"
19 #include "mozilla/Move.h" 20 #include "mozilla/Move.h"
20 #include "mozilla/Scoped.h" 21 #include "mozilla/Scoped.h"
21 #include "mozilla/UniquePtr.h" 22 #include "mozilla/UniquePtr.h"
22 #include "mozilla/MemoryChecking.h" 23 #include "mozilla/MemoryChecking.h"
23 #include "mozilla/Snprintf.h" 24
24 25 #ifdef MOZ_THREADSTACKHELPER_NATIVE
25 #ifdef __GNUC__ 26 #include "google_breakpad/processor/call_stack.h"
26 # pragma GCC diagnostic push 27 #include "google_breakpad/processor/basic_source_line_resolver.h"
27 # pragma GCC diagnostic ignored "-Wshadow" 28 #include "google_breakpad/processor/stack_frame_cpu.h"
29 #include "processor/basic_code_module.h"
30 #include "processor/basic_code_modules.h"
31 #endif
32
33 #if defined(MOZ_THREADSTACKHELPER_X86)
34 #include "processor/stackwalker_x86.h"
35 #elif defined(MOZ_THREADSTACKHELPER_X64)
36 #include "processor/stackwalker_amd64.h"
37 #elif defined(MOZ_THREADSTACKHELPER_ARM)
38 #include "processor/stackwalker_arm.h"
28 #endif 39 #endif
29 40
30 #if defined(MOZ_VALGRIND) 41 #if defined(MOZ_VALGRIND)
31 # include <valgrind/valgrind.h> 42 # include <valgrind/valgrind.h>
32 #endif 43 #endif
33 44
34 #include <string.h> 45 #include <string.h>
35 #include <vector> 46 #include <vector>
36 #include <cstdlib>
37 47
38 #ifdef XP_LINUX 48 #ifdef XP_LINUX
39 #ifdef ANDROID 49 #ifdef ANDROID
40 // Android NDK doesn't contain ucontext.h; use Breakpad's copy. 50 // Android NDK doesn't contain ucontext.h; use Breakpad's copy.
41 # include "common/android/include/sys/ucontext.h" 51 # include "common/android/include/sys/ucontext.h"
42 #else 52 #else
43 # include <ucontext.h> 53 # include <ucontext.h>
44 #endif 54 #endif
45 #include <unistd.h> 55 #include <unistd.h>
46 #include <sys/syscall.h> 56 #include <sys/syscall.h>
47 #endif
48
49 #ifdef __GNUC__
50 # pragma GCC diagnostic pop // -Wshadow
51 #endif 57 #endif
52 58
53 #if defined(XP_LINUX) || defined(XP_MACOSX) 59 #if defined(XP_LINUX) || defined(XP_MACOSX)
54 #include <pthread.h> 60 #include <pthread.h>
55 #endif 61 #endif
56 62
57 #ifdef ANDROID 63 #ifdef ANDROID
58 #ifndef SYS_gettid 64 #ifndef SYS_gettid
59 #define SYS_gettid __NR_gettid 65 #define SYS_gettid __NR_gettid
60 #endif 66 #endif
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 namespace { 209 namespace {
204 template<typename T> 210 template<typename T>
205 class ScopedSetPtr 211 class ScopedSetPtr
206 { 212 {
207 private: 213 private:
208 T*& mPtr; 214 T*& mPtr;
209 public: 215 public:
210 ScopedSetPtr(T*& p, T* val) : mPtr(p) { mPtr = val; } 216 ScopedSetPtr(T*& p, T* val) : mPtr(p) { mPtr = val; }
211 ~ScopedSetPtr() { mPtr = nullptr; } 217 ~ScopedSetPtr() { mPtr = nullptr; }
212 }; 218 };
213 } // namespace 219 }
214 220
215 void 221 void
216 ThreadStackHelper::GetStack(Stack& aStack) 222 ThreadStackHelper::GetStack(Stack& aStack)
217 { 223 {
218 // Always run PrepareStackBuffer first to clear aStack 224 // Always run PrepareStackBuffer first to clear aStack
219 if (!PrepareStackBuffer(aStack)) { 225 if (!PrepareStackBuffer(aStack)) {
220 // Skip and return empty aStack 226 // Skip and return empty aStack
221 return; 227 return;
222 } 228 }
223 229
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 279
274 FillStackBuffer(); 280 FillStackBuffer();
275 FillThreadContext(); 281 FillThreadContext();
276 282
277 MOZ_ALWAYS_TRUE(::thread_resume(mThreadID) == KERN_SUCCESS); 283 MOZ_ALWAYS_TRUE(::thread_resume(mThreadID) == KERN_SUCCESS);
278 284
279 #endif 285 #endif
280 } 286 }
281 287
282 #ifdef MOZ_THREADSTACKHELPER_NATIVE 288 #ifdef MOZ_THREADSTACKHELPER_NATIVE
289 class ThreadStackHelper::CodeModulesProvider
290 : public google_breakpad::CodeModules
291 {
292 private:
293 typedef google_breakpad::CodeModule CodeModule;
294 typedef google_breakpad::BasicCodeModule BasicCodeModule;
295
296 const SharedLibraryInfo mLibs;
297 mutable ScopedDeletePtr<BasicCodeModule> mModule;
298
299 public:
300 CodeModulesProvider() : mLibs(SharedLibraryInfo::GetInfoForSelf()) {}
301 virtual ~CodeModulesProvider() {}
302
303 virtual unsigned int module_count() const
304 {
305 return mLibs.GetSize();
306 }
307
308 virtual const CodeModule* GetModuleForAddress(uint64_t aAddress) const
309 {
310 MOZ_CRASH("Not implemented");
311 }
312
313 virtual const CodeModule* GetMainModule() const
314 {
315 return nullptr;
316 }
317
318 virtual const CodeModule* GetModuleAtSequence(unsigned int aSequence) const
319 {
320 MOZ_CRASH("Not implemented");
321 }
322
323 virtual const CodeModule* GetModuleAtIndex(unsigned int aIndex) const
324 {
325 const SharedLibrary& lib = mLibs.GetEntry(aIndex);
326 mModule = new BasicCodeModule(lib.GetStart(), lib.GetEnd() - lib.GetStart(),
327 lib.GetName(), lib.GetBreakpadId(),
328 lib.GetName(), lib.GetBreakpadId(), "");
329 // Keep mModule valid until the next GetModuleAtIndex call.
330 return mModule;
331 }
332
333 virtual const CodeModules* Copy() const
334 {
335 MOZ_CRASH("Not implemented");
336 }
337 };
338
283 class ThreadStackHelper::ThreadContext final 339 class ThreadStackHelper::ThreadContext final
340 : public google_breakpad::MemoryRegion
284 { 341 {
285 public: 342 public:
286 // TODO: provide per-platform definition of Context. 343 #if defined(MOZ_THREADSTACKHELPER_X86)
287 typedef struct {} Context; 344 typedef MDRawContextX86 Context;
288 345 #elif defined(MOZ_THREADSTACKHELPER_X64)
346 typedef MDRawContextAMD64 Context;
347 #elif defined(MOZ_THREADSTACKHELPER_ARM)
348 typedef MDRawContextARM Context;
349 #endif
289 // Limit copied stack to 4kB 350 // Limit copied stack to 4kB
290 static const size_t kMaxStackSize = 0x1000; 351 static const size_t kMaxStackSize = 0x1000;
291 // Limit unwound stack to 32 frames 352 // Limit unwound stack to 32 frames
292 static const unsigned int kMaxStackFrames = 32; 353 static const unsigned int kMaxStackFrames = 32;
293 // Whether this structure contains valid data 354 // Whether this structure contains valid data
294 bool mValid; 355 bool mValid;
295 // Processor context 356 // Processor context
296 Context mContext; 357 Context mContext;
297 // Stack area 358 // Stack area
298 UniquePtr<uint8_t[]> mStack; 359 UniquePtr<uint8_t[]> mStack;
299 // Start of stack area 360 // Start of stack area
300 uintptr_t mStackBase; 361 uintptr_t mStackBase;
301 // Size of stack area 362 // Size of stack area
302 size_t mStackSize; 363 size_t mStackSize;
303 // End of stack area 364 // End of stack area
304 const void* mStackEnd; 365 const void* mStackEnd;
305 366
306 ThreadContext() 367 ThreadContext()
307 : mValid(false) 368 : mValid(false)
308 , mStackBase(0) 369 , mStackBase(0)
309 , mStackSize(0) 370 , mStackSize(0)
310 , mStackEnd(nullptr) {} 371 , mStackEnd(nullptr) {}
372 virtual ~ThreadContext() {}
373
374 virtual uint64_t GetBase() const { return uint64_t(mStackBase); }
375 virtual uint32_t GetSize() const { return mStackSize; }
376 virtual bool GetMemoryAtAddress(uint64_t aAddress, uint8_t* aValue) const
377 {
378 return GetMemoryAtAddressInternal(aAddress, aValue);
379 }
380 virtual bool GetMemoryAtAddress(uint64_t aAddress, uint16_t* aValue) const
381 {
382 return GetMemoryAtAddressInternal(aAddress, aValue);
383 }
384 virtual bool GetMemoryAtAddress(uint64_t aAddress, uint32_t* aValue) const
385 {
386 return GetMemoryAtAddressInternal(aAddress, aValue);
387 }
388 virtual bool GetMemoryAtAddress(uint64_t aAddress, uint64_t* aValue) const
389 {
390 return GetMemoryAtAddressInternal(aAddress, aValue);
391 }
392
393 private:
394 template<typename T>
395 bool GetMemoryAtAddressInternal(uint64_t aAddress, T* aValue) const
396 {
397 const intptr_t offset = intptr_t(aAddress) - intptr_t(GetBase());
398 if (offset < 0 || uintptr_t(offset) > (GetSize() - sizeof(T))) {
399 return false;
400 }
401 *aValue = *reinterpret_cast<const T*>(&mStack[offset]);
402 return true;
403 }
311 }; 404 };
312 #endif // MOZ_THREADSTACKHELPER_NATIVE 405 #endif // MOZ_THREADSTACKHELPER_NATIVE
313 406
314 void 407 void
315 ThreadStackHelper::GetNativeStack(Stack& aStack) 408 ThreadStackHelper::GetNativeStack(Stack& aStack)
316 { 409 {
317 #ifdef MOZ_THREADSTACKHELPER_NATIVE 410 #ifdef MOZ_THREADSTACKHELPER_NATIVE
318 ThreadContext context; 411 ThreadContext context;
319 context.mStack = MakeUnique<uint8_t[]>(ThreadContext::kMaxStackSize); 412 context.mStack = MakeUnique<uint8_t[]>(ThreadContext::kMaxStackSize);
320 413
321 ScopedSetPtr<ThreadContext> contextPtr(mContextToFill, &context); 414 ScopedSetPtr<ThreadContext> contextPtr(mContextToFill, &context);
322 415
323 // Get pseudostack first and fill the thread context. 416 // Get pseudostack first and fill the thread context.
324 GetStack(aStack); 417 GetStack(aStack);
325 NS_ENSURE_TRUE_VOID(context.mValid); 418 NS_ENSURE_TRUE_VOID(context.mValid);
326 419
327 // TODO: walk the saved stack frames.
328 #endif // MOZ_THREADSTACKHELPER_NATIVE 420 #endif // MOZ_THREADSTACKHELPER_NATIVE
329 } 421 }
330 422
331 #ifdef XP_LINUX 423 #ifdef XP_LINUX
332 424
333 int ThreadStackHelper::sInitialized; 425 int ThreadStackHelper::sInitialized;
334 int ThreadStackHelper::sFillStackSignum; 426 int ThreadStackHelper::sFillStackSignum;
335 427
336 void 428 void
337 ThreadStackHelper::FillStackHandler(int aSignal, siginfo_t* aInfo, 429 ThreadStackHelper::FillStackHandler(int aSignal, siginfo_t* aInfo,
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 } 547 }
456 if (!basename) { 548 if (!basename) {
457 // If the (add-on) script is located under the {profile}/extensions 549 // If the (add-on) script is located under the {profile}/extensions
458 // directory, extract the path after the /extensions/ part. 550 // directory, extract the path after the /extensions/ part.
459 basename = GetPathAfterComponent(filename, "/extensions/"); 551 basename = GetPathAfterComponent(filename, "/extensions/");
460 } 552 }
461 if (!basename) { 553 if (!basename) {
462 // Only keep the file base name for paths outside the above formats. 554 // Only keep the file base name for paths outside the above formats.
463 basename = strrchr(filename, '/'); 555 basename = strrchr(filename, '/');
464 basename = basename ? basename + 1 : filename; 556 basename = basename ? basename + 1 : filename;
465 // Look for Windows path separator as well. 557 }
466 filename = strrchr(basename, '\\'); 558
467 if (filename) { 559 size_t len = PR_snprintf(buffer, sizeof(buffer), "%s:%u", basename, lineno);
468 basename = filename + 1;
469 }
470 }
471
472 size_t len = snprintf_literal(buffer, "%s:%u", basename, lineno);
473 if (len < sizeof(buffer)) { 560 if (len < sizeof(buffer)) {
474 if (mStackToFill->IsSameAsEntry(aPrevLabel, buffer)) { 561 if (mStackToFill->IsSameAsEntry(aPrevLabel, buffer)) {
475 return aPrevLabel; 562 return aPrevLabel;
476 } 563 }
477 564
478 // Keep track of the required buffer size 565 // Keep track of the required buffer size
479 aAvailableBufferSize -= (len + 1); 566 aAvailableBufferSize -= (len + 1);
480 if (aAvailableBufferSize >= 0) { 567 if (aAvailableBufferSize >= 0) {
481 // Buffer is big enough. 568 // Buffer is big enough.
482 return mStackToFill->InfallibleAppendViaBuffer(buffer, len); 569 return mStackToFill->InfallibleAppendViaBuffer(buffer, len);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
550 } 637 }
551 638
552 MOZ_ASAN_BLACKLIST void 639 MOZ_ASAN_BLACKLIST void
553 ThreadStackHelper::FillThreadContext(void* aContext) 640 ThreadStackHelper::FillThreadContext(void* aContext)
554 { 641 {
555 #ifdef MOZ_THREADSTACKHELPER_NATIVE 642 #ifdef MOZ_THREADSTACKHELPER_NATIVE
556 if (!mContextToFill) { 643 if (!mContextToFill) {
557 return; 644 return;
558 } 645 }
559 646
560 #if 0 // TODO: remove dependency on Breakpad structs.
561 #if defined(XP_LINUX) 647 #if defined(XP_LINUX)
562 const ucontext_t& context = *reinterpret_cast<ucontext_t*>(aContext); 648 const ucontext_t& context = *reinterpret_cast<ucontext_t*>(aContext);
563 #if defined(MOZ_THREADSTACKHELPER_X86) 649 #if defined(MOZ_THREADSTACKHELPER_X86)
564 mContextToFill->mContext.context_flags = MD_CONTEXT_X86_FULL; 650 mContextToFill->mContext.context_flags = MD_CONTEXT_X86_FULL;
565 mContextToFill->mContext.edi = context.uc_mcontext.gregs[REG_EDI]; 651 mContextToFill->mContext.edi = context.uc_mcontext.gregs[REG_EDI];
566 mContextToFill->mContext.esi = context.uc_mcontext.gregs[REG_ESI]; 652 mContextToFill->mContext.esi = context.uc_mcontext.gregs[REG_ESI];
567 mContextToFill->mContext.ebx = context.uc_mcontext.gregs[REG_EBX]; 653 mContextToFill->mContext.ebx = context.uc_mcontext.gregs[REG_EBX];
568 mContextToFill->mContext.edx = context.uc_mcontext.gregs[REG_EDX]; 654 mContextToFill->mContext.edx = context.uc_mcontext.gregs[REG_EDX];
569 mContextToFill->mContext.ecx = context.uc_mcontext.gregs[REG_ECX]; 655 mContextToFill->mContext.ecx = context.uc_mcontext.gregs[REG_ECX];
570 mContextToFill->mContext.eax = context.uc_mcontext.gregs[REG_EAX]; 656 mContextToFill->mContext.eax = context.uc_mcontext.gregs[REG_EAX];
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
708 intptr_t* dst = reinterpret_cast<intptr_t*>(&mContextToFill->mStack[0]); 794 intptr_t* dst = reinterpret_cast<intptr_t*>(&mContextToFill->mStack[0]);
709 const intptr_t* src = reinterpret_cast<intptr_t*>(sp); 795 const intptr_t* src = reinterpret_cast<intptr_t*>(sp);
710 for (intptr_t len = stackSize; len > 0; len -= sizeof(*src)) { 796 for (intptr_t len = stackSize; len > 0; len -= sizeof(*src)) {
711 *(dst++) = *(src++); 797 *(dst++) = *(src++);
712 } 798 }
713 #endif 799 #endif
714 800
715 mContextToFill->mStackBase = uintptr_t(sp); 801 mContextToFill->mStackBase = uintptr_t(sp);
716 mContextToFill->mStackSize = stackSize; 802 mContextToFill->mStackSize = stackSize;
717 mContextToFill->mValid = true; 803 mContextToFill->mValid = true;
718 #endif
719 #endif // MOZ_THREADSTACKHELPER_NATIVE 804 #endif // MOZ_THREADSTACKHELPER_NATIVE
720 } 805 }
721 806
722 } // namespace mozilla 807 } // namespace mozilla
723
LEFTRIGHT

Powered by Google App Engine
This is Rietveld