diff options
Diffstat (limited to 'src/java/jogamp/common/os/PlatformPropsImpl.java')
-rw-r--r-- | src/java/jogamp/common/os/PlatformPropsImpl.java | 405 |
1 files changed, 205 insertions, 200 deletions
diff --git a/src/java/jogamp/common/os/PlatformPropsImpl.java b/src/java/jogamp/common/os/PlatformPropsImpl.java index b12ab6f..b35533f 100644 --- a/src/java/jogamp/common/os/PlatformPropsImpl.java +++ b/src/java/jogamp/common/os/PlatformPropsImpl.java @@ -11,9 +11,9 @@ import java.security.PrivilegedAction; import java.util.List; import jogamp.common.Debug; -import jogamp.common.os.elf.ElfHeader; +import jogamp.common.os.elf.ElfHeaderPart1; +import jogamp.common.os.elf.ElfHeaderPart2; import jogamp.common.os.elf.SectionArmAttributes; -import jogamp.common.os.elf.SectionHeader; import com.jogamp.common.nio.Buffers; import com.jogamp.common.os.AndroidVersion; @@ -48,6 +48,13 @@ public abstract class PlatformPropsImpl { public static final VersionNumber Mavericks = new VersionNumber(10,9,0); } + /** + * Returns {@code true} if the given {@link CPUType}s and {@link ABIType}s are compatible. + */ + public static final boolean isCompatible(final CPUType cpu1, final ABIType abi1, final CPUType cpu2, final ABIType abi2) { + return cpu1.isCompatible(cpu2) && abi1.isCompatible(abi2); + } + // // static initialization order: // @@ -72,14 +79,20 @@ public abstract class PlatformPropsImpl { public static final String JAVA_RUNTIME_NAME; /** True if having {@link java.nio.LongBuffer} and {@link java.nio.DoubleBuffer} available. */ public static final boolean JAVA_SE; - /** True if being compatible w/ language level 6, e.g. JRE 1.6. Implies {@link #JAVA_SE}. <i>Note</i>: We claim Android is compatible. */ + /** + * True only if being compatible w/ language level 6, e.g. JRE 1.6. + * <p> + * Implies {@link #isJavaSE()}. + * </p> + * <p> + * <i>Note</i>: We claim Android is compatible. + * </p> + */ public static final boolean JAVA_6; public static final String NEWLINE; public static final boolean LITTLE_ENDIAN; - /* pp */ static final CPUType sCpuType; - public static final CPUType CPU_ARCH; public static final ABIType ABI_TYPE; public static final OSType OS_TYPE; @@ -126,111 +139,191 @@ public abstract class PlatformPropsImpl { OS_VERSION_NUMBER = new VersionNumber(OS_VERSION); OS_TYPE = getOSTypeImpl(OS_lower, isAndroid); - LITTLE_ENDIAN = queryIsLittleEndianImpl(); - - // Soft values, i.e. w/o probing binaries - final String sARCH = System.getProperty("os.arch"); - final String sARCH_lower = sARCH.toLowerCase(); - sCpuType = getCPUTypeImpl(sARCH_lower); - if( DEBUG ) { - System.err.println("Platform.Soft: sARCH "+sARCH+", sCpuType "+sCpuType); - if( isAndroid ) { - System.err.println("Android: CPU_ABI1 str "+AndroidVersion.CPU_ABI+", CPU_TYPE "+AndroidVersion.CPU_TYPE+", ABI_TYPE "+AndroidVersion.ABI_TYPE); - System.err.println("Android: CPU_ABI2 str "+AndroidVersion.CPU_ABI2+", CPU_TYPE2 "+AndroidVersion.CPU_TYPE2+", ABI_TYPE2 "+AndroidVersion.ABI_TYPE2); - } - } - // Hard values, i.e. w/ probing binaries // // FIXME / HACK: - // We use sCPUType for MachineDescriptionRuntime.getStatic() + // We use preCpuType for MachineDescriptionRuntime.getStatic() // until we have determined the final CPU_TYPE, etc. // MachineDescriptionRuntime gets notified via MachineDescriptionRuntime.notifyPropsInitialized() below. // // We could use Elf Ehdr's machine value to determine the bit-size // used for it's offset table! // However, 'os.arch' should be a good guess for this task. + final String elfCpuName; final CPUType elfCpuType; - final ABIType elfAbiType; + final ABIType elfABIType; + final int elfLittleEndian; final boolean elfValid; { - final CPUType[] _ehCpuType = { null }; - final ABIType[] _ehAbiType = { null }; - final ElfHeader eh = queryABITypeImpl(OS_TYPE, _ehCpuType, _ehAbiType); - if( null != eh && null != _ehCpuType[0] && null != _ehAbiType[0] ) { - elfCpuType = _ehCpuType[0]; - elfAbiType = _ehAbiType[0]; - if( isAndroid ) { - final CPUFamily aCpuFamily1 = null != AndroidVersion.CPU_TYPE ? AndroidVersion.CPU_TYPE.family : null; - final CPUFamily aCpuFamily2 = null != AndroidVersion.CPU_TYPE2 ? AndroidVersion.CPU_TYPE2.family : null; - if( elfCpuType.family != aCpuFamily1 && elfCpuType.family != aCpuFamily2 ) { - // Ooops ! - elfValid = false; - } else { - elfValid = true; - } - } else { - if( elfCpuType.family != sCpuType.family ) { - // Ooops ! - elfValid = false; - } else { - elfValid = true; + final String[] _elfCpuName = { null }; + final CPUType[] _elfCpuType = { null }; + final ABIType[] _elfAbiType = { null }; + final int[] _elfLittleEndian = { 0 }; // 1 - little, 2 - big + final boolean[] _elfValid = { false }; + AccessController.doPrivileged(new PrivilegedAction<Object>() { + @Override + public Object run() { + RandomAccessFile in = null; + try { + final File file = queryElfFile(OS_TYPE); + if(DEBUG) { + System.err.println("ELF-1: Using "+file); + } + in = new RandomAccessFile(file, "r"); + final ElfHeaderPart1 eh1 = readElfHeaderPart1(OS_TYPE, in); + if(DEBUG) { + System.err.println("ELF-1: Got "+eh1); + } + if( null != eh1 ) { + final ElfHeaderPart2 eh2 = readElfHeaderPart2(eh1, in); + if(DEBUG) { + System.err.println("ELF-2: Got "+eh2); + } + if( null != eh2 ) { + _elfCpuName[0] = eh2.cpuName; + _elfCpuType[0] = eh2.cpuType; + _elfAbiType[0] = eh2.abiType; + if( eh1.isLittleEndian() ) { + _elfLittleEndian[0] = 1; + } else if( eh1.isBigEndian() ) { + _elfLittleEndian[0] = 2; + } + _elfValid[0] = true; + } + } + } catch (final Throwable t) { + if(DEBUG) { + t.printStackTrace(); + } + } finally { + if(null != in) { + try { + in.close(); + } catch (final IOException e) { } + } } - } - if( DEBUG ) { - System.err.println("Platform.Elf: cpuType "+elfCpuType+", abiType "+elfAbiType+", valid "+elfValid); - } - } else { - elfCpuType = null; - elfAbiType = null; - elfValid = false; - if( DEBUG ) { - System.err.println("Platform.Elf: n/a"); - } + return null; + } }); + elfCpuName = _elfCpuName[0]; + elfCpuType = _elfCpuType[0]; + elfABIType = _elfAbiType[0]; + elfLittleEndian = _elfLittleEndian[0]; + elfValid = _elfValid[0]; + if( DEBUG ) { + System.err.println("Platform.Elf: valid "+elfValid+", elfCpuName "+elfCpuName+", cpuType "+elfCpuType+", abiType "+elfABIType+", elfLittleEndian "+elfLittleEndian); + } + } + + // Determine endianess, favor ELF value + final boolean littleEndian = queryIsLittleEndianImpl(); + if( elfValid ) { + switch( elfLittleEndian ) { + case 1: + LITTLE_ENDIAN = true; + break; + case 2: + LITTLE_ENDIAN = false; + break; + default: + LITTLE_ENDIAN = littleEndian; + break; } + } else { + LITTLE_ENDIAN = littleEndian; + } + if( DEBUG ) { + System.err.println("Platform.Endian: test-little "+littleEndian+", elf[valid "+elfValid+", val "+elfLittleEndian+"] -> LITTLE_ENDIAN "+LITTLE_ENDIAN); } + + // Property values for comparison + // We might take the property values even if ELF values are available, + // since the latter only reflect the CPU/ABI version of the binary files! + final String propARCH = System.getProperty("os.arch"); + final String propARCH_lower = propARCH.toLowerCase(); + final CPUType propCpuType = CPUType.query(propARCH_lower); + final ABIType propABIType = ABIType.query(propCpuType, propARCH_lower); + if( DEBUG ) { + System.err.println("Platform.Property: ARCH "+propARCH+", CpuType "+propCpuType+", ABIType "+propABIType); + } + + final int strategy; if( isAndroid ) { + if( DEBUG ) { + System.err.println("Android: CPU_ABI1 str "+AndroidVersion.CPU_ABI+", CPU_TYPE "+AndroidVersion.CPU_TYPE+", ABI_TYPE "+AndroidVersion.ABI_TYPE); + System.err.println("Android: CPU_ABI2 str "+AndroidVersion.CPU_ABI2+", CPU_TYPE2 "+AndroidVersion.CPU_TYPE2+", ABI_TYPE2 "+AndroidVersion.ABI_TYPE2); + } if( elfValid ) { - if( elfCpuType.family == AndroidVersion.CPU_TYPE.family && - elfAbiType == AndroidVersion.ABI_TYPE ) + if( null != AndroidVersion.CPU_TYPE && + isCompatible(elfCpuType, elfABIType, AndroidVersion.CPU_TYPE, AndroidVersion.ABI_TYPE) ) { + // ELF matches Android-1 ARCH = AndroidVersion.CPU_ABI; + ARCH_lower = ARCH; CPU_ARCH = AndroidVersion.CPU_TYPE; - } else { + strategy = 110; + } else if( null != AndroidVersion.CPU_TYPE2 && + isCompatible(elfCpuType, elfABIType, AndroidVersion.CPU_TYPE2, AndroidVersion.ABI_TYPE2) ) + { + // ELF matches Android-2 ARCH = AndroidVersion.CPU_ABI2; + ARCH_lower = ARCH; CPU_ARCH = AndroidVersion.CPU_TYPE2; + strategy = 111; + } else { + // We assume our ELF data beats AndroidVersion info (correctness) + ARCH = elfCpuType.toString(); + ARCH_lower = ARCH.toLowerCase(); + CPU_ARCH = elfCpuType; + strategy = 112; } - ABI_TYPE = elfAbiType; + ABI_TYPE = elfABIType; } else { - // default - if( AndroidVersion.CPU_TYPE.family == CPUFamily.ARM || null == AndroidVersion.CPU_TYPE2 ) { + if( AndroidVersion.CPU_TYPE.family == CPUFamily.ARM || + null == AndroidVersion.CPU_TYPE2 ) { + // Favor Android-1: Either b/c ARM Family, or no Android-2 ARCH = AndroidVersion.CPU_ABI; + ARCH_lower = ARCH; CPU_ARCH = AndroidVersion.CPU_TYPE; ABI_TYPE = AndroidVersion.ABI_TYPE; + strategy = 120; } else { + // Last resort Android-2 ARCH = AndroidVersion.CPU_ABI2; + ARCH_lower = ARCH; CPU_ARCH = AndroidVersion.CPU_TYPE2; ABI_TYPE = AndroidVersion.ABI_TYPE2; + strategy = 121; } } - ARCH_lower = ARCH; } else { - ARCH = sARCH; - ARCH_lower = sARCH_lower; - if( elfValid && CPUFamily.ARM == elfCpuType.family ) { - // Use Elf for ARM - CPU_ARCH = elfCpuType; - ABI_TYPE = elfAbiType; + if( elfValid ) { + if( isCompatible(elfCpuType, elfABIType, propCpuType, propABIType) ) { + // Use property ARCH, compatible w/ ELF + ARCH = propARCH; + ARCH_lower = propARCH_lower; + CPU_ARCH = propCpuType; + ABI_TYPE = propABIType; + strategy = 210; + } else { + // use ELF ARCH + ARCH = elfCpuName; + ARCH_lower = elfCpuName; + CPU_ARCH = elfCpuType; + ABI_TYPE = elfABIType; + strategy = 211; + } } else { - // Otherwise trust detailed os.arch (?) - CPU_ARCH = sCpuType; - ABI_TYPE = ABIType.GENERIC_ABI; + // Last resort: properties + ARCH = propARCH; + ARCH_lower = propARCH_lower; + CPU_ARCH = propCpuType; + ABI_TYPE = propABIType; + strategy = 220; } } if( DEBUG ) { - System.err.println("Platform.Hard: ARCH "+ARCH+", CPU_ARCH "+CPU_ARCH+", ABI_TYPE "+ABI_TYPE+" - isAndroid "+isAndroid+", elfValid "+elfValid); + System.err.println("Platform.Hard: ARCH "+ARCH+", CPU_ARCH "+CPU_ARCH+", ABI_TYPE "+ABI_TYPE+" - strategy "+strategy+"(isAndroid "+isAndroid+", elfValid "+elfValid+")"); } - MachineDescriptionRuntime.notifyPropsInitialized(); os_and_arch = getOSAndArch(OS_TYPE, CPU_ARCH, ABI_TYPE); } @@ -271,49 +364,6 @@ public abstract class PlatformPropsImpl { return 0x0C0D == tst_s.get(0); } - private static final CPUType getCPUTypeImpl(final String archLower) { - if( archLower.equals("x86") || // jvm + android - archLower.equals("i386") || - archLower.equals("i486") || - archLower.equals("i586") || - archLower.equals("i686") ) { - return CPUType.X86_32; - } else if( archLower.equals("x86_64") || - archLower.equals("amd64") ) { - return CPUType.X86_64; - } else if( archLower.equals("ia64") ) { - return CPUType.IA64; - } else if( archLower.equals("arm") ) { - return CPUType.ARM; - } else if( archLower.equals("armv5l") ) { - return CPUType.ARMv5; - } else if( archLower.equals("armv6l") ) { - return CPUType.ARMv6; - } else if( archLower.equals("armv7l") || - archLower.equals("armeabi") || // android - archLower.equals("armeabi-v7a") ) { // android - return CPUType.ARMv7; - } else if( archLower.equals("aarch64") || - archLower.equals("arm64") ) { - return CPUType.ARM64; - } else if( archLower.equals("armv8-a") || - archLower.equals("arm64-v8a") ) { - return CPUType.ARMv8_A; - } else if( archLower.equals("sparc") ) { - return CPUType.SPARC_32; - } else if( archLower.equals("sparcv9") ) { - return CPUType.SPARCV9_64; - } else if( archLower.equals("pa_risc2.0") ) { - return CPUType.PA_RISC2_0; - } else if( archLower.equals("ppc") ) { - return CPUType.PPC; - } else if( archLower.equals("mips") ) { // android - return CPUType.MIPS_32; - } else { - throw new RuntimeException("Please port CPU detection to your platform (" + OS_lower + "/" + archLower + ")"); - } - } - @SuppressWarnings("unused") private static final boolean contains(final String data, final String[] search) { if(null != data && null != search) { @@ -341,101 +391,53 @@ public abstract class PlatformPropsImpl { * Elf ARM Tags are read using {@link ElfHeader}, .. and {@link SectionArmAttributes#abiVFPArgsAcceptsVFPVariant(byte)}. * </p> */ - private static final ElfHeader queryABITypeImpl(final OSType osType, final CPUType[] cpuType, final ABIType[] abiType) { - return AccessController.doPrivileged(new PrivilegedAction<ElfHeader>() { - @Override - public ElfHeader run() { - ElfHeader res = null; - try { - File file = null; - if( OSType.ANDROID == osType ) { - file = new File(NativeLibrary.findLibrary("gluegen-rt", PlatformPropsImpl.class.getClassLoader())); - } else { - if( OSType.LINUX == osType ) { - file = new File("/proc/self/exe"); - if( !checkFileReadAccess(file) ) { - file = null; - } - } - if( null == file ) { - file = findSysLib("java"); - } - if( null == file ) { - file = findSysLib("jvm"); - } - } - if( null != file ) { - res = queryABITypeImpl(file, cpuType, abiType); - } - } catch(final Throwable t) { - if(DEBUG) { - t.printStackTrace(); - } - } - return res; - } } ); - } - private static final ElfHeader queryABITypeImpl(final File file, final CPUType[] cpuType, final ABIType[] abiType) { - ElfHeader res = null; - RandomAccessFile in = null; + private static final File queryElfFile(final OSType osType) { + File file = null; try { - in = new RandomAccessFile(file, "r"); - final ElfHeader eh = ElfHeader.read(in); - if(DEBUG) { - System.err.println("ELF: Got HDR "+file+": "+eh); - } - if( eh.isArm() ) { - boolean abiVFPArgsAcceptsVFPVariant = false; - final SectionHeader sh = eh.getSectionHeader(SectionHeader.SHT_ARM_ATTRIBUTES); - if( null != sh ) { - if(DEBUG) { - System.err.println("ELF: Got ARM Attribs Section Header: "+sh); - } - final SectionArmAttributes sArmAttrs = (SectionArmAttributes) sh.readSection(in); - if(DEBUG) { - System.err.println("ELF: Got ARM Attribs Section Block : "+sArmAttrs); - } - final SectionArmAttributes.Attribute abiVFPArgsAttr = sArmAttrs.get(SectionArmAttributes.Tag.ABI_VFP_args); - if( null != abiVFPArgsAttr ) { - abiVFPArgsAcceptsVFPVariant = SectionArmAttributes.abiVFPArgsAcceptsVFPVariant(abiVFPArgsAttr.getULEB128()); + if( OSType.ANDROID == osType ) { + file = new File(NativeLibrary.findLibrary("gluegen-rt", PlatformPropsImpl.class.getClassLoader())); + } else { + if( OSType.LINUX == osType ) { + file = new File("/proc/self/exe"); + if( !checkFileReadAccess(file) ) { + file = null; } } - cpuType[0] = CPUType.ARM; // lowest 32bit denominator, ok for us - abiType[0] = abiVFPArgsAcceptsVFPVariant ? ABIType.EABI_GNU_ARMHF : ABIType.EABI_GNU_ARMEL; - if(DEBUG) { - System.err.println("ELF: abiARM, abiVFPArgsAcceptsVFPVariant "+abiVFPArgsAcceptsVFPVariant); + if( null == file ) { + file = findSysLib("java"); + } + if( null == file ) { + file = findSysLib("jvm"); } - } else if ( eh.isAARCH64() ) { - cpuType[0] = CPUType.ARM64; - abiType[0] = ABIType.EABI_AARCH64; - } else if ( eh.isX86_64() ) { - cpuType[0] = CPUType.X86_64; - abiType[0] = ABIType.GENERIC_ABI; - } else if ( eh.isX86_32() ) { - cpuType[0] = CPUType.X86_32; - abiType[0] = ABIType.GENERIC_ABI; - } else if ( eh.isIA64() ) { - cpuType[0] = CPUType.IA64; - abiType[0] = ABIType.GENERIC_ABI; - } else if ( eh.isMips() ) { - cpuType[0] = CPUType.MIPS_32; // FIXME - abiType[0] = ABIType.GENERIC_ABI; } - res = eh; } catch(final Throwable t) { if(DEBUG) { - System.err.println("Caught: "+t.getMessage()); t.printStackTrace(); } - } finally { - if(null != in) { - try { - in.close(); - } catch (final IOException e) { } + } + return file; + } + private static final ElfHeaderPart1 readElfHeaderPart1(final OSType osType, final RandomAccessFile in) { + ElfHeaderPart1 res = null; + try { + res = ElfHeaderPart1.read(osType, in); + } catch(final Throwable t) { + if(DEBUG) { + System.err.println("Caught: "+t.getMessage()); + t.printStackTrace(); } } - if(DEBUG) { - System.err.println("ELF: res "+res+", cpuType "+cpuType[0]+", abiType "+abiType[0]); + return res; + } + private static final ElfHeaderPart2 readElfHeaderPart2(final ElfHeaderPart1 eh1, final RandomAccessFile in) { + ElfHeaderPart2 res = null; + try { + res = ElfHeaderPart2.read(eh1, in); + } catch(final Throwable t) { + if(DEBUG) { + System.err.println("Caught: "+t.getMessage()); + t.printStackTrace(); + } } return res; } @@ -551,6 +553,9 @@ public abstract class PlatformPropsImpl { case SPARC_32: _and_arch_tmp = "sparc"; break; + case PPC64: + _and_arch_tmp = "ppc64"; // TODO: sync with gluegen-cpptasks-base.xml + break; case PPC: _and_arch_tmp = "ppc"; // TODO: sync with gluegen-cpptasks-base.xml break; @@ -567,7 +572,7 @@ public abstract class PlatformPropsImpl { _and_arch_tmp = "risc2.0"; // TODO: sync with gluegen-cpptasks-base.xml break; default: - throw new InternalError("Complete case block"); + throw new InternalError("Unhandled CPUType: "+cpuType); } switch( osType ) { @@ -604,7 +609,7 @@ public abstract class PlatformPropsImpl { _and_arch_final = "hppa"; // TODO: really only hppa ? break; default: - throw new InternalError("Complete case block"); + throw new InternalError("Unhandled OSType: "+osType); } return os_ + "-" + _and_arch_final; } |