diff options
author | Sven Gothel <[email protected]> | 2013-02-08 19:21:10 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-02-08 19:21:10 +0100 |
commit | 371e1dbff6f5f255ab27ed0ab32368abb06eed82 (patch) | |
tree | 06cdfc232298a9305d7aaaa501fd831726ab52f2 /src | |
parent | 60409268e1d43be26b656b191d6684037f943123 (diff) |
Bug 681: Use ELF Header + ARM EABI Section Parsing in PlatformPropsImpl to to distinguish ARM soft-float/hard-float (part-2)
+ /**
+ * Returns the {@link ABIType} of the current platform using given {@link CPUType cpuType}
+ * and {@link OSType osType} as a hint.
+ * <p>
+ * Note the following queries are performed:
+ * <ul>
+ * <li> not {@link CPUFamily#ARM} -> {@link ABIType#GENERIC_ABI} </li>
+ * <li> else
+ * <ul>
+ * <li> not {@link OSType#LINUX} -> {@link ABIType#EABI_GNU_ARMEL} </li>
+ * <li> else
+ * <ul>
+ * <li> Elf ARM Tags -> {@link ABIType#EABI_GNU_ARMEL}, {@link ABIType#EABI_GNU_ARMHF} </li>
+ * </ul></li>
+ * </ul></li>
+ * </ul>
+ * </p>
+ * <p>
+ * Elf ARM Tags are read using {@link ElfHeader}, .. and {@link SectionArmAttributes#abiVFPArgsAcceptsVFPVariant(byte)}.
+ * </p>
+ *
+ * @param cpuType
+ * @param osType
+ * @return
+ */
+ private static final ABIType queryABITypeImpl(CPUType cpuType, OSType osType) {
Diffstat (limited to 'src')
-rw-r--r-- | src/java/jogamp/common/os/PlatformPropsImpl.java | 91 | ||||
-rw-r--r-- | src/java/jogamp/common/os/elf/ElfHeader.java | 64 | ||||
-rw-r--r-- | src/junit/com/jogamp/common/os/TestElfReader01.java | 22 |
3 files changed, 135 insertions, 42 deletions
diff --git a/src/java/jogamp/common/os/PlatformPropsImpl.java b/src/java/jogamp/common/os/PlatformPropsImpl.java index 8a4f2b2..0c597cb 100644 --- a/src/java/jogamp/common/os/PlatformPropsImpl.java +++ b/src/java/jogamp/common/os/PlatformPropsImpl.java @@ -1,11 +1,18 @@ package jogamp.common.os; +import java.io.IOException; +import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.nio.ShortBuffer; import java.security.AccessController; import java.security.PrivilegedAction; +import jogamp.common.Debug; +import jogamp.common.os.elf.ElfHeader; +import jogamp.common.os.elf.SectionArmAttributes; +import jogamp.common.os.elf.SectionHeader; + import com.jogamp.common.nio.Buffers; import com.jogamp.common.os.AndroidVersion; import com.jogamp.common.os.Platform; @@ -26,6 +33,8 @@ import com.jogamp.common.util.VersionNumber; * </p> */ public abstract class PlatformPropsImpl { + static final boolean DEBUG = Debug.debug("Platform"); + // // static initialization order: // @@ -81,8 +90,8 @@ public abstract class PlatformPropsImpl { LITTLE_ENDIAN = queryIsLittleEndianImpl(); CPU_ARCH = getCPUTypeImpl(ARCH_lower); - ABI_TYPE = guessABITypeImpl(CPU_ARCH); OS_TYPE = getOSTypeImpl(); + ABI_TYPE = queryABITypeImpl(CPU_ARCH, OS_TYPE); os_and_arch = getOSAndArch(OS_TYPE, CPU_ARCH, ABI_TYPE); } @@ -155,6 +164,7 @@ public abstract class PlatformPropsImpl { } } + @SuppressWarnings("unused") private static final boolean contains(String data, String[] search) { if(null != data && null != search) { for(int i=0; i<search.length; i++) { @@ -166,19 +176,80 @@ public abstract class PlatformPropsImpl { return false; } - private static final ABIType guessABITypeImpl(CPUType cpuType) { - if(CPUFamily.ARM != cpuType.family) { + /** + * Returns the {@link ABIType} of the current platform using given {@link CPUType cpuType} + * and {@link OSType osType} as a hint. + * <p> + * Note the following queries are performed: + * <ul> + * <li> not {@link CPUFamily#ARM} -> {@link ABIType#GENERIC_ABI} </li> + * <li> else + * <ul> + * <li> not {@link OSType#LINUX} -> {@link ABIType#EABI_GNU_ARMEL} </li> + * <li> else + * <ul> + * <li> Elf ARM Tags -> {@link ABIType#EABI_GNU_ARMEL}, {@link ABIType#EABI_GNU_ARMHF} </li> + * </ul></li> + * </ul></li> + * </ul> + * </p> + * <p> + * Elf ARM Tags are read using {@link ElfHeader}, .. and {@link SectionArmAttributes#abiVFPArgsAcceptsVFPVariant(byte)}. + * </p> + * + * @param cpuType + * @param osType + * @return + */ + private static final ABIType queryABITypeImpl(CPUType cpuType, OSType osType) { + if( CPUFamily.ARM != cpuType.family ) { return ABIType.GENERIC_ABI; } + // TODO: GNU/Linux-Android and other OS + // Android: /proc/self/exe: open failed: EACCES (Permission denied) + // ( OSType.LINUX != osType && OSType.ANDROID != osType ) ) + if( OSType.LINUX != osType ) { + return ABIType.EABI_GNU_ARMEL; + } return AccessController.doPrivileged(new PrivilegedAction<ABIType>() { - private final String[] gnueabihf = new String[] { "gnueabihf", "armhf" }; - public ABIType run() { - if ( contains(System.getProperty("sun.boot.library.path"), gnueabihf) || - contains(System.getProperty("java.library.path"), gnueabihf) || - contains(System.getProperty("java.home"), gnueabihf) ) { - return ABIType.EABI_GNU_ARMHF; + private final String GNU_LINUX_SELF_EXE = "/proc/self/exe"; + public ABIType run() { + boolean abiVFPArgsAcceptsVFPVariant = false; + RandomAccessFile in = null; + try { + in = new RandomAccessFile(GNU_LINUX_SELF_EXE, "r"); + final ElfHeader eh = ElfHeader.read(in); + if(DEBUG) { + System.err.println("ELF: Got HDR "+GNU_LINUX_SELF_EXE+": "+eh); + } + 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()); + } + } + } catch(Throwable t) { + t.printStackTrace(); + } finally { + if(null != in) { + try { + in.close(); + } catch (IOException e) { } + } + } + final ABIType res = abiVFPArgsAcceptsVFPVariant ? ABIType.EABI_GNU_ARMHF : ABIType.EABI_GNU_ARMEL; + if(DEBUG) { + System.err.println("ELF: abiVFPArgsAcceptsVFPVariant : "+abiVFPArgsAcceptsVFPVariant+" -> "+res); } - return ABIType.EABI_GNU_ARMEL; + return res; } } ); } diff --git a/src/java/jogamp/common/os/elf/ElfHeader.java b/src/java/jogamp/common/os/elf/ElfHeader.java index 85bdcf0..3b82a69 100644 --- a/src/java/jogamp/common/os/elf/ElfHeader.java +++ b/src/java/jogamp/common/os/elf/ElfHeader.java @@ -34,6 +34,7 @@ import java.nio.ByteBuffer; import static jogamp.common.os.elf.IOUtils.readBytes; import static jogamp.common.os.elf.IOUtils.seek; import static jogamp.common.os.elf.IOUtils.shortToInt; +import static jogamp.common.os.elf.IOUtils.toHexString; /** * ELF ABI Header @@ -370,6 +371,8 @@ public class ElfHeader { /** Public access to the {@link SectionHeader} */ public final SectionHeader[] sht; + private final String string; + /** * Note: The input stream shall stay untouch to be able to read sections! * @@ -397,6 +400,7 @@ public class ElfHeader { throw new IllegalArgumentException("Buffer is not an ELF Header"); } sht = readSectionHeaderTable(in); + string = toStringImpl(); } public final short getSize() { return d.getE_ehsize(); } @@ -415,29 +419,34 @@ public class ElfHeader { } /** - * Returns the processor's data encoding, - * 1 for {@link #ELFDATA2LSB}, 2 for for {@link #ELFDATA2MSB} - * and 0 for for {@link #ELFDATANONE} + * Returns the processor's data encoding, i.e. + * {@link #ELFDATA2LSB}, {@link #ELFDATA2MSB} or {@link #ELFDATANONE}; */ - public final int getDataEncodingMode() { - switch( d.getE_ident()[EI_DATA] ) { - case ELFDATA2LSB: return 1; - case ELFDATA2MSB: return 2; - default: return 0; - } + public final byte getDataEncodingMode() { + return d.getE_ident()[EI_DATA]; + } + + /** Returns the ELF file version, should be {@link #EV_CURRENT}. */ + public final byte getVersion() { + return d.getE_ident()[EI_VERSION]; } - /** 3 == Linux */ + /** Returns the operating system and ABI for this file, 3 == Linux. Note: Often not used. */ public final byte getOSABI() { return d.getE_ident()[EI_OSABI]; } + + /** Returns the version of the {@link #getOSABI() OSABI} for this file. */ + public final byte getOSABIVersion() { + return d.getE_ident()[EI_ABIVERSION]; + } - /** Returns the object file type */ + /** Returns the object file type, e.g. {@link #ET_EXEC}, .. */ public final short getType() { return d.getE_type(); } - /** Returns the required architecture for the file */ + /** Returns the required architecture for the file, e.g. {@link #EM_386}, .. */ public final short getMachine() { return d.getE_machine(); } @@ -518,6 +527,37 @@ public class ElfHeader { return null; } + public final String toString() { + return string; + } + + private final String toStringImpl() { + final String machineS; + if( isArm() ) { + machineS=", arm"; + } else if( isIntel() ) { + machineS=", intel"; + } else { + machineS=""; + } + final int enc = getDataEncodingMode(); + final String encS; + switch(enc) { + case 1: encS = "LSB"; break; + case 2: encS = "MSB"; break; + default: encS = "NON"; break; + } + final int armABI = getArmABI(); + final String armFlagsS; + if( 0 != armABI ) { + armFlagsS=", arm[abi "+armABI+", lGCC "+getArmLegacyGCCFlags()+", float "+getArmFloatMode()+"]"; + } else { + armFlagsS=""; + } + return "ElfHeader[vers "+getVersion()+", machine["+getMachine()+machineS+"], bits "+getArchClassBits()+", enc "+encS+ + ", abi[os "+getOSABI()+", vers "+getOSABIVersion()+"], flags["+toHexString(getFlags())+armFlagsS+"], type "+getType()+", sh-num "+sht.length+"]"; + } + final SectionHeader[] readSectionHeaderTable(RandomAccessFile in) throws IOException, IllegalArgumentException { // positioning { diff --git a/src/junit/com/jogamp/common/os/TestElfReader01.java b/src/junit/com/jogamp/common/os/TestElfReader01.java index fe6adc2..c04f2ac 100644 --- a/src/junit/com/jogamp/common/os/TestElfReader01.java +++ b/src/junit/com/jogamp/common/os/TestElfReader01.java @@ -39,27 +39,9 @@ public class TestElfReader01 extends JunitTracer { void testElfHeaderImpl(String file, boolean fileOutSections) throws IOException { RandomAccessFile in = new RandomAccessFile(file, "r"); try { - ElfHeader eh = ElfHeader.read(in); - byte[] e_ident = eh.d.getE_ident(); + final ElfHeader eh = ElfHeader.read(in); int i=0; - System.err.print("[0..4]: 0x"+toHexString(e_ident[i++])); - System.err.print(", 0x"+toHexString(e_ident[i++])); - System.err.print(", 0x"+toHexString(e_ident[i++])); - System.err.println(", 0x"+toHexString(e_ident[i++])); - System.err.println("e_class "+e_ident[ElfHeader.EI_CLASS]+", "+eh.getArchClassBits()+" bits"); - System.err.println("e_data "+e_ident[ElfHeader.EI_DATA]+", "+eh.getDataEncodingMode()); - System.err.println("e_flags "+toHexString(eh.getFlags())); - System.err.println(" ARM ABI "+eh.getArmABI()); - System.err.println(" ARM lGCC "+eh.getArmLegacyGCCFlags()); - System.err.println(" ARM FLOAT "+eh.getArmFloatMode()+", is hard-float "+(2 == eh.getArmFloatMode())); - System.err.println("e_version "+e_ident[ElfHeader.EI_VERSION]); - System.err.println("e_osabi "+eh.getOSABI()+", Linux "+ElfHeader.ELFOSABI_LINUX); - System.err.println("e_abiversion "+e_ident[ElfHeader.EI_ABIVERSION]); - System.err.println("e_machine "+eh.getMachine()+", isARM "+eh.isArm()+", isIntel "+eh.isIntel()); - System.err.println("e_version "+eh.d.getE_version()); - System.err.println("e_type "+eh.getType()); - System.err.println("EH Size "+eh.d.getE_ehsize()); - System.err.println("SH num "+eh.d.getE_shnum()); + System.err.println(eh); System.err.println("SH entsz "+eh.d.getE_shentsize()); System.err.println("SH off "+toHexString(eh.d.getE_shoff())); System.err.println("SH strndx "+eh.d.getE_shstrndx()); |