Issue #1751 -- Remove XP_MACOSX conditionals and support files from /xpcom

This commit is contained in:
Moonchild
2021-05-03 11:35:41 +00:00
parent b1eb04d3f0
commit 1bf0734a72
40 changed files with 27 additions and 2812 deletions
-17
View File
@@ -1,17 +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/. */
#ifndef mozilla_MacHelpers_h
#define mozilla_MacHelpers_h
#include "nsString.h"
namespace mozilla {
nsresult GetSelectedCityInfo(nsAString& aCountryCode);
} // namespace mozilla
#endif
-40
View File
@@ -1,40 +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 "nsString.h"
#include "MacHelpers.h"
#include "nsObjCExceptions.h"
#import <Foundation/Foundation.h>
namespace mozilla {
nsresult
GetSelectedCityInfo(nsAString& aCountryCode)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
// Can be replaced with [[NSLocale currentLocale] countryCode] once we build
// with the 10.12 SDK.
id countryCode = [[NSLocale currentLocale] objectForKey:NSLocaleCountryCode];
if (![countryCode isKindOfClass:[NSString class]]) {
return NS_ERROR_FAILURE;
}
const char* countryCodeUTF8 = [(NSString*)countryCode UTF8String];
if (!countryCodeUTF8) {
return NS_ERROR_FAILURE;
}
AppendUTF8toUTF16(countryCodeUTF8, aCountryCode);
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
} // namespace Mozilla
+1 -16
View File
@@ -28,17 +28,6 @@ XPIDL_SOURCES += [
'nsrootidl.idl',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
XPIDL_SOURCES += [
'nsIMacUtils.idl',
]
EXPORTS.mozilla += [
'MacHelpers.h',
]
UNIFIED_SOURCES += [
'MacHelpers.mm',
]
XPIDL_MODULE = 'xpcom_base'
EXPORTS += [
@@ -136,11 +125,7 @@ if CONFIG['OS_ARCH'] == 'Linux':
'SystemMemoryReporter.cpp',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
SOURCES += [
'nsMacUtilsImpl.cpp',
]
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
SOURCES += [
'nsCrashOnException.cpp',
]
+3 -13
View File
@@ -34,7 +34,7 @@
#include "nsString.h"
#endif
#if defined(XP_MACOSX) || defined(__DragonFly__) || defined(__FreeBSD__) \
#if defined(__DragonFly__) || defined(__FreeBSD__) \
|| defined(__NetBSD__) || defined(__OpenBSD__)
#include <stdbool.h>
#include <unistd.h>
@@ -58,9 +58,7 @@
#define KINFO_PROC struct kinfo_proc
#endif
#if defined(XP_MACOSX)
#define KP_FLAGS kp_proc.p_flag
#elif defined(__DragonFly__)
#if defined(__DragonFly__)
#define KP_FLAGS kp_flags
#elif defined(__FreeBSD__)
#define KP_FLAGS ki_flag
@@ -164,7 +162,7 @@ nsDebugImpl::GetIsDebuggerAttached(bool* aResult)
#if defined(XP_WIN)
*aResult = ::IsDebuggerPresent();
#elif defined(XP_MACOSX) || defined(__DragonFly__) || defined(__FreeBSD__) \
#elif defined(__DragonFly__) || defined(__FreeBSD__) \
|| defined(__NetBSD__) || defined(__OpenBSD__)
// Specify the info we're looking for
int mib[] = {
@@ -426,8 +424,6 @@ RealBreak()
{
#if defined(_WIN32)
::DebugBreak();
#elif defined(XP_MACOSX)
raise(SIGTRAP);
#elif defined(__GNUC__) && (defined(__i386__) || defined(__i386) || defined(__x86_64__))
asm("int $3");
#elif defined(__arm__)
@@ -511,12 +507,6 @@ Break(const char* aMsg)
}
RealBreak();
#elif defined(XP_MACOSX)
/* Note that we put this Mac OS X test above the GNUC/x86 test because the
* GNUC/x86 test is also true on Intel Mac OS X and we want the PPC/x86
* impls to be the same.
*/
RealBreak();
#elif defined(__GNUC__) && (defined(__i386__) || defined(__i386) || defined(__x86_64__))
RealBreak();
#elif defined(__arm__)
-32
View File
@@ -1,32 +0,0 @@
/* -*- Mode: C++; tab-width: 2; 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 "nsISupports.idl"
/**
* nsIMacUtils: Generic globally-available Mac-specific utilities.
*/
[scriptable, uuid(5E9072D7-FF95-455E-9466-8AF9841A72EC)]
interface nsIMacUtils : nsISupports
{
/**
* True when the main executable is a fat file supporting at least
* ppc and x86 (universal binary).
*/
readonly attribute boolean isUniversalBinary;
/**
* Returns a string containing a list of architectures delimited
* by "-". Architecture sets are always in the same order:
* ppc > i386 > ppc64 > x86_64 > (future additions)
*/
readonly attribute AString architecturesInBinary;
/**
* True when running under binary translation (Rosetta).
*/
readonly attribute boolean isTranslated;
};
-146
View File
@@ -1,146 +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 "nsMacUtilsImpl.h"
#include <CoreFoundation/CoreFoundation.h>
NS_IMPL_ISUPPORTS(nsMacUtilsImpl, nsIMacUtils)
nsresult
nsMacUtilsImpl::GetArchString(nsAString& aArchString)
{
if (!mBinaryArchs.IsEmpty()) {
aArchString.Assign(mBinaryArchs);
return NS_OK;
}
aArchString.Truncate();
bool foundPPC = false,
foundX86 = false,
foundPPC64 = false,
foundX86_64 = false;
CFBundleRef mainBundle = ::CFBundleGetMainBundle();
if (!mainBundle) {
return NS_ERROR_FAILURE;
}
CFArrayRef archList = ::CFBundleCopyExecutableArchitectures(mainBundle);
if (!archList) {
return NS_ERROR_FAILURE;
}
CFIndex archCount = ::CFArrayGetCount(archList);
for (CFIndex i = 0; i < archCount; i++) {
CFNumberRef arch =
static_cast<CFNumberRef>(::CFArrayGetValueAtIndex(archList, i));
int archInt = 0;
if (!::CFNumberGetValue(arch, kCFNumberIntType, &archInt)) {
::CFRelease(archList);
return NS_ERROR_FAILURE;
}
if (archInt == kCFBundleExecutableArchitecturePPC) {
foundPPC = true;
} else if (archInt == kCFBundleExecutableArchitectureI386) {
foundX86 = true;
} else if (archInt == kCFBundleExecutableArchitecturePPC64) {
foundPPC64 = true;
} else if (archInt == kCFBundleExecutableArchitectureX86_64) {
foundX86_64 = true;
}
}
::CFRelease(archList);
// The order in the string must always be the same so
// don't do this in the loop.
if (foundPPC) {
mBinaryArchs.AppendLiteral("ppc");
}
if (foundX86) {
if (!mBinaryArchs.IsEmpty()) {
mBinaryArchs.Append('-');
}
mBinaryArchs.AppendLiteral("i386");
}
if (foundPPC64) {
if (!mBinaryArchs.IsEmpty()) {
mBinaryArchs.Append('-');
}
mBinaryArchs.AppendLiteral("ppc64");
}
if (foundX86_64) {
if (!mBinaryArchs.IsEmpty()) {
mBinaryArchs.Append('-');
}
mBinaryArchs.AppendLiteral("x86_64");
}
aArchString.Assign(mBinaryArchs);
return (aArchString.IsEmpty() ? NS_ERROR_FAILURE : NS_OK);
}
NS_IMETHODIMP
nsMacUtilsImpl::GetIsUniversalBinary(bool* aIsUniversalBinary)
{
if (NS_WARN_IF(!aIsUniversalBinary)) {
return NS_ERROR_INVALID_ARG;
}
*aIsUniversalBinary = false;
nsAutoString archString;
nsresult rv = GetArchString(archString);
if (NS_FAILED(rv)) {
return rv;
}
// The delimiter char in the arch string is '-', so if that character
// is in the string we know we have multiple architectures.
*aIsUniversalBinary = (archString.Find("-") > -1);
return NS_OK;
}
NS_IMETHODIMP
nsMacUtilsImpl::GetArchitecturesInBinary(nsAString& aArchString)
{
return GetArchString(aArchString);
}
// True when running under binary translation (Rosetta).
NS_IMETHODIMP
nsMacUtilsImpl::GetIsTranslated(bool* aIsTranslated)
{
#ifdef __ppc__
static bool sInitialized = false;
// Initialize sIsNative to 1. If the sysctl fails because it doesn't
// exist, then translation is not possible, so the process must not be
// running translated.
static int32_t sIsNative = 1;
if (!sInitialized) {
size_t sz = sizeof(sIsNative);
sysctlbyname("sysctl.proc_native", &sIsNative, &sz, nullptr, 0);
sInitialized = true;
}
*aIsTranslated = !sIsNative;
#else
// Translation only exists for ppc code. Other architectures aren't
// translated.
*aIsTranslated = false;
#endif
return NS_OK;
}
-41
View File
@@ -1,41 +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/. */
#ifndef nsMacUtilsImpl_h___
#define nsMacUtilsImpl_h___
#include "nsIMacUtils.h"
#include "nsString.h"
#include "mozilla/Attributes.h"
class nsMacUtilsImpl final : public nsIMacUtils
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIMACUTILS
nsMacUtilsImpl()
{
}
private:
~nsMacUtilsImpl()
{
}
nsresult GetArchString(nsAString& aArchString);
// A string containing a "-" delimited list of architectures
// in our binary.
nsString mBinaryArchs;
};
// Global singleton service
// 697BD3FD-43E5-41CE-AD5E-C339175C0818
#define NS_MACUTILSIMPL_CID \
{0x697BD3FD, 0x43E5, 0x41CE, {0xAD, 0x5E, 0xC3, 0x39, 0x17, 0x5C, 0x08, 0x18}}
#define NS_MACUTILSIMPL_CONTRACTID "@mozilla.org/xpcom/mac-utils;1"
#endif /* nsMacUtilsImpl_h___ */
+1 -165
View File
@@ -395,168 +395,6 @@ ResidentFastDistinguishedAmount(int64_t* aN)
return ResidentDistinguishedAmount(aN);
}
#elif defined(XP_MACOSX)
#include <mach/mach_init.h>
#include <mach/mach_vm.h>
#include <mach/shared_region.h>
#include <mach/task.h>
#include <sys/sysctl.h>
static MOZ_MUST_USE bool
GetTaskBasicInfo(struct task_basic_info* aTi)
{
mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT;
kern_return_t kr = task_info(mach_task_self(), TASK_BASIC_INFO,
(task_info_t)aTi, &count);
return kr == KERN_SUCCESS;
}
// The VSIZE figure on Mac includes huge amounts of shared memory and is always
// absurdly high, eg. 2GB+ even at start-up. But both 'top' and 'ps' report
// it, so we might as well too.
#define HAVE_VSIZE_AND_RESIDENT_REPORTERS 1
static MOZ_MUST_USE nsresult
VsizeDistinguishedAmount(int64_t* aN)
{
task_basic_info ti;
if (!GetTaskBasicInfo(&ti)) {
return NS_ERROR_FAILURE;
}
*aN = ti.virtual_size;
return NS_OK;
}
// If we're using jemalloc on Mac, we need to instruct jemalloc to purge the
// pages it has madvise(MADV_FREE)'d before we read our RSS in order to get
// an accurate result. The OS will take away MADV_FREE'd pages when there's
// memory pressure, so ideally, they shouldn't count against our RSS.
//
// Purging these pages can take a long time for some users (see bug 789975),
// so we provide the option to get the RSS without purging first.
static MOZ_MUST_USE nsresult
ResidentDistinguishedAmountHelper(int64_t* aN, bool aDoPurge)
{
#ifdef HAVE_JEMALLOC_STATS
if (aDoPurge) {
jemalloc_purge_freed_pages();
}
#endif
task_basic_info ti;
if (!GetTaskBasicInfo(&ti)) {
return NS_ERROR_FAILURE;
}
*aN = ti.resident_size;
return NS_OK;
}
static MOZ_MUST_USE nsresult
ResidentFastDistinguishedAmount(int64_t* aN)
{
return ResidentDistinguishedAmountHelper(aN, /* doPurge = */ false);
}
static MOZ_MUST_USE nsresult
ResidentDistinguishedAmount(int64_t* aN)
{
return ResidentDistinguishedAmountHelper(aN, /* doPurge = */ true);
}
#define HAVE_RESIDENT_UNIQUE_REPORTER 1
static bool
InSharedRegion(mach_vm_address_t aAddr, cpu_type_t aType)
{
mach_vm_address_t base;
mach_vm_address_t size;
switch (aType) {
case CPU_TYPE_ARM:
base = SHARED_REGION_BASE_ARM;
size = SHARED_REGION_SIZE_ARM;
break;
case CPU_TYPE_I386:
base = SHARED_REGION_BASE_I386;
size = SHARED_REGION_SIZE_I386;
break;
case CPU_TYPE_X86_64:
base = SHARED_REGION_BASE_X86_64;
size = SHARED_REGION_SIZE_X86_64;
break;
default:
return false;
}
return base <= aAddr && aAddr < (base + size);
}
static MOZ_MUST_USE nsresult
ResidentUniqueDistinguishedAmount(int64_t* aN)
{
if (!aN) {
return NS_ERROR_FAILURE;
}
cpu_type_t cpu_type;
size_t len = sizeof(cpu_type);
if (sysctlbyname("sysctl.proc_cputype", &cpu_type, &len, NULL, 0) != 0) {
return NS_ERROR_FAILURE;
}
// Roughly based on libtop_update_vm_regions in
// http://www.opensource.apple.com/source/top/top-100.1.2/libtop.c
size_t privatePages = 0;
mach_vm_size_t size = 0;
for (mach_vm_address_t addr = MACH_VM_MIN_ADDRESS; ; addr += size) {
vm_region_top_info_data_t info;
mach_msg_type_number_t infoCount = VM_REGION_TOP_INFO_COUNT;
mach_port_t objectName;
kern_return_t kr =
mach_vm_region(mach_task_self(), &addr, &size, VM_REGION_TOP_INFO,
reinterpret_cast<vm_region_info_t>(&info),
&infoCount, &objectName);
if (kr == KERN_INVALID_ADDRESS) {
// Done iterating VM regions.
break;
} else if (kr != KERN_SUCCESS) {
return NS_ERROR_FAILURE;
}
if (InSharedRegion(addr, cpu_type) && info.share_mode != SM_PRIVATE) {
continue;
}
switch (info.share_mode) {
case SM_LARGE_PAGE:
// NB: Large pages are not shareable and always resident.
case SM_PRIVATE:
privatePages += info.private_pages_resident;
privatePages += info.shared_pages_resident;
break;
case SM_COW:
privatePages += info.private_pages_resident;
if (info.ref_count == 1) {
// Treat copy-on-write pages as private if they only have one reference.
privatePages += info.shared_pages_resident;
}
break;
case SM_SHARED:
default:
break;
}
}
vm_size_t pageSize;
if (host_page_size(mach_host_self(), &pageSize) != KERN_SUCCESS) {
pageSize = PAGE_SIZE;
}
*aN = privatePages * pageSize;
return NS_OK;
}
#elif defined(XP_WIN)
#include <windows.h>
@@ -1147,9 +985,7 @@ ResidentPeakDistinguishedAmount(int64_t* aN)
// - Solaris: pages? But some sources it actually always returns 0, so
// check for that
// - Linux, {Net/Open/Free}BSD, DragonFly: KiB
#ifdef XP_MACOSX
*aN = usage.ru_maxrss;
#elif defined(XP_SOLARIS)
#if defined(XP_SOLARIS)
*aN = usage.ru_maxrss * getpagesize();
#else
*aN = usage.ru_maxrss * 1024;
-77
View File
@@ -25,10 +25,6 @@
#include "nsWindowsHelpers.h"
#endif
#ifdef XP_MACOSX
#include "MacHelpers.h"
#endif
#ifdef MOZ_WIDGET_GTK
#include <gtk/gtk.h>
#include <dlfcn.h>
@@ -44,10 +40,6 @@
#include <string>
#endif
#ifdef XP_MACOSX
#include <sys/sysctl.h>
#endif
// Slot for NS_InitXPCOM2 to pass information to nsSystemInfo::Init.
// Only set to nonzero (potentially) if XP_UNIX. On such systems, the
// system call to discover the appropriate value is not thread-safe,
@@ -418,67 +410,6 @@ nsSystemInfo::Init()
cpuFamily = si.wProcessorLevel;
cpuModel = si.wProcessorRevision >> 8;
cpuStepping = si.wProcessorRevision & 0xFF;
#elif defined (XP_MACOSX)
// CPU speed
uint64_t sysctlValue64 = 0;
uint32_t sysctlValue32 = 0;
size_t len = 0;
len = sizeof(sysctlValue64);
if (!sysctlbyname("hw.cpufrequency_max", &sysctlValue64, &len, NULL, 0)) {
cpuSpeed = static_cast<int>(sysctlValue64/1000000);
}
MOZ_ASSERT(sizeof(sysctlValue64) == len);
len = sizeof(sysctlValue32);
if (!sysctlbyname("hw.physicalcpu_max", &sysctlValue32, &len, NULL, 0)) {
physicalCPUs = static_cast<int>(sysctlValue32);
}
MOZ_ASSERT(sizeof(sysctlValue32) == len);
len = sizeof(sysctlValue32);
if (!sysctlbyname("hw.logicalcpu_max", &sysctlValue32, &len, NULL, 0)) {
logicalCPUs = static_cast<int>(sysctlValue32);
}
MOZ_ASSERT(sizeof(sysctlValue32) == len);
len = sizeof(sysctlValue64);
if (!sysctlbyname("hw.l2cachesize", &sysctlValue64, &len, NULL, 0)) {
cacheSizeL2 = static_cast<int>(sysctlValue64/1024);
}
MOZ_ASSERT(sizeof(sysctlValue64) == len);
len = sizeof(sysctlValue64);
if (!sysctlbyname("hw.l3cachesize", &sysctlValue64, &len, NULL, 0)) {
cacheSizeL3 = static_cast<int>(sysctlValue64/1024);
}
MOZ_ASSERT(sizeof(sysctlValue64) == len);
if (!sysctlbyname("machdep.cpu.vendor", NULL, &len, NULL, 0)) {
char* cpuVendorStr = new char[len];
if (!sysctlbyname("machdep.cpu.vendor", cpuVendorStr, &len, NULL, 0)) {
cpuVendor = cpuVendorStr;
}
delete [] cpuVendorStr;
}
len = sizeof(sysctlValue32);
if (!sysctlbyname("machdep.cpu.family", &sysctlValue32, &len, NULL, 0)) {
cpuFamily = static_cast<int>(sysctlValue32);
}
MOZ_ASSERT(sizeof(sysctlValue32) == len);
len = sizeof(sysctlValue32);
if (!sysctlbyname("machdep.cpu.model", &sysctlValue32, &len, NULL, 0)) {
cpuModel = static_cast<int>(sysctlValue32);
}
MOZ_ASSERT(sizeof(sysctlValue32) == len);
len = sizeof(sysctlValue32);
if (!sysctlbyname("machdep.cpu.stepping", &sysctlValue32, &len, NULL, 0)) {
cpuStepping = static_cast<int>(sysctlValue32);
}
MOZ_ASSERT(sizeof(sysctlValue32) == len);
#elif defined(XP_LINUX)
// Get vendor, family, model, stepping, physical cores, L3 cache size
// from /proc/cpuinfo file
@@ -655,14 +586,6 @@ nsSystemInfo::Init()
}
#endif
#if defined(XP_MACOSX)
nsAutoString countryCode;
if (NS_SUCCEEDED(GetSelectedCityInfo(countryCode))) {
rv = SetPropertyAsAString(NS_LITERAL_STRING("countryCode"), countryCode);
NS_ENSURE_SUCCESS(rv, rv);
}
#endif
#if defined(MOZ_WIDGET_GTK)
// This must be done here because NSPR can only separate OS's when compiled, not libraries.
// 64 bytes is going to be well enough for "GTK " followed by 3 integers
+3 -15
View File
@@ -6,8 +6,6 @@
#if defined(XP_WIN)
#include <windows.h>
#include <objbase.h>
#elif defined(XP_MACOSX)
#include <CoreFoundation/CoreFoundation.h>
#else
#include <stdlib.h>
#include "prrng.h"
@@ -34,7 +32,7 @@ nsUUIDGenerator::Init()
// We're a service, so we're guaranteed that Init() is not going
// to be reentered while we're inside Init().
#if !defined(XP_WIN) && !defined(XP_MACOSX) && !defined(HAVE_ARC4RANDOM)
#if !defined(XP_WIN) && !defined(HAVE_ARC4RANDOM)
/* initialize random number generator using NSPR random noise */
unsigned int seed;
@@ -71,7 +69,7 @@ nsUUIDGenerator::Init()
}
#endif
#endif /* non XP_WIN and non XP_MACOSX and non ARC4RANDOM */
#endif /* non XP_WIN and non ARC4RANDOM */
return NS_OK;
}
@@ -106,17 +104,7 @@ nsUUIDGenerator::GenerateUUIDInPlace(nsID* aId)
if (FAILED(hr)) {
return NS_ERROR_FAILURE;
}
#elif defined(XP_MACOSX)
CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
if (!uuid) {
return NS_ERROR_FAILURE;
}
CFUUIDBytes bytes = CFUUIDGetUUIDBytes(uuid);
memcpy(aId, &bytes, sizeof(nsID));
CFRelease(uuid);
#else /* not windows or OS X; generate randomness using random(). */
#else /* not windows; generate randomness using random(). */
/* XXX we should be saving the return of setstate here and switching
* back to it; instead, we use the value returned when we called
* initstate, since older glibc's have broken setstate() return values
+1 -1
View File
@@ -28,7 +28,7 @@ private:
protected:
mozilla::Mutex mLock;
#if !defined(XP_WIN) && !defined(XP_MACOSX) && !defined(HAVE_ARC4RANDOM)
#if !defined(XP_WIN) && !defined(HAVE_ARC4RANDOM)
char mState[128];
char* mSavedState;
uint8_t mRBytes;
-42
View File
@@ -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])
{
+3 -16
View File
@@ -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
-385
View File
@@ -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
-3
View File
@@ -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();
}
-789
View File
@@ -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
-121
View File
@@ -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_
-7
View File
@@ -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']
-7
View File
@@ -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"
+1 -1
View File
@@ -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
@@ -33,10 +33,6 @@
#include <windows.h>
#endif
#ifdef XP_MACOSX
#include <signal.h>
#endif
#ifdef DEBUG
#define IMPLEMENT_BREAK_AFTER_LOAD
#endif
+4 -149
View File
@@ -12,16 +12,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/FileUtils.h"
#if defined(XP_MACOSX)
#include <fcntl.h>
#include <unistd.h>
#include <mach/machine.h>
#include <mach-o/fat.h>
#include <mach-o/loader.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <limits.h>
#elif defined(XP_UNIX)
#if defined(XP_UNIX)
#include <fcntl.h>
#include <unistd.h>
#if defined(LINUX)
@@ -56,20 +47,6 @@ mozilla::fallocate(PRFileDesc* aFD, int64_t aLength)
PR_Seek64(aFD, oldpos, PR_SEEK_SET);
return retval;
#elif defined(XP_MACOSX)
int fd = PR_FileDesc2NativeHandle(aFD);
fstore_t store = {F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, aLength};
// Try to get a continous chunk of disk space
int ret = fcntl(fd, F_PREALLOCATE, &store);
if (ret == -1) {
// OK, perhaps we are too fragmented, allocate non-continuous
store.fst_flags = F_ALLOCATEALL;
ret = fcntl(fd, F_PREALLOCATE, &store);
if (ret == -1) {
return false;
}
}
return ftruncate(fd, aLength) == 0;
#elif defined(XP_UNIX)
// The following is copied from fcntlSizeHint in sqlite
/* If the OS does not have posix_fallocate(), fake it. First use
@@ -225,7 +202,7 @@ mozilla::ReadAheadLib(nsIFile* aFile)
return;
}
ReadAheadLib(path.get());
#elif defined(LINUX) || defined(XP_MACOSX)
#elif defined(LINUX)
nsAutoCString nativePath;
if (!aFile || NS_FAILED(aFile->GetNativePath(nativePath))) {
return;
@@ -244,7 +221,7 @@ mozilla::ReadAheadFile(nsIFile* aFile, const size_t aOffset,
return;
}
ReadAheadFile(path.get(), aOffset, aCount, aOutFd);
#elif defined(LINUX) || defined(XP_MACOSX)
#elif defined(LINUX)
nsAutoCString nativePath;
if (!aFile || NS_FAILED(aFile->GetNativePath(nativePath))) {
return;
@@ -271,64 +248,6 @@ static const unsigned char ELFCLASS = ELFCLASS32;
typedef Elf32_Off Elf_Off;
#endif
#elif defined(XP_MACOSX)
#if defined(__i386__)
static const uint32_t CPU_TYPE = CPU_TYPE_X86;
#elif defined(__x86_64__)
static const uint32_t CPU_TYPE = CPU_TYPE_X86_64;
#elif defined(__ppc__)
static const uint32_t CPU_TYPE = CPU_TYPE_POWERPC;
#elif defined(__ppc64__)
static const uint32_t CPU_TYPE = CPU_TYPE_POWERPC64;
#else
#error Unsupported CPU type
#endif
#ifdef __LP64__
#undef LC_SEGMENT
#define LC_SEGMENT LC_SEGMENT_64
#undef MH_MAGIC
#define MH_MAGIC MH_MAGIC_64
#define cpu_mach_header mach_header_64
#define segment_command segment_command_64
#else
#define cpu_mach_header mach_header
#endif
class ScopedMMap
{
public:
explicit ScopedMMap(const char* aFilePath)
: buf(nullptr)
{
fd = open(aFilePath, O_RDONLY);
if (fd < 0) {
return;
}
struct stat st;
if (fstat(fd, &st) < 0) {
return;
}
size = st.st_size;
buf = (char*)mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0);
}
~ScopedMMap()
{
if (buf) {
munmap(buf, size);
}
if (fd >= 0) {
close(fd);
}
}
operator char*() { return buf; }
int getFd() { return fd; }
private:
int fd;
char* buf;
size_t size;
};
#endif
void
@@ -385,14 +304,6 @@ mozilla::ReadAhead(mozilla::filedesc_t aFd, const size_t aOffset,
readahead(aFd, aOffset, aCount);
#elif defined(XP_MACOSX)
struct radvisory ra;
ra.ra_offset = aOffset;
ra.ra_count = aCount;
// The F_RDADVISE fcntl is equivalent to Linux' readahead() system call.
fcntl(aFd, F_RDADVISE, &ra);
#endif
}
@@ -449,62 +360,6 @@ mozilla::ReadAheadLib(mozilla::pathstr_t aFilePath)
ReadAhead(fd, 0, end);
}
close(fd);
#elif defined(XP_MACOSX)
ScopedMMap buf(aFilePath);
char* base = buf;
if (!base) {
return;
}
// An OSX binary might either be a fat (universal) binary or a
// Mach-O binary. A fat binary actually embeds several Mach-O
// binaries. If we have a fat binary, find the offset where the
// Mach-O binary for our CPU type can be found.
struct fat_header* fh = (struct fat_header*)base;
if (OSSwapBigToHostInt32(fh->magic) == FAT_MAGIC) {
uint32_t nfat_arch = OSSwapBigToHostInt32(fh->nfat_arch);
struct fat_arch* arch = (struct fat_arch*)&buf[sizeof(struct fat_header)];
for (; nfat_arch; arch++, nfat_arch--) {
if (OSSwapBigToHostInt32(arch->cputype) == CPU_TYPE) {
base += OSSwapBigToHostInt32(arch->offset);
break;
}
}
if (base == buf) {
return;
}
}
// Check Mach-O magic in the Mach header
struct cpu_mach_header* mh = (struct cpu_mach_header*)base;
if (mh->magic != MH_MAGIC) {
return;
}
// The Mach header is followed by a sequence of load commands.
// Each command has a header containing the command type and the
// command size. LD_SEGMENT commands describes how the dynamic
// loader is going to map the file in memory. We use that
// information to find the biggest offset from the library that
// will be mapped in memory.
char* cmd = &base[sizeof(struct cpu_mach_header)];
uint32_t end = 0;
for (uint32_t ncmds = mh->ncmds; ncmds; ncmds--) {
struct segment_command* sh = (struct segment_command*)cmd;
if (sh->cmd != LC_SEGMENT) {
continue;
}
if (end < sh->fileoff + sh->filesize) {
end = sh->fileoff + sh->filesize;
}
cmd += sh->cmdsize;
}
// Let the kernel read ahead what the dynamic loader is going to
// map in memory soon after.
if (end > 0) {
ReadAhead(buf.getFd(), base - buf, end);
}
#endif
}
@@ -531,7 +386,7 @@ mozilla::ReadAheadFile(mozilla::pathstr_t aFilePath, const size_t aOffset,
if (!aOutFd) {
CloseHandle(fd);
}
#elif defined(LINUX) || defined(XP_MACOSX) || defined(XP_SOLARIS)
#elif defined(LINUX) || defined(XP_SOLARIS)
if (!aFilePath) {
if (aOutFd) {
*aOutFd = -1;
+1 -3
View File
@@ -124,9 +124,7 @@ void NS_MakeRandomString(char* aBuf, int32_t aBufLen);
// identify or replace all known path separators.
#define KNOWN_PATH_SEPARATORS "\\/"
#if defined(XP_MACOSX)
#define FILE_PATH_SEPARATOR "/"
#elif defined(XP_WIN)
#if defined(XP_WIN)
#define FILE_PATH_SEPARATOR "\\"
#elif defined(XP_UNIX)
#define FILE_PATH_SEPARATOR "/"
-12
View File
@@ -19,8 +19,6 @@
#ifdef XP_WIN
#include <windows.h>
#elif defined(XP_MACOSX)
#include <sys/resource.h>
#endif
using namespace mozilla;
@@ -439,12 +437,6 @@ nsAutoLowPriorityIO::nsAutoLowPriorityIO()
#if defined(XP_WIN)
lowIOPrioritySet = SetThreadPriority(GetCurrentThread(),
THREAD_MODE_BACKGROUND_BEGIN);
#elif defined(XP_MACOSX)
oldPriority = getiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_THREAD);
lowIOPrioritySet = oldPriority != -1 &&
setiopolicy_np(IOPOL_TYPE_DISK,
IOPOL_SCOPE_THREAD,
IOPOL_THROTTLE) != -1;
#else
lowIOPrioritySet = false;
#endif
@@ -457,9 +449,5 @@ nsAutoLowPriorityIO::~nsAutoLowPriorityIO()
// On Windows the old thread priority is automatically restored
SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_END);
}
#elif defined(XP_MACOSX)
if (MOZ_LIKELY(lowIOPrioritySet)) {
setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_THREAD, oldPriority);
}
#endif
}
-3
View File
@@ -1037,9 +1037,6 @@ public:
private:
bool lowIOPrioritySet;
#if defined(XP_MACOSX)
int oldPriority;
#endif
};
void
+1 -37
View File
@@ -97,11 +97,7 @@ static LibHandleType
GetLibHandle(pathstr_t aDependentLib)
{
LibHandleType libHandle = dlopen(aDependentLib,
RTLD_GLOBAL | RTLD_LAZY
#ifdef XP_MACOSX
| RTLD_FIRST
#endif
);
RTLD_GLOBAL | RTLD_LAZY);
if (!libHandle) {
fprintf(stderr, "XPCOMGlueLoad error for file %s:\n%s\n", aDependentLib,
dlerror());
@@ -235,22 +231,6 @@ XPCOMGlueLoad(const char* aXPCOMFile)
char xpcomDir[MAXPATHLEN];
#ifdef XP_WIN
const char* lastSlash = ns_strrpbrk(aXPCOMFile, "/\\");
#elif XP_MACOSX
// On OSX, the dependentlibs.list file lives under Contents/Resources.
// However, the actual libraries listed in dependentlibs.list live under
// Contents/MacOS. We want to read the list from Contents/Resources, then
// load the libraries from Contents/MacOS.
const char *tempSlash = strrchr(aXPCOMFile, '/');
size_t tempLen = size_t(tempSlash - aXPCOMFile);
if (tempLen > MAXPATHLEN) {
return nullptr;
}
char tempBuffer[MAXPATHLEN];
memcpy(tempBuffer, aXPCOMFile, tempLen);
tempBuffer[tempLen] = '\0';
const char *slash = strrchr(tempBuffer, '/');
tempLen = size_t(slash - tempBuffer);
const char *lastSlash = aXPCOMFile + tempLen;
#else
const char* lastSlash = strrchr(aXPCOMFile, '/');
#endif
@@ -259,19 +239,11 @@ XPCOMGlueLoad(const char* aXPCOMFile)
size_t len = size_t(lastSlash - aXPCOMFile);
if (len > MAXPATHLEN - sizeof(XPCOM_FILE_PATH_SEPARATOR
#ifdef XP_MACOSX
"Resources"
XPCOM_FILE_PATH_SEPARATOR
#endif
XPCOM_DEPENDENT_LIBS_LIST)) {
return nullptr;
}
memcpy(xpcomDir, aXPCOMFile, len);
strcpy(xpcomDir + len, XPCOM_FILE_PATH_SEPARATOR
#ifdef XP_MACOSX
"Resources"
XPCOM_FILE_PATH_SEPARATOR
#endif
XPCOM_DEPENDENT_LIBS_LIST);
cursor = xpcomDir + len + 1;
} else {
@@ -289,14 +261,6 @@ XPCOMGlueLoad(const char* aXPCOMFile)
return nullptr;
}
#ifdef XP_MACOSX
tempLen = size_t(cursor - xpcomDir);
if (tempLen > MAXPATHLEN - sizeof("MacOS" XPCOM_FILE_PATH_SEPARATOR) - 1) {
return nullptr;
}
strcpy(cursor, "MacOS" XPCOM_FILE_PATH_SEPARATOR);
cursor += strlen(cursor);
#endif
*cursor = '\0';
char buffer[MAXPATHLEN];
-34
View File
@@ -1,34 +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/. */
// This namespace contains methods with Obj-C/Cocoa implementations. The header
// is C/C++ for inclusion in C/C++-only files.
#ifndef CocoaFileUtils_h_
#define CocoaFileUtils_h_
#include "nscore.h"
#include <CoreFoundation/CoreFoundation.h>
namespace CocoaFileUtils {
nsresult RevealFileInFinder(CFURLRef aUrl);
nsresult OpenURL(CFURLRef aUrl);
nsresult GetFileCreatorCode(CFURLRef aUrl, OSType* aCreatorCode);
nsresult SetFileCreatorCode(CFURLRef aUrl, OSType aCreatorCode);
nsresult GetFileTypeCode(CFURLRef aUrl, OSType* aTypeCode);
nsresult SetFileTypeCode(CFURLRef aUrl, OSType aTypeCode);
void AddOriginMetadataToFile(const CFStringRef filePath,
const CFURLRef sourceURL,
const CFURLRef referrerURL);
void AddQuarantineMetadataToFile(const CFStringRef filePath,
const CFURLRef sourceURL,
const CFURLRef referrerURL,
const bool isFromWeb);
CFURLRef GetTemporaryFolderCFURLRef();
} // namespace CocoaFileUtils
#endif
-267
View File
@@ -1,267 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
// vim:set ts=2 sts=2 sw=2 et cin:
/* 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 "CocoaFileUtils.h"
#include "nsCocoaFeatures.h"
#include "nsCocoaUtils.h"
#include <Cocoa/Cocoa.h>
#include "nsObjCExceptions.h"
#include "nsDebug.h"
// Need to cope with us using old versions of the SDK and needing this on 10.10+
#if !defined(MAC_OS_X_VERSION_10_10) || (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_10)
const CFStringRef kCFURLQuarantinePropertiesKey = CFSTR("NSURLQuarantinePropertiesKey");
#endif
namespace CocoaFileUtils {
nsresult RevealFileInFinder(CFURLRef url)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
if (NS_WARN_IF(!url))
return NS_ERROR_INVALID_ARG;
NSAutoreleasePool* ap = [[NSAutoreleasePool alloc] init];
BOOL success = [[NSWorkspace sharedWorkspace] selectFile:[(NSURL*)url path] inFileViewerRootedAtPath:@""];
[ap release];
return (success ? NS_OK : NS_ERROR_FAILURE);
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
nsresult OpenURL(CFURLRef url)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
if (NS_WARN_IF(!url))
return NS_ERROR_INVALID_ARG;
NSAutoreleasePool* ap = [[NSAutoreleasePool alloc] init];
BOOL success = [[NSWorkspace sharedWorkspace] openURL:(NSURL*)url];
[ap release];
return (success ? NS_OK : NS_ERROR_FAILURE);
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
nsresult GetFileCreatorCode(CFURLRef url, OSType *creatorCode)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
if (NS_WARN_IF(!url) || NS_WARN_IF(!creatorCode))
return NS_ERROR_INVALID_ARG;
nsAutoreleasePool localPool;
NSString *resolvedPath = [[(NSURL*)url path] stringByResolvingSymlinksInPath];
if (!resolvedPath) {
return NS_ERROR_FAILURE;
}
NSDictionary* dict = [[NSFileManager defaultManager] attributesOfItemAtPath:resolvedPath error:nil];
if (!dict) {
return NS_ERROR_FAILURE;
}
NSNumber* creatorNum = (NSNumber*)[dict objectForKey:NSFileHFSCreatorCode];
if (!creatorNum) {
return NS_ERROR_FAILURE;
}
*creatorCode = [creatorNum unsignedLongValue];
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
nsresult SetFileCreatorCode(CFURLRef url, OSType creatorCode)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
if (NS_WARN_IF(!url))
return NS_ERROR_INVALID_ARG;
NSAutoreleasePool* ap = [[NSAutoreleasePool alloc] init];
NSDictionary* dict = [NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedLong:creatorCode] forKey:NSFileHFSCreatorCode];
BOOL success = [[NSFileManager defaultManager] setAttributes:dict ofItemAtPath:[(NSURL*)url path] error:nil];
[ap release];
return (success ? NS_OK : NS_ERROR_FAILURE);
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
nsresult GetFileTypeCode(CFURLRef url, OSType *typeCode)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
if (NS_WARN_IF(!url) || NS_WARN_IF(!typeCode))
return NS_ERROR_INVALID_ARG;
nsAutoreleasePool localPool;
NSString *resolvedPath = [[(NSURL*)url path] stringByResolvingSymlinksInPath];
if (!resolvedPath) {
return NS_ERROR_FAILURE;
}
NSDictionary* dict = [[NSFileManager defaultManager] attributesOfItemAtPath:resolvedPath error:nil];
if (!dict) {
return NS_ERROR_FAILURE;
}
NSNumber* typeNum = (NSNumber*)[dict objectForKey:NSFileHFSTypeCode];
if (!typeNum) {
return NS_ERROR_FAILURE;
}
*typeCode = [typeNum unsignedLongValue];
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
nsresult SetFileTypeCode(CFURLRef url, OSType typeCode)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
if (NS_WARN_IF(!url))
return NS_ERROR_INVALID_ARG;
NSAutoreleasePool* ap = [[NSAutoreleasePool alloc] init];
NSDictionary* dict = [NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedLong:typeCode] forKey:NSFileHFSTypeCode];
BOOL success = [[NSFileManager defaultManager] setAttributes:dict ofItemAtPath:[(NSURL*)url path] error:nil];
[ap release];
return (success ? NS_OK : NS_ERROR_FAILURE);
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
void AddOriginMetadataToFile(const CFStringRef filePath,
const CFURLRef sourceURL,
const CFURLRef referrerURL) {
typedef OSStatus (*MDItemSetAttribute_type)(MDItemRef, CFStringRef, CFTypeRef);
static MDItemSetAttribute_type mdItemSetAttributeFunc = NULL;
static bool did_symbol_lookup = false;
if (!did_symbol_lookup) {
did_symbol_lookup = true;
CFBundleRef metadata_bundle = ::CFBundleGetBundleWithIdentifier(CFSTR("com.apple.Metadata"));
if (!metadata_bundle) {
return;
}
mdItemSetAttributeFunc = (MDItemSetAttribute_type)
::CFBundleGetFunctionPointerForName(metadata_bundle, CFSTR("MDItemSetAttribute"));
}
if (!mdItemSetAttributeFunc) {
return;
}
MDItemRef mdItem = ::MDItemCreate(NULL, filePath);
if (!mdItem) {
return;
}
CFMutableArrayRef list = ::CFArrayCreateMutable(kCFAllocatorDefault, 2, NULL);
if (!list) {
::CFRelease(mdItem);
return;
}
// The first item in the list is the source URL of the downloaded file.
if (sourceURL) {
::CFArrayAppendValue(list, ::CFURLGetString(sourceURL));
}
// If the referrer is known, store that in the second position.
if (referrerURL) {
::CFArrayAppendValue(list, ::CFURLGetString(referrerURL));
}
mdItemSetAttributeFunc(mdItem, kMDItemWhereFroms, list);
::CFRelease(list);
::CFRelease(mdItem);
}
void AddQuarantineMetadataToFile(const CFStringRef filePath,
const CFURLRef sourceURL,
const CFURLRef referrerURL,
const bool isFromWeb) {
CFURLRef fileURL = ::CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
filePath,
kCFURLPOSIXPathStyle,
false);
// The properties key changed in 10.10:
CFStringRef quarantinePropKey;
if (nsCocoaFeatures::OnYosemiteOrLater()) {
quarantinePropKey = kCFURLQuarantinePropertiesKey;
} else {
quarantinePropKey = kLSItemQuarantineProperties;
}
CFDictionaryRef quarantineProps = NULL;
Boolean success = ::CFURLCopyResourcePropertyForKey(fileURL,
quarantinePropKey,
&quarantineProps,
NULL);
// If there aren't any quarantine properties then the user probably
// set up an exclusion and we don't need to add metadata.
if (!success || !quarantineProps) {
::CFRelease(fileURL);
return;
}
// We don't know what to do if the props aren't a dictionary.
if (::CFGetTypeID(quarantineProps) != ::CFDictionaryGetTypeID()) {
::CFRelease(fileURL);
::CFRelease(quarantineProps);
return;
}
// Make a mutable copy of the properties.
CFMutableDictionaryRef mutQuarantineProps =
::CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, (CFDictionaryRef)quarantineProps);
::CFRelease(quarantineProps);
// Add metadata that the OS couldn't infer.
if (!::CFDictionaryGetValue(mutQuarantineProps, kLSQuarantineTypeKey)) {
CFStringRef type = isFromWeb ? kLSQuarantineTypeWebDownload : kLSQuarantineTypeOtherDownload;
::CFDictionarySetValue(mutQuarantineProps, kLSQuarantineTypeKey, type);
}
if (!::CFDictionaryGetValue(mutQuarantineProps, kLSQuarantineOriginURLKey) && referrerURL) {
::CFDictionarySetValue(mutQuarantineProps, kLSQuarantineOriginURLKey, referrerURL);
}
if (!::CFDictionaryGetValue(mutQuarantineProps, kLSQuarantineDataURLKey) && sourceURL) {
::CFDictionarySetValue(mutQuarantineProps, kLSQuarantineDataURLKey, sourceURL);
}
// Set quarantine properties on file.
::CFURLSetResourcePropertyForKey(fileURL,
quarantinePropKey,
mutQuarantineProps,
NULL);
::CFRelease(fileURL);
::CFRelease(mutQuarantineProps);
}
CFURLRef GetTemporaryFolderCFURLRef()
{
NSString* tempDir = ::NSTemporaryDirectory();
return tempDir == nil ? NULL : (CFURLRef)[NSURL fileURLWithPath:tempDir
isDirectory:YES];
}
} // namespace CocoaFileUtils
-10
View File
@@ -37,11 +37,6 @@ XPIDL_SOURCES += [
'nsIUnicharOutputStream.idl',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
XPIDL_SOURCES += [
'nsILocalFileMac.idl',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
EXPORTS += ['nsLocalFileWin.h']
EXPORTS.mozilla += [
@@ -123,11 +118,6 @@ SOURCES += [
'FilePreferences.cpp',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
SOURCES += [
'CocoaFileUtils.mm',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
-179
View File
@@ -1,179 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "nsILocalFile.idl"
%{C++
#include <Carbon/Carbon.h>
#include <CoreFoundation/CoreFoundation.h>
%}
native OSType(OSType);
native FSSpec(FSSpec);
native FSRef(FSRef);
[ptr] native FSRefPtr(FSRef);
native CFURLRef(CFURLRef);
[scriptable, builtinclass, uuid(623eca5b-c25d-4e27-be5a-789a66c4b2f7)]
interface nsILocalFileMac : nsILocalFile
{
/**
* initWithCFURL
*
* Init this object with a CFURLRef
*
* NOTE: Supported only for XP_MACOSX
* NOTE: If the path of the CFURL is /a/b/c, at least a/b must exist beforehand.
*
* @param aCFURL the CoreFoundation URL
*
*/
[noscript] void initWithCFURL(in CFURLRef aCFURL);
/**
* initWithFSRef
*
* Init this object with an FSRef
*
* NOTE: Supported only for XP_MACOSX
*
* @param aFSRef the native FSRef
*
*/
[noscript] void initWithFSRef([const] in FSRefPtr aFSRef);
/**
* getCFURL
*
* Returns the CFURLRef of the file object. The caller is
* responsible for calling CFRelease() on it.
*
* NOTE: Observes the state of the followLinks attribute.
* If the file object is an alias and followLinks is TRUE, returns
* the target of the alias. If followLinks is FALSE, returns
* the unresolved alias file.
*
* NOTE: Supported only for XP_MACOSX
*
* @return
*
*/
[noscript] CFURLRef getCFURL();
/**
* getFSRef
*
* Returns the FSRef of the file object.
*
* NOTE: Observes the state of the followLinks attribute.
* If the file object is an alias and followLinks is TRUE, returns
* the target of the alias. If followLinks is FALSE, returns
* the unresolved alias file.
*
* NOTE: Supported only for XP_MACOSX
*
* @return
*
*/
[noscript] FSRef getFSRef();
/**
* getFSSpec
*
* Returns the FSSpec of the file object.
*
* NOTE: Observes the state of the followLinks attribute.
* If the file object is an alias and followLinks is TRUE, returns
* the target of the alias. If followLinks is FALSE, returns
* the unresolved alias file.
*
* @return
*
*/
[noscript] FSSpec getFSSpec();
/**
* fileSizeWithResFork
*
* Returns the combined size of both the data fork and the resource
* fork (if present) rather than just the size of the data fork
* as returned by GetFileSize()
*
*/
readonly attribute int64_t fileSizeWithResFork;
/**
* fileType, creator
*
* File type and creator attributes
*
*/
[noscript] attribute OSType fileType;
[noscript] attribute OSType fileCreator;
/**
* launchWithDoc
*
* Launch the application that this file points to with a document.
*
* @param aDocToLoad Must not be NULL. If no document, use nsIFile::launch
* @param aLaunchInBackground TRUE if the application should not come to the front.
*
*/
void launchWithDoc(in nsIFile aDocToLoad, in boolean aLaunchInBackground);
/**
* openDocWithApp
*
* Open the document that this file points to with the given application.
*
* @param aAppToOpenWith The application with which to open the document.
* If NULL, the creator code of the document is used
* to determine the application.
* @param aLaunchInBackground TRUE if the application should not come to the front.
*
*/
void openDocWithApp(in nsIFile aAppToOpenWith, in boolean aLaunchInBackground);
/**
* isPackage
*
* returns true if a directory is determined to be a package under Mac OS 9/X
*
*/
boolean isPackage();
/**
* bundleDisplayName
*
* returns the display name of the application bundle (usually the human
* readable name of the application)
*/
readonly attribute AString bundleDisplayName;
/**
* bundleIdentifier
*
* returns the identifier of the bundle
*/
readonly attribute AUTF8String bundleIdentifier;
/**
* Last modified time of a bundle's contents (as opposed to its package
* directory). Our convention is to make the bundle's Info.plist file
* stand in for the rest of its contents -- since this file contains the
* bundle's version information and other identifiers. For non-bundles
* this is the same as lastModifiedTime.
*/
readonly attribute int64_t bundleContentsLastModifiedTime;
};
%{C++
extern "C"
{
NS_EXPORT nsresult NS_NewLocalFileWithFSRef(const FSRef* aFSRef, bool aFollowSymlinks, nsILocalFileMac** result);
NS_EXPORT nsresult NS_NewLocalFileWithCFURL(const CFURLRef aURL, bool aFollowSymlinks, nsILocalFileMac** result);
}
%}
+1 -35
View File
@@ -5,44 +5,10 @@
#include "xpcom-private.h"
//-----------------------------------------------------------------------------
// XP_MACOSX
//-----------------------------------------------------------------------------
#if defined(XP_MACOSX)
#include "nsAString.h"
#include "nsReadableUtils.h"
#include "nsString.h"
nsresult
NS_CopyNativeToUnicode(const nsACString& aInput, nsAString& aOutput)
{
CopyUTF8toUTF16(aInput, aOutput);
return NS_OK;
}
nsresult
NS_CopyUnicodeToNative(const nsAString& aInput, nsACString& aOutput)
{
CopyUTF16toUTF8(aInput, aOutput);
return NS_OK;
}
void
NS_StartupNativeCharsetUtils()
{
}
void
NS_ShutdownNativeCharsetUtils()
{
}
//-----------------------------------------------------------------------------
// XP_UNIX
//-----------------------------------------------------------------------------
#elif defined(XP_UNIX)
#if defined(XP_UNIX)
#include <stdlib.h> // mbtowc, wctomb
#include <locale.h> // setlocale
+4 -9
View File
@@ -33,22 +33,17 @@ nsresult NS_CopyUnicodeToNative(const nsAString& aInput, nsACString& aOutput);
* name in UTF-8 out of nsIFile, we can just use |GetNativeLeafName| rather
* than using |GetLeafName| and converting the result to UTF-8 if the file
* system encoding is UTF-8.
* On Unix (but not on Mac OS X), it depends on the locale and is not known
* in advance (at the compilation time) so that this function needs to be
* a real function. On Mac OS X it's always UTF-8 while on Windows
* and other platforms (e.g. OS2), it's never UTF-8.
* On Unix, it depends on the locale and is not known in advance (at the
* compilation time) so that this function needs to be a real function.
* On Windows and other platforms (e.g. OS2), it's never UTF-8.
*/
#if defined(XP_UNIX) && !defined(XP_MACOSX)
#if defined(XP_UNIX)
bool NS_IsNativeUTF8();
#else
inline bool
NS_IsNativeUTF8()
{
#if defined(XP_MACOSX)
return true;
#else
return false;
#endif
}
#endif
@@ -53,9 +53,7 @@ __asm__ (
is what xptcstubs uses. */
".align 2\n\t"
".globl " SYMBOL_UNDERSCORE "NS_InvokeByIndex\n\t"
#ifndef XP_MACOSX
".type " SYMBOL_UNDERSCORE "NS_InvokeByIndex,@function\n"
#endif
SYMBOL_UNDERSCORE "NS_InvokeByIndex:\n\t"
"pushl %ebp\n\t"
"movl %esp, %ebp\n\t"
@@ -91,7 +89,5 @@ __asm__ (
"movl %ebp, %esp\n\t"
"popl %ebp\n\t"
"ret\n"
#ifndef XP_MACOSX
".size " SYMBOL_UNDERSCORE "NS_InvokeByIndex, . -" SYMBOL_UNDERSCORE "NS_InvokeByIndex\n\t"
#endif
);
@@ -66,20 +66,11 @@ PrepareAndDispatch(uint32_t methodIndex, nsXPTCStubBase* self, uint32_t* args)
}
} // extern "C"
#if !defined(XP_MACOSX)
#define STUB_HEADER(a, b) ".hidden " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase" #a "Stub" #b "Ev\n\t" \
".type " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase" #a "Stub" #b "Ev,@function\n"
#define STUB_SIZE(a, b) ".size " SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase" #a "Stub" #b "Ev,.-" SYMBOL_UNDERSCORE "_ZN14nsXPTCStubBase" #a "Stub" #b "Ev\n\t"
#else
#define STUB_HEADER(a, b)
#define STUB_SIZE(a, b)
#endif
// gcc3 mangling tends to insert the length of the method name
#define STUB_ENTRY(n) \
asm(".text\n\t" \
@@ -112,16 +103,12 @@ asm(".text\n\t" \
// static nsresult SharedStub(uint32_t methodIndex) __attribute__((regparm(1)))
asm(".text\n\t"
".align 2\n\t"
#if !defined(XP_MACOSX)
".type " SYMBOL_UNDERSCORE "SharedStub,@function\n\t"
#endif
SYMBOL_UNDERSCORE "SharedStub:\n\t"
"leal 0x08(%esp), %ecx\n\t"
"movl 0x04(%esp), %edx\n\t"
"jmp " SYMBOL_UNDERSCORE "PrepareAndDispatch\n\t"
#if !defined(XP_MACOSX)
".size " SYMBOL_UNDERSCORE "SharedStub,.-" SYMBOL_UNDERSCORE "SharedStub"
#endif
);
#define SENTINEL_ENTRY(n) \
+1 -1
View File
@@ -87,7 +87,7 @@ public:
// Use the system default in ASAN builds, because the default is assumed to be
// larger than the size we want to use and is hopefully sufficient for ASAN.
static const uint32_t kStackSize = nsIThreadManager::DEFAULT_STACK_SIZE;
#elif defined(XP_WIN) || defined(XP_MACOSX) || defined(LINUX)
#elif defined(XP_WIN) || defined(LINUX)
static const uint32_t kStackSize = (256 * 1024);
#else
// All other platforms use their system defaults.
+1 -23
View File
@@ -41,7 +41,7 @@
# pragma GCC diagnostic pop // -Wshadow
#endif
#if defined(XP_LINUX) || defined(XP_MACOSX)
#if defined(XP_LINUX)
#include <pthread.h>
#endif
@@ -97,8 +97,6 @@ ThreadStackHelper::ThreadStackHelper()
THREAD_SUSPEND_RESUME
, FALSE, 0);
MOZ_ASSERT(mInitialized);
#elif defined(XP_MACOSX)
mThreadID = mach_thread_self();
#endif
}
@@ -176,26 +174,6 @@ ThreadStackHelper::GetStack(Stack& aStack)
}
MOZ_ALWAYS_TRUE(::ResumeThread(mThreadID) != DWORD(-1));
#elif defined(XP_MACOSX)
# if defined(MOZ_VALGRIND) && defined(RUNNING_ON_VALGRIND)
if (RUNNING_ON_VALGRIND) {
/* thread_suspend and thread_resume sometimes hang runs on Valgrind,
for unknown reasons. So, just avoid them. See bug 1100911. */
return;
}
# endif
if (::thread_suspend(mThreadID) != KERN_SUCCESS) {
MOZ_ASSERT(false);
return;
}
FillStackBuffer();
FillThreadContext();
MOZ_ALWAYS_TRUE(::thread_resume(mThreadID) == KERN_SUCCESS);
#endif
}
-6
View File
@@ -18,8 +18,6 @@
#include <sys/types.h>
#elif defined(XP_WIN)
#include <windows.h>
#elif defined(XP_MACOSX)
#include <mach/mach.h>
#endif
namespace mozilla {
@@ -94,10 +92,6 @@ private:
bool mInitialized;
HANDLE mThreadID;
#elif defined(XP_MACOSX)
private:
thread_act_t mThreadID;
#endif
};
+1 -3
View File
@@ -19,9 +19,7 @@
#include "nsIWeakReferenceUtils.h"
#include "nsIObserver.h"
#include "nsString.h"
#ifndef XP_MACOSX
#include "prproces.h"
#endif
#if defined(PROCESSMODEL_WINAPI)
#include <windows.h>
#include <shellapi.h>
@@ -73,7 +71,7 @@ private:
int32_t mExitValue;
#if defined(PROCESSMODEL_WINAPI)
HANDLE mProcess;
#elif !defined(XP_MACOSX)
#else
PRProcess* mProcess;
#endif
};
-71
View File
@@ -33,31 +33,12 @@
#include "nsLiteralString.h"
#include "nsReadableUtils.h"
#else
#ifdef XP_MACOSX
#include <crt_externs.h>
#include <spawn.h>
#include <sys/wait.h>
#include <sys/errno.h>
#endif
#include <sys/types.h>
#include <signal.h>
#endif
using namespace mozilla;
#ifdef XP_MACOSX
cpu_type_t pref_cpu_types[2] = {
#if defined(__i386__)
CPU_TYPE_X86,
#elif defined(__x86_64__)
CPU_TYPE_X86_64,
#elif defined(__ppc__)
CPU_TYPE_POWERPC,
#endif
CPU_TYPE_ANY
};
#endif
//-------------------------------------------------------------------//
// nsIProcess implementation
//-------------------------------------------------------------------//
@@ -74,9 +55,7 @@ nsProcess::nsProcess()
, mObserver(nullptr)
, mWeakObserver(nullptr)
, mExitValue(-1)
#if !defined(XP_MACOSX)
, mProcess(nullptr)
#endif
{
}
@@ -261,34 +240,16 @@ nsProcess::Monitor(void* aArg)
return;
}
}
#else
#ifdef XP_MACOSX
int exitCode = -1;
int status = 0;
pid_t result;
do {
result = waitpid(process->mPid, &status, 0);
} while (result == -1 && errno == EINTR);
if (result == process->mPid) {
if (WIFEXITED(status)) {
exitCode = WEXITSTATUS(status);
} else if (WIFSIGNALED(status)) {
exitCode = 256; // match NSPR's signal exit status
}
}
#else
int32_t exitCode = -1;
if (PR_WaitProcess(process->mProcess, &exitCode) != PR_SUCCESS) {
exitCode = -1;
}
#endif
// Lock in case Kill or GetExitCode are called during this
{
MutexAutoLock lock(process->mLock);
#if !defined(XP_MACOSX)
process->mProcess = nullptr;
#endif
process->mExitValue = exitCode;
if (process->mShutdown) {
return;
@@ -499,34 +460,6 @@ nsProcess::RunProcess(bool aBlocking, char** aMyArgv, nsIObserver* aObserver,
}
mPid = GetProcessId(mProcess);
#elif defined(XP_MACOSX)
// Initialize spawn attributes.
posix_spawnattr_t spawnattr;
if (posix_spawnattr_init(&spawnattr) != 0) {
return NS_ERROR_FAILURE;
}
// Set spawn attributes.
size_t attr_count = ArrayLength(pref_cpu_types);
size_t attr_ocount = 0;
if (posix_spawnattr_setbinpref_np(&spawnattr, attr_count, pref_cpu_types,
&attr_ocount) != 0 ||
attr_ocount != attr_count) {
posix_spawnattr_destroy(&spawnattr);
return NS_ERROR_FAILURE;
}
// Note: |aMyArgv| is already null-terminated as required by posix_spawnp.
pid_t newPid = 0;
int result = posix_spawnp(&newPid, aMyArgv[0], nullptr, &spawnattr, aMyArgv,
*_NSGetEnviron());
mPid = static_cast<int32_t>(newPid);
posix_spawnattr_destroy(&spawnattr);
if (result != 0) {
return NS_ERROR_FAILURE;
}
#else
mProcess = PR_CreateProcess(aMyArgv[0], aMyArgv, nullptr, nullptr);
if (!mProcess) {
@@ -605,10 +538,6 @@ nsProcess::Kill()
if (TerminateProcess(mProcess, 0) == 0) {
return NS_ERROR_FAILURE;
}
#elif defined(XP_MACOSX)
if (kill(mPid, SIGKILL) != 0) {
return NS_ERROR_FAILURE;
}
#else
if (!mProcess || (PR_KillProcess(mProcess) != PR_SUCCESS)) {
return NS_ERROR_FAILURE;
-15
View File
@@ -52,11 +52,6 @@
#define HAVE_SCHED_SETAFFINITY
#endif
#ifdef XP_MACOSX
#include <mach/mach.h>
#include <mach/thread_policy.h>
#endif
#ifdef MOZ_CANARY
# include <unistd.h>
# include <execinfo.h>
@@ -375,16 +370,6 @@ SetThreadAffinity(unsigned int cpu)
sched_setaffinity(0, sizeof(cpus), &cpus);
// Don't assert sched_setaffinity's return value because it intermittently (?)
// fails with EINVAL on Linux x64 try runs.
#elif defined(XP_MACOSX)
// OS X does not provide APIs to pin threads to specific processors, but you
// can tag threads as belonging to the same "affinity set" and the OS will try
// to run them on the same processor. To run threads on different processors,
// tag them as belonging to different affinity sets. Tag 0, the default, means
// "no affinity" so let's pretend each CPU has its own tag `cpu+1`.
thread_affinity_policy_data_t policy;
policy.affinity_tag = cpu + 1;
MOZ_ALWAYS_TRUE(thread_policy_set(mach_thread_self(), THREAD_AFFINITY_POLICY,
&policy.affinity_tag, 1) == KERN_SUCCESS);
#elif defined(XP_WIN)
MOZ_ALWAYS_TRUE(SetThreadIdealProcessor(GetCurrentThread(), cpu) != -1);
#endif