зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1492121 - MOZ_BASE_PROFILER may be defined in BaseProfiler.h to enable Base Profiler - r=njn
Added baseprofiler to mozglue/moz.build, so it will be built. However all cpp files are dependent on `MOZ_BASE_PROFILER`, which is currently not #defined by default (in public/BaseProfiler.h). Differential Revision: https://phabricator.services.mozilla.com/D33258 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
38eb2d609e
Коммит
494369648d
|
@ -22,34 +22,38 @@
|
||||||
* standard-layout rules in the former.
|
* standard-layout rules in the former.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "EHABIStackWalk.h"
|
#include "BaseProfiler.h"
|
||||||
|
|
||||||
#include "BaseProfilerSharedLibraries.h"
|
#ifdef MOZ_BASE_PROFILER
|
||||||
#include "platform.h"
|
|
||||||
|
|
||||||
#include "mozilla/Atomics.h"
|
# include "EHABIStackWalk.h"
|
||||||
#include "mozilla/Attributes.h"
|
|
||||||
#include "mozilla/DebugOnly.h"
|
|
||||||
#include "mozilla/EndianUtils.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
# include "BaseProfilerSharedLibraries.h"
|
||||||
#include <elf.h>
|
# include "platform.h"
|
||||||
#include <stdint.h>
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#ifndef PT_ARM_EXIDX
|
# include "mozilla/Atomics.h"
|
||||||
# define PT_ARM_EXIDX 0x70000001
|
# include "mozilla/Attributes.h"
|
||||||
#endif
|
# include "mozilla/DebugOnly.h"
|
||||||
|
# include "mozilla/EndianUtils.h"
|
||||||
|
|
||||||
|
# include <algorithm>
|
||||||
|
# include <elf.h>
|
||||||
|
# include <stdint.h>
|
||||||
|
# include <vector>
|
||||||
|
# include <string>
|
||||||
|
|
||||||
|
# ifndef PT_ARM_EXIDX
|
||||||
|
# define PT_ARM_EXIDX 0x70000001
|
||||||
|
# endif
|
||||||
|
|
||||||
// Bug 1082817: ICS B2G has a buggy linker that doesn't always ensure
|
// Bug 1082817: ICS B2G has a buggy linker that doesn't always ensure
|
||||||
// that the EXIDX is sorted by address, as the spec requires. So in
|
// that the EXIDX is sorted by address, as the spec requires. So in
|
||||||
// that case we build and sort an array of pointers into the index,
|
// that case we build and sort an array of pointers into the index,
|
||||||
// and binary-search that; otherwise, we search the index in place
|
// and binary-search that; otherwise, we search the index in place
|
||||||
// (avoiding the time and space overhead of the indirection).
|
// (avoiding the time and space overhead of the indirection).
|
||||||
#if defined(ANDROID_VERSION) && ANDROID_VERSION < 16
|
# if defined(ANDROID_VERSION) && ANDROID_VERSION < 16
|
||||||
# define HAVE_UNSORTED_EXIDX
|
# define HAVE_UNSORTED_EXIDX
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
@ -90,7 +94,7 @@ class EHState {
|
||||||
|
|
||||||
enum { R_SP = 13, R_LR = 14, R_PC = 15 };
|
enum { R_SP = 13, R_LR = 14, R_PC = 15 };
|
||||||
|
|
||||||
#ifdef HAVE_UNSORTED_EXIDX
|
# ifdef HAVE_UNSORTED_EXIDX
|
||||||
class EHEntryHandle {
|
class EHEntryHandle {
|
||||||
const EHEntry* mValue;
|
const EHEntry* mValue;
|
||||||
|
|
||||||
|
@ -102,13 +106,13 @@ class EHEntryHandle {
|
||||||
bool operator<(const EHEntryHandle& lhs, const EHEntryHandle& rhs) {
|
bool operator<(const EHEntryHandle& lhs, const EHEntryHandle& rhs) {
|
||||||
return lhs.value()->startPC.compute() < rhs.value()->startPC.compute();
|
return lhs.value()->startPC.compute() < rhs.value()->startPC.compute();
|
||||||
}
|
}
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
class EHTable {
|
class EHTable {
|
||||||
uint32_t mStartPC;
|
uint32_t mStartPC;
|
||||||
uint32_t mEndPC;
|
uint32_t mEndPC;
|
||||||
uint32_t mBaseAddress;
|
uint32_t mBaseAddress;
|
||||||
#ifdef HAVE_UNSORTED_EXIDX
|
# ifdef HAVE_UNSORTED_EXIDX
|
||||||
// In principle we should be able to binary-search the index section in
|
// In principle we should be able to binary-search the index section in
|
||||||
// place, but the ICS toolchain's linker is noncompliant and produces
|
// place, but the ICS toolchain's linker is noncompliant and produces
|
||||||
// indices that aren't entirely sorted (e.g., libc). So we have this:
|
// indices that aren't entirely sorted (e.g., libc). So we have this:
|
||||||
|
@ -119,13 +123,13 @@ class EHTable {
|
||||||
static const EHEntry* entryGet(EntryIterator aEntry) {
|
static const EHEntry* entryGet(EntryIterator aEntry) {
|
||||||
return aEntry->value();
|
return aEntry->value();
|
||||||
}
|
}
|
||||||
#else
|
# else
|
||||||
typedef const EHEntry* EntryIterator;
|
typedef const EHEntry* EntryIterator;
|
||||||
EntryIterator mEntriesBegin, mEntriesEnd;
|
EntryIterator mEntriesBegin, mEntriesEnd;
|
||||||
EntryIterator entriesBegin() const { return mEntriesBegin; }
|
EntryIterator entriesBegin() const { return mEntriesBegin; }
|
||||||
EntryIterator entriesEnd() const { return mEntriesEnd; }
|
EntryIterator entriesEnd() const { return mEntriesEnd; }
|
||||||
static const EHEntry* entryGet(EntryIterator aEntry) { return aEntry; }
|
static const EHEntry* entryGet(EntryIterator aEntry) { return aEntry; }
|
||||||
#endif
|
# endif
|
||||||
std::string mName;
|
std::string mName;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -330,9 +334,9 @@ bool EHInterp::unwind() {
|
||||||
checkStack();
|
checkStack();
|
||||||
while (!mFailed) {
|
while (!mFailed) {
|
||||||
uint8_t insn = next();
|
uint8_t insn = next();
|
||||||
#if DEBUG_EHABI_UNWIND
|
# if DEBUG_EHABI_UNWIND
|
||||||
LOG("unwind insn = %02x", (unsigned)insn);
|
LOG("unwind insn = %02x", (unsigned)insn);
|
||||||
#endif
|
# endif
|
||||||
// Try to put the common cases first.
|
// Try to put the common cases first.
|
||||||
|
|
||||||
// 00xxxxxx: vsp = vsp + (xxxxxx << 2) + 4
|
// 00xxxxxx: vsp = vsp + (xxxxxx << 2) + 4
|
||||||
|
@ -456,9 +460,9 @@ bool EHInterp::unwind() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// unhandled instruction
|
// unhandled instruction
|
||||||
#ifdef DEBUG_EHABI_UNWIND
|
# ifdef DEBUG_EHABI_UNWIND
|
||||||
LOG("Unhandled EHABI instruction 0x%02x", insn);
|
LOG("Unhandled EHABI instruction 0x%02x", insn);
|
||||||
#endif
|
# endif
|
||||||
mFailed = true;
|
mFailed = true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -501,12 +505,12 @@ const EHEntry* EHTable::lookup(uint32_t aPC) const {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
while (end - begin > 1) {
|
while (end - begin > 1) {
|
||||||
#ifdef EHABI_UNWIND_MORE_ASSERTS
|
# ifdef EHABI_UNWIND_MORE_ASSERTS
|
||||||
if (entryGet(end - 1)->startPC.compute() <
|
if (entryGet(end - 1)->startPC.compute() <
|
||||||
entryGet(begin)->startPC.compute()) {
|
entryGet(begin)->startPC.compute()) {
|
||||||
MOZ_CRASH("unsorted exidx");
|
MOZ_CRASH("unsorted exidx");
|
||||||
}
|
}
|
||||||
#endif
|
# endif
|
||||||
EntryIterator mid = begin + (end - begin) / 2;
|
EntryIterator mid = begin + (end - begin) / 2;
|
||||||
if (aPC < reinterpret_cast<uint32_t>(entryGet(mid)->startPC.compute()))
|
if (aPC < reinterpret_cast<uint32_t>(entryGet(mid)->startPC.compute()))
|
||||||
end = mid;
|
end = mid;
|
||||||
|
@ -516,22 +520,22 @@ const EHEntry* EHTable::lookup(uint32_t aPC) const {
|
||||||
return entryGet(begin);
|
return entryGet(begin);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MOZ_LITTLE_ENDIAN
|
# if MOZ_LITTLE_ENDIAN
|
||||||
static const unsigned char hostEndian = ELFDATA2LSB;
|
static const unsigned char hostEndian = ELFDATA2LSB;
|
||||||
#elif MOZ_BIG_ENDIAN
|
# elif MOZ_BIG_ENDIAN
|
||||||
static const unsigned char hostEndian = ELFDATA2MSB;
|
static const unsigned char hostEndian = ELFDATA2MSB;
|
||||||
#else
|
# else
|
||||||
# error "No endian?"
|
# error "No endian?"
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
// Async signal unsafe: std::vector::reserve, std::string copy ctor.
|
// Async signal unsafe: std::vector::reserve, std::string copy ctor.
|
||||||
EHTable::EHTable(const void* aELF, size_t aSize, const std::string& aName)
|
EHTable::EHTable(const void* aELF, size_t aSize, const std::string& aName)
|
||||||
: mStartPC(~0), // largest uint32_t
|
: mStartPC(~0), // largest uint32_t
|
||||||
mEndPC(0),
|
mEndPC(0),
|
||||||
#ifndef HAVE_UNSORTED_EXIDX
|
# ifndef HAVE_UNSORTED_EXIDX
|
||||||
mEntriesBegin(nullptr),
|
mEntriesBegin(nullptr),
|
||||||
mEntriesEnd(nullptr),
|
mEntriesEnd(nullptr),
|
||||||
#endif
|
# endif
|
||||||
mName(aName) {
|
mName(aName) {
|
||||||
const uint32_t fileHeaderAddr = reinterpret_cast<uint32_t>(aELF);
|
const uint32_t fileHeaderAddr = reinterpret_cast<uint32_t>(aELF);
|
||||||
|
|
||||||
|
@ -574,14 +578,14 @@ EHTable::EHTable(const void* aELF, size_t aSize, const std::string& aName)
|
||||||
reinterpret_cast<const EHEntry*>(mBaseAddress + exidxHdr->p_vaddr);
|
reinterpret_cast<const EHEntry*>(mBaseAddress + exidxHdr->p_vaddr);
|
||||||
const EHEntry* endTable = reinterpret_cast<const EHEntry*>(
|
const EHEntry* endTable = reinterpret_cast<const EHEntry*>(
|
||||||
mBaseAddress + exidxHdr->p_vaddr + exidxHdr->p_memsz);
|
mBaseAddress + exidxHdr->p_vaddr + exidxHdr->p_memsz);
|
||||||
#ifdef HAVE_UNSORTED_EXIDX
|
# ifdef HAVE_UNSORTED_EXIDX
|
||||||
mEntries.reserve(endTable - startTable);
|
mEntries.reserve(endTable - startTable);
|
||||||
for (const EHEntry* i = startTable; i < endTable; ++i) mEntries.push_back(i);
|
for (const EHEntry* i = startTable; i < endTable; ++i) mEntries.push_back(i);
|
||||||
std::sort(mEntries.begin(), mEntries.end());
|
std::sort(mEntries.begin(), mEntries.end());
|
||||||
#else
|
# else
|
||||||
mEntriesBegin = startTable;
|
mEntriesBegin = startTable;
|
||||||
mEntriesEnd = endTable;
|
mEntriesEnd = endTable;
|
||||||
#endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
mozilla::Atomic<const EHAddrSpace*> EHAddrSpace::sCurrent(nullptr);
|
mozilla::Atomic<const EHAddrSpace*> EHAddrSpace::sCurrent(nullptr);
|
||||||
|
@ -616,7 +620,7 @@ void EHAddrSpace::Update() {
|
||||||
}
|
}
|
||||||
|
|
||||||
EHState::EHState(const mcontext_t& context) {
|
EHState::EHState(const mcontext_t& context) {
|
||||||
#ifdef linux
|
# ifdef linux
|
||||||
mRegs[0] = context.arm_r0;
|
mRegs[0] = context.arm_r0;
|
||||||
mRegs[1] = context.arm_r1;
|
mRegs[1] = context.arm_r1;
|
||||||
mRegs[2] = context.arm_r2;
|
mRegs[2] = context.arm_r2;
|
||||||
|
@ -633,9 +637,11 @@ EHState::EHState(const mcontext_t& context) {
|
||||||
mRegs[13] = context.arm_sp;
|
mRegs[13] = context.arm_sp;
|
||||||
mRegs[14] = context.arm_lr;
|
mRegs[14] = context.arm_lr;
|
||||||
mRegs[15] = context.arm_pc;
|
mRegs[15] = context.arm_pc;
|
||||||
#else
|
# else
|
||||||
# error "Unhandled OS for ARM EHABI unwinding"
|
# error "Unhandled OS for ARM EHABI unwinding"
|
||||||
#endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // MOZ_BASE_PROFILER
|
||||||
|
|
|
@ -4,9 +4,13 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "PageInformation.h"
|
#include "BaseProfiler.h"
|
||||||
|
|
||||||
#include "BaseProfileJSONWriter.h"
|
#ifdef MOZ_BASE_PROFILER
|
||||||
|
|
||||||
|
# include "PageInformation.h"
|
||||||
|
|
||||||
|
# include "BaseProfileJSONWriter.h"
|
||||||
|
|
||||||
PageInformation::PageInformation(const nsID& aDocShellId,
|
PageInformation::PageInformation(const nsID& aDocShellId,
|
||||||
uint32_t aDocShellHistoryId,
|
uint32_t aDocShellHistoryId,
|
||||||
|
@ -35,3 +39,5 @@ size_t PageInformation::SizeOfIncludingThis(
|
||||||
mozilla::MallocSizeOf aMallocSizeOf) const {
|
mozilla::MallocSizeOf aMallocSizeOf) const {
|
||||||
return aMallocSizeOf(this);
|
return aMallocSizeOf(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // MOZ_BASE_PROFILER
|
||||||
|
|
|
@ -4,14 +4,18 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "ProfileBuffer.h"
|
#include "BaseProfiler.h"
|
||||||
|
|
||||||
#include "ProfilerMarker.h"
|
#ifdef MOZ_BASE_PROFILER
|
||||||
|
|
||||||
#include "jsfriendapi.h"
|
# include "ProfileBuffer.h"
|
||||||
#include "mozilla/MathAlgorithms.h"
|
|
||||||
#include "nsJSPrincipals.h"
|
# include "ProfilerMarker.h"
|
||||||
#include "nsScriptSecurityManager.h"
|
|
||||||
|
# include "jsfriendapi.h"
|
||||||
|
# include "mozilla/MathAlgorithms.h"
|
||||||
|
# include "nsJSPrincipals.h"
|
||||||
|
# include "nsScriptSecurityManager.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
|
||||||
|
@ -188,3 +192,5 @@ void ProfileBufferCollector::CollectProfilingStackFrame(
|
||||||
mBuf.CollectCodeLocation(label, dynamicString, aFrame.flags(), line, column,
|
mBuf.CollectCodeLocation(label, dynamicString, aFrame.flags(), line, column,
|
||||||
Some(aFrame.categoryPair()));
|
Some(aFrame.categoryPair()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // MOZ_BASE_PROFILER
|
||||||
|
|
|
@ -4,21 +4,25 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "ProfileBufferEntry.h"
|
#include "BaseProfiler.h"
|
||||||
|
|
||||||
#include "platform.h"
|
#ifdef MOZ_BASE_PROFILER
|
||||||
#include "ProfileBuffer.h"
|
|
||||||
|
|
||||||
#include "js/TrackedOptimizationInfo.h"
|
# include "ProfileBufferEntry.h"
|
||||||
#include "jsapi.h"
|
|
||||||
#include "jsfriendapi.h"
|
|
||||||
#include "mozilla/Logging.h"
|
|
||||||
#include "mozilla/Sprintf.h"
|
|
||||||
#include "mozilla/StackWalk.h"
|
|
||||||
#include "nsThreadUtils.h"
|
|
||||||
#include "nsXULAppAPI.h"
|
|
||||||
|
|
||||||
#include <ostream>
|
# include "platform.h"
|
||||||
|
# include "ProfileBuffer.h"
|
||||||
|
|
||||||
|
# include "js/TrackedOptimizationInfo.h"
|
||||||
|
# include "jsapi.h"
|
||||||
|
# include "jsfriendapi.h"
|
||||||
|
# include "mozilla/Logging.h"
|
||||||
|
# include "mozilla/Sprintf.h"
|
||||||
|
# include "mozilla/StackWalk.h"
|
||||||
|
# include "nsThreadUtils.h"
|
||||||
|
# include "nsXULAppAPI.h"
|
||||||
|
|
||||||
|
# include <ostream>
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
|
||||||
|
@ -887,12 +891,12 @@ class EntryGetter {
|
||||||
// Because this is a format entirely internal to the Profiler, any parsing
|
// Because this is a format entirely internal to the Profiler, any parsing
|
||||||
// error indicates a bug in the ProfileBuffer writing or the parser itself,
|
// error indicates a bug in the ProfileBuffer writing or the parser itself,
|
||||||
// or possibly flaky hardware.
|
// or possibly flaky hardware.
|
||||||
#define ERROR_AND_CONTINUE(msg) \
|
# define ERROR_AND_CONTINUE(msg) \
|
||||||
{ \
|
{ \
|
||||||
fprintf(stderr, "ProfileBuffer parse error: %s", msg); \
|
fprintf(stderr, "ProfileBuffer parse error: %s", msg); \
|
||||||
MOZ_ASSERT(false, msg); \
|
MOZ_ASSERT(false, msg); \
|
||||||
continue; \
|
continue; \
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfileBuffer::StreamSamplesToJSON(SpliceableJSONWriter& aWriter,
|
void ProfileBuffer::StreamSamplesToJSON(SpliceableJSONWriter& aWriter,
|
||||||
int aThreadId, double aSinceTime,
|
int aThreadId, double aSinceTime,
|
||||||
|
@ -1317,17 +1321,17 @@ void ProfileBuffer::StreamProfilerOverheadToJSON(
|
||||||
aWriter.DoubleProperty("overheadDurations", overheads.sum);
|
aWriter.DoubleProperty("overheadDurations", overheads.sum);
|
||||||
aWriter.DoubleProperty("overheadPercentage",
|
aWriter.DoubleProperty("overheadPercentage",
|
||||||
overheads.sum / (lastTime - firstTime));
|
overheads.sum / (lastTime - firstTime));
|
||||||
#define PROFILER_STATS(name, var) \
|
# define PROFILER_STATS(name, var) \
|
||||||
aWriter.DoubleProperty("mean" name, (var).sum / (var).n); \
|
aWriter.DoubleProperty("mean" name, (var).sum / (var).n); \
|
||||||
aWriter.DoubleProperty("min" name, (var).min); \
|
aWriter.DoubleProperty("min" name, (var).min); \
|
||||||
aWriter.DoubleProperty("max" name, (var).max);
|
aWriter.DoubleProperty("max" name, (var).max);
|
||||||
PROFILER_STATS("Interval", intervals);
|
PROFILER_STATS("Interval", intervals);
|
||||||
PROFILER_STATS("Overhead", overheads);
|
PROFILER_STATS("Overhead", overheads);
|
||||||
PROFILER_STATS("Lockings", lockings);
|
PROFILER_STATS("Lockings", lockings);
|
||||||
PROFILER_STATS("Cleaning", cleanings);
|
PROFILER_STATS("Cleaning", cleanings);
|
||||||
PROFILER_STATS("Counter", counters);
|
PROFILER_STATS("Counter", counters);
|
||||||
PROFILER_STATS("Thread", threads);
|
PROFILER_STATS("Thread", threads);
|
||||||
#undef PROFILER_STATS
|
# undef PROFILER_STATS
|
||||||
aWriter.EndObject(); // statistics
|
aWriter.EndObject(); // statistics
|
||||||
}
|
}
|
||||||
aWriter.EndObject(); // profilerOverhead
|
aWriter.EndObject(); // profilerOverhead
|
||||||
|
@ -1572,7 +1576,7 @@ void ProfileBuffer::StreamMemoryToJSON(SpliceableJSONWriter& aWriter,
|
||||||
aWriter.EndObject(); // samples
|
aWriter.EndObject(); // samples
|
||||||
aWriter.EndObject(); // memory
|
aWriter.EndObject(); // memory
|
||||||
}
|
}
|
||||||
#undef ERROR_AND_CONTINUE
|
# undef ERROR_AND_CONTINUE
|
||||||
|
|
||||||
static void AddPausedRange(SpliceableJSONWriter& aWriter, const char* aReason,
|
static void AddPausedRange(SpliceableJSONWriter& aWriter, const char* aReason,
|
||||||
const Maybe<double>& aStartTime,
|
const Maybe<double>& aStartTime,
|
||||||
|
@ -1772,3 +1776,5 @@ void ProfileBuffer::DiscardSamplesBeforeTime(double aTime) {
|
||||||
|
|
||||||
// END ProfileBuffer
|
// END ProfileBuffer
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#endif // MOZ_BASE_PROFILER
|
||||||
|
|
|
@ -3,9 +3,13 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "BaseProfileJSONWriter.h"
|
#include "BaseProfiler.h"
|
||||||
|
|
||||||
#include "mozilla/HashFunctions.h"
|
#ifdef MOZ_BASE_PROFILER
|
||||||
|
|
||||||
|
# include "BaseProfileJSONWriter.h"
|
||||||
|
|
||||||
|
# include "mozilla/HashFunctions.h"
|
||||||
|
|
||||||
void ChunkedJSONWriteFunc::Write(const char* aStr) {
|
void ChunkedJSONWriteFunc::Write(const char* aStr) {
|
||||||
MOZ_ASSERT(mChunkPtr >= mChunkList.back().get() && mChunkPtr <= mChunkEnd);
|
MOZ_ASSERT(mChunkPtr >= mChunkList.back().get() && mChunkPtr <= mChunkEnd);
|
||||||
|
@ -112,3 +116,5 @@ void SpliceableChunkedJSONWriter::TakeAndSplice(ChunkedJSONWriteFunc* aFunc) {
|
||||||
WriteFunc()->Take(std::move(*aFunc));
|
WriteFunc()->Take(std::move(*aFunc));
|
||||||
mNeedComma[mDepth] = true;
|
mNeedComma[mDepth] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // MOZ_BASE_PROFILER
|
||||||
|
|
|
@ -4,17 +4,21 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "ProfiledThreadData.h"
|
#include "BaseProfiler.h"
|
||||||
|
|
||||||
#include "ProfileBuffer.h"
|
#ifdef MOZ_BASE_PROFILER
|
||||||
#include "BaseProfileJSONWriter.h"
|
|
||||||
|
|
||||||
#include "js/TraceLoggerAPI.h"
|
# include "ProfiledThreadData.h"
|
||||||
#include "mozilla/dom/ContentChild.h"
|
|
||||||
|
|
||||||
#if defined(GP_OS_darwin)
|
# include "ProfileBuffer.h"
|
||||||
# include <pthread.h>
|
# include "BaseProfileJSONWriter.h"
|
||||||
#endif
|
|
||||||
|
# include "js/TraceLoggerAPI.h"
|
||||||
|
# include "mozilla/dom/ContentChild.h"
|
||||||
|
|
||||||
|
# if defined(GP_OS_darwin)
|
||||||
|
# include <pthread.h>
|
||||||
|
# endif
|
||||||
|
|
||||||
ProfiledThreadData::ProfiledThreadData(ThreadInfo* aThreadInfo,
|
ProfiledThreadData::ProfiledThreadData(ThreadInfo* aThreadInfo,
|
||||||
nsIEventTarget* aEventTarget,
|
nsIEventTarget* aEventTarget,
|
||||||
|
@ -301,3 +305,5 @@ void ProfiledThreadData::NotifyAboutToLoseJSContext(
|
||||||
mJITFrameInfoForPreviousJSContexts = std::move(jitFrameInfo);
|
mJITFrameInfoForPreviousJSContexts = std::move(jitFrameInfo);
|
||||||
mBufferPositionWhenReceivedJSContext = mozilla::Nothing();
|
mBufferPositionWhenReceivedJSContext = mozilla::Nothing();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // MOZ_BASE_PROFILER
|
||||||
|
|
|
@ -4,12 +4,16 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "ProfilerBacktrace.h"
|
#include "BaseProfiler.h"
|
||||||
|
|
||||||
#include "ProfileBuffer.h"
|
#ifdef MOZ_BASE_PROFILER
|
||||||
#include "ProfiledThreadData.h"
|
|
||||||
#include "BaseProfileJSONWriter.h"
|
# include "ProfilerBacktrace.h"
|
||||||
#include "ThreadInfo.h"
|
|
||||||
|
# include "ProfileBuffer.h"
|
||||||
|
# include "ProfiledThreadData.h"
|
||||||
|
# include "BaseProfileJSONWriter.h"
|
||||||
|
# include "ThreadInfo.h"
|
||||||
|
|
||||||
ProfilerBacktrace::ProfilerBacktrace(const char* aName, int aThreadId,
|
ProfilerBacktrace::ProfilerBacktrace(const char* aName, int aThreadId,
|
||||||
mozilla::UniquePtr<ProfileBuffer> aBuffer)
|
mozilla::UniquePtr<ProfileBuffer> aBuffer)
|
||||||
|
@ -32,3 +36,5 @@ void ProfilerBacktrace::StreamJSON(SpliceableJSONWriter& aWriter,
|
||||||
/* aUnregisterTime */ mozilla::TimeStamp(),
|
/* aUnregisterTime */ mozilla::TimeStamp(),
|
||||||
/* aSinceTime */ 0, aUniqueStacks);
|
/* aSinceTime */ 0, aUniqueStacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // MOZ_BASE_PROFILER
|
||||||
|
|
|
@ -3,20 +3,23 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "BaseProfilerMarkerPayload.h"
|
|
||||||
|
|
||||||
#include "BaseProfiler.h"
|
#include "BaseProfiler.h"
|
||||||
#include "ProfileBufferEntry.h"
|
|
||||||
#include "BaseProfileJSONWriter.h"
|
|
||||||
#include "ProfilerBacktrace.h"
|
|
||||||
|
|
||||||
#include "gfxASurface.h"
|
#ifdef MOZ_BASE_PROFILER
|
||||||
#include "Layers.h"
|
|
||||||
#include "mozilla/Maybe.h"
|
|
||||||
#include "mozilla/net/HttpBaseChannel.h"
|
|
||||||
#include "mozilla/Sprintf.h"
|
|
||||||
|
|
||||||
#include <inttypes.h>
|
# include "BaseProfilerMarkerPayload.h"
|
||||||
|
|
||||||
|
# include "ProfileBufferEntry.h"
|
||||||
|
# include "BaseProfileJSONWriter.h"
|
||||||
|
# include "ProfilerBacktrace.h"
|
||||||
|
|
||||||
|
# include "gfxASurface.h"
|
||||||
|
# include "Layers.h"
|
||||||
|
# include "mozilla/Maybe.h"
|
||||||
|
# include "mozilla/net/HttpBaseChannel.h"
|
||||||
|
# include "mozilla/Sprintf.h"
|
||||||
|
|
||||||
|
# include <inttypes.h>
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
|
||||||
|
@ -296,3 +299,5 @@ void LongTaskMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
|
||||||
aUniqueStacks);
|
aUniqueStacks);
|
||||||
aWriter.StringProperty("category", "LongTask");
|
aWriter.StringProperty("category", "LongTask");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // MOZ_BASE_PROFILER
|
||||||
|
|
|
@ -4,28 +4,32 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "vm/GeckoProfiler-inl.h"
|
#include "BaseProfiler.h"
|
||||||
|
|
||||||
#include "mozilla/ArrayUtils.h"
|
#ifdef MOZ_BASE_PROFILER
|
||||||
#include "mozilla/DebugOnly.h"
|
|
||||||
#include "mozilla/Sprintf.h"
|
|
||||||
|
|
||||||
#include "jsnum.h"
|
# include "vm/GeckoProfiler-inl.h"
|
||||||
|
|
||||||
#include "gc/GC.h"
|
# include "mozilla/ArrayUtils.h"
|
||||||
#include "gc/PublicIterators.h"
|
# include "mozilla/DebugOnly.h"
|
||||||
#include "jit/BaselineFrame.h"
|
# include "mozilla/Sprintf.h"
|
||||||
#include "jit/BaselineJIT.h"
|
|
||||||
#include "jit/JitcodeMap.h"
|
|
||||||
#include "jit/JitFrames.h"
|
|
||||||
#include "jit/JitRealm.h"
|
|
||||||
#include "jit/JSJitFrameIter.h"
|
|
||||||
#include "js/TraceLoggerAPI.h"
|
|
||||||
#include "util/StringBuffer.h"
|
|
||||||
#include "vm/JSScript.h"
|
|
||||||
|
|
||||||
#include "gc/Marking-inl.h"
|
# include "jsnum.h"
|
||||||
#include "vm/JSScript-inl.h"
|
|
||||||
|
# include "gc/GC.h"
|
||||||
|
# include "gc/PublicIterators.h"
|
||||||
|
# include "jit/BaselineFrame.h"
|
||||||
|
# include "jit/BaselineJIT.h"
|
||||||
|
# include "jit/JitcodeMap.h"
|
||||||
|
# include "jit/JitFrames.h"
|
||||||
|
# include "jit/JitRealm.h"
|
||||||
|
# include "jit/JSJitFrameIter.h"
|
||||||
|
# include "js/TraceLoggerAPI.h"
|
||||||
|
# include "util/StringBuffer.h"
|
||||||
|
# include "vm/JSScript.h"
|
||||||
|
|
||||||
|
# include "gc/Marking-inl.h"
|
||||||
|
# include "vm/JSScript-inl.h"
|
||||||
|
|
||||||
using namespace js;
|
using namespace js;
|
||||||
|
|
||||||
|
@ -152,14 +156,14 @@ void GeckoProfilerRuntime::enable(bool enabled) {
|
||||||
r->wasm.ensureProfilingLabels(enabled);
|
r->wasm.ensureProfilingLabels(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef JS_STRUCTURED_SPEW
|
# ifdef JS_STRUCTURED_SPEW
|
||||||
// Enable the structured spewer if the environment variable is set.
|
// Enable the structured spewer if the environment variable is set.
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
cx->spewer().enableSpewing();
|
cx->spewer().enableSpewing();
|
||||||
} else {
|
} else {
|
||||||
cx->spewer().disableSpewing();
|
cx->spewer().disableSpewing();
|
||||||
}
|
}
|
||||||
#endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lookup the string for the function/script, creating one if necessary */
|
/* Lookup the string for the function/script, creating one if necessary */
|
||||||
|
@ -209,7 +213,7 @@ bool GeckoProfilerThread::enter(JSContext* cx, JSScript* script) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
# ifdef DEBUG
|
||||||
// In debug builds, assert the JS profiling stack frames already on the
|
// In debug builds, assert the JS profiling stack frames already on the
|
||||||
// stack have a non-null pc. Only look at the top frames to avoid quadratic
|
// stack have a non-null pc. Only look at the top frames to avoid quadratic
|
||||||
// behavior.
|
// behavior.
|
||||||
|
@ -221,7 +225,7 @@ bool GeckoProfilerThread::enter(JSContext* cx, JSScript* script) {
|
||||||
profilingStack_->frames[i].pc());
|
profilingStack_->frames[i].pc());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
profilingStack_->pushJsFrame("", dynamicString, script, script->code());
|
profilingStack_->pushJsFrame("", dynamicString, script, script->code());
|
||||||
return true;
|
return true;
|
||||||
|
@ -230,7 +234,7 @@ bool GeckoProfilerThread::enter(JSContext* cx, JSScript* script) {
|
||||||
void GeckoProfilerThread::exit(JSContext* cx, JSScript* script) {
|
void GeckoProfilerThread::exit(JSContext* cx, JSScript* script) {
|
||||||
profilingStack_->pop();
|
profilingStack_->pop();
|
||||||
|
|
||||||
#ifdef DEBUG
|
# ifdef DEBUG
|
||||||
/* Sanity check to make sure push/pop balanced */
|
/* Sanity check to make sure push/pop balanced */
|
||||||
uint32_t sp = profilingStack_->stackPointer;
|
uint32_t sp = profilingStack_->stackPointer;
|
||||||
if (sp < profilingStack_->stackCapacity()) {
|
if (sp < profilingStack_->stackCapacity()) {
|
||||||
|
@ -260,7 +264,7 @@ void GeckoProfilerThread::exit(JSContext* cx, JSScript* script) {
|
||||||
MOZ_ASSERT(frame.script() == script);
|
MOZ_ASSERT(frame.script() == script);
|
||||||
MOZ_ASSERT(strcmp((const char*)frame.dynamicString(), dynamicString) == 0);
|
MOZ_ASSERT(strcmp((const char*)frame.dynamicString(), dynamicString) == 0);
|
||||||
}
|
}
|
||||||
#endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -379,7 +383,7 @@ void GeckoProfilerRuntime::fixupStringsMapAfterMovingGC() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef JSGC_HASH_TABLE_CHECKS
|
# ifdef JSGC_HASH_TABLE_CHECKS
|
||||||
void GeckoProfilerRuntime::checkStringsMapAfterMovingGC() {
|
void GeckoProfilerRuntime::checkStringsMapAfterMovingGC() {
|
||||||
for (auto r = strings().all(); !r.empty(); r.popFront()) {
|
for (auto r = strings().all(); !r.empty(); r.popFront()) {
|
||||||
JSScript* script = r.front().key();
|
JSScript* script = r.front().key();
|
||||||
|
@ -388,7 +392,7 @@ void GeckoProfilerRuntime::checkStringsMapAfterMovingGC() {
|
||||||
MOZ_RELEASE_ASSERT(ptr.found() && &*ptr == &r.front());
|
MOZ_RELEASE_ASSERT(ptr.found() && &*ptr == &r.front());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
void ProfilingStackFrame::trace(JSTracer* trc) {
|
void ProfilingStackFrame::trace(JSTracer* trc) {
|
||||||
if (isJsFrame()) {
|
if (isJsFrame()) {
|
||||||
|
@ -571,3 +575,5 @@ JS_FRIEND_API const ProfilingCategoryPairInfo& GetProfilingCategoryPairInfo(
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace JS
|
} // namespace JS
|
||||||
|
|
||||||
|
#endif // MOZ_BASE_PROFILER
|
||||||
|
|
|
@ -4,13 +4,17 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "js/ProfilingStack.h"
|
#include "BaseProfiler.h"
|
||||||
|
|
||||||
#include "mozilla/IntegerRange.h"
|
#ifdef MOZ_BASE_PROFILER
|
||||||
#include "mozilla/UniquePtr.h"
|
|
||||||
#include "mozilla/UniquePtrExtensions.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
# include "js/ProfilingStack.h"
|
||||||
|
|
||||||
|
# include "mozilla/IntegerRange.h"
|
||||||
|
# include "mozilla/UniquePtr.h"
|
||||||
|
# include "mozilla/UniquePtrExtensions.h"
|
||||||
|
|
||||||
|
# include <algorithm>
|
||||||
|
|
||||||
using namespace js;
|
using namespace js;
|
||||||
|
|
||||||
|
@ -44,3 +48,5 @@ void ProfilingStack::ensureCapacitySlow() {
|
||||||
capacity = newCapacity;
|
capacity = newCapacity;
|
||||||
delete[] oldFrames;
|
delete[] oldFrames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // MOZ_BASE_PROFILER
|
||||||
|
|
|
@ -4,7 +4,11 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "RegisteredThread.h"
|
#include "BaseProfiler.h"
|
||||||
|
|
||||||
|
#ifdef MOZ_BASE_PROFILER
|
||||||
|
|
||||||
|
# include "RegisteredThread.h"
|
||||||
|
|
||||||
RegisteredThread::RegisteredThread(ThreadInfo* aInfo, nsIEventTarget* aThread,
|
RegisteredThread::RegisteredThread(ThreadInfo* aInfo, nsIEventTarget* aThread,
|
||||||
void* aStackTop)
|
void* aStackTop)
|
||||||
|
@ -19,10 +23,10 @@ RegisteredThread::RegisteredThread(ThreadInfo* aInfo, nsIEventTarget* aThread,
|
||||||
MOZ_COUNT_CTOR(RegisteredThread);
|
MOZ_COUNT_CTOR(RegisteredThread);
|
||||||
|
|
||||||
// We don't have to guess on mac
|
// We don't have to guess on mac
|
||||||
#if defined(GP_OS_darwin)
|
# if defined(GP_OS_darwin)
|
||||||
pthread_t self = pthread_self();
|
pthread_t self = pthread_self();
|
||||||
mStackTop = pthread_get_stackaddr_np(self);
|
mStackTop = pthread_get_stackaddr_np(self);
|
||||||
#endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
RegisteredThread::~RegisteredThread() { MOZ_COUNT_DTOR(RegisteredThread); }
|
RegisteredThread::~RegisteredThread() { MOZ_COUNT_DTOR(RegisteredThread); }
|
||||||
|
@ -41,3 +45,5 @@ size_t RegisteredThread::SizeOfIncludingThis(
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // MOZ_BASE_PROFILER
|
||||||
|
|
|
@ -4,14 +4,18 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#ifdef XP_WIN
|
#include "BaseProfiler.h"
|
||||||
# undef UNICODE
|
|
||||||
# undef _UNICODE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "VTuneProfiler.h"
|
#ifdef MOZ_BASE_PROFILER
|
||||||
#include "mozilla/Bootstrap.h"
|
|
||||||
#include <memory>
|
# ifdef XP_WIN
|
||||||
|
# undef UNICODE
|
||||||
|
# undef _UNICODE
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# include "VTuneProfiler.h"
|
||||||
|
# include "mozilla/Bootstrap.h"
|
||||||
|
# include <memory>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -80,3 +84,5 @@ void VTuneProfiler::RegisterThreadInternal(const char* aName) {
|
||||||
}
|
}
|
||||||
__itt_thread_set_name(aName);
|
__itt_thread_set_name(aName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // MOZ_BASE_PROFILER
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -4,40 +4,44 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "BaseProfilerSharedLibraries.h"
|
#include "BaseProfiler.h"
|
||||||
|
|
||||||
#define PATH_MAX_TOSTRING(x) #x
|
#ifdef MOZ_BASE_PROFILER
|
||||||
#define PATH_MAX_STRING(x) PATH_MAX_TOSTRING(x)
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <fstream>
|
|
||||||
#include "platform.h"
|
|
||||||
#include "mozilla/Sprintf.h"
|
|
||||||
#include "mozilla/Unused.h"
|
|
||||||
#include "nsDebug.h"
|
|
||||||
#include "nsNativeCharsetUtils.h"
|
|
||||||
#include <nsTArray.h>
|
|
||||||
|
|
||||||
#include "common/linux/file_id.h"
|
# include "BaseProfilerSharedLibraries.h"
|
||||||
#include <algorithm>
|
|
||||||
#include <dlfcn.h>
|
|
||||||
#include <features.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#if defined(GP_OS_linux)
|
# define PATH_MAX_TOSTRING(x) # x
|
||||||
# include <link.h> // dl_phdr_info
|
# define PATH_MAX_STRING(x) PATH_MAX_TOSTRING(x)
|
||||||
#elif defined(GP_OS_android)
|
# include <stdlib.h>
|
||||||
# include "AutoObjectMapper.h"
|
# include <stdio.h>
|
||||||
# include "ElfLoader.h" // dl_phdr_info
|
# include <string.h>
|
||||||
|
# include <limits.h>
|
||||||
|
# include <unistd.h>
|
||||||
|
# include <fstream>
|
||||||
|
# include "platform.h"
|
||||||
|
# include "mozilla/Sprintf.h"
|
||||||
|
# include "mozilla/Unused.h"
|
||||||
|
# include "nsDebug.h"
|
||||||
|
# include "nsNativeCharsetUtils.h"
|
||||||
|
# include <nsTArray.h>
|
||||||
|
|
||||||
|
# include "common/linux/file_id.h"
|
||||||
|
# include <algorithm>
|
||||||
|
# include <dlfcn.h>
|
||||||
|
# include <features.h>
|
||||||
|
# include <sys/types.h>
|
||||||
|
|
||||||
|
# if defined(GP_OS_linux)
|
||||||
|
# include <link.h> // dl_phdr_info
|
||||||
|
# elif defined(GP_OS_android)
|
||||||
|
# include "AutoObjectMapper.h"
|
||||||
|
# include "ElfLoader.h" // dl_phdr_info
|
||||||
extern "C" MOZ_EXPORT __attribute__((weak)) int dl_iterate_phdr(
|
extern "C" MOZ_EXPORT __attribute__((weak)) int dl_iterate_phdr(
|
||||||
int (*callback)(struct dl_phdr_info* info, size_t size, void* data),
|
int (*callback)(struct dl_phdr_info* info, size_t size, void* data),
|
||||||
void* data);
|
void* data);
|
||||||
#else
|
# else
|
||||||
# error "Unexpected configuration"
|
# error "Unexpected configuration"
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
struct LoadedLibraryInfo {
|
struct LoadedLibraryInfo {
|
||||||
LoadedLibraryInfo(const char* aName, unsigned long aBaseAddress,
|
LoadedLibraryInfo(const char* aName, unsigned long aBaseAddress,
|
||||||
|
@ -54,9 +58,9 @@ struct LoadedLibraryInfo {
|
||||||
unsigned long mLastMappingEnd;
|
unsigned long mLastMappingEnd;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(GP_OS_android)
|
# if defined(GP_OS_android)
|
||||||
static void outputMapperLog(const char* aBuf) { LOG("%s", aBuf); }
|
static void outputMapperLog(const char* aBuf) { LOG("%s", aBuf); }
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
static nsCString IDtoUUIDString(
|
static nsCString IDtoUUIDString(
|
||||||
const google_breakpad::wasteful_vector<uint8_t>& aIdentifier) {
|
const google_breakpad::wasteful_vector<uint8_t>& aIdentifier) {
|
||||||
|
@ -77,7 +81,7 @@ static nsCString getId(const char* bin_name) {
|
||||||
PageAllocator allocator;
|
PageAllocator allocator;
|
||||||
auto_wasteful_vector<uint8_t, kDefaultBuildIdSize> identifier(&allocator);
|
auto_wasteful_vector<uint8_t, kDefaultBuildIdSize> identifier(&allocator);
|
||||||
|
|
||||||
#if defined(GP_OS_android)
|
# if defined(GP_OS_android)
|
||||||
if (nsDependentCString(bin_name).Find("!/") != kNotFound) {
|
if (nsDependentCString(bin_name).Find("!/") != kNotFound) {
|
||||||
AutoObjectMapperFaultyLib mapper(outputMapperLog);
|
AutoObjectMapperFaultyLib mapper(outputMapperLog);
|
||||||
void* image = nullptr;
|
void* image = nullptr;
|
||||||
|
@ -88,7 +92,7 @@ static nsCString getId(const char* bin_name) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
FileID file_id(bin_name);
|
FileID file_id(bin_name);
|
||||||
if (file_id.ElfFileIdentifier(identifier)) {
|
if (file_id.ElfFileIdentifier(identifier)) {
|
||||||
|
@ -149,7 +153,7 @@ static int dl_iterate_callback(struct dl_phdr_info* dl_info, size_t size,
|
||||||
SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
|
SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
|
||||||
SharedLibraryInfo info;
|
SharedLibraryInfo info;
|
||||||
|
|
||||||
#if defined(GP_OS_linux)
|
# if defined(GP_OS_linux)
|
||||||
// We need to find the name of the executable (exeName, exeNameLen) and the
|
// We need to find the name of the executable (exeName, exeNameLen) and the
|
||||||
// address of its executable section (exeExeAddr) in the running image.
|
// address of its executable section (exeExeAddr) in the running image.
|
||||||
char exeName[PATH_MAX];
|
char exeName[PATH_MAX];
|
||||||
|
@ -168,9 +172,9 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long exeExeAddr = 0;
|
unsigned long exeExeAddr = 0;
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
#if defined(GP_OS_android)
|
# if defined(GP_OS_android)
|
||||||
// If dl_iterate_phdr doesn't exist, we give up immediately.
|
// If dl_iterate_phdr doesn't exist, we give up immediately.
|
||||||
if (!dl_iterate_phdr) {
|
if (!dl_iterate_phdr) {
|
||||||
// On ARM Android, dl_iterate_phdr is provided by the custom linker.
|
// On ARM Android, dl_iterate_phdr is provided by the custom linker.
|
||||||
|
@ -179,7 +183,7 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
|
||||||
// not call it.
|
// not call it.
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
// Read info from /proc/self/maps. We ignore most of it.
|
// Read info from /proc/self/maps. We ignore most of it.
|
||||||
pid_t pid = profiler_current_process_id();
|
pid_t pid = profiler_current_process_id();
|
||||||
|
@ -207,12 +211,12 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(GP_OS_linux)
|
# if defined(GP_OS_linux)
|
||||||
// Try to establish the main executable's load address.
|
// Try to establish the main executable's load address.
|
||||||
if (exeNameLen > 0 && strcmp(modulePath, exeName) == 0) {
|
if (exeNameLen > 0 && strcmp(modulePath, exeName) == 0) {
|
||||||
exeExeAddr = start;
|
exeExeAddr = start;
|
||||||
}
|
}
|
||||||
#elif defined(GP_OS_android)
|
# elif defined(GP_OS_android)
|
||||||
// Use /proc/pid/maps to get the dalvik-jit section since it has no
|
// Use /proc/pid/maps to get the dalvik-jit section since it has no
|
||||||
// associated phdrs.
|
// associated phdrs.
|
||||||
if (0 == strcmp(modulePath, "/dev/ashmem/dalvik-jit-code-cache")) {
|
if (0 == strcmp(modulePath, "/dev/ashmem/dalvik-jit-code-cache")) {
|
||||||
|
@ -224,7 +228,7 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
nsTArray<LoadedLibraryInfo> libInfoList;
|
nsTArray<LoadedLibraryInfo> libInfoList;
|
||||||
|
@ -239,7 +243,7 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
|
||||||
libInfo.mFirstMappingStart - libInfo.mBaseAddress));
|
libInfo.mFirstMappingStart - libInfo.mBaseAddress));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(GP_OS_linux)
|
# if defined(GP_OS_linux)
|
||||||
// Make another pass over the information we just harvested from
|
// Make another pass over the information we just harvested from
|
||||||
// dl_iterate_phdr. If we see a nameless object mapped at what we earlier
|
// dl_iterate_phdr. If we see a nameless object mapped at what we earlier
|
||||||
// established to be the main executable's load address, attach the
|
// established to be the main executable's load address, attach the
|
||||||
|
@ -254,10 +258,12 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharedLibraryInfo::Initialize() { /* do nothing */
|
void SharedLibraryInfo::Initialize() { /* do nothing */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // MOZ_BASE_PROFILER
|
||||||
|
|
|
@ -3,42 +3,46 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "BaseProfilerSharedLibraries.h"
|
#include "BaseProfiler.h"
|
||||||
|
|
||||||
#include "ClearOnShutdown.h"
|
#ifdef MOZ_BASE_PROFILER
|
||||||
#include "mozilla/StaticMutex.h"
|
|
||||||
#include "mozilla/Unused.h"
|
|
||||||
#include "nsNativeCharsetUtils.h"
|
|
||||||
#include <AvailabilityMacros.h>
|
|
||||||
|
|
||||||
#include <dlfcn.h>
|
# include "BaseProfilerSharedLibraries.h"
|
||||||
#include <mach-o/arch.h>
|
|
||||||
#include <mach-o/dyld_images.h>
|
# include "ClearOnShutdown.h"
|
||||||
#include <mach-o/dyld.h>
|
# include "mozilla/StaticMutex.h"
|
||||||
#include <mach-o/loader.h>
|
# include "mozilla/Unused.h"
|
||||||
#include <mach/mach_init.h>
|
# include "nsNativeCharsetUtils.h"
|
||||||
#include <mach/mach_traps.h>
|
# include <AvailabilityMacros.h>
|
||||||
#include <mach/task_info.h>
|
|
||||||
#include <mach/task.h>
|
# include <dlfcn.h>
|
||||||
#include <sstream>
|
# include <mach-o/arch.h>
|
||||||
#include <stdlib.h>
|
# include <mach-o/dyld_images.h>
|
||||||
#include <string.h>
|
# include <mach-o/dyld.h>
|
||||||
#include <vector>
|
# include <mach-o/loader.h>
|
||||||
|
# include <mach/mach_init.h>
|
||||||
|
# include <mach/mach_traps.h>
|
||||||
|
# include <mach/task_info.h>
|
||||||
|
# include <mach/task.h>
|
||||||
|
# include <sstream>
|
||||||
|
# include <stdlib.h>
|
||||||
|
# include <string.h>
|
||||||
|
# include <vector>
|
||||||
|
|
||||||
// Architecture specific abstraction.
|
// Architecture specific abstraction.
|
||||||
#if defined(GP_ARCH_x86)
|
# if defined(GP_ARCH_x86)
|
||||||
typedef mach_header platform_mach_header;
|
typedef mach_header platform_mach_header;
|
||||||
typedef segment_command mach_segment_command_type;
|
typedef segment_command mach_segment_command_type;
|
||||||
# define MACHO_MAGIC_NUMBER MH_MAGIC
|
# define MACHO_MAGIC_NUMBER MH_MAGIC
|
||||||
# define CMD_SEGMENT LC_SEGMENT
|
# define CMD_SEGMENT LC_SEGMENT
|
||||||
# define seg_size uint32_t
|
# define seg_size uint32_t
|
||||||
#else
|
# else
|
||||||
typedef mach_header_64 platform_mach_header;
|
typedef mach_header_64 platform_mach_header;
|
||||||
typedef segment_command_64 mach_segment_command_type;
|
typedef segment_command_64 mach_segment_command_type;
|
||||||
# define MACHO_MAGIC_NUMBER MH_MAGIC_64
|
# define MACHO_MAGIC_NUMBER MH_MAGIC_64
|
||||||
# define CMD_SEGMENT LC_SEGMENT_64
|
# define CMD_SEGMENT LC_SEGMENT_64
|
||||||
# define seg_size uint64_t
|
# define seg_size uint64_t
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
struct NativeSharedLibrary {
|
struct NativeSharedLibrary {
|
||||||
const platform_mach_header* header;
|
const platform_mach_header* header;
|
||||||
|
@ -183,3 +187,5 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
|
||||||
|
|
||||||
return sharedLibraryInfo;
|
return sharedLibraryInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // MOZ_BASE_PROFILER
|
||||||
|
|
|
@ -3,20 +3,24 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include <windows.h>
|
#include "BaseProfiler.h"
|
||||||
#include <dbghelp.h>
|
|
||||||
#include <sstream>
|
|
||||||
#include <psapi.h>
|
|
||||||
|
|
||||||
#include "BaseProfilerSharedLibraries.h"
|
#ifdef MOZ_BASE_PROFILER
|
||||||
#include "nsWindowsHelpers.h"
|
|
||||||
#include "mozilla/UniquePtr.h"
|
|
||||||
#include "mozilla/Unused.h"
|
|
||||||
#include "nsNativeCharsetUtils.h"
|
|
||||||
#include "nsPrintfCString.h"
|
|
||||||
#include "nsReadableUtils.h"
|
|
||||||
|
|
||||||
#define CV_SIGNATURE 0x53445352 // 'SDSR'
|
# include <windows.h>
|
||||||
|
# include <dbghelp.h>
|
||||||
|
# include <sstream>
|
||||||
|
# include <psapi.h>
|
||||||
|
|
||||||
|
# include "BaseProfilerSharedLibraries.h"
|
||||||
|
# include "nsWindowsHelpers.h"
|
||||||
|
# include "mozilla/UniquePtr.h"
|
||||||
|
# include "mozilla/Unused.h"
|
||||||
|
# include "nsNativeCharsetUtils.h"
|
||||||
|
# include "nsPrintfCString.h"
|
||||||
|
# include "nsReadableUtils.h"
|
||||||
|
|
||||||
|
# define CV_SIGNATURE 0x53445352 // 'SDSR'
|
||||||
|
|
||||||
struct CodeViewRecord70 {
|
struct CodeViewRecord70 {
|
||||||
uint32_t signature;
|
uint32_t signature;
|
||||||
|
@ -207,3 +211,5 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
|
||||||
|
|
||||||
void SharedLibraryInfo::Initialize() { /* do nothing */
|
void SharedLibraryInfo::Initialize() { /* do nothing */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // MOZ_BASE_PROFILER
|
||||||
|
|
|
@ -4,21 +4,25 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include <sys/mman.h>
|
#include "BaseProfiler.h"
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#include "mozilla/Assertions.h"
|
#ifdef MOZ_BASE_PROFILER
|
||||||
#include "mozilla/Sprintf.h"
|
|
||||||
|
|
||||||
#include "PlatformMacros.h"
|
# include <sys/mman.h>
|
||||||
#include "AutoObjectMapper.h"
|
# include <unistd.h>
|
||||||
|
# include <sys/types.h>
|
||||||
|
# include <sys/stat.h>
|
||||||
|
# include <fcntl.h>
|
||||||
|
|
||||||
#if defined(GP_OS_android)
|
# include "mozilla/Assertions.h"
|
||||||
# include <dlfcn.h>
|
# include "mozilla/Sprintf.h"
|
||||||
# include "mozilla/Types.h"
|
|
||||||
|
# include "PlatformMacros.h"
|
||||||
|
# include "AutoObjectMapper.h"
|
||||||
|
|
||||||
|
# if defined(GP_OS_android)
|
||||||
|
# include <dlfcn.h>
|
||||||
|
# include "mozilla/Types.h"
|
||||||
// FIXME move these out of mozglue/linker/ElfLoader.h into their
|
// FIXME move these out of mozglue/linker/ElfLoader.h into their
|
||||||
// own header, so as to avoid conflicts arising from two definitions
|
// own header, so as to avoid conflicts arising from two definitions
|
||||||
// of Array
|
// of Array
|
||||||
|
@ -28,10 +32,10 @@ MFBT_API void* __dl_mmap(void* handle, void* addr, size_t length, off_t offset);
|
||||||
MFBT_API void __dl_munmap(void* handle, void* addr, size_t length);
|
MFBT_API void __dl_munmap(void* handle, void* addr, size_t length);
|
||||||
}
|
}
|
||||||
// The following are for get_installation_lib_dir()
|
// The following are for get_installation_lib_dir()
|
||||||
# include "nsString.h"
|
# include "nsString.h"
|
||||||
# include "nsDirectoryServiceUtils.h"
|
# include "nsDirectoryServiceUtils.h"
|
||||||
# include "nsDirectoryServiceDefs.h"
|
# include "nsDirectoryServiceDefs.h"
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
// A helper function for creating failure error messages in
|
// A helper function for creating failure error messages in
|
||||||
// AutoObjectMapper*::Map.
|
// AutoObjectMapper*::Map.
|
||||||
|
@ -95,7 +99,7 @@ bool AutoObjectMapperPOSIX::Map(/*OUT*/ void** start, /*OUT*/ size_t* length,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(GP_OS_android)
|
# if defined(GP_OS_android)
|
||||||
// A helper function for AutoObjectMapperFaultyLib::Map. Finds out
|
// A helper function for AutoObjectMapperFaultyLib::Map. Finds out
|
||||||
// where the installation's lib directory is, since we'll have to look
|
// where the installation's lib directory is, since we'll have to look
|
||||||
// in there to get hold of libmozglue.so. Returned C string is heap
|
// in there to get hold of libmozglue.so. Returned C string is heap
|
||||||
|
@ -185,4 +189,6 @@ bool AutoObjectMapperFaultyLib::Map(/*OUT*/ void** start,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // defined(GP_OS_android)
|
# endif // defined(GP_OS_android)
|
||||||
|
|
||||||
|
#endif // MOZ_BASE_PROFILER
|
||||||
|
|
|
@ -37,15 +37,19 @@
|
||||||
// src/common/module.cc
|
// src/common/module.cc
|
||||||
// src/common/unique_string.cc
|
// src/common/unique_string.cc
|
||||||
|
|
||||||
|
#include "BaseProfiler.h"
|
||||||
|
|
||||||
|
#ifdef MOZ_BASE_PROFILER
|
||||||
|
|
||||||
// There's no internal-only interface for LulCommon. Hence include
|
// There's no internal-only interface for LulCommon. Hence include
|
||||||
// the external interface directly.
|
// the external interface directly.
|
||||||
#include "LulCommonExt.h"
|
# include "LulCommonExt.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
# include <stdlib.h>
|
||||||
#include <string.h>
|
# include <string.h>
|
||||||
|
|
||||||
#include <string>
|
# include <string>
|
||||||
#include <map>
|
# include <map>
|
||||||
|
|
||||||
namespace lul {
|
namespace lul {
|
||||||
|
|
||||||
|
@ -98,3 +102,5 @@ const UniqueString* UniqueStringUniverse::ToUniqueString(string str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace lul
|
} // namespace lul
|
||||||
|
|
||||||
|
#endif // MOZ_BASE_PROFILER
|
||||||
|
|
|
@ -41,23 +41,27 @@
|
||||||
// src/common/dwarf/dwarf2reader.cc
|
// src/common/dwarf/dwarf2reader.cc
|
||||||
// src/common/dwarf_cfi_to_module.cc
|
// src/common/dwarf_cfi_to_module.cc
|
||||||
|
|
||||||
#include <stdint.h>
|
#include "BaseProfiler.h"
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include <map>
|
#ifdef MOZ_BASE_PROFILER
|
||||||
#include <stack>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "mozilla/Assertions.h"
|
# include <stdint.h>
|
||||||
#include "mozilla/Sprintf.h"
|
# include <stdio.h>
|
||||||
|
# include <string.h>
|
||||||
|
# include <stdlib.h>
|
||||||
|
|
||||||
#include "LulCommonExt.h"
|
# include <map>
|
||||||
#include "LulDwarfInt.h"
|
# include <stack>
|
||||||
|
# include <string>
|
||||||
|
|
||||||
|
# include "mozilla/Assertions.h"
|
||||||
|
# include "mozilla/Sprintf.h"
|
||||||
|
|
||||||
|
# include "LulCommonExt.h"
|
||||||
|
# include "LulDwarfInt.h"
|
||||||
|
|
||||||
// Set this to 1 for verbose logging
|
// Set this to 1 for verbose logging
|
||||||
#define DEBUG_DWARF 0
|
# define DEBUG_DWARF 0
|
||||||
|
|
||||||
namespace lul {
|
namespace lul {
|
||||||
|
|
||||||
|
@ -2250,3 +2254,5 @@ void DwarfCFIToModule::Reporter::ExpressionCouldNotBeSummarised(
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace lul
|
} // namespace lul
|
||||||
|
|
||||||
|
#endif // MOZ_BASE_PROFILER
|
||||||
|
|
|
@ -4,15 +4,19 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "LulDwarfSummariser.h"
|
#include "BaseProfiler.h"
|
||||||
|
|
||||||
#include "LulDwarfExt.h"
|
#ifdef MOZ_BASE_PROFILER
|
||||||
|
|
||||||
#include "mozilla/Assertions.h"
|
# include "LulDwarfSummariser.h"
|
||||||
#include "mozilla/Sprintf.h"
|
|
||||||
|
# include "LulDwarfExt.h"
|
||||||
|
|
||||||
|
# include "mozilla/Assertions.h"
|
||||||
|
# include "mozilla/Sprintf.h"
|
||||||
|
|
||||||
// Set this to 1 for verbose logging
|
// Set this to 1 for verbose logging
|
||||||
#define DEBUG_SUMMARISER 0
|
# define DEBUG_SUMMARISER 0
|
||||||
|
|
||||||
namespace lul {
|
namespace lul {
|
||||||
|
|
||||||
|
@ -124,7 +128,7 @@ void Summariser::Rule(uintptr_t aAddress, int aNewReg, LExprHow how,
|
||||||
|
|
||||||
// FIXME: factor out common parts of the arch-dependent summarisers.
|
// FIXME: factor out common parts of the arch-dependent summarisers.
|
||||||
|
|
||||||
#if defined(GP_ARCH_arm)
|
# if defined(GP_ARCH_arm)
|
||||||
|
|
||||||
// ----------------- arm ----------------- //
|
// ----------------- arm ----------------- //
|
||||||
|
|
||||||
|
@ -246,7 +250,7 @@ void Summariser::Rule(uintptr_t aAddress, int aNewReg, LExprHow how,
|
||||||
mCurrRules.mR15expr = LExpr(NODEREF, DW_REG_ARM_R14, 0);
|
mCurrRules.mR15expr = LExpr(NODEREF, DW_REG_ARM_R14, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(GP_ARCH_arm64)
|
# elif defined(GP_ARCH_arm64)
|
||||||
|
|
||||||
// ----------------- arm64 ----------------- //
|
// ----------------- arm64 ----------------- //
|
||||||
|
|
||||||
|
@ -327,7 +331,7 @@ void Summariser::Rule(uintptr_t aAddress, int aNewReg, LExprHow how,
|
||||||
if (mCurrRules.mSPexpr.mHow == UNKNOWN) {
|
if (mCurrRules.mSPexpr.mHow == UNKNOWN) {
|
||||||
mCurrRules.mSPexpr = LExpr(NODEREF, DW_REG_CFA, 0);
|
mCurrRules.mSPexpr = LExpr(NODEREF, DW_REG_CFA, 0);
|
||||||
}
|
}
|
||||||
#elif defined(GP_ARCH_amd64) || defined(GP_ARCH_x86)
|
# elif defined(GP_ARCH_amd64) || defined(GP_ARCH_x86)
|
||||||
|
|
||||||
// ---------------- x64/x86 ---------------- //
|
// ---------------- x64/x86 ---------------- //
|
||||||
|
|
||||||
|
@ -427,7 +431,7 @@ void Summariser::Rule(uintptr_t aAddress, int aNewReg, LExprHow how,
|
||||||
mCurrRules.mXbpExpr = LExpr(NODEREF, DW_REG_INTEL_XBP, 0);
|
mCurrRules.mXbpExpr = LExpr(NODEREF, DW_REG_INTEL_XBP, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(GP_ARCH_mips64)
|
# elif defined(GP_ARCH_mips64)
|
||||||
// ---------------- mips ---------------- //
|
// ---------------- mips ---------------- //
|
||||||
//
|
//
|
||||||
// Now, can we add the rule to our summary? This depends on whether
|
// Now, can we add the rule to our summary? This depends on whether
|
||||||
|
@ -509,10 +513,10 @@ void Summariser::Rule(uintptr_t aAddress, int aNewReg, LExprHow how,
|
||||||
mCurrRules.mFPexpr = LExpr(NODEREF, DW_REG_MIPS_FP, 0);
|
mCurrRules.mFPexpr = LExpr(NODEREF, DW_REG_MIPS_FP, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
# else
|
||||||
|
|
||||||
# error "Unsupported arch"
|
# error "Unsupported arch"
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -551,3 +555,5 @@ void Summariser::End() {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace lul
|
} // namespace lul
|
||||||
|
|
||||||
|
#endif // MOZ_BASE_PROFILER
|
||||||
|
|
|
@ -45,37 +45,41 @@
|
||||||
// src/common/linux/elfutils.cc
|
// src/common/linux/elfutils.cc
|
||||||
// src/common/linux/file_id.cc
|
// src/common/linux/file_id.cc
|
||||||
|
|
||||||
#include <errno.h>
|
#include "BaseProfiler.h"
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
|
|
||||||
#include <set>
|
#ifdef MOZ_BASE_PROFILER
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "mozilla/Assertions.h"
|
# include <errno.h>
|
||||||
#include "mozilla/Sprintf.h"
|
# include <fcntl.h>
|
||||||
|
# include <stdio.h>
|
||||||
|
# include <string.h>
|
||||||
|
# include <sys/mman.h>
|
||||||
|
# include <sys/stat.h>
|
||||||
|
# include <unistd.h>
|
||||||
|
# include <arpa/inet.h>
|
||||||
|
|
||||||
#include "PlatformMacros.h"
|
# include <set>
|
||||||
#include "LulCommonExt.h"
|
# include <string>
|
||||||
#include "LulDwarfExt.h"
|
# include <vector>
|
||||||
#include "LulElfInt.h"
|
|
||||||
#include "LulMainInt.h"
|
|
||||||
|
|
||||||
#if defined(GP_PLAT_arm_android) && !defined(SHT_ARM_EXIDX)
|
# include "mozilla/Assertions.h"
|
||||||
|
# include "mozilla/Sprintf.h"
|
||||||
|
|
||||||
|
# include "PlatformMacros.h"
|
||||||
|
# include "LulCommonExt.h"
|
||||||
|
# include "LulDwarfExt.h"
|
||||||
|
# include "LulElfInt.h"
|
||||||
|
# include "LulMainInt.h"
|
||||||
|
|
||||||
|
# if defined(GP_PLAT_arm_android) && !defined(SHT_ARM_EXIDX)
|
||||||
// bionic and older glibsc don't define it
|
// bionic and older glibsc don't define it
|
||||||
# define SHT_ARM_EXIDX (SHT_LOPROC + 1)
|
# define SHT_ARM_EXIDX (SHT_LOPROC + 1)
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
// Old Linux header doesn't define EM_AARCH64
|
// Old Linux header doesn't define EM_AARCH64
|
||||||
#ifndef EM_AARCH64
|
# ifndef EM_AARCH64
|
||||||
# define EM_AARCH64 183
|
# define EM_AARCH64 183
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
// This namespace contains helper functions.
|
// This namespace contains helper functions.
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -744,7 +748,7 @@ bool FindElfSegment(const void* elf_mapped_base, uint32_t segment_type,
|
||||||
//
|
//
|
||||||
|
|
||||||
// ELF note name and desc are 32-bits word padded.
|
// ELF note name and desc are 32-bits word padded.
|
||||||
#define NOTE_PADDING(a) ((a + 3) & ~3)
|
# define NOTE_PADDING(a) ((a + 3) & ~3)
|
||||||
|
|
||||||
// These functions are also used inside the crashed process, so be safe
|
// These functions are also used inside the crashed process, so be safe
|
||||||
// and use the syscall/libc wrappers instead of direct syscalls or libc.
|
// and use the syscall/libc wrappers instead of direct syscalls or libc.
|
||||||
|
@ -869,3 +873,5 @@ void FileID::ConvertIdentifierToString(const uint8_t identifier[kMDGUIDSize],
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace lul
|
} // namespace lul
|
||||||
|
|
||||||
|
#endif // MOZ_BASE_PROFILER
|
||||||
|
|
|
@ -4,35 +4,37 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "LulMain.h"
|
#include "BaseProfiler.h"
|
||||||
|
|
||||||
#include <string.h>
|
#ifdef MOZ_BASE_PROFILER
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h> // write(), only for testing LUL
|
|
||||||
|
|
||||||
#include <algorithm> // std::sort
|
# include "LulMain.h"
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "mozilla/Assertions.h"
|
# include <string.h>
|
||||||
#include "mozilla/ArrayUtils.h"
|
# include <stdlib.h>
|
||||||
#include "mozilla/CheckedInt.h"
|
# include <stdio.h>
|
||||||
#include "mozilla/DebugOnly.h"
|
# include <unistd.h> // write(), only for testing LUL
|
||||||
#include "mozilla/MemoryChecking.h"
|
|
||||||
#include "mozilla/Move.h"
|
|
||||||
#include "mozilla/Sprintf.h"
|
|
||||||
#include "mozilla/UniquePtr.h"
|
|
||||||
#include "mozilla/Unused.h"
|
|
||||||
|
|
||||||
#include "LulCommonExt.h"
|
# include <algorithm> // std::sort
|
||||||
#include "LulElfExt.h"
|
# include <string>
|
||||||
|
|
||||||
#include "LulMainInt.h"
|
# include "mozilla/Assertions.h"
|
||||||
|
# include "mozilla/ArrayUtils.h"
|
||||||
|
# include "mozilla/CheckedInt.h"
|
||||||
|
# include "mozilla/DebugOnly.h"
|
||||||
|
# include "mozilla/MemoryChecking.h"
|
||||||
|
# include "mozilla/Move.h"
|
||||||
|
# include "mozilla/Sprintf.h"
|
||||||
|
# include "mozilla/UniquePtr.h"
|
||||||
|
# include "mozilla/Unused.h"
|
||||||
|
|
||||||
#include "BaseProfiler.h" // for profiler_current_thread_id()
|
# include "LulCommonExt.h"
|
||||||
|
# include "LulElfExt.h"
|
||||||
|
|
||||||
|
# include "LulMainInt.h"
|
||||||
|
|
||||||
// Set this to 1 for verbose logging
|
// Set this to 1 for verbose logging
|
||||||
#define DEBUG_MAIN 0
|
# define DEBUG_MAIN 0
|
||||||
|
|
||||||
namespace lul {
|
namespace lul {
|
||||||
|
|
||||||
|
@ -62,14 +64,14 @@ static const char* NameOf_DW_REG(int16_t aReg) {
|
||||||
switch (aReg) {
|
switch (aReg) {
|
||||||
case DW_REG_CFA:
|
case DW_REG_CFA:
|
||||||
return "cfa";
|
return "cfa";
|
||||||
#if defined(GP_ARCH_amd64) || defined(GP_ARCH_x86)
|
# if defined(GP_ARCH_amd64) || defined(GP_ARCH_x86)
|
||||||
case DW_REG_INTEL_XBP:
|
case DW_REG_INTEL_XBP:
|
||||||
return "xbp";
|
return "xbp";
|
||||||
case DW_REG_INTEL_XSP:
|
case DW_REG_INTEL_XSP:
|
||||||
return "xsp";
|
return "xsp";
|
||||||
case DW_REG_INTEL_XIP:
|
case DW_REG_INTEL_XIP:
|
||||||
return "xip";
|
return "xip";
|
||||||
#elif defined(GP_ARCH_arm)
|
# elif defined(GP_ARCH_arm)
|
||||||
case DW_REG_ARM_R7:
|
case DW_REG_ARM_R7:
|
||||||
return "r7";
|
return "r7";
|
||||||
case DW_REG_ARM_R11:
|
case DW_REG_ARM_R11:
|
||||||
|
@ -82,23 +84,23 @@ static const char* NameOf_DW_REG(int16_t aReg) {
|
||||||
return "r14";
|
return "r14";
|
||||||
case DW_REG_ARM_R15:
|
case DW_REG_ARM_R15:
|
||||||
return "r15";
|
return "r15";
|
||||||
#elif defined(GP_ARCH_arm64)
|
# elif defined(GP_ARCH_arm64)
|
||||||
case DW_REG_AARCH64_X29:
|
case DW_REG_AARCH64_X29:
|
||||||
return "x29";
|
return "x29";
|
||||||
case DW_REG_AARCH64_X30:
|
case DW_REG_AARCH64_X30:
|
||||||
return "x30";
|
return "x30";
|
||||||
case DW_REG_AARCH64_SP:
|
case DW_REG_AARCH64_SP:
|
||||||
return "sp";
|
return "sp";
|
||||||
#elif defined(GP_ARCH_mips64)
|
# elif defined(GP_ARCH_mips64)
|
||||||
case DW_REG_MIPS_SP:
|
case DW_REG_MIPS_SP:
|
||||||
return "sp";
|
return "sp";
|
||||||
case DW_REG_MIPS_FP:
|
case DW_REG_MIPS_FP:
|
||||||
return "fp";
|
return "fp";
|
||||||
case DW_REG_MIPS_PC:
|
case DW_REG_MIPS_PC:
|
||||||
return "pc";
|
return "pc";
|
||||||
#else
|
# else
|
||||||
# error "Unsupported arch"
|
# error "Unsupported arch"
|
||||||
#endif
|
# endif
|
||||||
default:
|
default:
|
||||||
return "???";
|
return "???";
|
||||||
}
|
}
|
||||||
|
@ -138,28 +140,28 @@ void RuleSet::Print(void (*aLog)(const char*)) const {
|
||||||
res += mCfaExpr.ShowRule("cfa");
|
res += mCfaExpr.ShowRule("cfa");
|
||||||
res += " in";
|
res += " in";
|
||||||
// For each reg we care about, print the recovery expression.
|
// For each reg we care about, print the recovery expression.
|
||||||
#if defined(GP_ARCH_amd64) || defined(GP_ARCH_x86)
|
# if defined(GP_ARCH_amd64) || defined(GP_ARCH_x86)
|
||||||
res += mXipExpr.ShowRule(" RA");
|
res += mXipExpr.ShowRule(" RA");
|
||||||
res += mXspExpr.ShowRule(" SP");
|
res += mXspExpr.ShowRule(" SP");
|
||||||
res += mXbpExpr.ShowRule(" BP");
|
res += mXbpExpr.ShowRule(" BP");
|
||||||
#elif defined(GP_ARCH_arm)
|
# elif defined(GP_ARCH_arm)
|
||||||
res += mR15expr.ShowRule(" R15");
|
res += mR15expr.ShowRule(" R15");
|
||||||
res += mR7expr.ShowRule(" R7");
|
res += mR7expr.ShowRule(" R7");
|
||||||
res += mR11expr.ShowRule(" R11");
|
res += mR11expr.ShowRule(" R11");
|
||||||
res += mR12expr.ShowRule(" R12");
|
res += mR12expr.ShowRule(" R12");
|
||||||
res += mR13expr.ShowRule(" R13");
|
res += mR13expr.ShowRule(" R13");
|
||||||
res += mR14expr.ShowRule(" R14");
|
res += mR14expr.ShowRule(" R14");
|
||||||
#elif defined(GP_ARCH_arm64)
|
# elif defined(GP_ARCH_arm64)
|
||||||
res += mX29expr.ShowRule(" X29");
|
res += mX29expr.ShowRule(" X29");
|
||||||
res += mX30expr.ShowRule(" X30");
|
res += mX30expr.ShowRule(" X30");
|
||||||
res += mSPexpr.ShowRule(" SP");
|
res += mSPexpr.ShowRule(" SP");
|
||||||
#elif defined(GP_ARCH_mips64)
|
# elif defined(GP_ARCH_mips64)
|
||||||
res += mPCexpr.ShowRule(" PC");
|
res += mPCexpr.ShowRule(" PC");
|
||||||
res += mSPexpr.ShowRule(" SP");
|
res += mSPexpr.ShowRule(" SP");
|
||||||
res += mFPexpr.ShowRule(" FP");
|
res += mFPexpr.ShowRule(" FP");
|
||||||
#else
|
# else
|
||||||
# error "Unsupported arch"
|
# error "Unsupported arch"
|
||||||
#endif
|
# endif
|
||||||
aLog(res.c_str());
|
aLog(res.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,14 +169,14 @@ LExpr* RuleSet::ExprForRegno(DW_REG_NUMBER aRegno) {
|
||||||
switch (aRegno) {
|
switch (aRegno) {
|
||||||
case DW_REG_CFA:
|
case DW_REG_CFA:
|
||||||
return &mCfaExpr;
|
return &mCfaExpr;
|
||||||
#if defined(GP_ARCH_amd64) || defined(GP_ARCH_x86)
|
# if defined(GP_ARCH_amd64) || defined(GP_ARCH_x86)
|
||||||
case DW_REG_INTEL_XIP:
|
case DW_REG_INTEL_XIP:
|
||||||
return &mXipExpr;
|
return &mXipExpr;
|
||||||
case DW_REG_INTEL_XSP:
|
case DW_REG_INTEL_XSP:
|
||||||
return &mXspExpr;
|
return &mXspExpr;
|
||||||
case DW_REG_INTEL_XBP:
|
case DW_REG_INTEL_XBP:
|
||||||
return &mXbpExpr;
|
return &mXbpExpr;
|
||||||
#elif defined(GP_ARCH_arm)
|
# elif defined(GP_ARCH_arm)
|
||||||
case DW_REG_ARM_R15:
|
case DW_REG_ARM_R15:
|
||||||
return &mR15expr;
|
return &mR15expr;
|
||||||
case DW_REG_ARM_R14:
|
case DW_REG_ARM_R14:
|
||||||
|
@ -187,23 +189,23 @@ LExpr* RuleSet::ExprForRegno(DW_REG_NUMBER aRegno) {
|
||||||
return &mR11expr;
|
return &mR11expr;
|
||||||
case DW_REG_ARM_R7:
|
case DW_REG_ARM_R7:
|
||||||
return &mR7expr;
|
return &mR7expr;
|
||||||
#elif defined(GP_ARCH_arm64)
|
# elif defined(GP_ARCH_arm64)
|
||||||
case DW_REG_AARCH64_X29:
|
case DW_REG_AARCH64_X29:
|
||||||
return &mX29expr;
|
return &mX29expr;
|
||||||
case DW_REG_AARCH64_X30:
|
case DW_REG_AARCH64_X30:
|
||||||
return &mX30expr;
|
return &mX30expr;
|
||||||
case DW_REG_AARCH64_SP:
|
case DW_REG_AARCH64_SP:
|
||||||
return &mSPexpr;
|
return &mSPexpr;
|
||||||
#elif defined(GP_ARCH_mips64)
|
# elif defined(GP_ARCH_mips64)
|
||||||
case DW_REG_MIPS_SP:
|
case DW_REG_MIPS_SP:
|
||||||
return &mSPexpr;
|
return &mSPexpr;
|
||||||
case DW_REG_MIPS_FP:
|
case DW_REG_MIPS_FP:
|
||||||
return &mFPexpr;
|
return &mFPexpr;
|
||||||
case DW_REG_MIPS_PC:
|
case DW_REG_MIPS_PC:
|
||||||
return &mPCexpr;
|
return &mPCexpr;
|
||||||
#else
|
# else
|
||||||
# error "Unknown arch"
|
# error "Unknown arch"
|
||||||
#endif
|
# endif
|
||||||
default:
|
default:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -364,7 +366,7 @@ void SecMap::PrepareRuleSets(uintptr_t aStart, size_t aLen) {
|
||||||
|
|
||||||
size_t n = mRuleSets.size();
|
size_t n = mRuleSets.size();
|
||||||
|
|
||||||
#ifdef DEBUG
|
# ifdef DEBUG
|
||||||
// Do a final check on the rules: their address ranges must be
|
// Do a final check on the rules: their address ranges must be
|
||||||
// ascending, non overlapping, non zero sized.
|
// ascending, non overlapping, non zero sized.
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
|
@ -377,7 +379,7 @@ void SecMap::PrepareRuleSets(uintptr_t aStart, size_t aLen) {
|
||||||
MOZ_ASSERT(prev->mAddr + prev->mLen <= here->mAddr);
|
MOZ_ASSERT(prev->mAddr + prev->mLen <= here->mAddr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
// Set the summary min and max address values.
|
// Set the summary min and max address values.
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
|
@ -398,14 +400,14 @@ void SecMap::PrepareRuleSets(uintptr_t aStart, size_t aLen) {
|
||||||
// Is now usable for binary search.
|
// Is now usable for binary search.
|
||||||
mUsable = true;
|
mUsable = true;
|
||||||
|
|
||||||
#if 0
|
# if 0
|
||||||
mLog("\nRulesets after preening\n");
|
mLog("\nRulesets after preening\n");
|
||||||
for (size_t i = 0; i < mRuleSets.size(); ++i) {
|
for (size_t i = 0; i < mRuleSets.size(); ++i) {
|
||||||
mRuleSets[i].Print(mLog);
|
mRuleSets[i].Print(mLog);
|
||||||
mLog("\n");
|
mLog("\n");
|
||||||
}
|
}
|
||||||
mLog("\n");
|
mLog("\n");
|
||||||
#endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SecMap::IsEmpty() { return mRuleSets.empty(); }
|
bool SecMap::IsEmpty() { return mRuleSets.empty(); }
|
||||||
|
@ -684,15 +686,15 @@ class PriMap {
|
||||||
// LUL //
|
// LUL //
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#define LUL_LOG(_str) \
|
# define LUL_LOG(_str) \
|
||||||
do { \
|
do { \
|
||||||
char buf[200]; \
|
char buf[200]; \
|
||||||
SprintfLiteral(buf, "LUL: pid %d tid %d lul-obj %p: %s", \
|
SprintfLiteral(buf, "LUL: pid %d tid %d lul-obj %p: %s", \
|
||||||
profiler_current_process_id(), \
|
profiler_current_process_id(), \
|
||||||
profiler_current_thread_id(), this, (_str)); \
|
profiler_current_thread_id(), this, (_str)); \
|
||||||
buf[sizeof(buf) - 1] = 0; \
|
buf[sizeof(buf) - 1] = 0; \
|
||||||
mLog(buf); \
|
mLog(buf); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
LUL::LUL(void (*aLog)(const char*))
|
LUL::LUL(void (*aLog)(const char*))
|
||||||
: mLog(aLog),
|
: mLog(aLog),
|
||||||
|
@ -896,14 +898,14 @@ static TaggedUWord EvaluateReg(int16_t aReg, const UnwindRegs* aOldRegs,
|
||||||
switch (aReg) {
|
switch (aReg) {
|
||||||
case DW_REG_CFA:
|
case DW_REG_CFA:
|
||||||
return aCFA;
|
return aCFA;
|
||||||
#if defined(GP_ARCH_amd64) || defined(GP_ARCH_x86)
|
# if defined(GP_ARCH_amd64) || defined(GP_ARCH_x86)
|
||||||
case DW_REG_INTEL_XBP:
|
case DW_REG_INTEL_XBP:
|
||||||
return aOldRegs->xbp;
|
return aOldRegs->xbp;
|
||||||
case DW_REG_INTEL_XSP:
|
case DW_REG_INTEL_XSP:
|
||||||
return aOldRegs->xsp;
|
return aOldRegs->xsp;
|
||||||
case DW_REG_INTEL_XIP:
|
case DW_REG_INTEL_XIP:
|
||||||
return aOldRegs->xip;
|
return aOldRegs->xip;
|
||||||
#elif defined(GP_ARCH_arm)
|
# elif defined(GP_ARCH_arm)
|
||||||
case DW_REG_ARM_R7:
|
case DW_REG_ARM_R7:
|
||||||
return aOldRegs->r7;
|
return aOldRegs->r7;
|
||||||
case DW_REG_ARM_R11:
|
case DW_REG_ARM_R11:
|
||||||
|
@ -916,23 +918,23 @@ static TaggedUWord EvaluateReg(int16_t aReg, const UnwindRegs* aOldRegs,
|
||||||
return aOldRegs->r14;
|
return aOldRegs->r14;
|
||||||
case DW_REG_ARM_R15:
|
case DW_REG_ARM_R15:
|
||||||
return aOldRegs->r15;
|
return aOldRegs->r15;
|
||||||
#elif defined(GP_ARCH_arm64)
|
# elif defined(GP_ARCH_arm64)
|
||||||
case DW_REG_AARCH64_X29:
|
case DW_REG_AARCH64_X29:
|
||||||
return aOldRegs->x29;
|
return aOldRegs->x29;
|
||||||
case DW_REG_AARCH64_X30:
|
case DW_REG_AARCH64_X30:
|
||||||
return aOldRegs->x30;
|
return aOldRegs->x30;
|
||||||
case DW_REG_AARCH64_SP:
|
case DW_REG_AARCH64_SP:
|
||||||
return aOldRegs->sp;
|
return aOldRegs->sp;
|
||||||
#elif defined(GP_ARCH_mips64)
|
# elif defined(GP_ARCH_mips64)
|
||||||
case DW_REG_MIPS_SP:
|
case DW_REG_MIPS_SP:
|
||||||
return aOldRegs->sp;
|
return aOldRegs->sp;
|
||||||
case DW_REG_MIPS_FP:
|
case DW_REG_MIPS_FP:
|
||||||
return aOldRegs->fp;
|
return aOldRegs->fp;
|
||||||
case DW_REG_MIPS_PC:
|
case DW_REG_MIPS_PC:
|
||||||
return aOldRegs->pc;
|
return aOldRegs->pc;
|
||||||
#else
|
# else
|
||||||
# error "Unsupported arch"
|
# error "Unsupported arch"
|
||||||
#endif
|
# endif
|
||||||
default:
|
default:
|
||||||
MOZ_ASSERT(0);
|
MOZ_ASSERT(0);
|
||||||
return TaggedUWord();
|
return TaggedUWord();
|
||||||
|
@ -951,17 +953,17 @@ TaggedUWord EvaluatePfxExpr(int32_t start, const UnwindRegs* aOldRegs,
|
||||||
int stackPointer = -1;
|
int stackPointer = -1;
|
||||||
for (int i = 0; i < N_STACK; i++) stack[i] = TaggedUWord();
|
for (int i = 0; i < N_STACK; i++) stack[i] = TaggedUWord();
|
||||||
|
|
||||||
#define PUSH(_tuw) \
|
# define PUSH(_tuw) \
|
||||||
do { \
|
do { \
|
||||||
if (stackPointer >= N_STACK - 1) goto fail; /* overflow */ \
|
if (stackPointer >= N_STACK - 1) goto fail; /* overflow */ \
|
||||||
stack[++stackPointer] = (_tuw); \
|
stack[++stackPointer] = (_tuw); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define POP(_lval) \
|
# define POP(_lval) \
|
||||||
do { \
|
do { \
|
||||||
if (stackPointer < 0) goto fail; /* underflow */ \
|
if (stackPointer < 0) goto fail; /* underflow */ \
|
||||||
_lval = stack[stackPointer--]; \
|
_lval = stack[stackPointer--]; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
// Cursor in the instruction sequence.
|
// Cursor in the instruction sequence.
|
||||||
size_t curr = start + 1;
|
size_t curr = start + 1;
|
||||||
|
@ -1067,8 +1069,8 @@ TaggedUWord EvaluatePfxExpr(int32_t start, const UnwindRegs* aOldRegs,
|
||||||
fail:
|
fail:
|
||||||
return TaggedUWord();
|
return TaggedUWord();
|
||||||
|
|
||||||
#undef PUSH
|
# undef PUSH
|
||||||
#undef POP
|
# undef POP
|
||||||
}
|
}
|
||||||
|
|
||||||
// RUNS IN NO-MALLOC CONTEXT
|
// RUNS IN NO-MALLOC CONTEXT
|
||||||
|
@ -1113,29 +1115,29 @@ static void UseRuleSet(/*MOD*/ UnwindRegs* aRegs, const StackImage* aStackImg,
|
||||||
// anew. If we don't even manage to compute a new PC value, then
|
// anew. If we don't even manage to compute a new PC value, then
|
||||||
// the caller will have to abandon the unwind.
|
// the caller will have to abandon the unwind.
|
||||||
// FIXME: Create and use instead: aRegs->SetAllInvalid();
|
// FIXME: Create and use instead: aRegs->SetAllInvalid();
|
||||||
#if defined(GP_ARCH_amd64) || defined(GP_ARCH_x86)
|
# if defined(GP_ARCH_amd64) || defined(GP_ARCH_x86)
|
||||||
aRegs->xbp = TaggedUWord();
|
aRegs->xbp = TaggedUWord();
|
||||||
aRegs->xsp = TaggedUWord();
|
aRegs->xsp = TaggedUWord();
|
||||||
aRegs->xip = TaggedUWord();
|
aRegs->xip = TaggedUWord();
|
||||||
#elif defined(GP_ARCH_arm)
|
# elif defined(GP_ARCH_arm)
|
||||||
aRegs->r7 = TaggedUWord();
|
aRegs->r7 = TaggedUWord();
|
||||||
aRegs->r11 = TaggedUWord();
|
aRegs->r11 = TaggedUWord();
|
||||||
aRegs->r12 = TaggedUWord();
|
aRegs->r12 = TaggedUWord();
|
||||||
aRegs->r13 = TaggedUWord();
|
aRegs->r13 = TaggedUWord();
|
||||||
aRegs->r14 = TaggedUWord();
|
aRegs->r14 = TaggedUWord();
|
||||||
aRegs->r15 = TaggedUWord();
|
aRegs->r15 = TaggedUWord();
|
||||||
#elif defined(GP_ARCH_arm64)
|
# elif defined(GP_ARCH_arm64)
|
||||||
aRegs->x29 = TaggedUWord();
|
aRegs->x29 = TaggedUWord();
|
||||||
aRegs->x30 = TaggedUWord();
|
aRegs->x30 = TaggedUWord();
|
||||||
aRegs->sp = TaggedUWord();
|
aRegs->sp = TaggedUWord();
|
||||||
aRegs->pc = TaggedUWord();
|
aRegs->pc = TaggedUWord();
|
||||||
#elif defined(GP_ARCH_mips64)
|
# elif defined(GP_ARCH_mips64)
|
||||||
aRegs->sp = TaggedUWord();
|
aRegs->sp = TaggedUWord();
|
||||||
aRegs->fp = TaggedUWord();
|
aRegs->fp = TaggedUWord();
|
||||||
aRegs->pc = TaggedUWord();
|
aRegs->pc = TaggedUWord();
|
||||||
#else
|
# else
|
||||||
# error "Unsupported arch"
|
# error "Unsupported arch"
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
// This is generally useful.
|
// This is generally useful.
|
||||||
const TaggedUWord inval = TaggedUWord();
|
const TaggedUWord inval = TaggedUWord();
|
||||||
|
@ -1149,14 +1151,14 @@ static void UseRuleSet(/*MOD*/ UnwindRegs* aRegs, const StackImage* aStackImg,
|
||||||
// value rules mention the CFA. In any case, compute the new values
|
// value rules mention the CFA. In any case, compute the new values
|
||||||
// for each register that we're tracking.
|
// for each register that we're tracking.
|
||||||
|
|
||||||
#if defined(GP_ARCH_amd64) || defined(GP_ARCH_x86)
|
# if defined(GP_ARCH_amd64) || defined(GP_ARCH_x86)
|
||||||
aRegs->xbp =
|
aRegs->xbp =
|
||||||
aRS->mXbpExpr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
aRS->mXbpExpr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
||||||
aRegs->xsp =
|
aRegs->xsp =
|
||||||
aRS->mXspExpr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
aRS->mXspExpr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
||||||
aRegs->xip =
|
aRegs->xip =
|
||||||
aRS->mXipExpr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
aRS->mXipExpr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
||||||
#elif defined(GP_ARCH_arm)
|
# elif defined(GP_ARCH_arm)
|
||||||
aRegs->r7 = aRS->mR7expr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
aRegs->r7 = aRS->mR7expr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
||||||
aRegs->r11 =
|
aRegs->r11 =
|
||||||
aRS->mR11expr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
aRS->mR11expr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
||||||
|
@ -1168,19 +1170,19 @@ static void UseRuleSet(/*MOD*/ UnwindRegs* aRegs, const StackImage* aStackImg,
|
||||||
aRS->mR14expr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
aRS->mR14expr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
||||||
aRegs->r15 =
|
aRegs->r15 =
|
||||||
aRS->mR15expr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
aRS->mR15expr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
||||||
#elif defined(GP_ARCH_arm64)
|
# elif defined(GP_ARCH_arm64)
|
||||||
aRegs->x29 =
|
aRegs->x29 =
|
||||||
aRS->mX29expr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
aRS->mX29expr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
||||||
aRegs->x30 =
|
aRegs->x30 =
|
||||||
aRS->mX30expr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
aRS->mX30expr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
||||||
aRegs->sp = aRS->mSPexpr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
aRegs->sp = aRS->mSPexpr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
||||||
#elif defined(GP_ARCH_mips64)
|
# elif defined(GP_ARCH_mips64)
|
||||||
aRegs->sp = aRS->mSPexpr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
aRegs->sp = aRS->mSPexpr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
||||||
aRegs->fp = aRS->mFPexpr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
aRegs->fp = aRS->mFPexpr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
||||||
aRegs->pc = aRS->mPCexpr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
aRegs->pc = aRS->mPCexpr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
||||||
#else
|
# else
|
||||||
# error "Unsupported arch"
|
# error "Unsupported arch"
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
// We're done. Any regs for which we didn't manage to compute a
|
// We're done. Any regs for which we didn't manage to compute a
|
||||||
// new value will now be marked as invalid.
|
// new value will now be marked as invalid.
|
||||||
|
@ -1207,7 +1209,7 @@ void LUL::Unwind(/*OUT*/ uintptr_t* aFramePCs,
|
||||||
if (DEBUG_MAIN) {
|
if (DEBUG_MAIN) {
|
||||||
char buf[300];
|
char buf[300];
|
||||||
mLog("\n");
|
mLog("\n");
|
||||||
#if defined(GP_ARCH_amd64) || defined(GP_ARCH_x86)
|
# if defined(GP_ARCH_amd64) || defined(GP_ARCH_x86)
|
||||||
SprintfLiteral(
|
SprintfLiteral(
|
||||||
buf, "LoopTop: rip %d/%llx rsp %d/%llx rbp %d/%llx\n",
|
buf, "LoopTop: rip %d/%llx rsp %d/%llx rbp %d/%llx\n",
|
||||||
(int)regs.xip.Valid(), (unsigned long long int)regs.xip.Value(),
|
(int)regs.xip.Valid(), (unsigned long long int)regs.xip.Value(),
|
||||||
|
@ -1215,7 +1217,7 @@ void LUL::Unwind(/*OUT*/ uintptr_t* aFramePCs,
|
||||||
(int)regs.xbp.Valid(), (unsigned long long int)regs.xbp.Value());
|
(int)regs.xbp.Valid(), (unsigned long long int)regs.xbp.Value());
|
||||||
buf[sizeof(buf) - 1] = 0;
|
buf[sizeof(buf) - 1] = 0;
|
||||||
mLog(buf);
|
mLog(buf);
|
||||||
#elif defined(GP_ARCH_arm)
|
# elif defined(GP_ARCH_arm)
|
||||||
SprintfLiteral(
|
SprintfLiteral(
|
||||||
buf,
|
buf,
|
||||||
"LoopTop: r15 %d/%llx r7 %d/%llx r11 %d/%llx"
|
"LoopTop: r15 %d/%llx r7 %d/%llx r11 %d/%llx"
|
||||||
|
@ -1228,7 +1230,7 @@ void LUL::Unwind(/*OUT*/ uintptr_t* aFramePCs,
|
||||||
(int)regs.r14.Valid(), (unsigned long long int)regs.r14.Value());
|
(int)regs.r14.Valid(), (unsigned long long int)regs.r14.Value());
|
||||||
buf[sizeof(buf) - 1] = 0;
|
buf[sizeof(buf) - 1] = 0;
|
||||||
mLog(buf);
|
mLog(buf);
|
||||||
#elif defined(GP_ARCH_arm64)
|
# elif defined(GP_ARCH_arm64)
|
||||||
SprintfLiteral(
|
SprintfLiteral(
|
||||||
buf,
|
buf,
|
||||||
"LoopTop: pc %d/%llx x29 %d/%llx x30 %d/%llx"
|
"LoopTop: pc %d/%llx x29 %d/%llx x30 %d/%llx"
|
||||||
|
@ -1239,7 +1241,7 @@ void LUL::Unwind(/*OUT*/ uintptr_t* aFramePCs,
|
||||||
(int)regs.sp.Valid(), (unsigned long long int)regs.sp.Value());
|
(int)regs.sp.Valid(), (unsigned long long int)regs.sp.Value());
|
||||||
buf[sizeof(buf) - 1] = 0;
|
buf[sizeof(buf) - 1] = 0;
|
||||||
mLog(buf);
|
mLog(buf);
|
||||||
#elif defined(GP_ARCH_mips64)
|
# elif defined(GP_ARCH_mips64)
|
||||||
SprintfLiteral(
|
SprintfLiteral(
|
||||||
buf, "LoopTop: pc %d/%llx sp %d/%llx fp %d/%llx\n",
|
buf, "LoopTop: pc %d/%llx sp %d/%llx fp %d/%llx\n",
|
||||||
(int)regs.pc.Valid(), (unsigned long long int)regs.pc.Value(),
|
(int)regs.pc.Valid(), (unsigned long long int)regs.pc.Value(),
|
||||||
|
@ -1247,26 +1249,26 @@ void LUL::Unwind(/*OUT*/ uintptr_t* aFramePCs,
|
||||||
(int)regs.fp.Valid(), (unsigned long long int)regs.fp.Value());
|
(int)regs.fp.Valid(), (unsigned long long int)regs.fp.Value());
|
||||||
buf[sizeof(buf) - 1] = 0;
|
buf[sizeof(buf) - 1] = 0;
|
||||||
mLog(buf);
|
mLog(buf);
|
||||||
#else
|
# else
|
||||||
# error "Unsupported arch"
|
# error "Unsupported arch"
|
||||||
#endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(GP_ARCH_amd64) || defined(GP_ARCH_x86)
|
# if defined(GP_ARCH_amd64) || defined(GP_ARCH_x86)
|
||||||
TaggedUWord ia = regs.xip;
|
TaggedUWord ia = regs.xip;
|
||||||
TaggedUWord sp = regs.xsp;
|
TaggedUWord sp = regs.xsp;
|
||||||
#elif defined(GP_ARCH_arm)
|
# elif defined(GP_ARCH_arm)
|
||||||
TaggedUWord ia = (*aFramesUsed == 0 ? regs.r15 : regs.r14);
|
TaggedUWord ia = (*aFramesUsed == 0 ? regs.r15 : regs.r14);
|
||||||
TaggedUWord sp = regs.r13;
|
TaggedUWord sp = regs.r13;
|
||||||
#elif defined(GP_ARCH_arm64)
|
# elif defined(GP_ARCH_arm64)
|
||||||
TaggedUWord ia = (*aFramesUsed == 0 ? regs.pc : regs.x30);
|
TaggedUWord ia = (*aFramesUsed == 0 ? regs.pc : regs.x30);
|
||||||
TaggedUWord sp = regs.sp;
|
TaggedUWord sp = regs.sp;
|
||||||
#elif defined(GP_ARCH_mips64)
|
# elif defined(GP_ARCH_mips64)
|
||||||
TaggedUWord ia = regs.pc;
|
TaggedUWord ia = regs.pc;
|
||||||
TaggedUWord sp = regs.sp;
|
TaggedUWord sp = regs.sp;
|
||||||
#else
|
# else
|
||||||
# error "Unsupported arch"
|
# error "Unsupported arch"
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
if (*aFramesUsed >= aFramesAvail) {
|
if (*aFramesUsed >= aFramesAvail) {
|
||||||
break;
|
break;
|
||||||
|
@ -1325,7 +1327,7 @@ void LUL::Unwind(/*OUT*/ uintptr_t* aFramePCs,
|
||||||
mLog(buf);
|
mLog(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(GP_PLAT_x86_android) || defined(GP_PLAT_x86_linux)
|
# if defined(GP_PLAT_x86_android) || defined(GP_PLAT_x86_linux)
|
||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
////
|
////
|
||||||
// On 32 bit x86-linux, syscalls are often done via the VDSO
|
// On 32 bit x86-linux, syscalls are often done via the VDSO
|
||||||
|
@ -1394,7 +1396,7 @@ void LUL::Unwind(/*OUT*/ uintptr_t* aFramePCs,
|
||||||
}
|
}
|
||||||
////
|
////
|
||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
#endif // defined(GP_PLAT_x86_android) || defined(GP_PLAT_x86_linux)
|
# endif // defined(GP_PLAT_x86_android) || defined(GP_PLAT_x86_linux)
|
||||||
|
|
||||||
// So, do we have a ruleset for this address? If so, use it now.
|
// So, do we have a ruleset for this address? If so, use it now.
|
||||||
if (ruleset) {
|
if (ruleset) {
|
||||||
|
@ -1408,7 +1410,7 @@ void LUL::Unwind(/*OUT*/ uintptr_t* aFramePCs,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(GP_PLAT_amd64_linux) || defined(GP_PLAT_x86_linux)
|
# if defined(GP_PLAT_amd64_linux) || defined(GP_PLAT_x86_linux)
|
||||||
// There's no RuleSet for the specified address. On amd64/x86_linux, see if
|
// There's no RuleSet for the specified address. On amd64/x86_linux, see if
|
||||||
// it's possible to recover the caller's frame by using the frame pointer.
|
// it's possible to recover the caller's frame by using the frame pointer.
|
||||||
|
|
||||||
|
@ -1457,7 +1459,7 @@ void LUL::Unwind(/*OUT*/ uintptr_t* aFramePCs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#elif defined(GP_ARCH_arm64)
|
# elif defined(GP_ARCH_arm64)
|
||||||
// Here is an example of generated code for prologue and epilogue..
|
// Here is an example of generated code for prologue and epilogue..
|
||||||
//
|
//
|
||||||
// stp x29, x30, [sp, #-16]!
|
// stp x29, x30, [sp, #-16]!
|
||||||
|
@ -1518,7 +1520,7 @@ void LUL::Unwind(/*OUT*/ uintptr_t* aFramePCs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // defined(GP_PLAT_amd64_linux) || defined(GP_PLAT_x86_linux)
|
# endif // defined(GP_PLAT_amd64_linux) || defined(GP_PLAT_x86_linux)
|
||||||
|
|
||||||
// We failed to recover a frame either using CFI or FP chasing, and we
|
// We failed to recover a frame either using CFI or FP chasing, and we
|
||||||
// have no other ways to recover the frame. So we have to give up.
|
// have no other ways to recover the frame. So we have to give up.
|
||||||
|
@ -1536,13 +1538,13 @@ void LUL::Unwind(/*OUT*/ uintptr_t* aFramePCs,
|
||||||
|
|
||||||
static const int LUL_UNIT_TEST_STACK_SIZE = 32768;
|
static const int LUL_UNIT_TEST_STACK_SIZE = 32768;
|
||||||
|
|
||||||
#if defined(GP_ARCH_mips64)
|
# if defined(GP_ARCH_mips64)
|
||||||
static __attribute__((noinline)) unsigned long __getpc(void) {
|
static __attribute__((noinline)) unsigned long __getpc(void) {
|
||||||
unsigned long rtaddr;
|
unsigned long rtaddr;
|
||||||
__asm__ volatile("move %0, $31" : "=r"(rtaddr));
|
__asm__ volatile("move %0, $31" : "=r"(rtaddr));
|
||||||
return rtaddr;
|
return rtaddr;
|
||||||
}
|
}
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
// This function is innermost in the test call sequence. It uses LUL
|
// This function is innermost in the test call sequence. It uses LUL
|
||||||
// to unwind, and compares the result with the sequence specified in
|
// to unwind, and compares the result with the sequence specified in
|
||||||
|
@ -1561,7 +1563,7 @@ static __attribute__((noinline)) bool GetAndCheckStackTrace(
|
||||||
// Get hold of the current unwind-start registers.
|
// Get hold of the current unwind-start registers.
|
||||||
UnwindRegs startRegs;
|
UnwindRegs startRegs;
|
||||||
memset(&startRegs, 0, sizeof(startRegs));
|
memset(&startRegs, 0, sizeof(startRegs));
|
||||||
#if defined(GP_ARCH_amd64)
|
# if defined(GP_ARCH_amd64)
|
||||||
volatile uintptr_t block[3];
|
volatile uintptr_t block[3];
|
||||||
MOZ_ASSERT(sizeof(block) == 24);
|
MOZ_ASSERT(sizeof(block) == 24);
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
|
@ -1581,7 +1583,7 @@ static __attribute__((noinline)) bool GetAndCheckStackTrace(
|
||||||
startRegs.xbp = TaggedUWord(block[2]);
|
startRegs.xbp = TaggedUWord(block[2]);
|
||||||
const uintptr_t REDZONE_SIZE = 128;
|
const uintptr_t REDZONE_SIZE = 128;
|
||||||
uintptr_t start = block[1] - REDZONE_SIZE;
|
uintptr_t start = block[1] - REDZONE_SIZE;
|
||||||
#elif defined(GP_PLAT_x86_linux) || defined(GP_PLAT_x86_android)
|
# elif defined(GP_PLAT_x86_linux) || defined(GP_PLAT_x86_android)
|
||||||
volatile uintptr_t block[3];
|
volatile uintptr_t block[3];
|
||||||
MOZ_ASSERT(sizeof(block) == 12);
|
MOZ_ASSERT(sizeof(block) == 12);
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
|
@ -1603,7 +1605,7 @@ static __attribute__((noinline)) bool GetAndCheckStackTrace(
|
||||||
startRegs.xbp = TaggedUWord(block[2]);
|
startRegs.xbp = TaggedUWord(block[2]);
|
||||||
const uintptr_t REDZONE_SIZE = 0;
|
const uintptr_t REDZONE_SIZE = 0;
|
||||||
uintptr_t start = block[1] - REDZONE_SIZE;
|
uintptr_t start = block[1] - REDZONE_SIZE;
|
||||||
#elif defined(GP_PLAT_arm_linux) || defined(GP_PLAT_arm_android)
|
# elif defined(GP_PLAT_arm_linux) || defined(GP_PLAT_arm_android)
|
||||||
volatile uintptr_t block[6];
|
volatile uintptr_t block[6];
|
||||||
MOZ_ASSERT(sizeof(block) == 24);
|
MOZ_ASSERT(sizeof(block) == 24);
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
|
@ -1632,7 +1634,7 @@ static __attribute__((noinline)) bool GetAndCheckStackTrace(
|
||||||
startRegs.r7 = TaggedUWord(block[5]);
|
startRegs.r7 = TaggedUWord(block[5]);
|
||||||
const uintptr_t REDZONE_SIZE = 0;
|
const uintptr_t REDZONE_SIZE = 0;
|
||||||
uintptr_t start = block[1] - REDZONE_SIZE;
|
uintptr_t start = block[1] - REDZONE_SIZE;
|
||||||
#elif defined(GP_ARCH_arm64)
|
# elif defined(GP_ARCH_arm64)
|
||||||
volatile uintptr_t block[4];
|
volatile uintptr_t block[4];
|
||||||
MOZ_ASSERT(sizeof(block) == 32);
|
MOZ_ASSERT(sizeof(block) == 32);
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
|
@ -1651,7 +1653,7 @@ static __attribute__((noinline)) bool GetAndCheckStackTrace(
|
||||||
startRegs.sp = TaggedUWord(block[3]);
|
startRegs.sp = TaggedUWord(block[3]);
|
||||||
const uintptr_t REDZONE_SIZE = 0;
|
const uintptr_t REDZONE_SIZE = 0;
|
||||||
uintptr_t start = block[1] - REDZONE_SIZE;
|
uintptr_t start = block[1] - REDZONE_SIZE;
|
||||||
#elif defined(GP_ARCH_mips64)
|
# elif defined(GP_ARCH_mips64)
|
||||||
volatile uintptr_t block[3];
|
volatile uintptr_t block[3];
|
||||||
MOZ_ASSERT(sizeof(block) == 24);
|
MOZ_ASSERT(sizeof(block) == 24);
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
|
@ -1666,9 +1668,9 @@ static __attribute__((noinline)) bool GetAndCheckStackTrace(
|
||||||
startRegs.fp = TaggedUWord(block[2]);
|
startRegs.fp = TaggedUWord(block[2]);
|
||||||
const uintptr_t REDZONE_SIZE = 0;
|
const uintptr_t REDZONE_SIZE = 0;
|
||||||
uintptr_t start = block[1] - REDZONE_SIZE;
|
uintptr_t start = block[1] - REDZONE_SIZE;
|
||||||
#else
|
# else
|
||||||
# error "Unsupported platform"
|
# error "Unsupported platform"
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
// Get hold of the innermost LUL_UNIT_TEST_STACK_SIZE bytes of the
|
// Get hold of the innermost LUL_UNIT_TEST_STACK_SIZE bytes of the
|
||||||
// stack.
|
// stack.
|
||||||
|
@ -1796,77 +1798,78 @@ static __attribute__((noinline)) bool GetAndCheckStackTrace(
|
||||||
// results on |aLUL|'s logging sink, and also returns a boolean
|
// results on |aLUL|'s logging sink, and also returns a boolean
|
||||||
// indicating whether or not the results are acceptable (correct).
|
// indicating whether or not the results are acceptable (correct).
|
||||||
|
|
||||||
#define DECL_TEST_FN(NAME) \
|
# define DECL_TEST_FN(NAME) \
|
||||||
bool NAME(LUL* aLUL, const char* strPorig, const char* strP);
|
bool NAME(LUL* aLUL, const char* strPorig, const char* strP);
|
||||||
|
|
||||||
#define GEN_TEST_FN(NAME, FRAMESIZE) \
|
# define GEN_TEST_FN(NAME, FRAMESIZE) \
|
||||||
bool NAME(LUL* aLUL, const char* strPorig, const char* strP) { \
|
bool NAME(LUL* aLUL, const char* strPorig, const char* strP) { \
|
||||||
/* Create a frame of size (at least) FRAMESIZE, so that the */ \
|
/* Create a frame of size (at least) FRAMESIZE, so that the */ \
|
||||||
/* 8 functions created by this macro offer some variation in frame */ \
|
/* 8 functions created by this macro offer some variation in frame */ \
|
||||||
/* sizes. This isn't as simple as it might seem, since a clever */ \
|
/* sizes. This isn't as simple as it might seem, since a clever */ \
|
||||||
/* optimizing compiler (eg, clang-5) detects that the array is unused */ \
|
/* optimizing compiler (eg, clang-5) detects that the array is unused */ \
|
||||||
/* and removes it. We try to defeat this by passing it to a function */ \
|
/* and removes it. We try to defeat this by passing it to a function */ \
|
||||||
/* in a different compilation unit, and hoping that clang does not */ \
|
/* in a different compilation unit, and hoping that clang does not */ \
|
||||||
/* notice that the call is a no-op. */ \
|
/* notice that the call is a no-op. */ \
|
||||||
char space[FRAMESIZE]; \
|
char space[FRAMESIZE]; \
|
||||||
Unused << write(1, space, 0); /* write zero bytes of |space| to stdout */ \
|
Unused << write(1, space, \
|
||||||
\
|
0); /* write zero bytes of |space| to stdout */ \
|
||||||
if (*strP == '\0') { \
|
\
|
||||||
/* We've come to the end of the director string. */ \
|
if (*strP == '\0') { \
|
||||||
/* Take a stack snapshot. */ \
|
/* We've come to the end of the director string. */ \
|
||||||
return GetAndCheckStackTrace(aLUL, strPorig); \
|
/* Take a stack snapshot. */ \
|
||||||
} else { \
|
return GetAndCheckStackTrace(aLUL, strPorig); \
|
||||||
/* Recurse onwards. This is a bit subtle. The obvious */ \
|
} else { \
|
||||||
/* thing to do here is call onwards directly, from within the */ \
|
/* Recurse onwards. This is a bit subtle. The obvious */ \
|
||||||
/* arms of the case statement. That gives a problem in that */ \
|
/* thing to do here is call onwards directly, from within the */ \
|
||||||
/* there will be multiple return points inside each function when */ \
|
/* arms of the case statement. That gives a problem in that */ \
|
||||||
/* unwinding, so it will be difficult to check for consistency */ \
|
/* there will be multiple return points inside each function when */ \
|
||||||
/* against the director string. Instead, we make an indirect */ \
|
/* unwinding, so it will be difficult to check for consistency */ \
|
||||||
/* call, so as to guarantee that there is only one call site */ \
|
/* against the director string. Instead, we make an indirect */ \
|
||||||
/* within each function. This does assume that the compiler */ \
|
/* call, so as to guarantee that there is only one call site */ \
|
||||||
/* won't transform it back to the simple direct-call form. */ \
|
/* within each function. This does assume that the compiler */ \
|
||||||
/* To discourage it from doing so, the call is bracketed with */ \
|
/* won't transform it back to the simple direct-call form. */ \
|
||||||
/* __asm__ __volatile__ sections so as to make it not-movable. */ \
|
/* To discourage it from doing so, the call is bracketed with */ \
|
||||||
bool (*nextFn)(LUL*, const char*, const char*) = NULL; \
|
/* __asm__ __volatile__ sections so as to make it not-movable. */ \
|
||||||
switch (*strP) { \
|
bool (*nextFn)(LUL*, const char*, const char*) = NULL; \
|
||||||
case '1': \
|
switch (*strP) { \
|
||||||
nextFn = TestFn1; \
|
case '1': \
|
||||||
break; \
|
nextFn = TestFn1; \
|
||||||
case '2': \
|
break; \
|
||||||
nextFn = TestFn2; \
|
case '2': \
|
||||||
break; \
|
nextFn = TestFn2; \
|
||||||
case '3': \
|
break; \
|
||||||
nextFn = TestFn3; \
|
case '3': \
|
||||||
break; \
|
nextFn = TestFn3; \
|
||||||
case '4': \
|
break; \
|
||||||
nextFn = TestFn4; \
|
case '4': \
|
||||||
break; \
|
nextFn = TestFn4; \
|
||||||
case '5': \
|
break; \
|
||||||
nextFn = TestFn5; \
|
case '5': \
|
||||||
break; \
|
nextFn = TestFn5; \
|
||||||
case '6': \
|
break; \
|
||||||
nextFn = TestFn6; \
|
case '6': \
|
||||||
break; \
|
nextFn = TestFn6; \
|
||||||
case '7': \
|
break; \
|
||||||
nextFn = TestFn7; \
|
case '7': \
|
||||||
break; \
|
nextFn = TestFn7; \
|
||||||
case '8': \
|
break; \
|
||||||
nextFn = TestFn8; \
|
case '8': \
|
||||||
break; \
|
nextFn = TestFn8; \
|
||||||
default: \
|
break; \
|
||||||
nextFn = TestFn8; \
|
default: \
|
||||||
break; \
|
nextFn = TestFn8; \
|
||||||
} \
|
break; \
|
||||||
/* "use" |space| immediately after the recursive call, */ \
|
} \
|
||||||
/* so as to dissuade clang from deallocating the space while */ \
|
/* "use" |space| immediately after the recursive call, */ \
|
||||||
/* the call is active, or otherwise messing with the stack frame. */ \
|
/* so as to dissuade clang from deallocating the space while */ \
|
||||||
__asm__ __volatile__("" ::: "cc", "memory"); \
|
/* the call is active, or otherwise messing with the stack frame. */ \
|
||||||
bool passed = nextFn(aLUL, strPorig, strP + 1); \
|
__asm__ __volatile__("" ::: "cc", "memory"); \
|
||||||
Unused << write(1, space, 0); \
|
bool passed = nextFn(aLUL, strPorig, strP + 1); \
|
||||||
__asm__ __volatile__("" ::: "cc", "memory"); \
|
Unused << write(1, space, 0); \
|
||||||
return passed; \
|
__asm__ __volatile__("" ::: "cc", "memory"); \
|
||||||
} \
|
return passed; \
|
||||||
}
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
// The test functions are mutually recursive, so it is necessary to
|
// The test functions are mutually recursive, so it is necessary to
|
||||||
// declare them before defining them.
|
// declare them before defining them.
|
||||||
|
@ -1950,3 +1953,5 @@ void RunLulUnitTests(/*OUT*/ int* aNTests, /*OUT*/ int* aNTestsPassed,
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace lul
|
} // namespace lul
|
||||||
|
|
||||||
|
#endif // MOZ_BASE_PROFILER
|
||||||
|
|
|
@ -3,17 +3,21 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include <stdio.h>
|
#include "BaseProfiler.h"
|
||||||
#include <signal.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "platform.h"
|
#ifdef MOZ_BASE_PROFILER
|
||||||
#include "PlatformMacros.h"
|
|
||||||
#include "LulMain.h"
|
# include <stdio.h>
|
||||||
#include "BaseProfilerSharedLibraries.h"
|
# include <signal.h>
|
||||||
#include "AutoObjectMapper.h"
|
# include <string.h>
|
||||||
|
# include <stdlib.h>
|
||||||
|
# include <time.h>
|
||||||
|
|
||||||
|
# include "platform.h"
|
||||||
|
# include "PlatformMacros.h"
|
||||||
|
# include "LulMain.h"
|
||||||
|
# include "BaseProfilerSharedLibraries.h"
|
||||||
|
# include "AutoObjectMapper.h"
|
||||||
|
|
||||||
// Contains miscellaneous helpers that are used to connect the Gecko Profiler
|
// Contains miscellaneous helpers that are used to connect the Gecko Profiler
|
||||||
// and LUL.
|
// and LUL.
|
||||||
|
@ -24,7 +28,7 @@
|
||||||
void read_procmaps(lul::LUL* aLUL) {
|
void read_procmaps(lul::LUL* aLUL) {
|
||||||
MOZ_ASSERT(aLUL->CountMappings() == 0);
|
MOZ_ASSERT(aLUL->CountMappings() == 0);
|
||||||
|
|
||||||
#if defined(GP_OS_linux) || defined(GP_OS_android)
|
# if defined(GP_OS_linux) || defined(GP_OS_android)
|
||||||
SharedLibraryInfo info = SharedLibraryInfo::GetInfoForSelf();
|
SharedLibraryInfo info = SharedLibraryInfo::GetInfoForSelf();
|
||||||
|
|
||||||
for (size_t i = 0; i < info.GetSize(); i++) {
|
for (size_t i = 0; i < info.GetSize(); i++) {
|
||||||
|
@ -32,13 +36,13 @@ void read_procmaps(lul::LUL* aLUL) {
|
||||||
|
|
||||||
std::string nativePath = lib.GetNativeDebugPath();
|
std::string nativePath = lib.GetNativeDebugPath();
|
||||||
|
|
||||||
# if defined(GP_OS_android)
|
# if defined(GP_OS_android)
|
||||||
// We're using faulty.lib. Use a special-case object mapper.
|
// We're using faulty.lib. Use a special-case object mapper.
|
||||||
AutoObjectMapperFaultyLib mapper(aLUL->mLog);
|
AutoObjectMapperFaultyLib mapper(aLUL->mLog);
|
||||||
# else
|
# else
|
||||||
// We can use the standard POSIX-based mapper.
|
// We can use the standard POSIX-based mapper.
|
||||||
AutoObjectMapperPOSIX mapper(aLUL->mLog);
|
AutoObjectMapperPOSIX mapper(aLUL->mLog);
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
// Ask |mapper| to map the object. Then hand its mapped address
|
// Ask |mapper| to map the object. Then hand its mapped address
|
||||||
// to NotifyAfterMap().
|
// to NotifyAfterMap().
|
||||||
|
@ -62,9 +66,9 @@ void read_procmaps(lul::LUL* aLUL) {
|
||||||
// unmaps the object.
|
// unmaps the object.
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
# else
|
||||||
# error "Unknown platform"
|
# error "Unknown platform"
|
||||||
#endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// LUL needs a callback for its logging sink.
|
// LUL needs a callback for its logging sink.
|
||||||
|
@ -76,3 +80,5 @@ void logging_sink_for_LUL(const char* str) {
|
||||||
MOZ_LOG(gProfilerLog, mozilla::LogLevel::Verbose,
|
MOZ_LOG(gProfilerLog, mozilla::LogLevel::Verbose,
|
||||||
("[%d] %s", profiler_current_process_id(), str));
|
("[%d] %s", profiler_current_process_id(), str));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // MOZ_BASE_PROFILER
|
||||||
|
|
|
@ -6,6 +6,12 @@
|
||||||
#ifndef PROFILEJSONWRITER_H
|
#ifndef PROFILEJSONWRITER_H
|
||||||
#define PROFILEJSONWRITER_H
|
#define PROFILEJSONWRITER_H
|
||||||
|
|
||||||
|
#include "BaseProfiler.h"
|
||||||
|
|
||||||
|
#ifndef MOZ_BASE_PROFILER
|
||||||
|
# error Do not #include this header when MOZ_BASE_PROFILER is not #defined.
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "mozilla/JSONWriter.h"
|
#include "mozilla/JSONWriter.h"
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,26 @@
|
||||||
#ifndef GeckoProfiler_h
|
#ifndef GeckoProfiler_h
|
||||||
#define GeckoProfiler_h
|
#define GeckoProfiler_h
|
||||||
|
|
||||||
// everything in here is also safe to include unconditionally, and only defines
|
// Everything in here is also safe to include unconditionally, and only defines
|
||||||
// empty macros if MOZ_BASE_PROFILER is unset
|
// empty macros if MOZ_GECKO_PROFILER or MOZ_BASE_PROFILER is unset.
|
||||||
|
|
||||||
|
// MOZ_BASE_PROFILER is #defined (or not) in this header, so it should be
|
||||||
|
// #included wherever Base Profiler may be used.
|
||||||
|
|
||||||
|
#ifdef MOZ_GECKO_PROFILER
|
||||||
|
// Disable Base Profiler for now; will be enabled on supported platforms in
|
||||||
|
// later patches.
|
||||||
|
# if 0
|
||||||
|
# define MOZ_BASE_PROFILER
|
||||||
|
# else
|
||||||
|
// Other platforms are currently not supported. But you may uncomment the
|
||||||
|
// following line to enable Base Profiler in your build.
|
||||||
|
//# define MOZ_BASE_PROFILER
|
||||||
|
# endif
|
||||||
|
#endif // MOZ_GECKO_PROFILER
|
||||||
|
|
||||||
|
// BaseProfilerCounts.h is also safe to include unconditionally, with empty
|
||||||
|
// macros if MOZ_BASE_PROFILER is unset.
|
||||||
#include "mozilla/BaseProfilerCounts.h"
|
#include "mozilla/BaseProfilerCounts.h"
|
||||||
|
|
||||||
#ifndef MOZ_BASE_PROFILER
|
#ifndef MOZ_BASE_PROFILER
|
||||||
|
|
|
@ -7,6 +7,12 @@
|
||||||
#ifndef ProfilerMarkerPayload_h
|
#ifndef ProfilerMarkerPayload_h
|
||||||
#define ProfilerMarkerPayload_h
|
#define ProfilerMarkerPayload_h
|
||||||
|
|
||||||
|
#include "BaseProfiler.h"
|
||||||
|
|
||||||
|
#ifndef MOZ_BASE_PROFILER
|
||||||
|
# error Do not #include this header when MOZ_BASE_PROFILER is not #defined.
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
|
@ -16,7 +22,6 @@
|
||||||
#include "mozilla/net/TimingStruct.h"
|
#include "mozilla/net/TimingStruct.h"
|
||||||
|
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
#include "BaseProfiler.h"
|
|
||||||
|
|
||||||
#include "js/Utility.h"
|
#include "js/Utility.h"
|
||||||
#include "gfxASurface.h"
|
#include "gfxASurface.h"
|
||||||
|
|
|
@ -7,8 +7,10 @@
|
||||||
#ifndef BASE_PROFILER_SHARED_LIBRARIES_H_
|
#ifndef BASE_PROFILER_SHARED_LIBRARIES_H_
|
||||||
#define BASE_PROFILER_SHARED_LIBRARIES_H_
|
#define BASE_PROFILER_SHARED_LIBRARIES_H_
|
||||||
|
|
||||||
|
#include "BaseProfiler.h"
|
||||||
|
|
||||||
#ifndef MOZ_BASE_PROFILER
|
#ifndef MOZ_BASE_PROFILER
|
||||||
# error This header does not have a useful implementation on your platform!
|
# error Do not #include this header when MOZ_BASE_PROFILER is not #defined.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "nsNativeCharsetUtils.h"
|
#include "nsNativeCharsetUtils.h"
|
||||||
|
|
|
@ -7,6 +7,12 @@
|
||||||
#ifndef js_ProfilingCategory_h
|
#ifndef js_ProfilingCategory_h
|
||||||
#define js_ProfilingCategory_h
|
#define js_ProfilingCategory_h
|
||||||
|
|
||||||
|
#include "BaseProfiler.h"
|
||||||
|
|
||||||
|
#ifndef MOZ_BASE_PROFILER
|
||||||
|
# error Do not #include this header when MOZ_BASE_PROFILER is not #defined.
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "jstypes.h" // JS_FRIEND_API
|
#include "jstypes.h" // JS_FRIEND_API
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
|
|
@ -7,6 +7,12 @@
|
||||||
#ifndef js_ProfilingStack_h
|
#ifndef js_ProfilingStack_h
|
||||||
#define js_ProfilingStack_h
|
#define js_ProfilingStack_h
|
||||||
|
|
||||||
|
#include "BaseProfiler.h"
|
||||||
|
|
||||||
|
#ifndef MOZ_BASE_PROFILER
|
||||||
|
# error Do not #include this header when MOZ_BASE_PROFILER is not #defined.
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
|
||||||
DIRS += ['android']
|
DIRS += ['android']
|
||||||
|
|
||||||
DIRS += [
|
DIRS += [
|
||||||
|
'baseprofiler',
|
||||||
'build',
|
'build',
|
||||||
'misc',
|
'misc',
|
||||||
]
|
]
|
||||||
|
|
Загрузка…
Ссылка в новой задаче