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

Side by Side Diff: xpcom/threads/ThreadStackHelper.cpp

Issue 29334661: Issue 3406 - [Adblock Browser for Android] Crash after updating to Android 6.0.1 (Closed)
Patch Set: Created Jan. 27, 2016, 10:19 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « widget/android/AndroidBridge.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
13 #ifdef MOZ_THREADSTACKHELPER_NATIVE 12 #ifdef MOZ_THREADSTACKHELPER_NATIVE
14 #include "shared-libraries.h" 13 #include "shared-libraries.h"
15 #endif 14 #endif
16 15
17 #include "mozilla/Assertions.h" 16 #include "mozilla/Assertions.h"
18 #include "mozilla/Attributes.h" 17 #include "mozilla/Attributes.h"
19 #include "mozilla/IntegerPrintfMacros.h" 18 #include "mozilla/IntegerPrintfMacros.h"
20 #include "mozilla/Move.h" 19 #include "mozilla/Move.h"
21 #include "mozilla/Scoped.h" 20 #include "mozilla/Scoped.h"
22 #include "mozilla/UniquePtr.h" 21 #include "mozilla/UniquePtr.h"
23 #include "mozilla/MemoryChecking.h" 22 #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"
39 #endif 28 #endif
40 29
41 #if defined(MOZ_VALGRIND) 30 #if defined(MOZ_VALGRIND)
42 # include <valgrind/valgrind.h> 31 # include <valgrind/valgrind.h>
43 #endif 32 #endif
44 33
45 #include <string.h> 34 #include <string.h>
46 #include <vector> 35 #include <vector>
36 #include <cstdlib>
47 37
48 #ifdef XP_LINUX 38 #ifdef XP_LINUX
49 #ifdef ANDROID 39 #ifdef ANDROID
50 // Android NDK doesn't contain ucontext.h; use Breakpad's copy. 40 // Android NDK doesn't contain ucontext.h; use Breakpad's copy.
51 # include "common/android/include/sys/ucontext.h" 41 # include "common/android/include/sys/ucontext.h"
52 #else 42 #else
53 # include <ucontext.h> 43 # include <ucontext.h>
54 #endif 44 #endif
55 #include <unistd.h> 45 #include <unistd.h>
56 #include <sys/syscall.h> 46 #include <sys/syscall.h>
57 #endif 47 #endif
58 48
49 #ifdef __GNUC__
50 # pragma GCC diagnostic pop // -Wshadow
51 #endif
52
59 #if defined(XP_LINUX) || defined(XP_MACOSX) 53 #if defined(XP_LINUX) || defined(XP_MACOSX)
60 #include <pthread.h> 54 #include <pthread.h>
61 #endif 55 #endif
62 56
63 #ifdef ANDROID 57 #ifdef ANDROID
64 #ifndef SYS_gettid 58 #ifndef SYS_gettid
65 #define SYS_gettid __NR_gettid 59 #define SYS_gettid __NR_gettid
66 #endif 60 #endif
67 #if defined(__arm__) && !defined(__NR_rt_tgsigqueueinfo) 61 #if defined(__arm__) && !defined(__NR_rt_tgsigqueueinfo)
68 // Some NDKs don't define this constant even though the kernel supports it. 62 // Some NDKs don't define this constant even though the kernel supports it.
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 namespace { 203 namespace {
210 template<typename T> 204 template<typename T>
211 class ScopedSetPtr 205 class ScopedSetPtr
212 { 206 {
213 private: 207 private:
214 T*& mPtr; 208 T*& mPtr;
215 public: 209 public:
216 ScopedSetPtr(T*& p, T* val) : mPtr(p) { mPtr = val; } 210 ScopedSetPtr(T*& p, T* val) : mPtr(p) { mPtr = val; }
217 ~ScopedSetPtr() { mPtr = nullptr; } 211 ~ScopedSetPtr() { mPtr = nullptr; }
218 }; 212 };
219 } 213 } // namespace
220 214
221 void 215 void
222 ThreadStackHelper::GetStack(Stack& aStack) 216 ThreadStackHelper::GetStack(Stack& aStack)
223 { 217 {
224 // Always run PrepareStackBuffer first to clear aStack 218 // Always run PrepareStackBuffer first to clear aStack
225 if (!PrepareStackBuffer(aStack)) { 219 if (!PrepareStackBuffer(aStack)) {
226 // Skip and return empty aStack 220 // Skip and return empty aStack
227 return; 221 return;
228 } 222 }
229 223
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 273
280 FillStackBuffer(); 274 FillStackBuffer();
281 FillThreadContext(); 275 FillThreadContext();
282 276
283 MOZ_ALWAYS_TRUE(::thread_resume(mThreadID) == KERN_SUCCESS); 277 MOZ_ALWAYS_TRUE(::thread_resume(mThreadID) == KERN_SUCCESS);
284 278
285 #endif 279 #endif
286 } 280 }
287 281
288 #ifdef MOZ_THREADSTACKHELPER_NATIVE 282 #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
339 class ThreadStackHelper::ThreadContext final 283 class ThreadStackHelper::ThreadContext final
340 : public google_breakpad::MemoryRegion
341 { 284 {
342 public: 285 public:
343 #if defined(MOZ_THREADSTACKHELPER_X86) 286 // TODO: provide per-platform definition of Context.
344 typedef MDRawContextX86 Context; 287 typedef struct {} Context;
345 #elif defined(MOZ_THREADSTACKHELPER_X64) 288
346 typedef MDRawContextAMD64 Context;
347 #elif defined(MOZ_THREADSTACKHELPER_ARM)
348 typedef MDRawContextARM Context;
349 #endif
350 // Limit copied stack to 4kB 289 // Limit copied stack to 4kB
351 static const size_t kMaxStackSize = 0x1000; 290 static const size_t kMaxStackSize = 0x1000;
352 // Limit unwound stack to 32 frames 291 // Limit unwound stack to 32 frames
353 static const unsigned int kMaxStackFrames = 32; 292 static const unsigned int kMaxStackFrames = 32;
354 // Whether this structure contains valid data 293 // Whether this structure contains valid data
355 bool mValid; 294 bool mValid;
356 // Processor context 295 // Processor context
357 Context mContext; 296 Context mContext;
358 // Stack area 297 // Stack area
359 UniquePtr<uint8_t[]> mStack; 298 UniquePtr<uint8_t[]> mStack;
360 // Start of stack area 299 // Start of stack area
361 uintptr_t mStackBase; 300 uintptr_t mStackBase;
362 // Size of stack area 301 // Size of stack area
363 size_t mStackSize; 302 size_t mStackSize;
364 // End of stack area 303 // End of stack area
365 const void* mStackEnd; 304 const void* mStackEnd;
366 305
367 ThreadContext() 306 ThreadContext()
368 : mValid(false) 307 : mValid(false)
369 , mStackBase(0) 308 , mStackBase(0)
370 , mStackSize(0) 309 , mStackSize(0)
371 , mStackEnd(nullptr) {} 310 , 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 }
404 }; 311 };
405 #endif // MOZ_THREADSTACKHELPER_NATIVE 312 #endif // MOZ_THREADSTACKHELPER_NATIVE
406 313
407 void 314 void
408 ThreadStackHelper::GetNativeStack(Stack& aStack) 315 ThreadStackHelper::GetNativeStack(Stack& aStack)
409 { 316 {
410 #ifdef MOZ_THREADSTACKHELPER_NATIVE 317 #ifdef MOZ_THREADSTACKHELPER_NATIVE
411 ThreadContext context; 318 ThreadContext context;
412 context.mStack = MakeUnique<uint8_t[]>(ThreadContext::kMaxStackSize); 319 context.mStack = MakeUnique<uint8_t[]>(ThreadContext::kMaxStackSize);
413 320
414 ScopedSetPtr<ThreadContext> contextPtr(mContextToFill, &context); 321 ScopedSetPtr<ThreadContext> contextPtr(mContextToFill, &context);
415 322
416 // Get pseudostack first and fill the thread context. 323 // Get pseudostack first and fill the thread context.
417 GetStack(aStack); 324 GetStack(aStack);
418 NS_ENSURE_TRUE_VOID(context.mValid); 325 NS_ENSURE_TRUE_VOID(context.mValid);
419 326
420 CodeModulesProvider modulesProvider; 327 // TODO: walk the saved stack frames.
421 google_breakpad::BasicCodeModules modules(&modulesProvider);
422 google_breakpad::BasicSourceLineResolver resolver;
423 google_breakpad::StackFrameSymbolizer symbolizer(nullptr, &resolver);
424
425 #if defined(MOZ_THREADSTACKHELPER_X86)
426 google_breakpad::StackwalkerX86 stackWalker(
427 nullptr, &context.mContext, &context, &modules, &symbolizer);
428 #elif defined(MOZ_THREADSTACKHELPER_X64)
429 google_breakpad::StackwalkerAMD64 stackWalker(
430 nullptr, &context.mContext, &context, &modules, &symbolizer);
431 #elif defined(MOZ_THREADSTACKHELPER_ARM)
432 google_breakpad::StackwalkerARM stackWalker(
433 nullptr, &context.mContext, -1, &context, &modules, &symbolizer);
434 #else
435 #error "Unsupported architecture"
436 #endif
437
438 google_breakpad::CallStack callStack;
439 std::vector<const google_breakpad::CodeModule*> modules_without_symbols;
440
441 google_breakpad::Stackwalker::set_max_frames(ThreadContext::kMaxStackFrames);
442 google_breakpad::Stackwalker::
443 set_max_frames_scanned(ThreadContext::kMaxStackFrames);
444
445 NS_ENSURE_TRUE_VOID(stackWalker.Walk(&callStack, &modules_without_symbols));
446
447 const std::vector<google_breakpad::StackFrame*>& frames(*callStack.frames());
448 for (intptr_t i = frames.size() - 1; i >= 0; i--) {
449 const google_breakpad::StackFrame& frame = *frames[i];
450 if (!frame.module) {
451 continue;
452 }
453 const string& module = frame.module->code_file();
454 #if defined(XP_LINUX) || defined(XP_MACOSX)
455 const char PATH_SEP = '/';
456 #elif defined(XP_WIN)
457 const char PATH_SEP = '\\';
458 #endif
459 const char* const module_basename = strrchr(module.c_str(), PATH_SEP);
460 const char* const module_name = module_basename ?
461 module_basename + 1 : module.c_str();
462
463 char buffer[0x100];
464 size_t len = 0;
465 if (!frame.function_name.empty()) {
466 len = PR_snprintf(buffer, sizeof(buffer), "%s:%s",
467 module_name, frame.function_name.c_str());
468 } else {
469 len = PR_snprintf(buffer, sizeof(buffer), "%s:0x%p",
470 module_name, (intptr_t)
471 (frame.instruction - frame.module->base_address()));
472 }
473 if (len) {
474 aStack.AppendViaBuffer(buffer, len);
475 }
476 }
477 #endif // MOZ_THREADSTACKHELPER_NATIVE 328 #endif // MOZ_THREADSTACKHELPER_NATIVE
478 } 329 }
479 330
480 #ifdef XP_LINUX 331 #ifdef XP_LINUX
481 332
482 int ThreadStackHelper::sInitialized; 333 int ThreadStackHelper::sInitialized;
483 int ThreadStackHelper::sFillStackSignum; 334 int ThreadStackHelper::sFillStackSignum;
484 335
485 void 336 void
486 ThreadStackHelper::FillStackHandler(int aSignal, siginfo_t* aInfo, 337 ThreadStackHelper::FillStackHandler(int aSignal, siginfo_t* aInfo,
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
604 } 455 }
605 if (!basename) { 456 if (!basename) {
606 // If the (add-on) script is located under the {profile}/extensions 457 // If the (add-on) script is located under the {profile}/extensions
607 // directory, extract the path after the /extensions/ part. 458 // directory, extract the path after the /extensions/ part.
608 basename = GetPathAfterComponent(filename, "/extensions/"); 459 basename = GetPathAfterComponent(filename, "/extensions/");
609 } 460 }
610 if (!basename) { 461 if (!basename) {
611 // Only keep the file base name for paths outside the above formats. 462 // Only keep the file base name for paths outside the above formats.
612 basename = strrchr(filename, '/'); 463 basename = strrchr(filename, '/');
613 basename = basename ? basename + 1 : filename; 464 basename = basename ? basename + 1 : filename;
465 // Look for Windows path separator as well.
466 filename = strrchr(basename, '\\');
467 if (filename) {
468 basename = filename + 1;
469 }
614 } 470 }
615 471
616 size_t len = PR_snprintf(buffer, sizeof(buffer), "%s:%u", basename, lineno); 472 size_t len = snprintf_literal(buffer, "%s:%u", basename, lineno);
617 if (len < sizeof(buffer)) { 473 if (len < sizeof(buffer)) {
618 if (mStackToFill->IsSameAsEntry(aPrevLabel, buffer)) { 474 if (mStackToFill->IsSameAsEntry(aPrevLabel, buffer)) {
619 return aPrevLabel; 475 return aPrevLabel;
620 } 476 }
621 477
622 // Keep track of the required buffer size 478 // Keep track of the required buffer size
623 aAvailableBufferSize -= (len + 1); 479 aAvailableBufferSize -= (len + 1);
624 if (aAvailableBufferSize >= 0) { 480 if (aAvailableBufferSize >= 0) {
625 // Buffer is big enough. 481 // Buffer is big enough.
626 return mStackToFill->InfallibleAppendViaBuffer(buffer, len); 482 return mStackToFill->InfallibleAppendViaBuffer(buffer, len);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
694 } 550 }
695 551
696 MOZ_ASAN_BLACKLIST void 552 MOZ_ASAN_BLACKLIST void
697 ThreadStackHelper::FillThreadContext(void* aContext) 553 ThreadStackHelper::FillThreadContext(void* aContext)
698 { 554 {
699 #ifdef MOZ_THREADSTACKHELPER_NATIVE 555 #ifdef MOZ_THREADSTACKHELPER_NATIVE
700 if (!mContextToFill) { 556 if (!mContextToFill) {
701 return; 557 return;
702 } 558 }
703 559
560 #if 0 // TODO: remove dependency on Breakpad structs.
704 #if defined(XP_LINUX) 561 #if defined(XP_LINUX)
705 const ucontext_t& context = *reinterpret_cast<ucontext_t*>(aContext); 562 const ucontext_t& context = *reinterpret_cast<ucontext_t*>(aContext);
706 #if defined(MOZ_THREADSTACKHELPER_X86) 563 #if defined(MOZ_THREADSTACKHELPER_X86)
707 mContextToFill->mContext.context_flags = MD_CONTEXT_X86_FULL; 564 mContextToFill->mContext.context_flags = MD_CONTEXT_X86_FULL;
708 mContextToFill->mContext.edi = context.uc_mcontext.gregs[REG_EDI]; 565 mContextToFill->mContext.edi = context.uc_mcontext.gregs[REG_EDI];
709 mContextToFill->mContext.esi = context.uc_mcontext.gregs[REG_ESI]; 566 mContextToFill->mContext.esi = context.uc_mcontext.gregs[REG_ESI];
710 mContextToFill->mContext.ebx = context.uc_mcontext.gregs[REG_EBX]; 567 mContextToFill->mContext.ebx = context.uc_mcontext.gregs[REG_EBX];
711 mContextToFill->mContext.edx = context.uc_mcontext.gregs[REG_EDX]; 568 mContextToFill->mContext.edx = context.uc_mcontext.gregs[REG_EDX];
712 mContextToFill->mContext.ecx = context.uc_mcontext.gregs[REG_ECX]; 569 mContextToFill->mContext.ecx = context.uc_mcontext.gregs[REG_ECX];
713 mContextToFill->mContext.eax = context.uc_mcontext.gregs[REG_EAX]; 570 mContextToFill->mContext.eax = context.uc_mcontext.gregs[REG_EAX];
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 intptr_t* dst = reinterpret_cast<intptr_t*>(&mContextToFill->mStack[0]); 708 intptr_t* dst = reinterpret_cast<intptr_t*>(&mContextToFill->mStack[0]);
852 const intptr_t* src = reinterpret_cast<intptr_t*>(sp); 709 const intptr_t* src = reinterpret_cast<intptr_t*>(sp);
853 for (intptr_t len = stackSize; len > 0; len -= sizeof(*src)) { 710 for (intptr_t len = stackSize; len > 0; len -= sizeof(*src)) {
854 *(dst++) = *(src++); 711 *(dst++) = *(src++);
855 } 712 }
856 #endif 713 #endif
857 714
858 mContextToFill->mStackBase = uintptr_t(sp); 715 mContextToFill->mStackBase = uintptr_t(sp);
859 mContextToFill->mStackSize = stackSize; 716 mContextToFill->mStackSize = stackSize;
860 mContextToFill->mValid = true; 717 mContextToFill->mValid = true;
718 #endif
861 #endif // MOZ_THREADSTACKHELPER_NATIVE 719 #endif // MOZ_THREADSTACKHELPER_NATIVE
862 } 720 }
863 721
864 } // namespace mozilla 722 } // namespace mozilla
723
OLDNEW
« no previous file with comments | « widget/android/AndroidBridge.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld