Bug 1634784 - Remove #ifdef MOZ_GECKO_PROFILER wrappers in mozglue/baseprofiler cpp files, and reorder includes. r=gerald

I apologize for mixing multiple types of changes in this patch. The mix is probably harder to review than necessary.

Because of the way these .cpp files are listed in mozglue/baseprofiler/moz.build,
they are only built when MOZ_GECKO_PROFILER is set. So the #ifdef MOZ_GECKO_PROFILER
wrapper is now unnecessary.
Removing this wrapper has many knock-on effects on other lines in these files
due to preprocessor line indentation.

As I was removing the #ifdefs, I was reordering includes as well, to follow the
include order laid out on https://google.github.io/styleguide/cppguide.html#Names_and_Order_of_Includes ;
namely, system headers should go before "your project's" .h files.

I also removed the BaseProfiler.h include from some files but not from all.
In the past, the BaseProfiler.h include served the purpose of picking up the
MOZ_BASE_PROFILER #define, and it's no longer needed for that reason.
There are probably lots of now-unnecessary BaseProfiler.h includes left.

Differential Revision: https://phabricator.services.mozilla.com/D73527
This commit is contained in:
Markus Stange 2020-05-05 22:00:49 +00:00
Родитель 6725e6df9a
Коммит 7c4a6b32f3
23 изменённых файлов: 749 добавлений и 864 удалений

Просмотреть файл

@ -24,35 +24,33 @@
#include "BaseProfiler.h"
#ifdef MOZ_GECKO_PROFILER
#include "EHABIStackWalk.h"
# include "EHABIStackWalk.h"
#include "BaseProfilerSharedLibraries.h"
#include "platform.h"
# include "BaseProfilerSharedLibraries.h"
# include "platform.h"
#include "mozilla/Atomics.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/EndianUtils.h"
# include "mozilla/Atomics.h"
# include "mozilla/DebugOnly.h"
# include "mozilla/EndianUtils.h"
#include <algorithm>
#include <elf.h>
#include <stdint.h>
#include <vector>
#include <string>
# include <algorithm>
# include <elf.h>
# include <stdint.h>
# include <vector>
# include <string>
# ifndef PT_ARM_EXIDX
# define PT_ARM_EXIDX 0x70000001
# endif
#ifndef PT_ARM_EXIDX
# define PT_ARM_EXIDX 0x70000001
#endif
// 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 case we build and sort an array of pointers into the index,
// and binary-search that; otherwise, we search the index in place
// (avoiding the time and space overhead of the indirection).
# if defined(ANDROID_VERSION) && ANDROID_VERSION < 16
# define HAVE_UNSORTED_EXIDX
# endif
#if defined(ANDROID_VERSION) && ANDROID_VERSION < 16
# define HAVE_UNSORTED_EXIDX
#endif
namespace mozilla {
namespace baseprofiler {
@ -94,7 +92,7 @@ class EHState {
enum { R_SP = 13, R_LR = 14, R_PC = 15 };
# ifdef HAVE_UNSORTED_EXIDX
#ifdef HAVE_UNSORTED_EXIDX
class EHEntryHandle {
const EHEntry* mValue;
@ -106,13 +104,13 @@ class EHEntryHandle {
bool operator<(const EHEntryHandle& lhs, const EHEntryHandle& rhs) {
return lhs.value()->startPC.compute() < rhs.value()->startPC.compute();
}
# endif
#endif
class EHTable {
uint32_t mStartPC;
uint32_t mEndPC;
uint32_t mBaseAddress;
# ifdef HAVE_UNSORTED_EXIDX
#ifdef HAVE_UNSORTED_EXIDX
// In principle we should be able to binary-search the index section in
// place, but the ICS toolchain's linker is noncompliant and produces
// indices that aren't entirely sorted (e.g., libc). So we have this:
@ -123,13 +121,13 @@ class EHTable {
static const EHEntry* entryGet(EntryIterator aEntry) {
return aEntry->value();
}
# else
#else
typedef const EHEntry* EntryIterator;
EntryIterator mEntriesBegin, mEntriesEnd;
EntryIterator entriesBegin() const { return mEntriesBegin; }
EntryIterator entriesEnd() const { return mEntriesEnd; }
static const EHEntry* entryGet(EntryIterator aEntry) { return aEntry; }
# endif
#endif
std::string mName;
public:
@ -334,9 +332,9 @@ bool EHInterp::unwind() {
checkStack();
while (!mFailed) {
uint8_t insn = next();
# if DEBUG_EHABI_UNWIND
#if DEBUG_EHABI_UNWIND
LOG("unwind insn = %02x", (unsigned)insn);
# endif
#endif
// Try to put the common cases first.
// 00xxxxxx: vsp = vsp + (xxxxxx << 2) + 4
@ -460,9 +458,9 @@ bool EHInterp::unwind() {
}
// unhandled instruction
# ifdef DEBUG_EHABI_UNWIND
#ifdef DEBUG_EHABI_UNWIND
LOG("Unhandled EHABI instruction 0x%02x", insn);
# endif
#endif
mFailed = true;
}
return false;
@ -505,12 +503,12 @@ const EHEntry* EHTable::lookup(uint32_t aPC) const {
return nullptr;
while (end - begin > 1) {
# ifdef EHABI_UNWIND_MORE_ASSERTS
#ifdef EHABI_UNWIND_MORE_ASSERTS
if (entryGet(end - 1)->startPC.compute() <
entryGet(begin)->startPC.compute()) {
MOZ_CRASH("unsorted exidx");
}
# endif
#endif
EntryIterator mid = begin + (end - begin) / 2;
if (aPC < reinterpret_cast<uint32_t>(entryGet(mid)->startPC.compute()))
end = mid;
@ -520,22 +518,22 @@ const EHEntry* EHTable::lookup(uint32_t aPC) const {
return entryGet(begin);
}
# if MOZ_LITTLE_ENDIAN()
#if MOZ_LITTLE_ENDIAN()
static const unsigned char hostEndian = ELFDATA2LSB;
# elif MOZ_BIG_ENDIAN()
#elif MOZ_BIG_ENDIAN()
static const unsigned char hostEndian = ELFDATA2MSB;
# else
# error "No endian?"
# endif
#else
# error "No endian?"
#endif
// Async signal unsafe: std::vector::reserve, std::string copy ctor.
EHTable::EHTable(const void* aELF, size_t aSize, const std::string& aName)
: mStartPC(~0), // largest uint32_t
mEndPC(0),
# ifndef HAVE_UNSORTED_EXIDX
#ifndef HAVE_UNSORTED_EXIDX
mEntriesBegin(nullptr),
mEntriesEnd(nullptr),
# endif
#endif
mName(aName) {
const uint32_t fileHeaderAddr = reinterpret_cast<uint32_t>(aELF);
@ -578,14 +576,14 @@ EHTable::EHTable(const void* aELF, size_t aSize, const std::string& aName)
reinterpret_cast<const EHEntry*>(mBaseAddress + exidxHdr->p_vaddr);
const EHEntry* endTable = reinterpret_cast<const EHEntry*>(
mBaseAddress + exidxHdr->p_vaddr + exidxHdr->p_memsz);
# ifdef HAVE_UNSORTED_EXIDX
#ifdef HAVE_UNSORTED_EXIDX
mEntries.reserve(endTable - startTable);
for (const EHEntry* i = startTable; i < endTable; ++i) mEntries.push_back(i);
std::sort(mEntries.begin(), mEntries.end());
# else
#else
mEntriesBegin = startTable;
mEntriesEnd = endTable;
# endif
#endif
}
Atomic<const EHAddrSpace*> EHAddrSpace::sCurrent(nullptr);
@ -620,7 +618,7 @@ void EHAddrSpace::Update() {
}
EHState::EHState(const mcontext_t& context) {
# ifdef linux
#ifdef linux
mRegs[0] = context.arm_r0;
mRegs[1] = context.arm_r1;
mRegs[2] = context.arm_r2;
@ -637,12 +635,10 @@ EHState::EHState(const mcontext_t& context) {
mRegs[13] = context.arm_sp;
mRegs[14] = context.arm_lr;
mRegs[15] = context.arm_pc;
# else
# error "Unhandled OS for ARM EHABI unwinding"
# endif
#else
# error "Unhandled OS for ARM EHABI unwinding"
#endif
}
} // namespace baseprofiler
} // namespace mozilla
#endif // MOZ_GECKO_PROFILER

Просмотреть файл

@ -4,13 +4,10 @@
* 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/. */
#include "PageInformation.h"
#include "BaseProfiler.h"
#ifdef MOZ_GECKO_PROFILER
# include "PageInformation.h"
# include "BaseProfileJSONWriter.h"
#include "BaseProfileJSONWriter.h"
namespace mozilla {
namespace baseprofiler {
@ -50,5 +47,3 @@ size_t PageInformation::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
} // namespace baseprofiler
} // namespace mozilla
#endif // MOZ_GECKO_PROFILER

Просмотреть файл

@ -4,14 +4,12 @@
* 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/. */
#include "ProfileBuffer.h"
#include "mozilla/MathAlgorithms.h"
#include "BaseProfiler.h"
#ifdef MOZ_GECKO_PROFILER
# include "ProfileBuffer.h"
# include "mozilla/MathAlgorithms.h"
namespace mozilla {
namespace baseprofiler {
@ -33,15 +31,15 @@ ProfileBufferBlockIndex ProfileBuffer::AddEntry(
ProfileChunkedBuffer& aProfileChunkedBuffer,
const ProfileBufferEntry& aEntry) {
switch (aEntry.GetKind()) {
# define SWITCH_KIND(KIND, TYPE, SIZE) \
case ProfileBufferEntry::Kind::KIND: { \
return aProfileChunkedBuffer.PutFrom(&aEntry, 1 + (SIZE)); \
break; \
}
#define SWITCH_KIND(KIND, TYPE, SIZE) \
case ProfileBufferEntry::Kind::KIND: { \
return aProfileChunkedBuffer.PutFrom(&aEntry, 1 + (SIZE)); \
break; \
}
FOR_EACH_PROFILE_BUFFER_ENTRY_KIND(SWITCH_KIND)
# undef SWITCH_KIND
#undef SWITCH_KIND
default:
MOZ_ASSERT(false, "Unhandled baseprofiler::ProfilerBuffer entry KIND");
return ProfileBufferBlockIndex{};
@ -207,5 +205,3 @@ void ProfileBufferCollector::CollectProfilingStackFrame(
} // namespace baseprofiler
} // namespace mozilla
#endif // MOZ_GECKO_PROFILER

Просмотреть файл

@ -4,22 +4,19 @@
* 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/. */
#include "ProfileBufferEntry.h"
#include <ostream>
#include <type_traits>
#include "mozilla/Logging.h"
#include "mozilla/Sprintf.h"
#include "mozilla/StackWalk.h"
#include "BaseProfiler.h"
#ifdef MOZ_GECKO_PROFILER
# include "ProfileBufferEntry.h"
# include "BaseProfilerMarkerPayload.h"
# include "platform.h"
# include "ProfileBuffer.h"
# include "mozilla/Logging.h"
# include "mozilla/Sprintf.h"
# include "mozilla/StackWalk.h"
# include <ostream>
# include <type_traits>
#include "BaseProfilerMarkerPayload.h"
#include "platform.h"
#include "ProfileBuffer.h"
namespace mozilla {
namespace baseprofiler {
@ -577,12 +574,12 @@ class EntryGetter {
// Because this is a format entirely internal to the Profiler, any parsing
// error indicates a bug in the ProfileBuffer writing or the parser itself,
// or possibly flaky hardware.
# define ERROR_AND_CONTINUE(msg) \
{ \
fprintf(stderr, "ProfileBuffer parse error: %s", msg); \
MOZ_ASSERT(false, msg); \
continue; \
}
#define ERROR_AND_CONTINUE(msg) \
{ \
fprintf(stderr, "ProfileBuffer parse error: %s", msg); \
MOZ_ASSERT(false, msg); \
continue; \
}
void ProfileBuffer::StreamSamplesToJSON(SpliceableJSONWriter& aWriter,
int aThreadId, double aSinceTime,
@ -959,17 +956,17 @@ void ProfileBuffer::StreamProfilerOverheadToJSON(
aWriter.DoubleProperty("overheadDurations", overheads.sum);
aWriter.DoubleProperty("overheadPercentage",
overheads.sum / (lastTime - firstTime));
# define PROFILER_STATS(name, var) \
aWriter.DoubleProperty("mean" name, (var).sum / (var).n); \
aWriter.DoubleProperty("min" name, (var).min); \
aWriter.DoubleProperty("max" name, (var).max);
#define PROFILER_STATS(name, var) \
aWriter.DoubleProperty("mean" name, (var).sum / (var).n); \
aWriter.DoubleProperty("min" name, (var).min); \
aWriter.DoubleProperty("max" name, (var).max);
PROFILER_STATS("Interval", intervals);
PROFILER_STATS("Overhead", overheads);
PROFILER_STATS("Lockings", lockings);
PROFILER_STATS("Cleaning", cleanings);
PROFILER_STATS("Counter", counters);
PROFILER_STATS("Thread", threads);
# undef PROFILER_STATS
#undef PROFILER_STATS
aWriter.EndObject(); // statistics
}
aWriter.EndObject(); // profilerOverhead
@ -1162,7 +1159,7 @@ void ProfileBuffer::StreamCountersToJSON(SpliceableJSONWriter& aWriter,
});
}
# undef ERROR_AND_CONTINUE
#undef ERROR_AND_CONTINUE
static void AddPausedRange(SpliceableJSONWriter& aWriter, const char* aReason,
const Maybe<double>& aStartTime,
@ -1376,5 +1373,3 @@ void ProfileBuffer::DiscardSamplesBeforeTime(double aTime) {
} // namespace baseprofiler
} // namespace mozilla
#endif // MOZ_GECKO_PROFILER

Просмотреть файл

@ -3,14 +3,12 @@
* 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/. */
#include "BaseProfileJSONWriter.h"
#include "mozilla/HashFunctions.h"
#include "BaseProfiler.h"
#ifdef MOZ_GECKO_PROFILER
# include "BaseProfileJSONWriter.h"
# include "mozilla/HashFunctions.h"
namespace mozilla {
namespace baseprofiler {
@ -128,5 +126,3 @@ void SpliceableChunkedJSONWriter::TakeAndSplice(ChunkedJSONWriteFunc* aFunc) {
} // namespace baseprofiler
} // namespace mozilla
#endif // MOZ_GECKO_PROFILER

Просмотреть файл

@ -4,18 +4,15 @@
* 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/. */
#include "ProfiledThreadData.h"
#include "BaseProfiler.h"
#include "ProfileBuffer.h"
#include "BaseProfileJSONWriter.h"
#ifdef MOZ_GECKO_PROFILER
# include "ProfiledThreadData.h"
# include "ProfileBuffer.h"
# include "BaseProfileJSONWriter.h"
# if defined(GP_OS_darwin)
# include <pthread.h>
# endif
#if defined(GP_OS_darwin)
# include <pthread.h>
#endif
namespace mozilla {
namespace baseprofiler {
@ -170,5 +167,3 @@ void StreamSamplesAndMarkers(const char* aName, int aThreadId,
} // namespace baseprofiler
} // namespace mozilla
#endif // MOZ_GECKO_PROFILER

Просмотреть файл

@ -4,16 +4,13 @@
* 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/. */
#include "ProfilerBacktrace.h"
#include "BaseProfiler.h"
#ifdef MOZ_GECKO_PROFILER
# include "ProfilerBacktrace.h"
# include "ProfileBuffer.h"
# include "ProfiledThreadData.h"
# include "BaseProfileJSONWriter.h"
# include "ThreadInfo.h"
#include "BaseProfileJSONWriter.h"
#include "ProfileBuffer.h"
#include "ProfiledThreadData.h"
#include "ThreadInfo.h"
namespace mozilla {
namespace baseprofiler {
@ -79,5 +76,3 @@ ProfileBufferEntryReader::
};
} // namespace mozilla
#endif // MOZ_GECKO_PROFILER

Просмотреть файл

@ -3,20 +3,17 @@
* 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/. */
#include "BaseProfilerMarkerPayload.h"
#include <inttypes.h>
#include "mozilla/Maybe.h"
#include "mozilla/Sprintf.h"
#include "BaseProfiler.h"
#ifdef MOZ_GECKO_PROFILER
# include "BaseProfilerMarkerPayload.h"
# include "ProfileBufferEntry.h"
# include "BaseProfileJSONWriter.h"
# include "ProfilerBacktrace.h"
# include "mozilla/Maybe.h"
# include "mozilla/Sprintf.h"
# include <inttypes.h>
#include "BaseProfileJSONWriter.h"
#include "ProfileBufferEntry.h"
#include "ProfilerBacktrace.h"
namespace mozilla {
namespace baseprofiler {
@ -542,5 +539,3 @@ void LongTaskMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter,
} // namespace baseprofiler
} // namespace mozilla
#endif // MOZ_GECKO_PROFILER

Просмотреть файл

@ -4,15 +4,13 @@
* 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/. */
#include "BaseProfilingCategory.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Assertions.h"
#include "BaseProfiler.h"
#ifdef MOZ_GECKO_PROFILER
# include "BaseProfilingCategory.h"
# include "mozilla/ArrayUtils.h"
# include "mozilla/Assertions.h"
namespace mozilla {
namespace baseprofiler {
@ -71,5 +69,3 @@ const ProfilingCategoryPairInfo& GetProfilingCategoryPairInfo(
} // namespace baseprofiler
} // namespace mozilla
#endif // MOZ_GECKO_PROFILER

Просмотреть файл

@ -4,18 +4,16 @@
* 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/. */
#include "BaseProfilingStack.h"
#include <algorithm>
#include "mozilla/IntegerRange.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/UniquePtrExtensions.h"
#include "BaseProfiler.h"
#ifdef MOZ_GECKO_PROFILER
# include "BaseProfilingStack.h"
# include "mozilla/IntegerRange.h"
# include "mozilla/UniquePtr.h"
# include "mozilla/UniquePtrExtensions.h"
# include <algorithm>
namespace mozilla {
namespace baseprofiler {
@ -52,5 +50,3 @@ void ProfilingStack::ensureCapacitySlow() {
} // namespace baseprofiler
} // namespace mozilla
#endif // MOZ_GECKO_PROFILER

Просмотреть файл

@ -4,12 +4,10 @@
* 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/. */
#include "RegisteredThread.h"
#include "BaseProfiler.h"
#ifdef MOZ_GECKO_PROFILER
# include "RegisteredThread.h"
namespace mozilla {
namespace baseprofiler {
@ -19,10 +17,10 @@ RegisteredThread::RegisteredThread(ThreadInfo* aInfo, void* aStackTop)
mStackTop(aStackTop),
mThreadInfo(aInfo) {
// We don't have to guess on mac
# if defined(GP_OS_darwin)
#if defined(GP_OS_darwin)
pthread_t self = pthread_self();
mStackTop = pthread_get_stackaddr_np(self);
# endif
#endif
}
RegisteredThread::~RegisteredThread() {}
@ -43,5 +41,3 @@ size_t RegisteredThread::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
} // namespace baseprofiler
} // namespace mozilla
#endif // MOZ_GECKO_PROFILER

Просмотреть файл

@ -4,19 +4,17 @@
* 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/. */
#ifdef XP_WIN
# undef UNICODE
# undef _UNICODE
#endif
#include "VTuneProfiler.h"
#include <memory>
#include "BaseProfiler.h"
#ifdef MOZ_GECKO_PROFILER
# ifdef XP_WIN
# undef UNICODE
# undef _UNICODE
# endif
# include "VTuneProfiler.h"
# include <memory>
namespace mozilla {
namespace baseprofiler {
@ -92,5 +90,3 @@ void VTuneProfiler::RegisterThreadInternal(const char* aName) {
} // namespace baseprofiler
} // namespace mozilla
#endif // MOZ_GECKO_PROFILER

Просмотреть файл

@ -26,95 +26,92 @@
// ProfileBuffer. The sampling is done from off-thread, and so uses
// SuspendAndSampleAndResumeThread() to get the register values.
#include "BaseProfiler.h"
#include "platform.h"
#ifdef MOZ_GECKO_PROFILER
# include "platform.h"
# include "PageInformation.h"
# include "ProfiledThreadData.h"
# include "ProfilerBacktrace.h"
# include "ProfileBuffer.h"
# include "BaseProfilerMarkerPayload.h"
# include "RegisteredThread.h"
# include "BaseProfilerSharedLibraries.h"
# include "ThreadInfo.h"
# include "VTuneProfiler.h"
#include <algorithm>
#include <errno.h>
#include <fstream>
#include <ostream>
#include <sstream>
// #include "memory_hooks.h"
# include "mozilla/ArrayUtils.h"
# include "mozilla/Atomics.h"
# include "mozilla/AutoProfilerLabel.h"
# include "mozilla/BaseProfilerDetail.h"
# include "mozilla/DoubleConversion.h"
# include "mozilla/Printf.h"
# include "mozilla/ProfileBufferChunkManagerSingle.h"
# include "mozilla/ProfileBufferChunkManagerWithLocalLimit.h"
# include "mozilla/ProfileChunkedBuffer.h"
# include "mozilla/Services.h"
# include "mozilla/Span.h"
# include "mozilla/StackWalk.h"
# include "mozilla/StaticPtr.h"
# include "mozilla/ThreadLocal.h"
# include "mozilla/TimeStamp.h"
# include "mozilla/Tuple.h"
# include "mozilla/UniquePtr.h"
# include "mozilla/Vector.h"
# include "prdtoa.h"
# include "prtime.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Atomics.h"
#include "mozilla/AutoProfilerLabel.h"
#include "mozilla/BaseProfilerDetail.h"
#include "mozilla/DoubleConversion.h"
#include "mozilla/Printf.h"
#include "mozilla/ProfileBufferChunkManagerSingle.h"
#include "mozilla/ProfileBufferChunkManagerWithLocalLimit.h"
#include "mozilla/ProfileChunkedBuffer.h"
#include "mozilla/Services.h"
#include "mozilla/Span.h"
#include "mozilla/StackWalk.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/ThreadLocal.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Tuple.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/Vector.h"
#include "prdtoa.h"
#include "prtime.h"
# include <algorithm>
# include <errno.h>
# include <fstream>
# include <ostream>
# include <sstream>
#include "BaseProfiler.h"
#include "PageInformation.h"
#include "ProfiledThreadData.h"
#include "ProfilerBacktrace.h"
#include "ProfileBuffer.h"
#include "BaseProfilerMarkerPayload.h"
#include "RegisteredThread.h"
#include "BaseProfilerSharedLibraries.h"
#include "ThreadInfo.h"
#include "VTuneProfiler.h"
// Win32 builds always have frame pointers, so FramePointerStackWalk() always
// works.
# if defined(GP_PLAT_x86_windows)
# define HAVE_NATIVE_UNWIND
# define USE_FRAME_POINTER_STACK_WALK
# endif
#if defined(GP_PLAT_x86_windows)
# define HAVE_NATIVE_UNWIND
# define USE_FRAME_POINTER_STACK_WALK
#endif
// Win64 builds always omit frame pointers, so we use the slower
// MozStackWalk(), which works in that case.
# if defined(GP_PLAT_amd64_windows)
# define HAVE_NATIVE_UNWIND
# define USE_MOZ_STACK_WALK
# endif
#if defined(GP_PLAT_amd64_windows)
# define HAVE_NATIVE_UNWIND
# define USE_MOZ_STACK_WALK
#endif
// AArch64 Win64 doesn't seem to use frame pointers, so we use the slower
// MozStackWalk().
# if defined(GP_PLAT_arm64_windows)
# define HAVE_NATIVE_UNWIND
# define USE_MOZ_STACK_WALK
# endif
#if defined(GP_PLAT_arm64_windows)
# define HAVE_NATIVE_UNWIND
# define USE_MOZ_STACK_WALK
#endif
// Mac builds only have frame pointers when MOZ_PROFILING is specified, so
// FramePointerStackWalk() only works in that case. We don't use MozStackWalk()
// on Mac.
# if defined(GP_OS_darwin) && defined(MOZ_PROFILING)
# define HAVE_NATIVE_UNWIND
# define USE_FRAME_POINTER_STACK_WALK
# endif
#if defined(GP_OS_darwin) && defined(MOZ_PROFILING)
# define HAVE_NATIVE_UNWIND
# define USE_FRAME_POINTER_STACK_WALK
#endif
// Android builds use the ARM Exception Handling ABI to unwind.
# if defined(GP_PLAT_arm_linux) || defined(GP_PLAT_arm_android)
# define HAVE_NATIVE_UNWIND
# define USE_EHABI_STACKWALK
# include "EHABIStackWalk.h"
# endif
#if defined(GP_PLAT_arm_linux) || defined(GP_PLAT_arm_android)
# define HAVE_NATIVE_UNWIND
# define USE_EHABI_STACKWALK
# include "EHABIStackWalk.h"
#endif
// Linux builds use LUL, which uses DWARF info to unwind stacks.
# if defined(GP_PLAT_amd64_linux) || defined(GP_PLAT_x86_linux) || \
defined(GP_PLAT_amd64_android) || defined(GP_PLAT_x86_android) || \
defined(GP_PLAT_mips64_linux) || defined(GP_PLAT_arm64_linux) || \
defined(GP_PLAT_arm64_android)
# define HAVE_NATIVE_UNWIND
# define USE_LUL_STACKWALK
# include "lul/LulMain.h"
# include "lul/platform-linux-lul.h"
#if defined(GP_PLAT_amd64_linux) || defined(GP_PLAT_x86_linux) || \
defined(GP_PLAT_amd64_android) || defined(GP_PLAT_x86_android) || \
defined(GP_PLAT_mips64_linux) || defined(GP_PLAT_arm64_linux) || \
defined(GP_PLAT_arm64_android)
# define HAVE_NATIVE_UNWIND
# define USE_LUL_STACKWALK
# include "lul/LulMain.h"
# include "lul/platform-linux-lul.h"
// On linux we use LUL for periodic samples and synchronous samples, but we use
// FramePointerStackWalk for backtrace samples when MOZ_PROFILING is enabled.
@ -125,28 +122,28 @@
// in a shared library without framepointers, however LUL can take a long time
// to initialize, which is undesirable for consumers of
// profiler_suspend_and_sample_thread like the Background Hang Reporter.
# if defined(MOZ_PROFILING)
# define USE_FRAME_POINTER_STACK_WALK
# endif
# if defined(MOZ_PROFILING)
# define USE_FRAME_POINTER_STACK_WALK
# endif
#endif
// We can only stackwalk without expensive initialization on platforms which
// support FramePointerStackWalk or MozStackWalk. LUL Stackwalking requires
// initializing LUL, and EHABIStackWalk requires initializing EHABI, both of
// which can be expensive.
# if defined(USE_FRAME_POINTER_STACK_WALK) || defined(USE_MOZ_STACK_WALK)
# define HAVE_FASTINIT_NATIVE_UNWIND
# endif
#if defined(USE_FRAME_POINTER_STACK_WALK) || defined(USE_MOZ_STACK_WALK)
# define HAVE_FASTINIT_NATIVE_UNWIND
#endif
# ifdef MOZ_VALGRIND
# include <valgrind/memcheck.h>
# else
# define VALGRIND_MAKE_MEM_DEFINED(_addr, _len) ((void)0)
# endif
#ifdef MOZ_VALGRIND
# include <valgrind/memcheck.h>
#else
# define VALGRIND_MAKE_MEM_DEFINED(_addr, _len) ((void)0)
#endif
# if defined(GP_OS_linux) || defined(GP_OS_android)
# include <ucontext.h>
# endif
#if defined(GP_OS_linux) || defined(GP_OS_android)
# include <ucontext.h>
#endif
namespace mozilla {
namespace baseprofiler {
@ -166,11 +163,11 @@ bool LogTest(int aLevelToTest) {
void PrintToConsole(const char* aFmt, ...) {
va_list args;
va_start(args, aFmt);
# if defined(ANDROID)
#if defined(ANDROID)
__android_log_vprint(ANDROID_LOG_INFO, "Gecko", aFmt, args);
# else
#else
vfprintf(stderr, aFmt, args);
# endif
#endif
va_end(args);
}
@ -178,21 +175,21 @@ void PrintToConsole(const char* aFmt, ...) {
static uint32_t AvailableFeatures() {
uint32_t features = 0;
# define ADD_FEATURE(n_, str_, Name_, desc_) \
ProfilerFeature::Set##Name_(features);
#define ADD_FEATURE(n_, str_, Name_, desc_) \
ProfilerFeature::Set##Name_(features);
// Add all the possible features.
BASE_PROFILER_FOR_EACH_FEATURE(ADD_FEATURE)
# undef ADD_FEATURE
#undef ADD_FEATURE
// Now remove features not supported on this platform/configuration.
ProfilerFeature::ClearJava(features);
ProfilerFeature::ClearJS(features);
ProfilerFeature::ClearScreenshots(features);
# if !defined(HAVE_NATIVE_UNWIND)
#if !defined(HAVE_NATIVE_UNWIND)
ProfilerFeature::ClearStackWalk(features);
# endif
#endif
ProfilerFeature::ClearTaskTracer(features);
ProfilerFeature::ClearTrackOptimizations(features);
ProfilerFeature::ClearJSTracer(features);
@ -238,24 +235,24 @@ detail::BaseProfilerMutex PSAutoLock::gPSMutex;
// fields.
typedef const PSAutoLock& PSLockRef;
# define PS_GET(type_, name_) \
static type_ name_(PSLockRef) { \
MOZ_ASSERT(sInstance); \
return sInstance->m##name_; \
}
#define PS_GET(type_, name_) \
static type_ name_(PSLockRef) { \
MOZ_ASSERT(sInstance); \
return sInstance->m##name_; \
}
# define PS_GET_LOCKLESS(type_, name_) \
static type_ name_() { \
MOZ_ASSERT(sInstance); \
return sInstance->m##name_; \
}
#define PS_GET_LOCKLESS(type_, name_) \
static type_ name_() { \
MOZ_ASSERT(sInstance); \
return sInstance->m##name_; \
}
# define PS_GET_AND_SET(type_, name_) \
PS_GET(type_, name_) \
static void Set##name_(PSLockRef, type_ a##name_) { \
MOZ_ASSERT(sInstance); \
sInstance->m##name_ = a##name_; \
}
#define PS_GET_AND_SET(type_, name_) \
PS_GET(type_, name_) \
static void Set##name_(PSLockRef, type_ a##name_) { \
MOZ_ASSERT(sInstance); \
sInstance->m##name_ = a##name_; \
}
// All functions in this file can run on multiple threads unless they have an
// NS_IsMainThread() assertion.
@ -288,10 +285,10 @@ class CorePS {
// profiler_add_marker). It is *not* used inside the critical section of
// the sampler, because mutexes cannot be used there.
mCoreBuffer(ProfileChunkedBuffer::ThreadSafety::WithMutex)
# ifdef USE_LUL_STACKWALK
#ifdef USE_LUL_STACKWALK
,
mLul(nullptr)
# endif
#endif
{
}
@ -341,11 +338,11 @@ class CorePS {
// measured above)
// - CorePS::mInterposeObserver
# if defined(USE_LUL_STACKWALK)
#if defined(USE_LUL_STACKWALK)
if (sInstance->mLul) {
aLulSize += sInstance->mLul->SizeOfIncludingThis(aMallocSizeOf);
}
# endif
#endif
}
// No PSLockRef is needed for this field because it's immutable.
@ -438,7 +435,7 @@ class CorePS {
}
}
# ifdef USE_LUL_STACKWALK
#ifdef USE_LUL_STACKWALK
static lul::LUL* Lul(PSLockRef) {
MOZ_ASSERT(sInstance);
return sInstance->mLul.get();
@ -447,7 +444,7 @@ class CorePS {
MOZ_ASSERT(sInstance);
sInstance->mLul = std::move(aLul);
}
# endif
#endif
PS_GET_AND_SET(const std::string&, ProcessName)
@ -483,10 +480,10 @@ class CorePS {
// Non-owning pointers to all active counters
Vector<BaseProfilerCount*> mCounters;
# ifdef USE_LUL_STACKWALK
#ifdef USE_LUL_STACKWALK
// LUL's state. Null prior to the first activation, non-null thereafter.
UniquePtr<lul::LUL> mLul;
# endif
#endif
// Process name, provided by child process initialization code.
std::string mProcessName;
@ -603,13 +600,13 @@ class ActivePS {
// main loop within Run() is blocked until this function's caller
// unlocks gPSMutex.
mSamplerThread(NewSamplerThread(aLock, mGeneration, aInterval))
# undef HAS_FEATURE
#undef HAS_FEATURE
,
mIsPaused(false)
# if defined(GP_OS_linux)
#if defined(GP_OS_linux)
,
mWasPaused(false)
# endif
#endif
{
// Deep copy aFilters.
MOZ_ALWAYS_TRUE(mFilters.resize(aFilterCount));
@ -727,15 +724,15 @@ class ActivePS {
PS_GET(uint32_t, Features)
# define PS_GET_FEATURE(n_, str_, Name_, desc_) \
static bool Feature##Name_(PSLockRef) { \
MOZ_ASSERT(sInstance); \
return ProfilerFeature::Has##Name_(sInstance->mFeatures); \
}
#define PS_GET_FEATURE(n_, str_, Name_, desc_) \
static bool Feature##Name_(PSLockRef) { \
MOZ_ASSERT(sInstance); \
return ProfilerFeature::Has##Name_(sInstance->mFeatures); \
}
BASE_PROFILER_FOR_EACH_FEATURE(PS_GET_FEATURE)
# undef PS_GET_FEATURE
#undef PS_GET_FEATURE
PS_GET(const Vector<std::string>&, Filters)
@ -854,9 +851,9 @@ class ActivePS {
PS_GET_AND_SET(bool, IsPaused)
# if defined(GP_OS_linux)
#if defined(GP_OS_linux)
PS_GET_AND_SET(bool, WasPaused)
# endif
#endif
static void DiscardExpiredDeadProfiledThreads(PSLockRef) {
MOZ_ASSERT(sInstance);
@ -1009,11 +1006,11 @@ class ActivePS {
// Is the profiler paused?
bool mIsPaused;
# if defined(GP_OS_linux)
#if defined(GP_OS_linux)
// Used to record whether the profiler was paused just before forking. False
// at all times except just before/after forking.
bool mWasPaused;
# endif
#endif
struct ExitProfile {
std::string mJSON;
@ -1025,9 +1022,9 @@ class ActivePS {
ActivePS* ActivePS::sInstance = nullptr;
uint32_t ActivePS::sNextGeneration = 0;
# undef PS_GET
# undef PS_GET_LOCKLESS
# undef PS_GET_AND_SET
#undef PS_GET
#undef PS_GET_LOCKLESS
#undef PS_GET_AND_SET
Atomic<uint32_t, MemoryOrdering::Relaxed> RacyFeatures::sActiveAndFeatures(0);
@ -1148,10 +1145,10 @@ class Registers {
public:
Registers() : mPC{nullptr}, mSP{nullptr}, mFP{nullptr}, mLR{nullptr} {}
# if defined(HAVE_NATIVE_UNWIND)
#if defined(HAVE_NATIVE_UNWIND)
// Fills in mPC, mSP, mFP, mLR, and mContext for a synchronous sample.
void SyncPopulate();
# endif
#endif
void Clear() { memset(this, 0, sizeof(*this)); }
@ -1162,11 +1159,11 @@ class Registers {
Address mSP; // Stack pointer.
Address mFP; // Frame pointer.
Address mLR; // ARM link register.
# if defined(GP_OS_linux) || defined(GP_OS_android)
#if defined(GP_OS_linux) || defined(GP_OS_android)
// This contains all the registers, which means it duplicates the four fields
// above. This is ok.
ucontext_t* mContext; // The context from the signal handler.
# endif
#endif
};
// Setting MAX_NATIVE_FRAMES too high risks the unwinder wasting a lot of time
@ -1289,11 +1286,11 @@ static void MergeStacks(uint32_t aFeatures, bool aIsSynchronous,
}
}
# if defined(GP_OS_windows) && defined(USE_MOZ_STACK_WALK)
#if defined(GP_OS_windows) && defined(USE_MOZ_STACK_WALK)
static HANDLE GetThreadHandle(PlatformData* aData);
# endif
#endif
# if defined(USE_FRAME_POINTER_STACK_WALK) || defined(USE_MOZ_STACK_WALK)
#if defined(USE_FRAME_POINTER_STACK_WALK) || defined(USE_MOZ_STACK_WALK)
static void StackWalkCallback(uint32_t aFrameNumber, void* aPC, void* aSP,
void* aClosure) {
NativeStack* nativeStack = static_cast<NativeStack*>(aClosure);
@ -1302,9 +1299,9 @@ static void StackWalkCallback(uint32_t aFrameNumber, void* aPC, void* aSP,
nativeStack->mPCs[nativeStack->mCount] = aPC;
nativeStack->mCount++;
}
# endif
#endif
# if defined(USE_FRAME_POINTER_STACK_WALK)
#if defined(USE_FRAME_POINTER_STACK_WALK)
static void DoFramePointerBacktrace(PSLockRef aLock,
const RegisteredThread& aRegisteredThread,
const Registers& aRegs,
@ -1328,9 +1325,9 @@ static void DoFramePointerBacktrace(PSLockRef aLock,
const_cast<void*>(stackEnd));
}
}
# endif
#endif
# if defined(USE_MOZ_STACK_WALK)
#if defined(USE_MOZ_STACK_WALK)
static void DoMozStackWalkBacktrace(PSLockRef aLock,
const RegisteredThread& aRegisteredThread,
const Registers& aRegs,
@ -1352,9 +1349,9 @@ static void DoMozStackWalkBacktrace(PSLockRef aLock,
MozStackWalkThread(StackWalkCallback, /* skipFrames */ 0, maxFrames,
&aNativeStack, thread, /* context */ nullptr);
}
# endif
#endif
# ifdef USE_EHABI_STACKWALK
#ifdef USE_EHABI_STACKWALK
static void DoEHABIBacktrace(PSLockRef aLock,
const RegisteredThread& aRegisteredThread,
const Registers& aRegs,
@ -1372,12 +1369,12 @@ static void DoEHABIBacktrace(PSLockRef aLock,
aNativeStack.mPCs + aNativeStack.mCount,
MAX_NATIVE_FRAMES - aNativeStack.mCount);
}
# endif
#endif
# ifdef USE_LUL_STACKWALK
#ifdef USE_LUL_STACKWALK
// See the comment at the callsite for why this function is necessary.
# if defined(MOZ_HAVE_ASAN_BLACKLIST)
# if defined(MOZ_HAVE_ASAN_BLACKLIST)
MOZ_ASAN_BLACKLIST static void ASAN_memcpy(void* aDst, const void* aSrc,
size_t aLen) {
// The obvious thing to do here is call memcpy(). However, although
@ -1391,7 +1388,7 @@ MOZ_ASAN_BLACKLIST static void ASAN_memcpy(void* aDst, const void* aSrc,
dst[i] = src[i];
}
}
# endif
# endif
static void DoLULBacktrace(PSLockRef aLock,
const RegisteredThread& aRegisteredThread,
@ -1405,33 +1402,33 @@ static void DoLULBacktrace(PSLockRef aLock,
lul::UnwindRegs startRegs;
memset(&startRegs, 0, sizeof(startRegs));
# if defined(GP_PLAT_amd64_linux) || defined(GP_PLAT_amd64_android)
# if defined(GP_PLAT_amd64_linux) || defined(GP_PLAT_amd64_android)
startRegs.xip = lul::TaggedUWord(mc->gregs[REG_RIP]);
startRegs.xsp = lul::TaggedUWord(mc->gregs[REG_RSP]);
startRegs.xbp = lul::TaggedUWord(mc->gregs[REG_RBP]);
# elif defined(GP_PLAT_arm_linux) || defined(GP_PLAT_arm_android)
# elif defined(GP_PLAT_arm_linux) || defined(GP_PLAT_arm_android)
startRegs.r15 = lul::TaggedUWord(mc->arm_pc);
startRegs.r14 = lul::TaggedUWord(mc->arm_lr);
startRegs.r13 = lul::TaggedUWord(mc->arm_sp);
startRegs.r12 = lul::TaggedUWord(mc->arm_ip);
startRegs.r11 = lul::TaggedUWord(mc->arm_fp);
startRegs.r7 = lul::TaggedUWord(mc->arm_r7);
# elif defined(GP_PLAT_arm64_linux) || defined(GP_PLAT_arm64_android)
# elif defined(GP_PLAT_arm64_linux) || defined(GP_PLAT_arm64_android)
startRegs.pc = lul::TaggedUWord(mc->pc);
startRegs.x29 = lul::TaggedUWord(mc->regs[29]);
startRegs.x30 = lul::TaggedUWord(mc->regs[30]);
startRegs.sp = lul::TaggedUWord(mc->sp);
# elif defined(GP_PLAT_x86_linux) || defined(GP_PLAT_x86_android)
# elif defined(GP_PLAT_x86_linux) || defined(GP_PLAT_x86_android)
startRegs.xip = lul::TaggedUWord(mc->gregs[REG_EIP]);
startRegs.xsp = lul::TaggedUWord(mc->gregs[REG_ESP]);
startRegs.xbp = lul::TaggedUWord(mc->gregs[REG_EBP]);
# elif defined(GP_PLAT_mips64_linux)
# elif defined(GP_PLAT_mips64_linux)
startRegs.pc = lul::TaggedUWord(mc->pc);
startRegs.sp = lul::TaggedUWord(mc->gregs[29]);
startRegs.fp = lul::TaggedUWord(mc->gregs[30]);
# else
# error "Unknown plat"
# endif
# else
# error "Unknown plat"
# endif
// Copy up to N_STACK_BYTES from rsp-REDZONE upwards, but not going past the
// stack's registered top point. Do some basic sanity checks too. This
@ -1467,24 +1464,24 @@ static void DoLULBacktrace(PSLockRef aLock,
lul::StackImage stackImg;
{
# if defined(GP_PLAT_amd64_linux) || defined(GP_PLAT_amd64_android)
# if defined(GP_PLAT_amd64_linux) || defined(GP_PLAT_amd64_android)
uintptr_t rEDZONE_SIZE = 128;
uintptr_t start = startRegs.xsp.Value() - rEDZONE_SIZE;
# elif defined(GP_PLAT_arm_linux) || defined(GP_PLAT_arm_android)
# elif defined(GP_PLAT_arm_linux) || defined(GP_PLAT_arm_android)
uintptr_t rEDZONE_SIZE = 0;
uintptr_t start = startRegs.r13.Value() - rEDZONE_SIZE;
# elif defined(GP_PLAT_arm64_linux) || defined(GP_PLAT_arm64_android)
# elif defined(GP_PLAT_arm64_linux) || defined(GP_PLAT_arm64_android)
uintptr_t rEDZONE_SIZE = 0;
uintptr_t start = startRegs.sp.Value() - rEDZONE_SIZE;
# elif defined(GP_PLAT_x86_linux) || defined(GP_PLAT_x86_android)
# elif defined(GP_PLAT_x86_linux) || defined(GP_PLAT_x86_android)
uintptr_t rEDZONE_SIZE = 0;
uintptr_t start = startRegs.xsp.Value() - rEDZONE_SIZE;
# elif defined(GP_PLAT_mips64_linux)
# elif defined(GP_PLAT_mips64_linux)
uintptr_t rEDZONE_SIZE = 0;
uintptr_t start = startRegs.sp.Value() - rEDZONE_SIZE;
# else
# error "Unknown plat"
# endif
# else
# error "Unknown plat"
# endif
uintptr_t end = reinterpret_cast<uintptr_t>(aRegisteredThread.StackTop());
uintptr_t ws = sizeof(void*);
start &= ~(ws - 1);
@ -1507,11 +1504,11 @@ static void DoLULBacktrace(PSLockRef aLock,
//
// This code is very much a custom stack unwind mechanism! So we use an
// alternative memcpy() implementation that is ignored by ASAN.
# if defined(MOZ_HAVE_ASAN_BLACKLIST)
# if defined(MOZ_HAVE_ASAN_BLACKLIST)
ASAN_memcpy(&stackImg.mContents[0], (void*)start, nToCopy);
# else
# else
memcpy(&stackImg.mContents[0], (void*)start, nToCopy);
# endif
# endif
(void)VALGRIND_MAKE_MEM_DEFINED(&stackImg.mContents[0], nToCopy);
}
}
@ -1530,9 +1527,9 @@ static void DoLULBacktrace(PSLockRef aLock,
lul->mStats.mFP += framePointerFramesAcquired;
}
# endif
#endif
# ifdef HAVE_NATIVE_UNWIND
#ifdef HAVE_NATIVE_UNWIND
static void DoNativeBacktrace(PSLockRef aLock,
const RegisteredThread& aRegisteredThread,
const Registers& aRegs,
@ -1542,19 +1539,19 @@ static void DoNativeBacktrace(PSLockRef aLock,
// profiler_suspend_and_sample_thread() for details). The only part of the
// ordering that matters is that LUL must precede FRAME_POINTER, because on
// Linux they can both be present.
# if defined(USE_LUL_STACKWALK)
# if defined(USE_LUL_STACKWALK)
DoLULBacktrace(aLock, aRegisteredThread, aRegs, aNativeStack);
# elif defined(USE_EHABI_STACKWALK)
# elif defined(USE_EHABI_STACKWALK)
DoEHABIBacktrace(aLock, aRegisteredThread, aRegs, aNativeStack);
# elif defined(USE_FRAME_POINTER_STACK_WALK)
# elif defined(USE_FRAME_POINTER_STACK_WALK)
DoFramePointerBacktrace(aLock, aRegisteredThread, aRegs, aNativeStack);
# elif defined(USE_MOZ_STACK_WALK)
# elif defined(USE_MOZ_STACK_WALK)
DoMozStackWalkBacktrace(aLock, aRegisteredThread, aRegs, aNativeStack);
# else
# error "Invalid configuration"
# endif
}
# else
# error "Invalid configuration"
# endif
}
#endif
// Writes some components shared by periodic and synchronous profiles to
// ActivePS's ProfileBuffer. (This should only be called from DoSyncSample()
@ -1576,14 +1573,14 @@ static inline void DoSharedSample(PSLockRef aLock, bool aIsSynchronous,
ProfileBufferCollector collector(aBuffer, ActivePS::Features(aLock),
aSamplePos);
NativeStack nativeStack;
# if defined(HAVE_NATIVE_UNWIND)
#if defined(HAVE_NATIVE_UNWIND)
if (ActivePS::FeatureStackWalk(aLock)) {
DoNativeBacktrace(aLock, aRegisteredThread, aRegs, nativeStack);
MergeStacks(ActivePS::Features(aLock), aIsSynchronous, aRegisteredThread,
aRegs, nativeStack, collector);
} else
# endif
#endif
{
MergeStacks(ActivePS::Features(aLock), aIsSynchronous, aRegisteredThread,
aRegs, nativeStack, collector);
@ -1680,24 +1677,24 @@ static void StreamCategories(SpliceableJSONWriter& aWriter) {
// ...
// ]
# define CATEGORY_JSON_BEGIN_CATEGORY(name, labelAsString, color) \
aWriter.Start(); \
aWriter.StringProperty("name", labelAsString); \
aWriter.StringProperty("color", color); \
aWriter.StartArrayProperty("subcategories");
# define CATEGORY_JSON_SUBCATEGORY(supercategory, name, labelAsString) \
aWriter.StringElement(labelAsString);
# define CATEGORY_JSON_END_CATEGORY \
aWriter.EndArray(); \
aWriter.EndObject();
#define CATEGORY_JSON_BEGIN_CATEGORY(name, labelAsString, color) \
aWriter.Start(); \
aWriter.StringProperty("name", labelAsString); \
aWriter.StringProperty("color", color); \
aWriter.StartArrayProperty("subcategories");
#define CATEGORY_JSON_SUBCATEGORY(supercategory, name, labelAsString) \
aWriter.StringElement(labelAsString);
#define CATEGORY_JSON_END_CATEGORY \
aWriter.EndArray(); \
aWriter.EndObject();
BASE_PROFILING_CATEGORY_LIST(CATEGORY_JSON_BEGIN_CATEGORY,
CATEGORY_JSON_SUBCATEGORY,
CATEGORY_JSON_END_CATEGORY)
# undef CATEGORY_JSON_BEGIN_CATEGORY
# undef CATEGORY_JSON_SUBCATEGORY
# undef CATEGORY_JSON_END_CATEGORY
#undef CATEGORY_JSON_BEGIN_CATEGORY
#undef CATEGORY_JSON_SUBCATEGORY
#undef CATEGORY_JSON_END_CATEGORY
}
static int64_t MicrosecondsSince1970();
@ -1742,11 +1739,11 @@ static void StreamMetaJSCustomObject(PSLockRef aLock,
aWriter.DoubleProperty("interval", ActivePS::Interval(aLock));
aWriter.IntProperty("stackwalk", ActivePS::FeatureStackWalk(aLock));
# ifdef DEBUG
#ifdef DEBUG
aWriter.IntProperty("debug", 1);
# else
#else
aWriter.IntProperty("debug", 0);
# endif
#endif
aWriter.IntProperty("gcpoison", 0);
@ -1946,14 +1943,14 @@ static void PrintUsageThenExit(int aExitCode) {
unsigned(BASE_PROFILER_DEFAULT_STARTUP_ENTRIES.Value() *
scBytesPerEntry));
# define PRINT_FEATURE(n_, str_, Name_, desc_) \
PrintToConsole(" %c %5u: \"%s\" (%s)\n", \
FeatureCategory(ProfilerFeature::Name_), \
ProfilerFeature::Name_, str_, desc_);
#define PRINT_FEATURE(n_, str_, Name_, desc_) \
PrintToConsole(" %c %5u: \"%s\" (%s)\n", \
FeatureCategory(ProfilerFeature::Name_), \
ProfilerFeature::Name_, str_, desc_);
BASE_PROFILER_FOR_EACH_FEATURE(PRINT_FEATURE)
# undef PRINT_FEATURE
#undef PRINT_FEATURE
PrintToConsole(
" - \"default\" (All above D+S defaults)\n"
@ -1978,11 +1975,11 @@ static void PrintUsageThenExit(int aExitCode) {
"\n"
" This platform %s native unwinding.\n"
"\n",
# if defined(HAVE_NATIVE_UNWIND)
#if defined(HAVE_NATIVE_UNWIND)
"supports"
# else
#else
"does not support"
# endif
#endif
);
exit(aExitCode);
@ -1991,9 +1988,9 @@ static void PrintUsageThenExit(int aExitCode) {
////////////////////////////////////////////////////////////////////////
// BEGIN Sampler
# if defined(GP_OS_linux) || defined(GP_OS_android)
#if defined(GP_OS_linux) || defined(GP_OS_android)
struct SigHandlerCoordinator;
# endif
#endif
// Sampler performs setup and teardown of the state required to sample with the
// profiler. Sampler may exist when ActivePS is not present.
@ -2028,7 +2025,7 @@ class Sampler {
const TimeStamp& aNow, const Func& aProcessRegs);
private:
# if defined(GP_OS_linux) || defined(GP_OS_android)
#if defined(GP_OS_linux) || defined(GP_OS_android)
// Used to restore the SIGPROF handler when ours is removed.
struct sigaction mOldSigprofHandler;
@ -2045,7 +2042,7 @@ class Sampler {
// thread and the samplee thread's signal handler. It's static because the
// samplee thread's signal handler is static.
static struct SigHandlerCoordinator* sSigHandlerCoordinator;
# endif
#endif
};
// END Sampler
@ -2086,11 +2083,11 @@ class SamplerThread {
const int mIntervalMicroseconds;
// The OS-specific handle for the sampler thread.
# if defined(GP_OS_windows)
#if defined(GP_OS_windows)
HANDLE mThread;
# elif defined(GP_OS_darwin) || defined(GP_OS_linux) || defined(GP_OS_android)
#elif defined(GP_OS_darwin) || defined(GP_OS_linux) || defined(GP_OS_android)
pthread_t mThread;
# endif
#endif
SamplerThread(const SamplerThread&) = delete;
void operator=(const SamplerThread&) = delete;
@ -2250,14 +2247,14 @@ void SamplerThread::Run() {
}
}
# if defined(USE_LUL_STACKWALK)
#if defined(USE_LUL_STACKWALK)
// The LUL unwind object accumulates frame statistics. Periodically we
// should poke it to give it a chance to print those statistics. This
// involves doing I/O (fprintf, __android_log_print, etc.) and so
// can't safely be done from the critical section inside
// SuspendAndSampleAndResumeThread, which is why it is done here.
CorePS::Lul(lock)->MaybeShowStats();
# endif
#endif
TimeStamp threadsSampled = TimeStamp::NowUnfuzzed();
{
@ -2298,15 +2295,15 @@ void SamplerThread::Run() {
// We #include these files directly because it means those files can use
// declarations from this file trivially. These provide target-specific
// implementations of all SamplerThread methods except Run().
# if defined(GP_OS_windows)
# include "platform-win32.cpp"
# elif defined(GP_OS_darwin)
# include "platform-macos.cpp"
# elif defined(GP_OS_linux) || defined(GP_OS_android)
# include "platform-linux-android.cpp"
# else
# error "bad platform"
# endif
#if defined(GP_OS_windows)
# include "platform-win32.cpp"
#elif defined(GP_OS_darwin)
# include "platform-macos.cpp"
#elif defined(GP_OS_linux) || defined(GP_OS_android)
# include "platform-linux-android.cpp"
#else
# error "bad platform"
#endif
namespace mozilla {
namespace baseprofiler {
@ -2330,14 +2327,14 @@ static uint32_t ParseFeature(const char* aFeature, bool aIsStartup) {
AvailableFeatures();
}
# define PARSE_FEATURE_BIT(n_, str_, Name_, desc_) \
if (strcmp(aFeature, str_) == 0) { \
return ProfilerFeature::Name_; \
}
#define PARSE_FEATURE_BIT(n_, str_, Name_, desc_) \
if (strcmp(aFeature, str_) == 0) { \
return ProfilerFeature::Name_; \
}
BASE_PROFILER_FOR_EACH_FEATURE(PARSE_FEATURE_BIT)
# undef PARSE_FEATURE_BIT
#undef PARSE_FEATURE_BIT
PrintToConsole("\nUnrecognized feature \"%s\".\n\n", aFeature);
PrintUsageThenExit(1);
@ -2879,14 +2876,14 @@ static void locked_profiler_start(PSLockRef aLock, PowerOfTwo32 aCapacity,
LOG("- duration = %.2f", aDuration ? *aDuration : -1);
LOG("- interval = %.2f", aInterval);
# define LOG_FEATURE(n_, str_, Name_, desc_) \
if (ProfilerFeature::Has##Name_(aFeatures)) { \
LOG("- feature = %s", str_); \
}
#define LOG_FEATURE(n_, str_, Name_, desc_) \
if (ProfilerFeature::Has##Name_(aFeatures)) { \
LOG("- feature = %s", str_); \
}
BASE_PROFILER_FOR_EACH_FEATURE(LOG_FEATURE)
# undef LOG_FEATURE
#undef LOG_FEATURE
for (uint32_t i = 0; i < aFilterCount; i++) {
LOG("- threads = %s", aFilters[i]);
@ -2895,9 +2892,9 @@ static void locked_profiler_start(PSLockRef aLock, PowerOfTwo32 aCapacity,
MOZ_RELEASE_ASSERT(CorePS::Exists() && !ActivePS::Exists(aLock));
# if defined(GP_PLAT_amd64_windows)
#if defined(GP_PLAT_amd64_windows)
InitializeWin64ProfilerHooks();
# endif
#endif
// Fall back to the default values if the passed-in values are unreasonable.
// Less than 8192 entries (65536 bytes) may not be enough for the most complex
@ -3343,11 +3340,11 @@ UniqueProfilerBacktrace profiler_get_backtrace() {
TimeStamp now = TimeStamp::NowUnfuzzed();
Registers regs;
# if defined(HAVE_NATIVE_UNWIND)
#if defined(HAVE_NATIVE_UNWIND)
regs.SyncPopulate();
# else
#else
regs.Clear();
# endif
#endif
auto bufferManager = MakeUnique<ProfileChunkedBuffer>(
ProfileChunkedBuffer::ThreadSafety::WithoutMutex,
@ -3424,7 +3421,7 @@ void profiler_add_marker_for_thread(int aThreadId,
return;
}
# ifdef DEBUG
#ifdef DEBUG
{
PSAutoLock lock;
if (!ActivePS::Exists(lock)) {
@ -3444,7 +3441,7 @@ void profiler_add_marker_for_thread(int aThreadId,
}
MOZ_ASSERT(realThread, "Invalid thread id");
}
# endif
#endif
// Insert the marker into the buffer
TimeStamp origin = (aPayload && !aPayload->GetStartTime().IsNull())
@ -3541,25 +3538,25 @@ void profiler_suspend_and_sample_thread(int aThreadId, uint32_t aFeatures,
// The target thread is now suspended. Collect a native
// backtrace, and call the callback.
bool isSynchronous = false;
# if defined(HAVE_FASTINIT_NATIVE_UNWIND)
#if defined(HAVE_FASTINIT_NATIVE_UNWIND)
if (aSampleNative) {
// We can only use FramePointerStackWalk or MozStackWalk from
// suspend_and_sample_thread as other stackwalking methods may not be
// initialized.
# if defined(USE_FRAME_POINTER_STACK_WALK)
# if defined(USE_FRAME_POINTER_STACK_WALK)
DoFramePointerBacktrace(lock, registeredThread, aRegs,
nativeStack);
# elif defined(USE_MOZ_STACK_WALK)
# elif defined(USE_MOZ_STACK_WALK)
DoMozStackWalkBacktrace(lock, registeredThread, aRegs,
nativeStack);
# else
# error "Invalid configuration"
# endif
# else
# error "Invalid configuration"
# endif
MergeStacks(aFeatures, isSynchronous, registeredThread, aRegs,
nativeStack, aCollector);
} else
# endif
#endif
{
MergeStacks(aFeatures, isSynchronous, registeredThread, aRegs,
nativeStack, aCollector);
@ -3583,5 +3580,3 @@ void profiler_suspend_and_sample_thread(int aThreadId, uint32_t aFeatures,
} // namespace baseprofiler
} // namespace mozilla
#endif // MOZ_GECKO_PROFILER

Просмотреть файл

@ -4,49 +4,45 @@
* 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/. */
#include "BaseProfiler.h"
#include "BaseProfilerSharedLibraries.h"
#ifdef MOZ_GECKO_PROFILER
#define PATH_MAX_TOSTRING(x) #x
#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 "BaseProfilerSharedLibraries.h"
#include <algorithm>
#include <arpa/inet.h>
#include <dlfcn.h>
#include <elf.h>
#include <fcntl.h>
#include <features.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <vector>
# define PATH_MAX_TOSTRING(x) # x
# 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"
#if defined(MOZ_LINKER)
# include "AutoObjectMapper.h"
#endif
#if defined(GP_OS_linux) || defined(GP_OS_android)
# include <link.h> // dl_phdr_info, ElfW()
#else
# error "Unexpected configuration"
#endif
# include <algorithm>
# include <arpa/inet.h>
# include <dlfcn.h>
# include <elf.h>
# include <fcntl.h>
# include <features.h>
# include <sys/mman.h>
# include <sys/stat.h>
# include <sys/types.h>
# include <vector>
# if defined(MOZ_LINKER)
# include "AutoObjectMapper.h"
# endif
# if defined(GP_OS_linux) || defined(GP_OS_android)
# include <link.h> // dl_phdr_info, ElfW()
# else
# error "Unexpected configuration"
# endif
# if defined(GP_OS_android)
#if defined(GP_OS_android)
extern "C" MOZ_EXPORT __attribute__((weak)) int dl_iterate_phdr(
int (*callback)(struct dl_phdr_info* info, size_t size, void* data),
void* data);
# endif
#endif
// ----------------------------------------------------------------------------
// Starting imports from toolkit/crashreporter/google-breakpad/, as needed by
@ -182,15 +178,15 @@ class MemoryMappedFile {
return false;
}
# if defined(__x86_64__) || defined(__aarch64__) || \
(defined(__mips__) && _MIPS_SIM == _ABI64)
#if defined(__x86_64__) || defined(__aarch64__) || \
(defined(__mips__) && _MIPS_SIM == _ABI64)
struct stat st;
if (fstat(fd, &st) == -1 || st.st_size < 0) {
# else
#else
struct stat64 st;
if (fstat64(fd, &st) == -1 || st.st_size < 0) {
# endif
#endif
close(fd);
return false;
}
@ -357,7 +353,7 @@ class FileID {
}
// ELF note name and desc are 32-bits word padded.
# define NOTE_PADDING(a) ((a + 3) & ~3)
#define NOTE_PADDING(a) ((a + 3) & ~3)
static bool ElfClassBuildIDNoteIdentifier(const void* section, size_t length,
std::vector<uint8_t>& identifier) {
@ -651,10 +647,10 @@ struct LoadedLibraryInfo {
unsigned long mLastMappingEnd;
};
# if defined(MOZ_LINKER)
#if defined(MOZ_LINKER)
static void outputMapperLog(const char* aBuf) { /* LOG("%s", aBuf); */
}
# endif
#endif
static std::string IDtoUUIDString(const std::vector<uint8_t>& aIdentifier) {
std::string uuid = FileID::ConvertIdentifierToUUIDString(aIdentifier);
@ -668,7 +664,7 @@ static std::string getId(const char* bin_name) {
std::vector<uint8_t> identifier;
identifier.reserve(kDefaultBuildIdSize);
# if defined(MOZ_LINKER)
#if defined(MOZ_LINKER)
if (std::string(bin_name).find(std::string("!/")) != std::string::npos) {
AutoObjectMapperFaultyLib mapper(outputMapperLog);
void* image = nullptr;
@ -679,7 +675,7 @@ static std::string getId(const char* bin_name) {
}
}
}
# endif
#endif
FileID file_id(bin_name);
if (file_id.ElfFileIdentifier(identifier)) {
@ -736,7 +732,7 @@ static int dl_iterate_callback(struct dl_phdr_info* dl_info, size_t size,
SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
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
// address of its executable section (exeExeAddr) in the running image.
char exeName[PATH_MAX];
@ -755,9 +751,9 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
}
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) {
// On ARM Android, dl_iterate_phdr is provided by the custom linker.
@ -766,7 +762,7 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
// not call it.
return info;
}
# endif
#endif
// Read info from /proc/self/maps. We ignore most of it.
pid_t pid = mozilla::baseprofiler::profiler_current_process_id();
@ -794,12 +790,12 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
continue;
}
# if defined(GP_OS_linux)
#if defined(GP_OS_linux)
// Try to establish the main executable's load address.
if (exeNameLen > 0 && strcmp(modulePath, exeName) == 0) {
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
// associated phdrs.
if (0 == strcmp(modulePath, "/dev/ashmem/dalvik-jit-code-cache")) {
@ -811,7 +807,7 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
break;
}
}
# endif
#endif
}
std::vector<LoadedLibraryInfo> libInfoList;
@ -826,7 +822,7 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
libInfo.mFirstMappingStart - libInfo.mBaseAddress));
}
# if defined(GP_OS_linux)
#if defined(GP_OS_linux)
// Make another pass over the information we just harvested from
// 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
@ -842,12 +838,10 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
break;
}
}
# endif
#endif
return info;
}
void SharedLibraryInfo::Initialize() { /* do nothing */
}
#endif // MOZ_GECKO_PROFILER

Просмотреть файл

@ -3,45 +3,41 @@
* 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/. */
#include "BaseProfiler.h"
#include "BaseProfilerSharedLibraries.h"
#ifdef MOZ_GECKO_PROFILER
#include "platform.h"
# include "BaseProfilerSharedLibraries.h"
#include "mozilla/Unused.h"
#include <AvailabilityMacros.h>
# include "platform.h"
# include "mozilla/Unused.h"
# include <AvailabilityMacros.h>
# include <dlfcn.h>
# include <mach-o/arch.h>
# include <mach-o/dyld_images.h>
# include <mach-o/dyld.h>
# 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>
#include <dlfcn.h>
#include <mach-o/arch.h>
#include <mach-o/dyld_images.h>
#include <mach-o/dyld.h>
#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.
# if defined(GP_ARCH_x86)
#if defined(GP_ARCH_x86)
typedef mach_header platform_mach_header;
typedef segment_command mach_segment_command_type;
# define MACHO_MAGIC_NUMBER MH_MAGIC
# define CMD_SEGMENT LC_SEGMENT
# define seg_size uint32_t
# else
# define MACHO_MAGIC_NUMBER MH_MAGIC
# define CMD_SEGMENT LC_SEGMENT
# define seg_size uint32_t
#else
typedef mach_header_64 platform_mach_header;
typedef segment_command_64 mach_segment_command_type;
# define MACHO_MAGIC_NUMBER MH_MAGIC_64
# define CMD_SEGMENT LC_SEGMENT_64
# define seg_size uint64_t
# endif
# define MACHO_MAGIC_NUMBER MH_MAGIC_64
# define CMD_SEGMENT LC_SEGMENT_64
# define seg_size uint64_t
#endif
struct NativeSharedLibrary {
const platform_mach_header* header;
@ -184,5 +180,3 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
return sharedLibraryInfo;
}
#endif // MOZ_GECKO_PROFILER

Просмотреть файл

@ -3,23 +3,19 @@
* 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/. */
#include "BaseProfiler.h"
#include <windows.h>
#include <dbghelp.h>
#include <sstream>
#include <psapi.h>
#ifdef MOZ_GECKO_PROFILER
#include "BaseProfilerSharedLibraries.h"
# include <windows.h>
# include <dbghelp.h>
# include <sstream>
# include <psapi.h>
#include "mozilla/UniquePtr.h"
#include "mozilla/Unused.h"
# include "BaseProfilerSharedLibraries.h"
#include <string>
# include "mozilla/UniquePtr.h"
# include "mozilla/Unused.h"
# include <string>
# define CV_SIGNATURE 0x53445352 // 'SDSR'
#define CV_SIGNATURE 0x53445352 // 'SDSR'
struct CodeViewRecord70 {
uint32_t signature;
@ -237,5 +233,3 @@ SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
void SharedLibraryInfo::Initialize() { /* do nothing */
}
#endif // MOZ_GECKO_PROFILER

Просмотреть файл

@ -4,28 +4,25 @@
* 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/. */
#include <sys/mman.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "mozilla/Assertions.h"
#include "mozilla/Sprintf.h"
#include "BaseProfiler.h"
#include "PlatformMacros.h"
#include "AutoObjectMapper.h"
#ifdef MOZ_GECKO_PROFILER
# include <sys/mman.h>
# include <unistd.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include "mozilla/Assertions.h"
# include "mozilla/Sprintf.h"
# include "PlatformMacros.h"
# include "AutoObjectMapper.h"
# if defined(MOZ_LINKER)
# include <dlfcn.h>
# include "mozilla/Types.h"
# if defined(ANDROID)
# include <sys/system_properties.h>
# endif
#if defined(MOZ_LINKER)
# include <dlfcn.h>
# include "mozilla/Types.h"
# if defined(ANDROID)
# include <sys/system_properties.h>
# endif
// FIXME move these out of mozglue/linker/ElfLoader.h into their
// own header, so as to avoid conflicts arising from two definitions
// of Array
@ -34,7 +31,7 @@ MFBT_API size_t __dl_get_mappable_length(void* handle);
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);
}
# endif
#endif
// A helper function for creating failure error messages in
// AutoObjectMapper*::Map.
@ -98,8 +95,8 @@ bool AutoObjectMapperPOSIX::Map(/*OUT*/ void** start, /*OUT*/ size_t* length,
return true;
}
# if defined(MOZ_LINKER)
# if defined(ANDROID)
#if defined(MOZ_LINKER)
# if defined(ANDROID)
static int GetAndroidSDKVersion() {
static int version = 0;
if (version) {
@ -113,7 +110,7 @@ static int GetAndroidSDKVersion() {
}
return version;
}
# endif
# endif
AutoObjectMapperFaultyLib::AutoObjectMapperFaultyLib(void (*aLog)(const char*))
: AutoObjectMapperPOSIX(aLog), mHdl(nullptr) {}
@ -142,15 +139,13 @@ bool AutoObjectMapperFaultyLib::Map(/*OUT*/ void** start,
std::string fileName) {
MOZ_ASSERT(!mHdl);
# if defined(ANDROID)
# if defined(ANDROID)
if (GetAndroidSDKVersion() >= 23) {
return AutoObjectMapperPOSIX::Map(start, length, fileName);
}
# endif
# endif
return false;
}
# endif // defined(MOZ_LINKER)
#endif // MOZ_GECKO_PROFILER
#endif // defined(MOZ_LINKER)

Просмотреть файл

@ -37,19 +37,17 @@
// src/common/module.cc
// src/common/unique_string.cc
#include "BaseProfiler.h"
#ifdef MOZ_GECKO_PROFILER
// There's no internal-only interface for LulCommon. Hence include
// the external interface directly.
# include "LulCommonExt.h"
#include "LulCommonExt.h"
# include <stdlib.h>
# include <string.h>
#include <stdlib.h>
#include <string.h>
# include <string>
# include <map>
#include <string>
#include <map>
#include "BaseProfiler.h"
namespace lul {
@ -102,5 +100,3 @@ const UniqueString* UniqueStringUniverse::ToUniqueString(string str) {
}
} // namespace lul
#endif // MOZ_GECKO_PROFILER

Просмотреть файл

@ -41,27 +41,23 @@
// src/common/dwarf/dwarf2reader.cc
// src/common/dwarf_cfi_to_module.cc
#include "BaseProfiler.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef MOZ_GECKO_PROFILER
#include <map>
#include <stack>
#include <string>
# include <stdint.h>
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
#include "mozilla/Assertions.h"
#include "mozilla/Sprintf.h"
# include <map>
# include <stack>
# include <string>
# include "mozilla/Assertions.h"
# include "mozilla/Sprintf.h"
# include "LulCommonExt.h"
# include "LulDwarfInt.h"
#include "LulCommonExt.h"
#include "LulDwarfInt.h"
// Set this to 1 for verbose logging
# define DEBUG_DWARF 0
#define DEBUG_DWARF 0
namespace lul {
@ -2254,5 +2250,3 @@ void DwarfCFIToModule::Reporter::ExpressionCouldNotBeSummarised(
}
} // namespace lul
#endif // MOZ_GECKO_PROFILER

Просмотреть файл

@ -4,19 +4,15 @@
* 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/. */
#include "BaseProfiler.h"
#include "LulDwarfSummariser.h"
#ifdef MOZ_GECKO_PROFILER
#include "mozilla/Assertions.h"
#include "mozilla/Sprintf.h"
# include "LulDwarfSummariser.h"
# include "LulDwarfExt.h"
# include "mozilla/Assertions.h"
# include "mozilla/Sprintf.h"
#include "LulDwarfExt.h"
// Set this to 1 for verbose logging
# define DEBUG_SUMMARISER 0
#define DEBUG_SUMMARISER 0
namespace lul {
@ -128,7 +124,7 @@ void Summariser::Rule(uintptr_t aAddress, int aNewReg, LExprHow how,
// FIXME: factor out common parts of the arch-dependent summarisers.
# if defined(GP_ARCH_arm)
#if defined(GP_ARCH_arm)
// ----------------- arm ----------------- //
@ -250,7 +246,7 @@ void Summariser::Rule(uintptr_t aAddress, int aNewReg, LExprHow how,
mCurrRules.mR15expr = LExpr(NODEREF, DW_REG_ARM_R14, 0);
}
# elif defined(GP_ARCH_arm64)
#elif defined(GP_ARCH_arm64)
// ----------------- arm64 ----------------- //
@ -331,7 +327,7 @@ void Summariser::Rule(uintptr_t aAddress, int aNewReg, LExprHow how,
if (mCurrRules.mSPexpr.mHow == UNKNOWN) {
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 ---------------- //
@ -431,7 +427,7 @@ void Summariser::Rule(uintptr_t aAddress, int aNewReg, LExprHow how,
mCurrRules.mXbpExpr = LExpr(NODEREF, DW_REG_INTEL_XBP, 0);
}
# elif defined(GP_ARCH_mips64)
#elif defined(GP_ARCH_mips64)
// ---------------- mips ---------------- //
//
// Now, can we add the rule to our summary? This depends on whether
@ -513,10 +509,10 @@ void Summariser::Rule(uintptr_t aAddress, int aNewReg, LExprHow how,
mCurrRules.mFPexpr = LExpr(NODEREF, DW_REG_MIPS_FP, 0);
}
# else
#else
# error "Unsupported arch"
# endif
# error "Unsupported arch"
#endif
return;
@ -555,5 +551,3 @@ void Summariser::End() {
}
} // namespace lul
#endif // MOZ_GECKO_PROFILER

Просмотреть файл

@ -45,42 +45,38 @@
// src/common/linux/elfutils.cc
// src/common/linux/file_id.cc
#include "BaseProfiler.h"
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <arpa/inet.h>
#ifdef MOZ_GECKO_PROFILER
#include <set>
#include <string>
#include <vector>
# include <errno.h>
# include <fcntl.h>
# include <libgen.h>
# include <stdio.h>
# include <string.h>
# include <sys/mman.h>
# include <sys/stat.h>
# include <unistd.h>
# include <arpa/inet.h>
#include "mozilla/Assertions.h"
#include "mozilla/Sprintf.h"
# include <set>
# include <string>
# include <vector>
#include "PlatformMacros.h"
#include "LulCommonExt.h"
#include "LulDwarfExt.h"
#include "LulElfInt.h"
#include "LulMainInt.h"
# 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)
#if defined(GP_PLAT_arm_android) && !defined(SHT_ARM_EXIDX)
// bionic and older glibsc don't define it
# define SHT_ARM_EXIDX (SHT_LOPROC + 1)
# endif
# define SHT_ARM_EXIDX (SHT_LOPROC + 1)
#endif
// Old Linux header doesn't define EM_AARCH64
# ifndef EM_AARCH64
# define EM_AARCH64 183
# endif
#ifndef EM_AARCH64
# define EM_AARCH64 183
#endif
// This namespace contains helper functions.
namespace {
@ -749,7 +745,7 @@ bool FindElfSegment(const void* elf_mapped_base, uint32_t segment_type,
//
// 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
// and use the syscall/libc wrappers instead of direct syscalls or libc.
@ -874,5 +870,3 @@ void FileID::ConvertIdentifierToString(const uint8_t identifier[kMDGUIDSize],
}
} // namespace lul
#endif // MOZ_GECKO_PROFILER

Просмотреть файл

@ -4,40 +4,36 @@
* 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/. */
#include "LulMain.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h> // write(), only for testing LUL
#include <algorithm> // std::sort
#include <string>
#include <utility>
#include "mozilla/Assertions.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/MemoryChecking.h"
#include "mozilla/Sprintf.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/Unused.h"
#include "BaseProfiler.h"
#ifdef MOZ_GECKO_PROFILER
# include "LulMain.h"
# include <string.h>
# include <stdlib.h>
# include <stdio.h>
# include <unistd.h> // write(), only for testing LUL
# include <algorithm> // std::sort
# include <string>
# include <utility>
# include "mozilla/Assertions.h"
# include "mozilla/ArrayUtils.h"
# include "mozilla/CheckedInt.h"
# include "mozilla/DebugOnly.h"
# include "mozilla/MemoryChecking.h"
# include "mozilla/Sprintf.h"
# include "mozilla/UniquePtr.h"
# include "mozilla/Unused.h"
# include "LulCommonExt.h"
# include "LulElfExt.h"
# include "LulMainInt.h"
#include "LulCommonExt.h"
#include "LulElfExt.h"
#include "LulMainInt.h"
using mozilla::baseprofiler::profiler_current_process_id;
using mozilla::baseprofiler::profiler_current_thread_id;
// Set this to 1 for verbose logging
# define DEBUG_MAIN 0
#define DEBUG_MAIN 0
namespace lul {
@ -67,14 +63,14 @@ static const char* NameOf_DW_REG(int16_t aReg) {
switch (aReg) {
case DW_REG_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:
return "xbp";
case DW_REG_INTEL_XSP:
return "xsp";
case DW_REG_INTEL_XIP:
return "xip";
# elif defined(GP_ARCH_arm)
#elif defined(GP_ARCH_arm)
case DW_REG_ARM_R7:
return "r7";
case DW_REG_ARM_R11:
@ -87,23 +83,23 @@ static const char* NameOf_DW_REG(int16_t aReg) {
return "r14";
case DW_REG_ARM_R15:
return "r15";
# elif defined(GP_ARCH_arm64)
#elif defined(GP_ARCH_arm64)
case DW_REG_AARCH64_X29:
return "x29";
case DW_REG_AARCH64_X30:
return "x30";
case DW_REG_AARCH64_SP:
return "sp";
# elif defined(GP_ARCH_mips64)
#elif defined(GP_ARCH_mips64)
case DW_REG_MIPS_SP:
return "sp";
case DW_REG_MIPS_FP:
return "fp";
case DW_REG_MIPS_PC:
return "pc";
# else
# error "Unsupported arch"
# endif
#else
# error "Unsupported arch"
#endif
default:
return "???";
}
@ -143,28 +139,28 @@ void RuleSet::Print(void (*aLog)(const char*)) const {
res += mCfaExpr.ShowRule("cfa");
res += " in";
// 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 += mXspExpr.ShowRule(" SP");
res += mXbpExpr.ShowRule(" BP");
# elif defined(GP_ARCH_arm)
#elif defined(GP_ARCH_arm)
res += mR15expr.ShowRule(" R15");
res += mR7expr.ShowRule(" R7");
res += mR11expr.ShowRule(" R11");
res += mR12expr.ShowRule(" R12");
res += mR13expr.ShowRule(" R13");
res += mR14expr.ShowRule(" R14");
# elif defined(GP_ARCH_arm64)
#elif defined(GP_ARCH_arm64)
res += mX29expr.ShowRule(" X29");
res += mX30expr.ShowRule(" X30");
res += mSPexpr.ShowRule(" SP");
# elif defined(GP_ARCH_mips64)
#elif defined(GP_ARCH_mips64)
res += mPCexpr.ShowRule(" PC");
res += mSPexpr.ShowRule(" SP");
res += mFPexpr.ShowRule(" FP");
# else
# error "Unsupported arch"
# endif
#else
# error "Unsupported arch"
#endif
aLog(res.c_str());
}
@ -172,14 +168,14 @@ LExpr* RuleSet::ExprForRegno(DW_REG_NUMBER aRegno) {
switch (aRegno) {
case DW_REG_CFA:
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:
return &mXipExpr;
case DW_REG_INTEL_XSP:
return &mXspExpr;
case DW_REG_INTEL_XBP:
return &mXbpExpr;
# elif defined(GP_ARCH_arm)
#elif defined(GP_ARCH_arm)
case DW_REG_ARM_R15:
return &mR15expr;
case DW_REG_ARM_R14:
@ -192,23 +188,23 @@ LExpr* RuleSet::ExprForRegno(DW_REG_NUMBER aRegno) {
return &mR11expr;
case DW_REG_ARM_R7:
return &mR7expr;
# elif defined(GP_ARCH_arm64)
#elif defined(GP_ARCH_arm64)
case DW_REG_AARCH64_X29:
return &mX29expr;
case DW_REG_AARCH64_X30:
return &mX30expr;
case DW_REG_AARCH64_SP:
return &mSPexpr;
# elif defined(GP_ARCH_mips64)
#elif defined(GP_ARCH_mips64)
case DW_REG_MIPS_SP:
return &mSPexpr;
case DW_REG_MIPS_FP:
return &mFPexpr;
case DW_REG_MIPS_PC:
return &mPCexpr;
# else
# error "Unknown arch"
# endif
#else
# error "Unknown arch"
#endif
default:
return nullptr;
}
@ -369,7 +365,7 @@ void SecMap::PrepareRuleSets(uintptr_t aStart, size_t aLen) {
size_t n = mRuleSets.size();
# ifdef DEBUG
#ifdef DEBUG
// Do a final check on the rules: their address ranges must be
// ascending, non overlapping, non zero sized.
if (n > 0) {
@ -382,7 +378,7 @@ void SecMap::PrepareRuleSets(uintptr_t aStart, size_t aLen) {
MOZ_ASSERT(prev->mAddr + prev->mLen <= here->mAddr);
}
}
# endif
#endif
// Set the summary min and max address values.
if (n == 0) {
@ -403,14 +399,14 @@ void SecMap::PrepareRuleSets(uintptr_t aStart, size_t aLen) {
// Is now usable for binary search.
mUsable = true;
# if 0
#if 0
mLog("\nRulesets after preening\n");
for (size_t i = 0; i < mRuleSets.size(); ++i) {
mRuleSets[i].Print(mLog);
mLog("\n");
}
mLog("\n");
# endif
#endif
}
bool SecMap::IsEmpty() { return mRuleSets.empty(); }
@ -689,15 +685,15 @@ class PriMap {
// LUL //
////////////////////////////////////////////////////////////////
# define LUL_LOG(_str) \
do { \
char buf[200]; \
SprintfLiteral(buf, "LUL: pid %d tid %d lul-obj %p: %s", \
profiler_current_process_id(), \
profiler_current_thread_id(), this, (_str)); \
buf[sizeof(buf) - 1] = 0; \
mLog(buf); \
} while (0)
#define LUL_LOG(_str) \
do { \
char buf[200]; \
SprintfLiteral(buf, "LUL: pid %d tid %d lul-obj %p: %s", \
profiler_current_process_id(), \
profiler_current_thread_id(), this, (_str)); \
buf[sizeof(buf) - 1] = 0; \
mLog(buf); \
} while (0)
LUL::LUL(void (*aLog)(const char*))
: mLog(aLog),
@ -901,14 +897,14 @@ static TaggedUWord EvaluateReg(int16_t aReg, const UnwindRegs* aOldRegs,
switch (aReg) {
case DW_REG_CFA:
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:
return aOldRegs->xbp;
case DW_REG_INTEL_XSP:
return aOldRegs->xsp;
case DW_REG_INTEL_XIP:
return aOldRegs->xip;
# elif defined(GP_ARCH_arm)
#elif defined(GP_ARCH_arm)
case DW_REG_ARM_R7:
return aOldRegs->r7;
case DW_REG_ARM_R11:
@ -921,23 +917,23 @@ static TaggedUWord EvaluateReg(int16_t aReg, const UnwindRegs* aOldRegs,
return aOldRegs->r14;
case DW_REG_ARM_R15:
return aOldRegs->r15;
# elif defined(GP_ARCH_arm64)
#elif defined(GP_ARCH_arm64)
case DW_REG_AARCH64_X29:
return aOldRegs->x29;
case DW_REG_AARCH64_X30:
return aOldRegs->x30;
case DW_REG_AARCH64_SP:
return aOldRegs->sp;
# elif defined(GP_ARCH_mips64)
#elif defined(GP_ARCH_mips64)
case DW_REG_MIPS_SP:
return aOldRegs->sp;
case DW_REG_MIPS_FP:
return aOldRegs->fp;
case DW_REG_MIPS_PC:
return aOldRegs->pc;
# else
# error "Unsupported arch"
# endif
#else
# error "Unsupported arch"
#endif
default:
MOZ_ASSERT(0);
return TaggedUWord();
@ -956,17 +952,17 @@ TaggedUWord EvaluatePfxExpr(int32_t start, const UnwindRegs* aOldRegs,
int stackPointer = -1;
for (int i = 0; i < N_STACK; i++) stack[i] = TaggedUWord();
# define PUSH(_tuw) \
do { \
if (stackPointer >= N_STACK - 1) goto fail; /* overflow */ \
stack[++stackPointer] = (_tuw); \
} while (0)
#define PUSH(_tuw) \
do { \
if (stackPointer >= N_STACK - 1) goto fail; /* overflow */ \
stack[++stackPointer] = (_tuw); \
} while (0)
# define POP(_lval) \
do { \
if (stackPointer < 0) goto fail; /* underflow */ \
_lval = stack[stackPointer--]; \
} while (0)
#define POP(_lval) \
do { \
if (stackPointer < 0) goto fail; /* underflow */ \
_lval = stack[stackPointer--]; \
} while (0)
// Cursor in the instruction sequence.
size_t curr = start + 1;
@ -1072,8 +1068,8 @@ TaggedUWord EvaluatePfxExpr(int32_t start, const UnwindRegs* aOldRegs,
fail:
return TaggedUWord();
# undef PUSH
# undef POP
#undef PUSH
#undef POP
}
// RUNS IN NO-MALLOC CONTEXT
@ -1118,29 +1114,29 @@ static void UseRuleSet(/*MOD*/ UnwindRegs* aRegs, const StackImage* aStackImg,
// anew. If we don't even manage to compute a new PC value, then
// the caller will have to abandon the unwind.
// 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->xsp = TaggedUWord();
aRegs->xip = TaggedUWord();
# elif defined(GP_ARCH_arm)
#elif defined(GP_ARCH_arm)
aRegs->r7 = TaggedUWord();
aRegs->r11 = TaggedUWord();
aRegs->r12 = TaggedUWord();
aRegs->r13 = TaggedUWord();
aRegs->r14 = TaggedUWord();
aRegs->r15 = TaggedUWord();
# elif defined(GP_ARCH_arm64)
#elif defined(GP_ARCH_arm64)
aRegs->x29 = TaggedUWord();
aRegs->x30 = TaggedUWord();
aRegs->sp = TaggedUWord();
aRegs->pc = TaggedUWord();
# elif defined(GP_ARCH_mips64)
#elif defined(GP_ARCH_mips64)
aRegs->sp = TaggedUWord();
aRegs->fp = TaggedUWord();
aRegs->pc = TaggedUWord();
# else
# error "Unsupported arch"
# endif
#else
# error "Unsupported arch"
#endif
// This is generally useful.
const TaggedUWord inval = TaggedUWord();
@ -1154,14 +1150,14 @@ static void UseRuleSet(/*MOD*/ UnwindRegs* aRegs, const StackImage* aStackImg,
// value rules mention the CFA. In any case, compute the new values
// 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 =
aRS->mXbpExpr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
aRegs->xsp =
aRS->mXspExpr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
aRegs->xip =
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->r11 =
aRS->mR11expr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
@ -1173,19 +1169,19 @@ static void UseRuleSet(/*MOD*/ UnwindRegs* aRegs, const StackImage* aStackImg,
aRS->mR14expr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
aRegs->r15 =
aRS->mR15expr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
# elif defined(GP_ARCH_arm64)
#elif defined(GP_ARCH_arm64)
aRegs->x29 =
aRS->mX29expr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
aRegs->x30 =
aRS->mX30expr.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->fp = aRS->mFPexpr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
aRegs->pc = aRS->mPCexpr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
# else
# error "Unsupported arch"
# endif
#else
# error "Unsupported arch"
#endif
// We're done. Any regs for which we didn't manage to compute a
// new value will now be marked as invalid.
@ -1212,7 +1208,7 @@ void LUL::Unwind(/*OUT*/ uintptr_t* aFramePCs,
if (DEBUG_MAIN) {
char buf[300];
mLog("\n");
# if defined(GP_ARCH_amd64) || defined(GP_ARCH_x86)
#if defined(GP_ARCH_amd64) || defined(GP_ARCH_x86)
SprintfLiteral(
buf, "LoopTop: rip %d/%llx rsp %d/%llx rbp %d/%llx\n",
(int)regs.xip.Valid(), (unsigned long long int)regs.xip.Value(),
@ -1220,7 +1216,7 @@ void LUL::Unwind(/*OUT*/ uintptr_t* aFramePCs,
(int)regs.xbp.Valid(), (unsigned long long int)regs.xbp.Value());
buf[sizeof(buf) - 1] = 0;
mLog(buf);
# elif defined(GP_ARCH_arm)
#elif defined(GP_ARCH_arm)
SprintfLiteral(
buf,
"LoopTop: r15 %d/%llx r7 %d/%llx r11 %d/%llx"
@ -1233,7 +1229,7 @@ void LUL::Unwind(/*OUT*/ uintptr_t* aFramePCs,
(int)regs.r14.Valid(), (unsigned long long int)regs.r14.Value());
buf[sizeof(buf) - 1] = 0;
mLog(buf);
# elif defined(GP_ARCH_arm64)
#elif defined(GP_ARCH_arm64)
SprintfLiteral(
buf,
"LoopTop: pc %d/%llx x29 %d/%llx x30 %d/%llx"
@ -1244,7 +1240,7 @@ void LUL::Unwind(/*OUT*/ uintptr_t* aFramePCs,
(int)regs.sp.Valid(), (unsigned long long int)regs.sp.Value());
buf[sizeof(buf) - 1] = 0;
mLog(buf);
# elif defined(GP_ARCH_mips64)
#elif defined(GP_ARCH_mips64)
SprintfLiteral(
buf, "LoopTop: pc %d/%llx sp %d/%llx fp %d/%llx\n",
(int)regs.pc.Valid(), (unsigned long long int)regs.pc.Value(),
@ -1252,26 +1248,26 @@ void LUL::Unwind(/*OUT*/ uintptr_t* aFramePCs,
(int)regs.fp.Valid(), (unsigned long long int)regs.fp.Value());
buf[sizeof(buf) - 1] = 0;
mLog(buf);
# else
# error "Unsupported arch"
# endif
#else
# error "Unsupported arch"
#endif
}
# if defined(GP_ARCH_amd64) || defined(GP_ARCH_x86)
#if defined(GP_ARCH_amd64) || defined(GP_ARCH_x86)
TaggedUWord ia = regs.xip;
TaggedUWord sp = regs.xsp;
# elif defined(GP_ARCH_arm)
#elif defined(GP_ARCH_arm)
TaggedUWord ia = (*aFramesUsed == 0 ? regs.r15 : regs.r14);
TaggedUWord sp = regs.r13;
# elif defined(GP_ARCH_arm64)
#elif defined(GP_ARCH_arm64)
TaggedUWord ia = (*aFramesUsed == 0 ? regs.pc : regs.x30);
TaggedUWord sp = regs.sp;
# elif defined(GP_ARCH_mips64)
#elif defined(GP_ARCH_mips64)
TaggedUWord ia = regs.pc;
TaggedUWord sp = regs.sp;
# else
# error "Unsupported arch"
# endif
#else
# error "Unsupported arch"
#endif
if (*aFramesUsed >= aFramesAvail) {
break;
@ -1330,7 +1326,7 @@ void LUL::Unwind(/*OUT*/ uintptr_t* aFramePCs,
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
@ -1399,7 +1395,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.
if (ruleset) {
@ -1413,8 +1409,8 @@ void LUL::Unwind(/*OUT*/ uintptr_t* aFramePCs,
continue;
}
# if defined(GP_PLAT_amd64_linux) || defined(GP_PLAT_x86_linux) || \
defined(GP_PLAT_amd64_android) || defined(GP_PLAT_x86_android)
#if defined(GP_PLAT_amd64_linux) || defined(GP_PLAT_x86_linux) || \
defined(GP_PLAT_amd64_android) || defined(GP_PLAT_x86_android)
// 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.
@ -1463,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..
//
// stp x29, x30, [sp, #-16]!
@ -1524,8 +1520,8 @@ void LUL::Unwind(/*OUT*/ uintptr_t* aFramePCs,
}
}
}
# endif // defined(GP_PLAT_amd64_linux) || defined(GP_PLAT_x86_linux) ||
// defined(GP_PLAT_amd64_android) || defined(GP_PLAT_x86_android)
#endif // defined(GP_PLAT_amd64_linux) || defined(GP_PLAT_x86_linux) ||
// defined(GP_PLAT_amd64_android) || defined(GP_PLAT_x86_android)
// 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.
@ -1543,13 +1539,13 @@ void LUL::Unwind(/*OUT*/ uintptr_t* aFramePCs,
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) {
unsigned long rtaddr;
__asm__ volatile("move %0, $31" : "=r"(rtaddr));
return rtaddr;
}
# endif
#endif
// This function is innermost in the test call sequence. It uses LUL
// to unwind, and compares the result with the sequence specified in
@ -1568,7 +1564,7 @@ static __attribute__((noinline)) bool GetAndCheckStackTrace(
// Get hold of the current unwind-start registers.
UnwindRegs startRegs;
memset(&startRegs, 0, sizeof(startRegs));
# if defined(GP_ARCH_amd64)
#if defined(GP_ARCH_amd64)
volatile uintptr_t block[3];
MOZ_ASSERT(sizeof(block) == 24);
__asm__ __volatile__(
@ -1588,7 +1584,7 @@ static __attribute__((noinline)) bool GetAndCheckStackTrace(
startRegs.xbp = TaggedUWord(block[2]);
const uintptr_t REDZONE_SIZE = 128;
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];
MOZ_ASSERT(sizeof(block) == 12);
__asm__ __volatile__(
@ -1610,7 +1606,7 @@ static __attribute__((noinline)) bool GetAndCheckStackTrace(
startRegs.xbp = TaggedUWord(block[2]);
const uintptr_t REDZONE_SIZE = 0;
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];
MOZ_ASSERT(sizeof(block) == 24);
__asm__ __volatile__(
@ -1639,7 +1635,7 @@ static __attribute__((noinline)) bool GetAndCheckStackTrace(
startRegs.r7 = TaggedUWord(block[5]);
const uintptr_t REDZONE_SIZE = 0;
uintptr_t start = block[1] - REDZONE_SIZE;
# elif defined(GP_ARCH_arm64)
#elif defined(GP_ARCH_arm64)
volatile uintptr_t block[4];
MOZ_ASSERT(sizeof(block) == 32);
__asm__ __volatile__(
@ -1658,7 +1654,7 @@ static __attribute__((noinline)) bool GetAndCheckStackTrace(
startRegs.sp = TaggedUWord(block[3]);
const uintptr_t REDZONE_SIZE = 0;
uintptr_t start = block[1] - REDZONE_SIZE;
# elif defined(GP_ARCH_mips64)
#elif defined(GP_ARCH_mips64)
volatile uintptr_t block[3];
MOZ_ASSERT(sizeof(block) == 24);
__asm__ __volatile__(
@ -1673,9 +1669,9 @@ static __attribute__((noinline)) bool GetAndCheckStackTrace(
startRegs.fp = TaggedUWord(block[2]);
const uintptr_t REDZONE_SIZE = 0;
uintptr_t start = block[1] - REDZONE_SIZE;
# else
# error "Unsupported platform"
# endif
#else
# error "Unsupported platform"
#endif
// Get hold of the innermost LUL_UNIT_TEST_STACK_SIZE bytes of the
// stack.
@ -1803,78 +1799,77 @@ static __attribute__((noinline)) bool GetAndCheckStackTrace(
// results on |aLUL|'s logging sink, and also returns a boolean
// indicating whether or not the results are acceptable (correct).
# define DECL_TEST_FN(NAME) \
bool NAME(LUL* aLUL, const char* strPorig, const char* strP);
#define DECL_TEST_FN(NAME) \
bool NAME(LUL* aLUL, const char* strPorig, const char* strP);
# define GEN_TEST_FN(NAME, FRAMESIZE) \
bool NAME(LUL* aLUL, const char* strPorig, const char* strP) { \
/* Create a frame of size (at least) FRAMESIZE, so that the */ \
/* 8 functions created by this macro offer some variation in frame */ \
/* sizes. This isn't as simple as it might seem, since a clever */ \
/* 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 */ \
/* in a different compilation unit, and hoping that clang does not */ \
/* notice that the call is a no-op. */ \
char space[FRAMESIZE]; \
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. */ \
/* Take a stack snapshot. */ \
return GetAndCheckStackTrace(aLUL, strPorig); \
} else { \
/* Recurse onwards. This is a bit subtle. The obvious */ \
/* thing to do here is call onwards directly, from within the */ \
/* arms of the case statement. That gives a problem in that */ \
/* there will be multiple return points inside each function when */ \
/* unwinding, so it will be difficult to check for consistency */ \
/* against the director string. Instead, we make an indirect */ \
/* call, so as to guarantee that there is only one call site */ \
/* within each function. This does assume that the compiler */ \
/* won't transform it back to the simple direct-call form. */ \
/* To discourage it from doing so, the call is bracketed with */ \
/* __asm__ __volatile__ sections so as to make it not-movable. */ \
bool (*nextFn)(LUL*, const char*, const char*) = NULL; \
switch (*strP) { \
case '1': \
nextFn = TestFn1; \
break; \
case '2': \
nextFn = TestFn2; \
break; \
case '3': \
nextFn = TestFn3; \
break; \
case '4': \
nextFn = TestFn4; \
break; \
case '5': \
nextFn = TestFn5; \
break; \
case '6': \
nextFn = TestFn6; \
break; \
case '7': \
nextFn = TestFn7; \
break; \
case '8': \
nextFn = TestFn8; \
break; \
default: \
nextFn = TestFn8; \
break; \
} \
/* "use" |space| immediately after the recursive call, */ \
/* so as to dissuade clang from deallocating the space while */ \
/* the call is active, or otherwise messing with the stack frame. */ \
__asm__ __volatile__("" ::: "cc", "memory"); \
bool passed = nextFn(aLUL, strPorig, strP + 1); \
Unused << write(1, space, 0); \
__asm__ __volatile__("" ::: "cc", "memory"); \
return passed; \
} \
}
#define GEN_TEST_FN(NAME, FRAMESIZE) \
bool NAME(LUL* aLUL, const char* strPorig, const char* strP) { \
/* Create a frame of size (at least) FRAMESIZE, so that the */ \
/* 8 functions created by this macro offer some variation in frame */ \
/* sizes. This isn't as simple as it might seem, since a clever */ \
/* 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 */ \
/* in a different compilation unit, and hoping that clang does not */ \
/* notice that the call is a no-op. */ \
char space[FRAMESIZE]; \
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. */ \
/* Take a stack snapshot. */ \
return GetAndCheckStackTrace(aLUL, strPorig); \
} else { \
/* Recurse onwards. This is a bit subtle. The obvious */ \
/* thing to do here is call onwards directly, from within the */ \
/* arms of the case statement. That gives a problem in that */ \
/* there will be multiple return points inside each function when */ \
/* unwinding, so it will be difficult to check for consistency */ \
/* against the director string. Instead, we make an indirect */ \
/* call, so as to guarantee that there is only one call site */ \
/* within each function. This does assume that the compiler */ \
/* won't transform it back to the simple direct-call form. */ \
/* To discourage it from doing so, the call is bracketed with */ \
/* __asm__ __volatile__ sections so as to make it not-movable. */ \
bool (*nextFn)(LUL*, const char*, const char*) = NULL; \
switch (*strP) { \
case '1': \
nextFn = TestFn1; \
break; \
case '2': \
nextFn = TestFn2; \
break; \
case '3': \
nextFn = TestFn3; \
break; \
case '4': \
nextFn = TestFn4; \
break; \
case '5': \
nextFn = TestFn5; \
break; \
case '6': \
nextFn = TestFn6; \
break; \
case '7': \
nextFn = TestFn7; \
break; \
case '8': \
nextFn = TestFn8; \
break; \
default: \
nextFn = TestFn8; \
break; \
} \
/* "use" |space| immediately after the recursive call, */ \
/* so as to dissuade clang from deallocating the space while */ \
/* the call is active, or otherwise messing with the stack frame. */ \
__asm__ __volatile__("" ::: "cc", "memory"); \
bool passed = nextFn(aLUL, strPorig, strP + 1); \
Unused << write(1, space, 0); \
__asm__ __volatile__("" ::: "cc", "memory"); \
return passed; \
} \
}
// The test functions are mutually recursive, so it is necessary to
// declare them before defining them.
@ -1958,5 +1953,3 @@ void RunLulUnitTests(/*OUT*/ int* aNTests, /*OUT*/ int* aNTestsPassed,
}
} // namespace lul
#endif // MOZ_GECKO_PROFILER

Просмотреть файл

@ -3,21 +3,18 @@
* 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/. */
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include "AutoObjectMapper.h"
#include "BaseProfiler.h"
#ifdef MOZ_GECKO_PROFILER
# include <stdio.h>
# include <signal.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"
#include "BaseProfilerSharedLibraries.h"
#include "platform.h"
#include "PlatformMacros.h"
#include "LulMain.h"
// Contains miscellaneous helpers that are used to connect the Gecko Profiler
// and LUL.
@ -28,7 +25,7 @@
void read_procmaps(lul::LUL* aLUL) {
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();
for (size_t i = 0; i < info.GetSize(); i++) {
@ -36,13 +33,13 @@ void read_procmaps(lul::LUL* aLUL) {
std::string nativePath = lib.GetDebugPath();
# if defined(MOZ_LINKER)
# if defined(MOZ_LINKER)
// We're using faulty.lib. Use a special-case object mapper.
AutoObjectMapperFaultyLib mapper(aLUL->mLog);
# else
# else
// We can use the standard POSIX-based mapper.
AutoObjectMapperPOSIX mapper(aLUL->mLog);
# endif
# endif
// Ask |mapper| to map the object. Then hand its mapped address
// to NotifyAfterMap().
@ -66,9 +63,9 @@ void read_procmaps(lul::LUL* aLUL) {
// unmaps the object.
}
# else
# error "Unknown platform"
# endif
#else
# error "Unknown platform"
#endif
}
// LUL needs a callback for its logging sink.
@ -82,5 +79,3 @@ void logging_sink_for_LUL(const char* str) {
// platform.cpp.
// VERBOSE_LOG("[%d] %s", profiler_current_process_id(), str);
}
#endif // MOZ_GECKO_PROFILER