summaryrefslogtreecommitdiff
path: root/xpcom/build
diff options
context:
space:
mode:
Diffstat (limited to 'xpcom/build')
-rw-r--r--xpcom/build/BinaryPath.h42
-rw-r--r--xpcom/build/PoisonIOInterposer.h19
-rw-r--r--xpcom/build/PoisonIOInterposerMac.cpp385
-rw-r--r--xpcom/build/XPCOMInit.cpp3
-rw-r--r--xpcom/build/mach_override.c789
-rw-r--r--xpcom/build/mach_override.h121
-rw-r--r--xpcom/build/moz.build7
-rw-r--r--xpcom/build/nsXPCOMPrivate.h7
-rw-r--r--xpcom/build/nsXULAppAPI.h2
9 files changed, 4 insertions, 1371 deletions
diff --git a/xpcom/build/BinaryPath.h b/xpcom/build/BinaryPath.h
index 6c2622a557..8ad7e8aac2 100644
--- a/xpcom/build/BinaryPath.h
+++ b/xpcom/build/BinaryPath.h
@@ -9,8 +9,6 @@
#include "nsXPCOMPrivate.h" // for MAXPATHLEN
#ifdef XP_WIN
#include <windows.h>
-#elif defined(XP_MACOSX)
-#include <CoreFoundation/CoreFoundation.h>
#elif defined(XP_UNIX)
#include <sys/stat.h>
#include <string.h>
@@ -43,46 +41,6 @@ private:
return NS_ERROR_FAILURE;
}
-#elif defined(XP_MACOSX)
- static nsresult Get(const char* argv0, char aResult[MAXPATHLEN])
- {
- // Works even if we're not bundled.
- CFBundleRef appBundle = CFBundleGetMainBundle();
- if (!appBundle) {
- return NS_ERROR_FAILURE;
- }
-
- CFURLRef executableURL = CFBundleCopyExecutableURL(appBundle);
- if (!executableURL) {
- return NS_ERROR_FAILURE;
- }
-
- nsresult rv;
- if (CFURLGetFileSystemRepresentation(executableURL, false, (UInt8*)aResult,
- MAXPATHLEN)) {
- // Sanitize path in case the app was launched from Terminal via
- // './firefox' for example.
- size_t readPos = 0;
- size_t writePos = 0;
- while (aResult[readPos] != '\0') {
- if (aResult[readPos] == '.' && aResult[readPos + 1] == '/') {
- readPos += 2;
- } else {
- aResult[writePos] = aResult[readPos];
- readPos++;
- writePos++;
- }
- }
- aResult[writePos] = '\0';
- rv = NS_OK;
- } else {
- rv = NS_ERROR_FAILURE;
- }
-
- CFRelease(executableURL);
- return rv;
- }
-
#elif defined(XP_UNIX)
static nsresult Get(const char* aArgv0, char aResult[MAXPATHLEN])
{
diff --git a/xpcom/build/PoisonIOInterposer.h b/xpcom/build/PoisonIOInterposer.h
index 20edbd5aa8..6a34e39a0c 100644
--- a/xpcom/build/PoisonIOInterposer.h
+++ b/xpcom/build/PoisonIOInterposer.h
@@ -35,7 +35,7 @@ void MozillaUnRegisterDebugFILE(FILE* aFile);
MOZ_END_EXTERN_C
-#if defined(XP_WIN) || defined(XP_MACOSX)
+#if defined(XP_WIN)
#ifdef __cplusplus
namespace mozilla {
@@ -53,16 +53,6 @@ bool IsDebugFile(intptr_t aFileID);
*/
void InitPoisonIOInterposer();
-#ifdef XP_MACOSX
-/**
- * Check that writes are dirty before reporting I/O (Mac OS X only)
- * This is necessary for late-write checks on Mac OS X, but reading the buffer
- * from file to see if we're writing dirty bits is expensive, so we don't want
- * to do this for everything else that uses
- */
-void OnlyReportDirtyWrites();
-#endif /* XP_MACOSX */
-
/**
* Clear IO poisoning, this is only safe to do on the main-thread when no other
* threads are running.
@@ -72,19 +62,16 @@ void ClearPoisonIOInterposer();
} // namespace mozilla
#endif /* __cplusplus */
-#else /* XP_WIN || XP_MACOSX */
+#else /* XP_WIN */
#ifdef __cplusplus
namespace mozilla {
inline bool IsDebugFile(intptr_t aFileID) { return true; }
inline void InitPoisonIOInterposer() {}
inline void ClearPoisonIOInterposer() {}
-#ifdef XP_MACOSX
-inline void OnlyReportDirtyWrites() {}
-#endif /* XP_MACOSX */
} // namespace mozilla
#endif /* __cplusplus */
-#endif /* XP_WIN || XP_MACOSX */
+#endif /* XP_WIN */
#endif // mozilla_PoisonIOInterposer_h
diff --git a/xpcom/build/PoisonIOInterposerMac.cpp b/xpcom/build/PoisonIOInterposerMac.cpp
deleted file mode 100644
index dca9ba0297..0000000000
--- a/xpcom/build/PoisonIOInterposerMac.cpp
+++ /dev/null
@@ -1,385 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * 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 "PoisonIOInterposer.h"
-#include "mach_override.h"
-
-#include "mozilla/ArrayUtils.h"
-#include "mozilla/Assertions.h"
-#include "mozilla/DebugOnly.h"
-#include "mozilla/IOInterposer.h"
-#include "mozilla/Mutex.h"
-#include "mozilla/ProcessedStack.h"
-#include "mozilla/Telemetry.h"
-#include "mozilla/UniquePtrExtensions.h"
-#include "nsPrintfCString.h"
-#include "mozilla/StackWalk.h"
-#include "nsTraceRefcnt.h"
-#include "plstr.h"
-#include "prio.h"
-
-#include <algorithm>
-#include <vector>
-
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-#include <aio.h>
-#include <dlfcn.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#ifdef MOZ_REPLACE_MALLOC
-#include "replace_malloc_bridge.h"
-#endif
-
-namespace {
-
-using namespace mozilla;
-
-// Bit tracking if poisoned writes are enabled
-static bool sIsEnabled = false;
-
-// Check if writes are dirty before reporting IO
-static bool sOnlyReportDirtyWrites = false;
-
-// Routines for write validation
-bool IsValidWrite(int aFd, const void* aWbuf, size_t aCount);
-bool IsIPCWrite(int aFd, const struct stat& aBuf);
-
-/******************************** IO AutoTimer ********************************/
-
-/**
- * RAII class for timing the duration of an I/O call and reporting the result
- * to the IOInterposeObserver API.
- */
-class MacIOAutoObservation : public IOInterposeObserver::Observation
-{
-public:
- MacIOAutoObservation(IOInterposeObserver::Operation aOp, int aFd)
- : IOInterposeObserver::Observation(aOp, sReference, sIsEnabled &&
- !IsDebugFile(aFd))
- , mFd(aFd)
- , mHasQueriedFilename(false)
- , mFilename(nullptr)
- {
- }
-
- MacIOAutoObservation(IOInterposeObserver::Operation aOp, int aFd,
- const void* aBuf, size_t aCount)
- : IOInterposeObserver::Observation(aOp, sReference, sIsEnabled &&
- !IsDebugFile(aFd) &&
- IsValidWrite(aFd, aBuf, aCount))
- , mFd(aFd)
- , mHasQueriedFilename(false)
- , mFilename(nullptr)
- {
- }
-
- // Custom implementation of IOInterposeObserver::Observation::Filename
- const char16_t* Filename() override;
-
- ~MacIOAutoObservation()
- {
- Report();
- if (mFilename) {
- free(mFilename);
- mFilename = nullptr;
- }
- }
-
-private:
- int mFd;
- bool mHasQueriedFilename;
- char16_t* mFilename;
- static const char* sReference;
-};
-
-const char* MacIOAutoObservation::sReference = "PoisonIOInterposer";
-
-// Get filename for this observation
-const char16_t*
-MacIOAutoObservation::Filename()
-{
- // If mHasQueriedFilename is true, then we already have it
- if (mHasQueriedFilename) {
- return mFilename;
- }
- char filename[MAXPATHLEN];
- if (fcntl(mFd, F_GETPATH, filename) != -1) {
- mFilename = UTF8ToNewUnicode(nsDependentCString(filename));
- } else {
- mFilename = nullptr;
- }
- mHasQueriedFilename = true;
-
- // Return filename
- return mFilename;
-}
-
-/****************************** Write Validation ******************************/
-
-// We want to detect "actual" writes, not IPC. Some IPC mechanisms are
-// implemented with file descriptors, so filter them out.
-bool
-IsIPCWrite(int aFd, const struct stat& aBuf)
-{
- if ((aBuf.st_mode & S_IFMT) == S_IFIFO) {
- return true;
- }
-
- if ((aBuf.st_mode & S_IFMT) != S_IFSOCK) {
- return false;
- }
-
- sockaddr_storage address;
- socklen_t len = sizeof(address);
- if (getsockname(aFd, (sockaddr*)&address, &len) != 0) {
- return true; // Ignore the aFd if we can't find what it is.
- }
-
- return address.ss_family == AF_UNIX;
-}
-
-// We want to report actual disk IO not things that don't move bits on the disk
-bool
-IsValidWrite(int aFd, const void* aWbuf, size_t aCount)
-{
- // Ignore writes of zero bytes, Firefox does some during shutdown.
- if (aCount == 0) {
- return false;
- }
-
- {
- struct stat buf;
- int rv = fstat(aFd, &buf);
- if (rv != 0) {
- return true;
- }
-
- if (IsIPCWrite(aFd, buf)) {
- return false;
- }
- }
-
- // For writev we pass a nullptr aWbuf. We should only get here from
- // dbm, and it uses write, so assert that we have aWbuf.
- if (!aWbuf) {
- return true;
- }
-
- // Break, here if we're allowed to report non-dirty writes
- if (!sOnlyReportDirtyWrites) {
- return true;
- }
-
- // As a really bad hack, accept writes that don't change the on disk
- // content. This is needed because dbm doesn't keep track of dirty bits
- // and can end up writing the same data to disk twice. Once when the
- // user (nss) asks it to sync and once when closing the database.
- auto wbuf2 = MakeUniqueFallible<char[]>(aCount);
- if (!wbuf2) {
- return true;
- }
- off_t pos = lseek(aFd, 0, SEEK_CUR);
- if (pos == -1) {
- return true;
- }
- ssize_t r = read(aFd, wbuf2.get(), aCount);
- if (r < 0 || (size_t)r != aCount) {
- return true;
- }
- int cmp = memcmp(aWbuf, wbuf2.get(), aCount);
- if (cmp != 0) {
- return true;
- }
- off_t pos2 = lseek(aFd, pos, SEEK_SET);
- if (pos2 != pos) {
- return true;
- }
-
- // Otherwise this is not a valid write
- return false;
-}
-
-/*************************** Function Interception ***************************/
-
-/** Structure for declaration of function override */
-struct FuncData
-{
- const char* Name; // Name of the function for the ones we use dlsym
- const void* Wrapper; // The function that we will replace 'Function' with
- void* Function; // The function that will be replaced with 'Wrapper'
- void* Buffer; // Will point to the jump buffer that lets us call
- // 'Function' after it has been replaced.
-};
-
-// Wrap aio_write. We have not seen it before, so just assert/report it.
-typedef ssize_t (*aio_write_t)(struct aiocb* aAioCbp);
-ssize_t wrap_aio_write(struct aiocb* aAioCbp);
-FuncData aio_write_data = { 0, (void*)wrap_aio_write, (void*)aio_write };
-ssize_t
-wrap_aio_write(struct aiocb* aAioCbp)
-{
- MacIOAutoObservation timer(IOInterposeObserver::OpWrite,
- aAioCbp->aio_fildes);
-
- aio_write_t old_write = (aio_write_t)aio_write_data.Buffer;
- return old_write(aAioCbp);
-}
-
-// Wrap pwrite-like functions.
-// We have not seen them before, so just assert/report it.
-typedef ssize_t (*pwrite_t)(int aFd, const void* buf, size_t aNumBytes,
- off_t aOffset);
-template<FuncData& foo>
-ssize_t
-wrap_pwrite_temp(int aFd, const void* aBuf, size_t aNumBytes, off_t aOffset)
-{
- MacIOAutoObservation timer(IOInterposeObserver::OpWrite, aFd);
- pwrite_t old_write = (pwrite_t)foo.Buffer;
- return old_write(aFd, aBuf, aNumBytes, aOffset);
-}
-
-// Define a FuncData for a pwrite-like functions.
-#define DEFINE_PWRITE_DATA(X, NAME) \
-FuncData X ## _data = { NAME, (void*) wrap_pwrite_temp<X ## _data> }; \
-
-// This exists everywhere.
-DEFINE_PWRITE_DATA(pwrite, "pwrite")
-// These exist on 32 bit OS X
-DEFINE_PWRITE_DATA(pwrite_NOCANCEL_UNIX2003, "pwrite$NOCANCEL$UNIX2003");
-DEFINE_PWRITE_DATA(pwrite_UNIX2003, "pwrite$UNIX2003");
-// This exists on 64 bit OS X
-DEFINE_PWRITE_DATA(pwrite_NOCANCEL, "pwrite$NOCANCEL");
-
-
-typedef ssize_t (*writev_t)(int aFd, const struct iovec* aIov, int aIovCount);
-template<FuncData& foo>
-ssize_t
-wrap_writev_temp(int aFd, const struct iovec* aIov, int aIovCount)
-{
- MacIOAutoObservation timer(IOInterposeObserver::OpWrite, aFd, nullptr,
- aIovCount);
- writev_t old_write = (writev_t)foo.Buffer;
- return old_write(aFd, aIov, aIovCount);
-}
-
-// Define a FuncData for a writev-like functions.
-#define DEFINE_WRITEV_DATA(X, NAME) \
-FuncData X ## _data = { NAME, (void*) wrap_writev_temp<X ## _data> }; \
-
-// This exists everywhere.
-DEFINE_WRITEV_DATA(writev, "writev");
-// These exist on 32 bit OS X
-DEFINE_WRITEV_DATA(writev_NOCANCEL_UNIX2003, "writev$NOCANCEL$UNIX2003");
-DEFINE_WRITEV_DATA(writev_UNIX2003, "writev$UNIX2003");
-// This exists on 64 bit OS X
-DEFINE_WRITEV_DATA(writev_NOCANCEL, "writev$NOCANCEL");
-
-typedef ssize_t (*write_t)(int aFd, const void* aBuf, size_t aCount);
-template<FuncData& foo>
-ssize_t
-wrap_write_temp(int aFd, const void* aBuf, size_t aCount)
-{
- MacIOAutoObservation timer(IOInterposeObserver::OpWrite, aFd, aBuf, aCount);
- write_t old_write = (write_t)foo.Buffer;
- return old_write(aFd, aBuf, aCount);
-}
-
-// Define a FuncData for a write-like functions.
-#define DEFINE_WRITE_DATA(X, NAME) \
-FuncData X ## _data = { NAME, (void*) wrap_write_temp<X ## _data> }; \
-
-// This exists everywhere.
-DEFINE_WRITE_DATA(write, "write");
-// These exist on 32 bit OS X
-DEFINE_WRITE_DATA(write_NOCANCEL_UNIX2003, "write$NOCANCEL$UNIX2003");
-DEFINE_WRITE_DATA(write_UNIX2003, "write$UNIX2003");
-// This exists on 64 bit OS X
-DEFINE_WRITE_DATA(write_NOCANCEL, "write$NOCANCEL");
-
-FuncData* Functions[] = {
- &aio_write_data,
-
- &pwrite_data,
- &pwrite_NOCANCEL_UNIX2003_data,
- &pwrite_UNIX2003_data,
- &pwrite_NOCANCEL_data,
-
- &write_data,
- &write_NOCANCEL_UNIX2003_data,
- &write_UNIX2003_data,
- &write_NOCANCEL_data,
-
- &writev_data,
- &writev_NOCANCEL_UNIX2003_data,
- &writev_UNIX2003_data,
- &writev_NOCANCEL_data
-};
-
-const int NumFunctions = ArrayLength(Functions);
-
-} // namespace
-
-/******************************** IO Poisoning ********************************/
-
-namespace mozilla {
-
-void
-InitPoisonIOInterposer()
-{
- // Enable reporting from poisoned write methods
- sIsEnabled = true;
-
- // Make sure we only poison writes once!
- static bool WritesArePoisoned = false;
- if (WritesArePoisoned) {
- return;
- }
- WritesArePoisoned = true;
-
- // stdout and stderr are OK.
- MozillaRegisterDebugFD(1);
- MozillaRegisterDebugFD(2);
-
-#ifdef MOZ_REPLACE_MALLOC
- // The contract with InitDebugFd is that the given registry can be used
- // at any moment, so the instance needs to persist longer than the scope
- // of this functions.
- static DebugFdRegistry registry;
- ReplaceMalloc::InitDebugFd(registry);
-#endif
-
- for (int i = 0; i < NumFunctions; ++i) {
- FuncData* d = Functions[i];
- if (!d->Function) {
- d->Function = dlsym(RTLD_DEFAULT, d->Name);
- }
- if (!d->Function) {
- continue;
- }
- DebugOnly<mach_error_t> t = mach_override_ptr(d->Function, d->Wrapper,
- &d->Buffer);
- MOZ_ASSERT(t == err_none);
- }
-}
-
-void
-OnlyReportDirtyWrites()
-{
- sOnlyReportDirtyWrites = true;
-}
-
-void
-ClearPoisonIOInterposer()
-{
- // Not sure how or if we can unpoison the functions. Would be nice, but no
- // worries we won't need to do this anyway.
- sIsEnabled = false;
-}
-
-} // namespace mozilla
diff --git a/xpcom/build/XPCOMInit.cpp b/xpcom/build/XPCOMInit.cpp
index 86b4dc6bdf..18aed6528a 100644
--- a/xpcom/build/XPCOMInit.cpp
+++ b/xpcom/build/XPCOMInit.cpp
@@ -1015,9 +1015,6 @@ ShutdownXPCOM(nsIServiceManager* aServMgr)
PROFILER_MARKER("Shutdown xpcom");
// If we are doing any shutdown checks, poison writes.
if (gShutdownChecks != SCM_NOTHING) {
-#ifdef XP_MACOSX
- mozilla::OnlyReportDirtyWrites();
-#endif /* XP_MACOSX */
mozilla::BeginLateWriteChecks();
}
diff --git a/xpcom/build/mach_override.c b/xpcom/build/mach_override.c
deleted file mode 100644
index 9e4940d298..0000000000
--- a/xpcom/build/mach_override.c
+++ /dev/null
@@ -1,789 +0,0 @@
-// Copied from upstream at revision 195c13743fe0ebc658714e2a9567d86529f20443.
-// mach_override.c semver:1.2.0
-// Copyright (c) 2003-2012 Jonathan 'Wolf' Rentzsch: http://rentzsch.com
-// Some rights reserved: http://opensource.org/licenses/mit
-// https://github.com/rentzsch/mach_override
-
-#include "mach_override.h"
-
-#include <mach-o/dyld.h>
-#include <mach/mach_host.h>
-#include <mach/mach_init.h>
-#include <mach/vm_map.h>
-#include <sys/mman.h>
-
-#include <CoreServices/CoreServices.h>
-
-/**************************
-*
-* Constants
-*
-**************************/
-#pragma mark -
-#pragma mark (Constants)
-
-#define kPageSize 4096
-#if defined(__ppc__) || defined(__POWERPC__)
-
-long kIslandTemplate[] = {
- 0x9001FFFC, // stw r0,-4(SP)
- 0x3C00DEAD, // lis r0,0xDEAD
- 0x6000BEEF, // ori r0,r0,0xBEEF
- 0x7C0903A6, // mtctr r0
- 0x8001FFFC, // lwz r0,-4(SP)
- 0x60000000, // nop ; optionally replaced
- 0x4E800420 // bctr
-};
-
-#define kAddressHi 3
-#define kAddressLo 5
-#define kInstructionHi 10
-#define kInstructionLo 11
-
-#elif defined(__i386__)
-
-#define kOriginalInstructionsSize 16
-// On X86 we migh need to instert an add with a 32 bit immediate after the
-// original instructions.
-#define kMaxFixupSizeIncrease 5
-
-unsigned char kIslandTemplate[] = {
- // kOriginalInstructionsSize nop instructions so that we
- // should have enough space to host original instructions
- 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
- 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
- // Now the real jump instruction
- 0xE9, 0xEF, 0xBE, 0xAD, 0xDE
-};
-
-#define kInstructions 0
-#define kJumpAddress kInstructions + kOriginalInstructionsSize + 1
-#elif defined(__x86_64__)
-
-#define kOriginalInstructionsSize 32
-// On X86-64 we never need to instert a new instruction.
-#define kMaxFixupSizeIncrease 0
-
-#define kJumpAddress kOriginalInstructionsSize + 6
-
-unsigned char kIslandTemplate[] = {
- // kOriginalInstructionsSize nop instructions so that we
- // should have enough space to host original instructions
- 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
- 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
- 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
- 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
- // Now the real jump instruction
- 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
-};
-
-#endif
-
-/**************************
-*
-* Data Types
-*
-**************************/
-#pragma mark -
-#pragma mark (Data Types)
-
-typedef struct {
- char instructions[sizeof(kIslandTemplate)];
-} BranchIsland;
-
-/**************************
-*
-* Funky Protos
-*
-**************************/
-#pragma mark -
-#pragma mark (Funky Protos)
-
-static mach_error_t
-allocateBranchIsland(
- BranchIsland **island,
- void *originalFunctionAddress);
-
- mach_error_t
-freeBranchIsland(
- BranchIsland *island );
-
-#if defined(__ppc__) || defined(__POWERPC__)
- mach_error_t
-setBranchIslandTarget(
- BranchIsland *island,
- const void *branchTo,
- long instruction );
-#endif
-
-#if defined(__i386__) || defined(__x86_64__)
-mach_error_t
-setBranchIslandTarget_i386(
- BranchIsland *island,
- const void *branchTo,
- char* instructions );
-void
-atomic_mov64(
- uint64_t *targetAddress,
- uint64_t value );
-
- static Boolean
-eatKnownInstructions(
- unsigned char *code,
- uint64_t *newInstruction,
- int *howManyEaten,
- char *originalInstructions,
- int *originalInstructionCount,
- uint8_t *originalInstructionSizes );
-
- static void
-fixupInstructions(
- uint32_t offset,
- void *instructionsToFix,
- int instructionCount,
- uint8_t *instructionSizes );
-#endif
-
-/*******************************************************************************
-*
-* Interface
-*
-*******************************************************************************/
-#pragma mark -
-#pragma mark (Interface)
-
-#if defined(__i386__) || defined(__x86_64__)
-mach_error_t makeIslandExecutable(void *address) {
- mach_error_t err = err_none;
- uintptr_t page = (uintptr_t)address & ~(uintptr_t)(kPageSize-1);
- int e = err_none;
- e |= mprotect((void *)page, kPageSize, PROT_EXEC | PROT_READ | PROT_WRITE);
- e |= msync((void *)page, kPageSize, MS_INVALIDATE );
- if (e) {
- err = err_cannot_override;
- }
- return err;
-}
-#endif
-
- mach_error_t
-mach_override_ptr(
- void *originalFunctionAddress,
- const void *overrideFunctionAddress,
- void **originalFunctionReentryIsland )
-{
- assert( originalFunctionAddress );
- assert( overrideFunctionAddress );
-
- // this addresses overriding such functions as AudioOutputUnitStart()
- // test with modified DefaultOutputUnit project
-#if defined(__x86_64__)
- for(;;){
- if(*(uint16_t*)originalFunctionAddress==0x25FF) // jmp qword near [rip+0x????????]
- originalFunctionAddress=*(void**)((char*)originalFunctionAddress+6+*(int32_t *)((uint16_t*)originalFunctionAddress+1));
- else break;
- }
-#elif defined(__i386__)
- for(;;){
- if(*(uint16_t*)originalFunctionAddress==0x25FF) // jmp *0x????????
- originalFunctionAddress=**(void***)((uint16_t*)originalFunctionAddress+1);
- else break;
- }
-#endif
-
- long *originalFunctionPtr = (long*) originalFunctionAddress;
- mach_error_t err = err_none;
-
-#if defined(__ppc__) || defined(__POWERPC__)
- // Ensure first instruction isn't 'mfctr'.
- #define kMFCTRMask 0xfc1fffff
- #define kMFCTRInstruction 0x7c0903a6
-
- long originalInstruction = *originalFunctionPtr;
- if( !err && ((originalInstruction & kMFCTRMask) == kMFCTRInstruction) )
- err = err_cannot_override;
-#elif defined(__i386__) || defined(__x86_64__)
- int eatenCount = 0;
- int originalInstructionCount = 0;
- char originalInstructions[kOriginalInstructionsSize];
- uint8_t originalInstructionSizes[kOriginalInstructionsSize];
- uint64_t jumpRelativeInstruction = 0; // JMP
-
- Boolean overridePossible = eatKnownInstructions ((unsigned char *)originalFunctionPtr,
- &jumpRelativeInstruction, &eatenCount,
- originalInstructions, &originalInstructionCount,
- originalInstructionSizes );
- if (eatenCount + kMaxFixupSizeIncrease > kOriginalInstructionsSize) {
- //printf ("Too many instructions eaten\n");
- overridePossible = false;
- }
- if (!overridePossible) err = err_cannot_override;
- if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__);
-#endif
-
- // Make the original function implementation writable.
- if( !err ) {
- err = vm_protect( mach_task_self(),
- (vm_address_t) originalFunctionPtr, 8, false,
- (VM_PROT_ALL | VM_PROT_COPY) );
- if( err )
- err = vm_protect( mach_task_self(),
- (vm_address_t) originalFunctionPtr, 8, false,
- (VM_PROT_DEFAULT | VM_PROT_COPY) );
- }
- if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__);
-
- // Allocate and target the escape island to the overriding function.
- BranchIsland *escapeIsland = NULL;
- if( !err )
- err = allocateBranchIsland( &escapeIsland, originalFunctionAddress );
- if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__);
-
-
-#if defined(__ppc__) || defined(__POWERPC__)
- if( !err )
- err = setBranchIslandTarget( escapeIsland, overrideFunctionAddress, 0 );
-
- // Build the branch absolute instruction to the escape island.
- long branchAbsoluteInstruction = 0; // Set to 0 just to silence warning.
- if( !err ) {
- long escapeIslandAddress = ((long) escapeIsland) & 0x3FFFFFF;
- branchAbsoluteInstruction = 0x48000002 | escapeIslandAddress;
- }
-#elif defined(__i386__) || defined(__x86_64__)
- if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__);
-
- if( !err )
- err = setBranchIslandTarget_i386( escapeIsland, overrideFunctionAddress, 0 );
-
- if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__);
- // Build the jump relative instruction to the escape island
-#endif
-
-
-#if defined(__i386__) || defined(__x86_64__)
- if (!err) {
- uint32_t addressOffset = ((char*)escapeIsland - (char*)originalFunctionPtr - 5);
- addressOffset = OSSwapInt32(addressOffset);
-
- jumpRelativeInstruction |= 0xE900000000000000LL;
- jumpRelativeInstruction |= ((uint64_t)addressOffset & 0xffffffff) << 24;
- jumpRelativeInstruction = OSSwapInt64(jumpRelativeInstruction);
- }
-#endif
-
- // Optionally allocate & return the reentry island. This may contain relocated
- // jmp instructions and so has all the same addressing reachability requirements
- // the escape island has to the original function, except the escape island is
- // technically our original function.
- BranchIsland *reentryIsland = NULL;
- if( !err && originalFunctionReentryIsland ) {
- err = allocateBranchIsland( &reentryIsland, escapeIsland);
- if( !err )
- *originalFunctionReentryIsland = reentryIsland;
- }
-
-#if defined(__ppc__) || defined(__POWERPC__)
- // Atomically:
- // o If the reentry island was allocated:
- // o Insert the original instruction into the reentry island.
- // o Target the reentry island at the 2nd instruction of the
- // original function.
- // o Replace the original instruction with the branch absolute.
- if( !err ) {
- int escapeIslandEngaged = false;
- do {
- if( reentryIsland )
- err = setBranchIslandTarget( reentryIsland,
- (void*) (originalFunctionPtr+1), originalInstruction );
- if( !err ) {
- escapeIslandEngaged = CompareAndSwap( originalInstruction,
- branchAbsoluteInstruction,
- (UInt32*)originalFunctionPtr );
- if( !escapeIslandEngaged ) {
- // Someone replaced the instruction out from under us,
- // re-read the instruction, make sure it's still not
- // 'mfctr' and try again.
- originalInstruction = *originalFunctionPtr;
- if( (originalInstruction & kMFCTRMask) == kMFCTRInstruction)
- err = err_cannot_override;
- }
- }
- } while( !err && !escapeIslandEngaged );
- }
-#elif defined(__i386__) || defined(__x86_64__)
- // Atomically:
- // o If the reentry island was allocated:
- // o Insert the original instructions into the reentry island.
- // o Target the reentry island at the first non-replaced
- // instruction of the original function.
- // o Replace the original first instructions with the jump relative.
- //
- // Note that on i386, we do not support someone else changing the code under our feet
- if ( !err ) {
- uint32_t offset = (uintptr_t)originalFunctionPtr - (uintptr_t)reentryIsland;
- fixupInstructions(offset, originalInstructions,
- originalInstructionCount, originalInstructionSizes );
-
- if( reentryIsland )
- err = setBranchIslandTarget_i386( reentryIsland,
- (void*) ((char *)originalFunctionPtr+eatenCount), originalInstructions );
- // try making islands executable before planting the jmp
-#if defined(__x86_64__) || defined(__i386__)
- if( !err )
- err = makeIslandExecutable(escapeIsland);
- if( !err && reentryIsland )
- err = makeIslandExecutable(reentryIsland);
-#endif
- if ( !err )
- atomic_mov64((uint64_t *)originalFunctionPtr, jumpRelativeInstruction);
- }
-#endif
-
- // Clean up on error.
- if( err ) {
- if( reentryIsland )
- freeBranchIsland( reentryIsland );
- if( escapeIsland )
- freeBranchIsland( escapeIsland );
- }
-
- return err;
-}
-
-/*******************************************************************************
-*
-* Implementation
-*
-*******************************************************************************/
-#pragma mark -
-#pragma mark (Implementation)
-
-static bool jump_in_range(intptr_t from, intptr_t to) {
- intptr_t field_value = to - from - 5;
- int32_t field_value_32 = field_value;
- return field_value == field_value_32;
-}
-
-/*******************************************************************************
- Implementation: Allocates memory for a branch island.
-
- @param island <- The allocated island.
- @result <- mach_error_t
-
- ***************************************************************************/
-
-static mach_error_t
-allocateBranchIslandAux(
- BranchIsland **island,
- void *originalFunctionAddress,
- bool forward)
-{
- assert( island );
- assert( sizeof( BranchIsland ) <= kPageSize );
-
- vm_map_t task_self = mach_task_self();
- vm_address_t original_address = (vm_address_t) originalFunctionAddress;
- vm_address_t address = original_address;
-
- for (;;) {
- vm_size_t vmsize = 0;
- memory_object_name_t object = 0;
- kern_return_t kr = 0;
- vm_region_flavor_t flavor = VM_REGION_BASIC_INFO;
- // Find the region the address is in.
-#if __WORDSIZE == 32
- vm_region_basic_info_data_t info;
- mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
- kr = vm_region(task_self, &address, &vmsize, flavor,
- (vm_region_info_t)&info, &info_count, &object);
-#else
- vm_region_basic_info_data_64_t info;
- mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64;
- kr = vm_region_64(task_self, &address, &vmsize, flavor,
- (vm_region_info_t)&info, &info_count, &object);
-#endif
- if (kr != KERN_SUCCESS)
- return kr;
- assert((address & (kPageSize - 1)) == 0);
-
- // Go to the first page before or after this region
- vm_address_t new_address = forward ? address + vmsize : address - kPageSize;
-#if __WORDSIZE == 64
- if(!jump_in_range(original_address, new_address))
- break;
-#endif
- address = new_address;
-
- // Try to allocate this page.
- kr = vm_allocate(task_self, &address, kPageSize, 0);
- if (kr == KERN_SUCCESS) {
- *island = (BranchIsland*) address;
- return err_none;
- }
- if (kr != KERN_NO_SPACE)
- return kr;
- }
-
- return KERN_NO_SPACE;
-}
-
-static mach_error_t
-allocateBranchIsland(
- BranchIsland **island,
- void *originalFunctionAddress)
-{
- mach_error_t err =
- allocateBranchIslandAux(island, originalFunctionAddress, true);
- if (!err)
- return err;
- return allocateBranchIslandAux(island, originalFunctionAddress, false);
-}
-
-
-/*******************************************************************************
- Implementation: Deallocates memory for a branch island.
-
- @param island -> The island to deallocate.
- @result <- mach_error_t
-
- ***************************************************************************/
-
- mach_error_t
-freeBranchIsland(
- BranchIsland *island )
-{
- assert( island );
- assert( (*(long*)&island->instructions[0]) == kIslandTemplate[0] );
- assert( sizeof( BranchIsland ) <= kPageSize );
- return vm_deallocate( mach_task_self(), (vm_address_t) island,
- kPageSize );
-}
-
-/*******************************************************************************
- Implementation: Sets the branch island's target, with an optional
- instruction.
-
- @param island -> The branch island to insert target into.
- @param branchTo -> The address of the target.
- @param instruction -> Optional instruction to execute prior to branch. Set
- to zero for nop.
- @result <- mach_error_t
-
- ***************************************************************************/
-#if defined(__ppc__) || defined(__POWERPC__)
- mach_error_t
-setBranchIslandTarget(
- BranchIsland *island,
- const void *branchTo,
- long instruction )
-{
- // Copy over the template code.
- bcopy( kIslandTemplate, island->instructions, sizeof( kIslandTemplate ) );
-
- // Fill in the address.
- ((short*)island->instructions)[kAddressLo] = ((long) branchTo) & 0x0000FFFF;
- ((short*)island->instructions)[kAddressHi]
- = (((long) branchTo) >> 16) & 0x0000FFFF;
-
- // Fill in the (optional) instuction.
- if( instruction != 0 ) {
- ((short*)island->instructions)[kInstructionLo]
- = instruction & 0x0000FFFF;
- ((short*)island->instructions)[kInstructionHi]
- = (instruction >> 16) & 0x0000FFFF;
- }
-
- //MakeDataExecutable( island->instructions, sizeof( kIslandTemplate ) );
- msync( island->instructions, sizeof( kIslandTemplate ), MS_INVALIDATE );
-
- return err_none;
-}
-#endif
-
-#if defined(__i386__)
- mach_error_t
-setBranchIslandTarget_i386(
- BranchIsland *island,
- const void *branchTo,
- char* instructions )
-{
-
- // Copy over the template code.
- bcopy( kIslandTemplate, island->instructions, sizeof( kIslandTemplate ) );
-
- // copy original instructions
- if (instructions) {
- bcopy (instructions, island->instructions + kInstructions, kOriginalInstructionsSize);
- }
-
- // Fill in the address.
- int32_t addressOffset = (char *)branchTo - (island->instructions + kJumpAddress + 4);
- *((int32_t *)(island->instructions + kJumpAddress)) = addressOffset;
-
- msync( island->instructions, sizeof( kIslandTemplate ), MS_INVALIDATE );
- return err_none;
-}
-
-#elif defined(__x86_64__)
-mach_error_t
-setBranchIslandTarget_i386(
- BranchIsland *island,
- const void *branchTo,
- char* instructions )
-{
- // Copy over the template code.
- bcopy( kIslandTemplate, island->instructions, sizeof( kIslandTemplate ) );
-
- // Copy original instructions.
- if (instructions) {
- bcopy (instructions, island->instructions, kOriginalInstructionsSize);
- }
-
- // Fill in the address.
- *((uint64_t *)(island->instructions + kJumpAddress)) = (uint64_t)branchTo;
- msync( island->instructions, sizeof( kIslandTemplate ), MS_INVALIDATE );
-
- return err_none;
-}
-#endif
-
-
-#if defined(__i386__) || defined(__x86_64__)
-// simplistic instruction matching
-typedef struct {
- unsigned int length; // max 15
- unsigned char mask[15]; // sequence of bytes in memory order
- unsigned char constraint[15]; // sequence of bytes in memory order
-} AsmInstructionMatch;
-
-#if defined(__i386__)
-static AsmInstructionMatch possibleInstructions[] = {
- { 0x5, {0xFF, 0x00, 0x00, 0x00, 0x00}, {0xE9, 0x00, 0x00, 0x00, 0x00} }, // jmp 0x????????
- { 0x5, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, {0x55, 0x89, 0xe5, 0xc9, 0xc3} }, // push %ebp; mov %esp,%ebp; leave; ret
- { 0x1, {0xFF}, {0x90} }, // nop
- { 0x1, {0xFF}, {0x55} }, // push %esp
- { 0x2, {0xFF, 0xFF}, {0x89, 0xE5} }, // mov %esp,%ebp
- { 0x1, {0xFF}, {0x53} }, // push %ebx
- { 0x3, {0xFF, 0xFF, 0x00}, {0x83, 0xEC, 0x00} }, // sub 0x??, %esp
- { 0x6, {0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}, {0x81, 0xEC, 0x00, 0x00, 0x00, 0x00} }, // sub 0x??, %esp with 32bit immediate
- { 0x1, {0xFF}, {0x57} }, // push %edi
- { 0x1, {0xFF}, {0x56} }, // push %esi
- { 0x2, {0xFF, 0xFF}, {0x31, 0xC0} }, // xor %eax, %eax
- { 0x3, {0xFF, 0x4F, 0x00}, {0x8B, 0x45, 0x00} }, // mov $imm(%ebp), %reg
- { 0x3, {0xFF, 0x4C, 0x00}, {0x8B, 0x40, 0x00} }, // mov $imm(%eax-%edx), %reg
- { 0x4, {0xFF, 0xFF, 0xFF, 0x00}, {0x8B, 0x4C, 0x24, 0x00} }, // mov $imm(%esp), %ecx
- { 0x5, {0xFF, 0x00, 0x00, 0x00, 0x00}, {0xB8, 0x00, 0x00, 0x00, 0x00} }, // mov $imm, %eax
- { 0x6, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, {0xE8, 0x00, 0x00, 0x00, 0x00, 0x58} }, // call $imm; pop %eax
- { 0x0 }
-};
-#elif defined(__x86_64__)
-static AsmInstructionMatch possibleInstructions[] = {
- { 0x5, {0xFF, 0x00, 0x00, 0x00, 0x00}, {0xE9, 0x00, 0x00, 0x00, 0x00} }, // jmp 0x????????
- { 0x1, {0xFF}, {0x90} }, // nop
- { 0x1, {0xF8}, {0x50} }, // push %rX
- { 0x3, {0xFF, 0xFF, 0xFF}, {0x48, 0x89, 0xE5} }, // mov %rsp,%rbp
- { 0x4, {0xFF, 0xFF, 0xFF, 0x00}, {0x48, 0x83, 0xEC, 0x00} }, // sub 0x??, %rsp
- { 0x4, {0xFB, 0xFF, 0x00, 0x00}, {0x48, 0x89, 0x00, 0x00} }, // move onto rbp
- { 0x4, {0xFF, 0xFF, 0xFF, 0xFF}, {0x40, 0x0f, 0xbe, 0xce} }, // movsbl %sil, %ecx
- { 0x2, {0xFF, 0x00}, {0x41, 0x00} }, // push %rXX
- { 0x2, {0xFF, 0x00}, {0x85, 0x00} }, // test %rX,%rX
- { 0x5, {0xF8, 0x00, 0x00, 0x00, 0x00}, {0xB8, 0x00, 0x00, 0x00, 0x00} }, // mov $imm, %reg
- { 0x3, {0xFF, 0xFF, 0x00}, {0xFF, 0x77, 0x00} }, // pushq $imm(%rdi)
- { 0x2, {0xFF, 0xFF}, {0x31, 0xC0} }, // xor %eax, %eax
- { 0x2, {0xFF, 0xFF}, {0x89, 0xF8} }, // mov %edi, %eax
-
- //leaq offset(%rip),%rax
- { 0x7, {0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}, {0x48, 0x8d, 0x05, 0x00, 0x00, 0x00, 0x00} },
-
- { 0x0 }
-};
-#endif
-
-static Boolean codeMatchesInstruction(unsigned char *code, AsmInstructionMatch* instruction)
-{
- Boolean match = true;
-
- size_t i;
- for (i=0; i<instruction->length; i++) {
- unsigned char mask = instruction->mask[i];
- unsigned char constraint = instruction->constraint[i];
- unsigned char codeValue = code[i];
-
- match = ((codeValue & mask) == constraint);
- if (!match) break;
- }
-
- return match;
-}
-
-#if defined(__i386__) || defined(__x86_64__)
- static Boolean
-eatKnownInstructions(
- unsigned char *code,
- uint64_t *newInstruction,
- int *howManyEaten,
- char *originalInstructions,
- int *originalInstructionCount,
- uint8_t *originalInstructionSizes )
-{
- Boolean allInstructionsKnown = true;
- int totalEaten = 0;
- unsigned char* ptr = code;
- int remainsToEat = 5; // a JMP instruction takes 5 bytes
- int instructionIndex = 0;
-
- if (howManyEaten) *howManyEaten = 0;
- if (originalInstructionCount) *originalInstructionCount = 0;
- while (remainsToEat > 0) {
- Boolean curInstructionKnown = false;
-
- // See if instruction matches one we know
- AsmInstructionMatch* curInstr = possibleInstructions;
- do {
- if ((curInstructionKnown = codeMatchesInstruction(ptr, curInstr))) break;
- curInstr++;
- } while (curInstr->length > 0);
-
- // if all instruction matches failed, we don't know current instruction then, stop here
- if (!curInstructionKnown) {
- allInstructionsKnown = false;
- fprintf(stderr, "mach_override: some instructions unknown! Need to update mach_override.c\n");
- break;
- }
-
- // At this point, we've matched curInstr
- int eaten = curInstr->length;
- ptr += eaten;
- remainsToEat -= eaten;
- totalEaten += eaten;
-
- if (originalInstructionSizes) originalInstructionSizes[instructionIndex] = eaten;
- instructionIndex += 1;
- if (originalInstructionCount) *originalInstructionCount = instructionIndex;
- }
-
-
- if (howManyEaten) *howManyEaten = totalEaten;
-
- if (originalInstructions) {
- Boolean enoughSpaceForOriginalInstructions = (totalEaten < kOriginalInstructionsSize);
-
- if (enoughSpaceForOriginalInstructions) {
- memset(originalInstructions, 0x90 /* NOP */, kOriginalInstructionsSize); // fill instructions with NOP
- bcopy(code, originalInstructions, totalEaten);
- } else {
- // printf ("Not enough space in island to store original instructions. Adapt the island definition and kOriginalInstructionsSize\n");
- return false;
- }
- }
-
- if (allInstructionsKnown) {
- // save last 3 bytes of first 64bits of codre we'll replace
- uint64_t currentFirst64BitsOfCode = *((uint64_t *)code);
- currentFirst64BitsOfCode = OSSwapInt64(currentFirst64BitsOfCode); // back to memory representation
- currentFirst64BitsOfCode &= 0x0000000000FFFFFFLL;
-
- // keep only last 3 instructions bytes, first 5 will be replaced by JMP instr
- *newInstruction &= 0xFFFFFFFFFF000000LL; // clear last 3 bytes
- *newInstruction |= (currentFirst64BitsOfCode & 0x0000000000FFFFFFLL); // set last 3 bytes
- }
-
- return allInstructionsKnown;
-}
-
- static void
-fixupInstructions(
- uint32_t offset,
- void *instructionsToFix,
- int instructionCount,
- uint8_t *instructionSizes )
-{
- // The start of "leaq offset(%rip),%rax"
- static const uint8_t LeaqHeader[] = {0x48, 0x8d, 0x05};
-
- int index;
- for (index = 0;index < instructionCount;index += 1)
- {
- if (*(uint8_t*)instructionsToFix == 0xE9) // 32-bit jump relative
- {
- uint32_t *jumpOffsetPtr = (uint32_t*)((uintptr_t)instructionsToFix + 1);
- *jumpOffsetPtr += offset;
- }
-
- // leaq offset(%rip),%rax
- if (memcmp(instructionsToFix, LeaqHeader, 3) == 0) {
- uint32_t *LeaqOffsetPtr = (uint32_t*)((uintptr_t)instructionsToFix + 3);
- *LeaqOffsetPtr += offset;
- }
-
- // 32-bit call relative to the next addr; pop %eax
- if (*(uint8_t*)instructionsToFix == 0xE8)
- {
- // Just this call is larger than the jump we use, so we
- // know this is the last instruction.
- assert(index == (instructionCount - 1));
- assert(instructionSizes[index] == 6);
-
- // Insert "addl $offset, %eax" in the end so that when
- // we jump to the rest of the function %eax has the
- // value it would have if eip had been pushed by the
- // call in its original position.
- uint8_t *op = instructionsToFix;
- op += 6;
- *op = 0x05; // addl
- uint32_t *addImmPtr = (uint32_t*)(op + 1);
- *addImmPtr = offset;
- }
-
- instructionsToFix = (void*)((uintptr_t)instructionsToFix + instructionSizes[index]);
- }
-}
-#endif
-
-#if defined(__i386__)
-__asm(
- ".text;"
- ".align 2, 0x90;"
- "_atomic_mov64:;"
- " pushl %ebp;"
- " movl %esp, %ebp;"
- " pushl %esi;"
- " pushl %ebx;"
- " pushl %ecx;"
- " pushl %eax;"
- " pushl %edx;"
-
- // atomic push of value to an address
- // we use cmpxchg8b, which compares content of an address with
- // edx:eax. If they are equal, it atomically puts 64bit value
- // ecx:ebx in address.
- // We thus put contents of address in edx:eax to force ecx:ebx
- // in address
- " mov 8(%ebp), %esi;" // esi contains target address
- " mov 12(%ebp), %ebx;"
- " mov 16(%ebp), %ecx;" // ecx:ebx now contains value to put in target address
- " mov (%esi), %eax;"
- " mov 4(%esi), %edx;" // edx:eax now contains value currently contained in target address
- " lock; cmpxchg8b (%esi);" // atomic move.
-
- // restore registers
- " popl %edx;"
- " popl %eax;"
- " popl %ecx;"
- " popl %ebx;"
- " popl %esi;"
- " popl %ebp;"
- " ret"
-);
-#elif defined(__x86_64__)
-void atomic_mov64(
- uint64_t *targetAddress,
- uint64_t value )
-{
- *targetAddress = value;
-}
-#endif
-#endif
diff --git a/xpcom/build/mach_override.h b/xpcom/build/mach_override.h
deleted file mode 100644
index d9be988a34..0000000000
--- a/xpcom/build/mach_override.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*******************************************************************************
- mach_override.h
- Copyright (c) 2003-2009 Jonathan 'Wolf' Rentzsch: <http://rentzsch.com>
- Some rights reserved: <http://opensource.org/licenses/mit-license.php>
-
- ***************************************************************************/
-
-/***************************************************************************//**
- @mainpage mach_override
- @author Jonathan 'Wolf' Rentzsch: <http://rentzsch.com>
-
- This package, coded in C to the Mach API, allows you to override ("patch")
- program- and system-supplied functions at runtime. You can fully replace
- functions with your implementations, or merely head- or tail-patch the
- original implementations.
-
- Use it by #include'ing mach_override.h from your .c, .m or .mm file(s).
-
- @todo Discontinue use of Carbon's MakeDataExecutable() and
- CompareAndSwap() calls and start using the Mach equivalents, if they
- exist. If they don't, write them and roll them in. That way, this
- code will be pure Mach, which will make it easier to use everywhere.
- Update: MakeDataExecutable() has been replaced by
- msync(MS_INVALIDATE). There is an OSCompareAndSwap in libkern, but
- I'm currently unsure if I can link against it. May have to roll in
- my own version...
- @todo Stop using an entire 4K high-allocated VM page per 28-byte escape
- branch island. Done right, this will dramatically speed up escape
- island allocations when they number over 250. Then again, if you're
- overriding more than 250 functions, maybe speed isn't your main
- concern...
- @todo Add detection of: b, bl, bla, bc, bcl, bcla, bcctrl, bclrl
- first-instructions. Initially, we should refuse to override
- functions beginning with these instructions. Eventually, we should
- dynamically rewrite them to make them position-independent.
- @todo Write mach_unoverride(), which would remove an override placed on a
- function. Must be multiple-override aware, which means an almost
- complete rewrite under the covers, because the target address can't
- be spread across two load instructions like it is now since it will
- need to be atomically updatable.
- @todo Add non-rentry variants of overrides to test_mach_override.
-
- ***************************************************************************/
-
-#ifndef _mach_override_
-#define _mach_override_
-
-#include <sys/types.h>
-#include <mach/error.h>
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-/**
- Returned if the function to be overrided begins with a 'mfctr' instruction.
-*/
-#define err_cannot_override (err_local|1)
-
-/************************************************************************************//**
- Dynamically overrides the function implementation referenced by
- originalFunctionAddress with the implentation pointed to by overrideFunctionAddress.
- Optionally returns a pointer to a "reentry island" which, if jumped to, will resume
- the original implementation.
-
- @param originalFunctionAddress -> Required address of the function to
- override (with overrideFunctionAddress).
- @param overrideFunctionAddress -> Required address to the overriding
- function.
- @param originalFunctionReentryIsland <- Optional pointer to pointer to the
- reentry island. Can be nullptr.
- @result <- err_cannot_override if the original
- function's implementation begins with
- the 'mfctr' instruction.
-
- ************************************************************************************/
-
- mach_error_t
-mach_override_ptr(
- void *originalFunctionAddress,
- const void *overrideFunctionAddress,
- void **originalFunctionReentryIsland );
-
-/************************************************************************************//**
-
-
- ************************************************************************************/
-
-#ifdef __cplusplus
-
-#define MACH_OVERRIDE( ORIGINAL_FUNCTION_RETURN_TYPE, ORIGINAL_FUNCTION_NAME, ORIGINAL_FUNCTION_ARGS, ERR ) \
- { \
- static ORIGINAL_FUNCTION_RETURN_TYPE (*ORIGINAL_FUNCTION_NAME##_reenter)ORIGINAL_FUNCTION_ARGS; \
- static bool ORIGINAL_FUNCTION_NAME##_overriden = false; \
- class mach_override_class__##ORIGINAL_FUNCTION_NAME { \
- public: \
- static kern_return_t override(void *originalFunctionPtr) { \
- kern_return_t result = err_none; \
- if (!ORIGINAL_FUNCTION_NAME##_overriden) { \
- ORIGINAL_FUNCTION_NAME##_overriden = true; \
- result = mach_override_ptr( (void*)originalFunctionPtr, \
- (void*)mach_override_class__##ORIGINAL_FUNCTION_NAME::replacement, \
- (void**)&ORIGINAL_FUNCTION_NAME##_reenter ); \
- } \
- return result; \
- } \
- static ORIGINAL_FUNCTION_RETURN_TYPE replacement ORIGINAL_FUNCTION_ARGS {
-
-#define END_MACH_OVERRIDE( ORIGINAL_FUNCTION_NAME ) \
- } \
- }; \
- \
- err = mach_override_class__##ORIGINAL_FUNCTION_NAME::override((void*)ORIGINAL_FUNCTION_NAME); \
- }
-
-#endif
-
-#ifdef __cplusplus
- }
-#endif
-#endif // _mach_override_
diff --git a/xpcom/build/moz.build b/xpcom/build/moz.build
index c58b4db3f5..bc20b8aedd 100644
--- a/xpcom/build/moz.build
+++ b/xpcom/build/moz.build
@@ -32,13 +32,6 @@ if CONFIG['OS_ARCH'] == 'WINNT':
'PoisonIOInterposerBase.cpp',
'PoisonIOInterposerWin.cpp',
]
-elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
- UNIFIED_SOURCES += [
- 'PoisonIOInterposerBase.cpp',
- 'PoisonIOInterposerMac.cpp',
- ]
- SOURCES += ['mach_override.c']
- SOURCES['mach_override.c'].flags += ['-Wno-unused-function']
else:
SOURCES += ['PoisonIOInterposerStub.cpp']
diff --git a/xpcom/build/nsXPCOMPrivate.h b/xpcom/build/nsXPCOMPrivate.h
index c5f6553c03..6c3a2bc0ab 100644
--- a/xpcom/build/nsXPCOMPrivate.h
+++ b/xpcom/build/nsXPCOMPrivate.h
@@ -254,15 +254,8 @@ void LogTerm();
#define XPCOM_DLL XUL_DLL
-// you have to love apple..
-#ifdef XP_MACOSX
-#define XPCOM_SEARCH_KEY "DYLD_LIBRARY_PATH"
-#define GRE_FRAMEWORK_NAME "XUL.framework"
-#define XUL_DLL "XUL"
-#else
#define XPCOM_SEARCH_KEY "LD_LIBRARY_PATH"
#define XUL_DLL "libxul" MOZ_DLL_SUFFIX
-#endif
#define GRE_CONF_NAME ".gre.config"
#define GRE_CONF_PATH "/etc/gre.conf"
diff --git a/xpcom/build/nsXULAppAPI.h b/xpcom/build/nsXULAppAPI.h
index ffb50565a0..78760f0431 100644
--- a/xpcom/build/nsXULAppAPI.h
+++ b/xpcom/build/nsXULAppAPI.h
@@ -106,7 +106,7 @@
*/
#define XRE_SYS_SHARE_EXTENSION_PARENT_DIR "XRESysSExtPD"
-#if defined(XP_UNIX) || defined(XP_MACOSX)
+#if defined(XP_UNIX)
/**
* Directory service keys for the system-wide and user-specific
* directories where host manifests used by the WebExtensions