Bug 1196381 - Eliminate breakpad dependency in ThreadStackHelper; r=nfroyd r=snorp

The breakpad dependency in ThreadStackHelper is preventing us from
upgrading our in-tree copy to a newer version (bug 1069556). This patch
gets rid of that dependency. This makes native stack frames not work
for BHR, but because of the ftp.m.o decommissioning, native
symbolication was already broken and naive stack frames already don't
work, so we don't really lose anything from this patch.

Eventually we want to make ThreadStackHelper use other means of
unwinding, such as LUL for Linux

I added | #if 0 | around the code to fill the thread context, but left
the code in because I think we'll evenually want to reuse some of that
code.
This commit is contained in:
Jim Chen 2015-09-18 09:17:10 -04:00
parent b4389f1282
commit 5d85f6dea6
2 changed files with 6 additions and 164 deletions

View File

@ -22,22 +22,6 @@
#include "mozilla/MemoryChecking.h"
#include "mozilla/Snprintf.h"
#ifdef MOZ_THREADSTACKHELPER_NATIVE
#include "google_breakpad/processor/call_stack.h"
#include "google_breakpad/processor/basic_source_line_resolver.h"
#include "google_breakpad/processor/stack_frame_cpu.h"
#include "processor/basic_code_module.h"
#include "processor/basic_code_modules.h"
#endif
#if defined(MOZ_THREADSTACKHELPER_X86)
#include "processor/stackwalker_x86.h"
#elif defined(MOZ_THREADSTACKHELPER_X64)
#include "processor/stackwalker_amd64.h"
#elif defined(MOZ_THREADSTACKHELPER_ARM)
#include "processor/stackwalker_arm.h"
#endif
#if defined(MOZ_VALGRIND)
# include <valgrind/valgrind.h>
#endif
@ -287,67 +271,12 @@ ThreadStackHelper::GetStack(Stack& aStack)
}
#ifdef MOZ_THREADSTACKHELPER_NATIVE
class ThreadStackHelper::CodeModulesProvider
: public google_breakpad::CodeModules
{
private:
typedef google_breakpad::CodeModule CodeModule;
typedef google_breakpad::BasicCodeModule BasicCodeModule;
const SharedLibraryInfo mLibs;
mutable ScopedDeletePtr<BasicCodeModule> mModule;
public:
CodeModulesProvider() : mLibs(SharedLibraryInfo::GetInfoForSelf()) {}
virtual ~CodeModulesProvider() {}
virtual unsigned int module_count() const
{
return mLibs.GetSize();
}
virtual const CodeModule* GetModuleForAddress(uint64_t aAddress) const
{
MOZ_CRASH("Not implemented");
}
virtual const CodeModule* GetMainModule() const
{
return nullptr;
}
virtual const CodeModule* GetModuleAtSequence(unsigned int aSequence) const
{
MOZ_CRASH("Not implemented");
}
virtual const CodeModule* GetModuleAtIndex(unsigned int aIndex) const
{
const SharedLibrary& lib = mLibs.GetEntry(aIndex);
mModule = new BasicCodeModule(lib.GetStart(), lib.GetEnd() - lib.GetStart(),
lib.GetName(), lib.GetBreakpadId(),
lib.GetName(), lib.GetBreakpadId(), "");
// Keep mModule valid until the next GetModuleAtIndex call.
return mModule;
}
virtual const CodeModules* Copy() const
{
MOZ_CRASH("Not implemented");
}
};
class ThreadStackHelper::ThreadContext final
: public google_breakpad::MemoryRegion
{
public:
#if defined(MOZ_THREADSTACKHELPER_X86)
typedef MDRawContextX86 Context;
#elif defined(MOZ_THREADSTACKHELPER_X64)
typedef MDRawContextAMD64 Context;
#elif defined(MOZ_THREADSTACKHELPER_ARM)
typedef MDRawContextARM Context;
#endif
// TODO: provide per-platform definition of Context.
typedef struct {} Context;
// Limit copied stack to 4kB
static const size_t kMaxStackSize = 0x1000;
// Limit unwound stack to 32 frames
@ -370,38 +299,6 @@ public:
, mStackBase(0)
, mStackSize(0)
, mStackEnd(nullptr) {}
virtual ~ThreadContext() {}
virtual uint64_t GetBase() const { return uint64_t(mStackBase); }
virtual uint32_t GetSize() const { return mStackSize; }
virtual bool GetMemoryAtAddress(uint64_t aAddress, uint8_t* aValue) const
{
return GetMemoryAtAddressInternal(aAddress, aValue);
}
virtual bool GetMemoryAtAddress(uint64_t aAddress, uint16_t* aValue) const
{
return GetMemoryAtAddressInternal(aAddress, aValue);
}
virtual bool GetMemoryAtAddress(uint64_t aAddress, uint32_t* aValue) const
{
return GetMemoryAtAddressInternal(aAddress, aValue);
}
virtual bool GetMemoryAtAddress(uint64_t aAddress, uint64_t* aValue) const
{
return GetMemoryAtAddressInternal(aAddress, aValue);
}
private:
template<typename T>
bool GetMemoryAtAddressInternal(uint64_t aAddress, T* aValue) const
{
const intptr_t offset = intptr_t(aAddress) - intptr_t(GetBase());
if (offset < 0 || uintptr_t(offset) > (GetSize() - sizeof(T))) {
return false;
}
*aValue = *reinterpret_cast<const T*>(&mStack[offset]);
return true;
}
};
#endif // MOZ_THREADSTACKHELPER_NATIVE
@ -418,63 +315,7 @@ ThreadStackHelper::GetNativeStack(Stack& aStack)
GetStack(aStack);
NS_ENSURE_TRUE_VOID(context.mValid);
CodeModulesProvider modulesProvider;
google_breakpad::BasicCodeModules modules(&modulesProvider);
google_breakpad::BasicSourceLineResolver resolver;
google_breakpad::StackFrameSymbolizer symbolizer(nullptr, &resolver);
#if defined(MOZ_THREADSTACKHELPER_X86)
google_breakpad::StackwalkerX86 stackWalker(
nullptr, &context.mContext, &context, &modules, &symbolizer);
#elif defined(MOZ_THREADSTACKHELPER_X64)
google_breakpad::StackwalkerAMD64 stackWalker(
nullptr, &context.mContext, &context, &modules, &symbolizer);
#elif defined(MOZ_THREADSTACKHELPER_ARM)
google_breakpad::StackwalkerARM stackWalker(
nullptr, &context.mContext, -1, &context, &modules, &symbolizer);
#else
#error "Unsupported architecture"
#endif
google_breakpad::CallStack callStack;
std::vector<const google_breakpad::CodeModule*> modules_without_symbols;
google_breakpad::Stackwalker::set_max_frames(ThreadContext::kMaxStackFrames);
google_breakpad::Stackwalker::
set_max_frames_scanned(ThreadContext::kMaxStackFrames);
NS_ENSURE_TRUE_VOID(stackWalker.Walk(&callStack, &modules_without_symbols));
const std::vector<google_breakpad::StackFrame*>& frames(*callStack.frames());
for (intptr_t i = frames.size() - 1; i >= 0; i--) {
const google_breakpad::StackFrame& frame = *frames[i];
if (!frame.module) {
continue;
}
const string& module = frame.module->code_file();
#if defined(XP_LINUX) || defined(XP_MACOSX)
const char PATH_SEP = '/';
#elif defined(XP_WIN)
const char PATH_SEP = '\\';
#endif
const char* const module_basename = strrchr(module.c_str(), PATH_SEP);
const char* const module_name = module_basename ?
module_basename + 1 : module.c_str();
char buffer[0x100];
size_t len = 0;
if (!frame.function_name.empty()) {
len = snprintf_literal(buffer, "%s:%s",
module_name, frame.function_name.c_str());
} else {
len = snprintf_literal(buffer, "%s:0x%p", module_name,
(intptr_t)(frame.instruction -
frame.module->base_address()));
}
if (len) {
aStack.AppendViaBuffer(buffer, len);
}
}
// TODO: walk the saved stack frames.
#endif // MOZ_THREADSTACKHELPER_NATIVE
}
@ -707,6 +548,7 @@ ThreadStackHelper::FillThreadContext(void* aContext)
return;
}
#if 0 // TODO: remove dependency on Breakpad structs.
#if defined(XP_LINUX)
const ucontext_t& context = *reinterpret_cast<ucontext_t*>(aContext);
#if defined(MOZ_THREADSTACKHELPER_X86)
@ -864,6 +706,7 @@ ThreadStackHelper::FillThreadContext(void* aContext)
mContextToFill->mStackBase = uintptr_t(sp);
mContextToFill->mStackSize = stackSize;
mContextToFill->mValid = true;
#endif
#endif // MOZ_THREADSTACKHELPER_NATIVE
}

View File

@ -66,7 +66,6 @@ private:
#ifdef MOZ_THREADSTACKHELPER_PSEUDO
const PseudoStack* const mPseudoStack;
#ifdef MOZ_THREADSTACKHELPER_NATIVE
class CodeModulesProvider;
class ThreadContext;
// Set to non-null if GetStack should get the thread context.
ThreadContext* mContextToFill;