summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2013-02-08 19:21:10 +0100
committerSven Gothel <[email protected]>2013-02-08 19:21:10 +0100
commit371e1dbff6f5f255ab27ed0ab32368abb06eed82 (patch)
tree06cdfc232298a9305d7aaaa501fd831726ab52f2 /src
parent60409268e1d43be26b656b191d6684037f943123 (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.java91
-rw-r--r--src/java/jogamp/common/os/elf/ElfHeader.java64
-rw-r--r--src/junit/com/jogamp/common/os/TestElfReader01.java22
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());