зеркало из https://github.com/mozilla/pjs.git
Provide API in xpcom macutils for determining universal binary type. b=572125 r=benwa
This commit is contained in:
Родитель
5d2b2437ae
Коммит
fdcf53b706
|
@ -41,7 +41,7 @@
|
|||
* nsIMacUtils: Generic globally-available Mac-specific utilities.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(F6FC107C-5CBA-4C5C-A35E-B69D580D1DB6)]
|
||||
[scriptable, uuid(5E9072D7-FF95-455E-9466-8AF9841A72EC)]
|
||||
interface nsIMacUtils : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -50,6 +50,13 @@ interface nsIMacUtils : nsISupports
|
|||
*/
|
||||
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).
|
||||
*/
|
||||
|
|
|
@ -38,93 +38,110 @@
|
|||
#include "nsMacUtilsImpl.h"
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <mach-o/fat.h>
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsMacUtilsImpl, nsIMacUtils)
|
||||
|
||||
/* readonly attribute boolean isUniversalBinary; */
|
||||
// True when the main executable is a fat file supporting at least
|
||||
// ppc and x86 (universal binary).
|
||||
NS_IMETHODIMP nsMacUtilsImpl::GetIsUniversalBinary(PRBool *aIsUniversalBinary)
|
||||
nsresult nsMacUtilsImpl::GetArchString(nsAString& archString)
|
||||
{
|
||||
static PRBool sInitialized = PR_FALSE,
|
||||
sIsUniversalBinary = PR_FALSE;
|
||||
|
||||
if (sInitialized) {
|
||||
*aIsUniversalBinary = sIsUniversalBinary;
|
||||
if (!mBinaryArchs.IsEmpty()) {
|
||||
archString.Assign(mBinaryArchs);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
archString.Truncate();
|
||||
|
||||
PRBool foundPPC = PR_FALSE,
|
||||
foundX86 = PR_FALSE;
|
||||
CFURLRef executableURL = nsnull;
|
||||
int fd = -1;
|
||||
foundX86 = PR_FALSE,
|
||||
foundPPC64 = PR_FALSE,
|
||||
foundX86_64 = PR_FALSE;
|
||||
|
||||
CFBundleRef mainBundle;
|
||||
if (!(mainBundle = ::CFBundleGetMainBundle()))
|
||||
goto done;
|
||||
|
||||
if (!(executableURL = ::CFBundleCopyExecutableURL(mainBundle)))
|
||||
goto done;
|
||||
|
||||
char executablePath[PATH_MAX];
|
||||
if (!::CFURLGetFileSystemRepresentation(executableURL, PR_TRUE,
|
||||
(UInt8*) executablePath,
|
||||
sizeof(executablePath)))
|
||||
goto done;
|
||||
|
||||
if ((fd = open(executablePath, O_RDONLY)) == -1)
|
||||
goto done;
|
||||
|
||||
struct fat_header fatHeader;
|
||||
if (read(fd, &fatHeader, sizeof(fatHeader)) != sizeof(fatHeader))
|
||||
goto done;
|
||||
|
||||
// The fat header is always stored on disk as big-endian.
|
||||
fatHeader.magic = CFSwapInt32BigToHost(fatHeader.magic);
|
||||
fatHeader.nfat_arch = CFSwapInt32BigToHost(fatHeader.nfat_arch);
|
||||
|
||||
// Main executable is thin.
|
||||
if (fatHeader.magic != FAT_MAGIC)
|
||||
goto done;
|
||||
|
||||
// Loop over each architecture in the file. We're presently only
|
||||
// interested in 32-bit PPC and x86.
|
||||
for (PRUint32 i = 0 ; i < fatHeader.nfat_arch ; i++) {
|
||||
struct fat_arch fatArch;
|
||||
if (read(fd, &fatArch, sizeof(fatArch)) != sizeof(fatArch))
|
||||
goto done;
|
||||
|
||||
// This is still part of the fat header, so byte-swap as needed.
|
||||
fatArch.cputype = CFSwapInt32BigToHost(fatArch.cputype);
|
||||
|
||||
// Don't mask out the ABI bits. This allows identification of ppc64
|
||||
// as distinct from ppc. CPU_TYPE_X86 is preferred to CPU_TYPE_I386
|
||||
// but does not exist prior to the 10.4 headers.
|
||||
if (fatArch.cputype == CPU_TYPE_POWERPC)
|
||||
foundPPC = PR_TRUE;
|
||||
else if (fatArch.cputype == CPU_TYPE_I386)
|
||||
foundX86 = PR_TRUE;
|
||||
CFBundleRef mainBundle = ::CFBundleGetMainBundle();
|
||||
if (!mainBundle) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (foundPPC && foundX86)
|
||||
sIsUniversalBinary = PR_TRUE;
|
||||
CFArrayRef archList = ::CFBundleCopyExecutableArchitectures(mainBundle);
|
||||
if (!archList) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
done:
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
if (executableURL)
|
||||
::CFRelease(executableURL);
|
||||
CFIndex archCount = ::CFArrayGetCount(archList);
|
||||
for (CFIndex i = 0; i < archCount; i++) {
|
||||
CFNumberRef arch = static_cast<CFNumberRef>(::CFArrayGetValueAtIndex(archList, i));
|
||||
|
||||
*aIsUniversalBinary = sIsUniversalBinary;
|
||||
sInitialized = PR_TRUE;
|
||||
int archInt = 0;
|
||||
if (!::CFNumberGetValue(arch, kCFNumberIntType, &archInt)) {
|
||||
::CFRelease(archList);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (archInt == kCFBundleExecutableArchitecturePPC)
|
||||
foundPPC = PR_TRUE;
|
||||
else if (archInt == kCFBundleExecutableArchitectureI386)
|
||||
foundX86 = PR_TRUE;
|
||||
else if (archInt == kCFBundleExecutableArchitecturePPC64)
|
||||
foundPPC64 = PR_TRUE;
|
||||
else if (archInt == kCFBundleExecutableArchitectureX86_64)
|
||||
foundX86_64 = PR_TRUE;
|
||||
}
|
||||
|
||||
::CFRelease(archList);
|
||||
|
||||
// The order in the string must always be the same so
|
||||
// don't do this in the loop.
|
||||
if (foundPPC) {
|
||||
mBinaryArchs.Append(NS_LITERAL_STRING("ppc"));
|
||||
}
|
||||
|
||||
if (foundX86) {
|
||||
if (!mBinaryArchs.IsEmpty()) {
|
||||
mBinaryArchs.Append(NS_LITERAL_STRING("-"));
|
||||
}
|
||||
mBinaryArchs.Append(NS_LITERAL_STRING("i386"));
|
||||
}
|
||||
|
||||
if (foundPPC64) {
|
||||
if (!mBinaryArchs.IsEmpty()) {
|
||||
mBinaryArchs.Append(NS_LITERAL_STRING("-"));
|
||||
}
|
||||
mBinaryArchs.Append(NS_LITERAL_STRING("ppc64"));
|
||||
}
|
||||
|
||||
if (foundX86_64) {
|
||||
if (!mBinaryArchs.IsEmpty()) {
|
||||
mBinaryArchs.Append(NS_LITERAL_STRING("-"));
|
||||
}
|
||||
mBinaryArchs.Append(NS_LITERAL_STRING("x86_64"));
|
||||
}
|
||||
|
||||
archString.Assign(mBinaryArchs);
|
||||
|
||||
return (archString.IsEmpty() ? NS_ERROR_FAILURE : NS_OK);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMacUtilsImpl::GetIsUniversalBinary(PRBool *aIsUniversalBinary)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aIsUniversalBinary);
|
||||
*aIsUniversalBinary = PR_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& archString)
|
||||
{
|
||||
return GetArchString(archString);
|
||||
}
|
||||
|
||||
/* readonly attribute boolean isTranslated; */
|
||||
// True when running under binary translation (Rosetta).
|
||||
NS_IMETHODIMP nsMacUtilsImpl::GetIsTranslated(PRBool *aIsTranslated)
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#define nsMacUtilsImpl_h___
|
||||
|
||||
#include "nsIMacUtils.h"
|
||||
#include "nsString.h"
|
||||
|
||||
class nsMacUtilsImpl : public nsIMacUtils
|
||||
{
|
||||
|
@ -50,6 +51,12 @@ public:
|
|||
|
||||
private:
|
||||
~nsMacUtilsImpl() {}
|
||||
|
||||
nsresult GetArchString(nsAString& archString);
|
||||
|
||||
// A string containing a "-" delimited list of architectures
|
||||
// in our binary.
|
||||
nsString mBinaryArchs;
|
||||
};
|
||||
|
||||
// Global singleton service
|
||||
|
|
Загрузка…
Ссылка в новой задаче