From d6af6fa80cac3227bdeee851efb40b6611b26b2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Bl=C3=A4sing?= Date: Mon, 21 May 2018 22:03:19 +0200 Subject: [PATCH 1/3] Fix values for SHT_LOUSER and SHT_HIUSER --- .../java/nl/lxtreme/binutils/elf/SectionType.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/nl/lxtreme/binutils/elf/SectionType.java b/src/main/java/nl/lxtreme/binutils/elf/SectionType.java index 7e00153..a6aaa88 100644 --- a/src/main/java/nl/lxtreme/binutils/elf/SectionType.java +++ b/src/main/java/nl/lxtreme/binutils/elf/SectionType.java @@ -43,12 +43,12 @@ public class SectionType { REL, SHLIB, DYNSYM, INIT_ARRAY, FINI_ARRAY, PREINIT_ARRAY, GROUP, SYMTAB_SHNDX, GNU_ATTRIBUTES, GNU_HASH, GNU_LIBLIST, CHECKSUM, SUNW_MOVE, SUNW_COMDAT, SUNW_SYMINFO, GNU_VERDEF, GNU_VERNEED, GNU_VERSYM }; - private static final int SHT_LOOS = 0x60000000; - private static final int SHT_HIOS = 0x6fffffff; - private static final int SHT_LOPROC = 0x70000000; - private static final int SHT_HIPROC = 0x7fffffff; - private static final int SHT_LOUSER = 0x70000000; - private static final int SHT_HIUSER = 0x7fffffff; + private static final long SHT_LOOS = 0x60000000L; + private static final long SHT_HIOS = 0x6fffffffL; + private static final long SHT_LOPROC = 0x70000000L; + private static final long SHT_HIPROC = 0x7fffffffL; + private static final long SHT_LOUSER = 0x80000000L; + private static final long SHT_HIUSER = 0xffffffffL; public static SectionType valueOf(int value) { for (SectionType st : VALUES) { From b9ec405ce50265511c03f2ae8d5cbde86947a9c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Bl=C3=A4sing?= Date: Mon, 21 May 2018 22:13:02 +0200 Subject: [PATCH 2/3] Add section types for ARM Architecture --- src/main/java/nl/lxtreme/binutils/elf/SectionType.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/nl/lxtreme/binutils/elf/SectionType.java b/src/main/java/nl/lxtreme/binutils/elf/SectionType.java index a6aaa88..df19be4 100644 --- a/src/main/java/nl/lxtreme/binutils/elf/SectionType.java +++ b/src/main/java/nl/lxtreme/binutils/elf/SectionType.java @@ -38,6 +38,11 @@ public class SectionType { public static final SectionType GNU_VERDEF = new SectionType(0x6ffffffd, "GNU version definition section"); public static final SectionType GNU_VERNEED = new SectionType(0x6ffffffe, "GNU version needs section"); public static final SectionType GNU_VERSYM = new SectionType(0x6fffffff, "GNU version symbol table"); + public static final SectionType SHT_ARM_EXIDX = new SectionType(0x70000001, "Exception Index table"); + public static final SectionType SHT_ARM_PREEMPTMAP = new SectionType(0x70000002, "BPABI DLL dynamic linking pre-emption map"); + public static final SectionType SHT_ARM_ATTRIBUTES = new SectionType(0x70000003, "Object file compatibility attributes"); + public static final SectionType SHT_ARM_DEBUGOVERLAY = new SectionType(0x70000004, "DBGOVL 1"); + public static final SectionType SHT_ARM_OVERLAYSECTION = new SectionType(0x70000005, "DBGOVL 2"); private static final SectionType[] VALUES = { NULL, PROGBITS, SYMTAB, STRTAB, RELA, HASH, DYNAMIC, NOTE, NOBITS, REL, SHLIB, DYNSYM, INIT_ARRAY, FINI_ARRAY, PREINIT_ARRAY, GROUP, SYMTAB_SHNDX, GNU_ATTRIBUTES, GNU_HASH, From 2d2584c8cb949707d2e1af26579524777e1a4e63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Bl=C3=A4sing?= Date: Sat, 26 May 2018 21:02:09 +0200 Subject: [PATCH 3/3] Add ARM Build Attribute Parser Implemented is a parser for the ELF Section, that holds the ARM build attributes (name: .ARM.attributes). The vendor sections can be accessed by vendor name. For the public attributes (pseudo vendor: "aeabi") a parser for the file wide attributes was implemented. Section and Symbol attribuges are ignored. --- .../binutils/elf/ArmAeabiAttributesTag.java | 163 +++++++++++++++++ .../lxtreme/binutils/elf/ArmAttributes.java | 61 +++++++ .../binutils/elf/ArmAttributesTag.java | 164 ++++++++++++++++++ .../binutils/elf/ArmEabiAttributes.java | 48 +++++ .../binutils/elf/ArmParameterType.java | 80 +++++++++ .../binutils/elf/ArmAttributesTest.java | 53 ++++++ 6 files changed, 569 insertions(+) create mode 100644 src/main/java/nl/lxtreme/binutils/elf/ArmAeabiAttributesTag.java create mode 100644 src/main/java/nl/lxtreme/binutils/elf/ArmAttributes.java create mode 100644 src/main/java/nl/lxtreme/binutils/elf/ArmAttributesTag.java create mode 100644 src/main/java/nl/lxtreme/binutils/elf/ArmEabiAttributes.java create mode 100644 src/main/java/nl/lxtreme/binutils/elf/ArmParameterType.java create mode 100644 src/test/java/nl/lxtreme/binutils/elf/ArmAttributesTest.java diff --git a/src/main/java/nl/lxtreme/binutils/elf/ArmAeabiAttributesTag.java b/src/main/java/nl/lxtreme/binutils/elf/ArmAeabiAttributesTag.java new file mode 100644 index 0000000..8bcdd0f --- /dev/null +++ b/src/main/java/nl/lxtreme/binutils/elf/ArmAeabiAttributesTag.java @@ -0,0 +1,163 @@ +/* + * BinUtils - access various binary formats from Java + * + * (C) Copyright 2018 - Matthias Bläsing - mblaesing@doppel-helix.eu + * + * Licensed under Apache License v2. + */ +package nl.lxtreme.binutils.elf; + +import java.math.BigInteger; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +public class ArmAeabiAttributesTag { + + private final int value; + private final String name; + private final ArmParameterType parameterType; + + public ArmAeabiAttributesTag(int value, String name, ArmParameterType parameterType) { + this.value = value; + this.name = name; + this.parameterType = parameterType; + } + + public int getValue() { + return value; + } + + public String getName() { + return name; + } + + public ArmParameterType getParameterType() { + return parameterType; + } + + @Override + public String toString() { + return name + " (" + value + ")"; + } + + @Override + public int hashCode() { + int hash = 7; + hash = 67 * hash + this.value; + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final ArmAeabiAttributesTag other = (ArmAeabiAttributesTag) obj; + if (this.value != other.value) { + return false; + } + return true; + } + + private static final List tags = new LinkedList(); + private static final Map valueMap = new HashMap(); + private static final Map nameMap = new HashMap(); + + // Enumerated from ARM IHI 0045E, 2.5 Attributes summary and history + public static final ArmAeabiAttributesTag File = addTag(1, "File", ArmParameterType.UINT32); + public static final ArmAeabiAttributesTag Section = addTag(2, "Section", ArmParameterType.UINT32); + public static final ArmAeabiAttributesTag Symbol = addTag(3, "Symbol", ArmParameterType.UINT32); + public static final ArmAeabiAttributesTag CPU_raw_name = addTag(4, "CPU_raw_name", ArmParameterType.NTBS); + public static final ArmAeabiAttributesTag CPU_name = addTag(5, "CPU_name", ArmParameterType.NTBS); + public static final ArmAeabiAttributesTag CPU_arch = addTag(6, "CPU_arch", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag CPU_arch_profile = addTag(7, "CPU_arch_profile", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag ARM_ISA_use = addTag(8, "ARM_ISA_use", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag THUMB_ISA_use= addTag(9, "THUMB_ISA_use", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag FP_arch = addTag(10, "FP_arch", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag WMMX_arch = addTag(11, "WMMX_arch", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag Advanced_SIMD_arch = addTag(12, "Advanced_SIMD_arch", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag PCS_config = addTag(13, "PCS_config", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag ABI_PCS_R9_use = addTag(14, "ABI_PCS_R9_use", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag ABI_PCS_RW_data = addTag(15, "ABI_PCS_RW_data", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag ABI_PCS_RO_data = addTag(16, "ABI_PCS_RO_data", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag ABI_PCS_GOT_use = addTag(17, "ABI_PCS_GOT_use", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag ABI_PCS_wchar_t = addTag(18, "ABI_PCS_wchar_t", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag ABI_FP_rounding = addTag(19, "ABI_FP_rounding", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag ABI_FP_denormal = addTag(20, "ABI_FP_denormal", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag ABI_FP_exceptions = addTag(21, "ABI_FP_exceptions", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag ABI_FP_user_exceptions = addTag(22, "ABI_FP_user_exceptions", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag ABI_FP_number_model = addTag(23, "ABI_FP_number_model", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag ABI_align_needed= addTag(24, "ABI_align_needed", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag ABI_align8_preserved = addTag(25, "ABI_align8_preserved", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag ABI_enum_size= addTag(26, "ABI_enum_size", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag ABI_HardFP_use = addTag(27, "ABI_HardFP_use", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag ABI_VFP_args = addTag(28, "ABI_VFP_args", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag ABI_WMMX_args = addTag(29, "ABI_WMMX_args", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag ABI_optimization_goals = addTag(30, "ABI_optimization_goals", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag ABI_FP_optimization_goals = addTag(31, "ABI_FP_optimization_goals", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag compatibility = addTag(32, "compatibility", ArmParameterType.NTBS); + public static final ArmAeabiAttributesTag CPU_unaligned_access = addTag(34, "CPU_unaligned_access", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag FP_HP_extension = addTag(36, "FP_HP_extension", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag ABI_FP_16bit_format = addTag(38, "ABI_FP_16bit_format", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag MPextension_use = addTag(42, "MPextension_use", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag DIV_use = addTag(44, "DIV_use", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag nodefaults = addTag(64, "nodefaults", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag also_compatible_with = addTag(65, "also_compatible_with", ArmParameterType.NTBS); + public static final ArmAeabiAttributesTag conformance = addTag(67, "conformance", ArmParameterType.NTBS); + public static final ArmAeabiAttributesTag T2EE_use = addTag(66, "T2EE_use", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag Virtualization_use = addTag(68, "Virtualization_use", ArmParameterType.ULEB128); + public static final ArmAeabiAttributesTag MPextension_use2 = addTag(70, "MPextension_use", ArmParameterType.ULEB128); + + private static ArmAeabiAttributesTag addTag(int value, String name, ArmParameterType type) { + ArmAeabiAttributesTag tag = new ArmAeabiAttributesTag(value, name, type); + + if (!valueMap.containsKey(tag.getValue())) { + valueMap.put(tag.getValue(), tag); + } + if (!nameMap.containsKey(tag.getName())) { + nameMap.put(tag.getName(), tag); + } + tags.add(tag); + return tag; + } + + public static List getTags() { + return Collections.unmodifiableList(tags); + } + + public static ArmAeabiAttributesTag getByName(String name) { + return nameMap.get(name); + } + + public static ArmAeabiAttributesTag getByValue(int value) { + if(valueMap.containsKey(value)) { + return valueMap.get(value); + } else { + ArmAeabiAttributesTag pseudoTag = new ArmAeabiAttributesTag(value, "Unknown " + value, getParameterType(value)); + return pseudoTag; + } + } + + private static ArmParameterType getParameterType(int value) { + // ARM IHI 0045E, 2.2.6 Coding extensibility and compatibility + ArmAeabiAttributesTag tag = getByValue(value); + if (tag == null) { + if ((value % 2) == 0) { + return ArmParameterType.ULEB128; + } else { + return ArmParameterType.NTBS; + } + } else { + return tag.getParameterType(); + } + } +} diff --git a/src/main/java/nl/lxtreme/binutils/elf/ArmAttributes.java b/src/main/java/nl/lxtreme/binutils/elf/ArmAttributes.java new file mode 100644 index 0000000..5186ec6 --- /dev/null +++ b/src/main/java/nl/lxtreme/binutils/elf/ArmAttributes.java @@ -0,0 +1,61 @@ +/* + * BinUtils - access various binary formats from Java + * + * (C) Copyright 2018 - Matthias Bläsing - mblaesing@doppel-helix.eu + * + * Licensed under Apache License v2. + */ +package nl.lxtreme.binutils.elf; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; + +class ArmAttributes { + /** + * Name of pseudo vendor for ARM Eabi attributes + */ + public static final String AEABI = "aeabi"; + private Map attributeBuffers = new HashMap<>(); + + public ArmAttributes(ByteBuffer bb) throws IOException + { + byte format = bb.get(); + if (format != 0x41) + { + // Version A + // Not supported + throw new IOException(String.format("Unrecognized format: %02x", format)); + } + + Map>> result = new HashMap<>(); + while (bb.position() < bb.limit()) { + int posSectionStart = bb.position(); + int sectionLength = bb.getInt(); + if (sectionLength <= 0) { + // Fail! + break; + } + + String vendorName = ArmParameterType.NTBS.readFromByteBuffer(bb); + + ByteBuffer sectionData = bb.slice(); + sectionData.order(bb.order()); + sectionData.limit(sectionLength - (bb.position() - posSectionStart)); + + attributeBuffers.put(vendorName, sectionData); + + bb.position(posSectionStart + sectionLength); + } + } + + public boolean hasVendorName(String name) { + return attributeBuffers.containsKey(name); + } + + public ByteBuffer getByVendorName(String name) { + return attributeBuffers.get(name); + } + +} diff --git a/src/main/java/nl/lxtreme/binutils/elf/ArmAttributesTag.java b/src/main/java/nl/lxtreme/binutils/elf/ArmAttributesTag.java new file mode 100644 index 0000000..9f0bb4f --- /dev/null +++ b/src/main/java/nl/lxtreme/binutils/elf/ArmAttributesTag.java @@ -0,0 +1,164 @@ +/* + * BinUtils - access various binary formats from Java + * + * (C) Copyright 2018 - Matthias Bläsing - mblaesing@doppel-helix.eu + * + * Licensed under Apache License v2. + */ +package nl.lxtreme.binutils.elf; + +import java.math.BigInteger; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + + +class ArmAttributesTag { + + private final int value; + private final String name; + private final ArmParameterType parameterType; + + public ArmAttributesTag(int value, String name, ArmParameterType parameterType) { + this.value = value; + this.name = name; + this.parameterType = parameterType; + } + + public int getValue() { + return value; + } + + public String getName() { + return name; + } + + public ArmParameterType getParameterType() { + return parameterType; + } + + @Override + public String toString() { + return name + " (" + value + ")"; + } + + @Override + public int hashCode() { + int hash = 7; + hash = 67 * hash + this.value; + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final ArmAttributesTag other = (ArmAttributesTag) obj; + if (this.value != other.value) { + return false; + } + return true; + } + + private static final List tags = new LinkedList(); + private static final Map valueMap = new HashMap(); + private static final Map nameMap = new HashMap(); + + // Enumerated from ARM IHI 0045E, 2.5 Attributes summary and history + public static final ArmAttributesTag File = addTag(1, "File", ArmParameterType.UINT32); + public static final ArmAttributesTag Section = addTag(2, "Section", ArmParameterType.UINT32); + public static final ArmAttributesTag Symbol = addTag(3, "Symbol", ArmParameterType.UINT32); + public static final ArmAttributesTag CPU_raw_name = addTag(4, "CPU_raw_name", ArmParameterType.NTBS); + public static final ArmAttributesTag CPU_name = addTag(5, "CPU_name", ArmParameterType.NTBS); + public static final ArmAttributesTag CPU_arch = addTag(6, "CPU_arch", ArmParameterType.ULEB128); + public static final ArmAttributesTag CPU_arch_profile = addTag(7, "CPU_arch_profile", ArmParameterType.ULEB128); + public static final ArmAttributesTag ARM_ISA_use = addTag(8, "ARM_ISA_use", ArmParameterType.ULEB128); + public static final ArmAttributesTag THUMB_ISA_use= addTag(9, "THUMB_ISA_use", ArmParameterType.ULEB128); + public static final ArmAttributesTag FP_arch = addTag(10, "FP_arch", ArmParameterType.ULEB128); + public static final ArmAttributesTag WMMX_arch = addTag(11, "WMMX_arch", ArmParameterType.ULEB128); + public static final ArmAttributesTag Advanced_SIMD_arch = addTag(12, "Advanced_SIMD_arch", ArmParameterType.ULEB128); + public static final ArmAttributesTag PCS_config = addTag(13, "PCS_config", ArmParameterType.ULEB128); + public static final ArmAttributesTag ABI_PCS_R9_use = addTag(14, "ABI_PCS_R9_use", ArmParameterType.ULEB128); + public static final ArmAttributesTag ABI_PCS_RW_data = addTag(15, "ABI_PCS_RW_data", ArmParameterType.ULEB128); + public static final ArmAttributesTag ABI_PCS_RO_data = addTag(16, "ABI_PCS_RO_data", ArmParameterType.ULEB128); + public static final ArmAttributesTag ABI_PCS_GOT_use = addTag(17, "ABI_PCS_GOT_use", ArmParameterType.ULEB128); + public static final ArmAttributesTag ABI_PCS_wchar_t = addTag(18, "ABI_PCS_wchar_t", ArmParameterType.ULEB128); + public static final ArmAttributesTag ABI_FP_rounding = addTag(19, "ABI_FP_rounding", ArmParameterType.ULEB128); + public static final ArmAttributesTag ABI_FP_denormal = addTag(20, "ABI_FP_denormal", ArmParameterType.ULEB128); + public static final ArmAttributesTag ABI_FP_exceptions = addTag(21, "ABI_FP_exceptions", ArmParameterType.ULEB128); + public static final ArmAttributesTag ABI_FP_user_exceptions = addTag(22, "ABI_FP_user_exceptions", ArmParameterType.ULEB128); + public static final ArmAttributesTag ABI_FP_number_model = addTag(23, "ABI_FP_number_model", ArmParameterType.ULEB128); + public static final ArmAttributesTag ABI_align_needed= addTag(24, "ABI_align_needed", ArmParameterType.ULEB128); + public static final ArmAttributesTag ABI_align8_preserved = addTag(25, "ABI_align8_preserved", ArmParameterType.ULEB128); + public static final ArmAttributesTag ABI_enum_size= addTag(26, "ABI_enum_size", ArmParameterType.ULEB128); + public static final ArmAttributesTag ABI_HardFP_use = addTag(27, "ABI_HardFP_use", ArmParameterType.ULEB128); + public static final ArmAttributesTag ABI_VFP_args = addTag(28, "ABI_VFP_args", ArmParameterType.ULEB128); + public static final ArmAttributesTag ABI_WMMX_args = addTag(29, "ABI_WMMX_args", ArmParameterType.ULEB128); + public static final ArmAttributesTag ABI_optimization_goals = addTag(30, "ABI_optimization_goals", ArmParameterType.ULEB128); + public static final ArmAttributesTag ABI_FP_optimization_goals = addTag(31, "ABI_FP_optimization_goals", ArmParameterType.ULEB128); + public static final ArmAttributesTag compatibility = addTag(32, "compatibility", ArmParameterType.NTBS); + public static final ArmAttributesTag CPU_unaligned_access = addTag(34, "CPU_unaligned_access", ArmParameterType.ULEB128); + public static final ArmAttributesTag FP_HP_extension = addTag(36, "FP_HP_extension", ArmParameterType.ULEB128); + public static final ArmAttributesTag ABI_FP_16bit_format = addTag(38, "ABI_FP_16bit_format", ArmParameterType.ULEB128); + public static final ArmAttributesTag MPextension_use = addTag(42, "MPextension_use", ArmParameterType.ULEB128); + public static final ArmAttributesTag DIV_use = addTag(44, "DIV_use", ArmParameterType.ULEB128); + public static final ArmAttributesTag nodefaults = addTag(64, "nodefaults", ArmParameterType.ULEB128); + public static final ArmAttributesTag also_compatible_with = addTag(65, "also_compatible_with", ArmParameterType.NTBS); + public static final ArmAttributesTag conformance = addTag(67, "conformance", ArmParameterType.NTBS); + public static final ArmAttributesTag T2EE_use = addTag(66, "T2EE_use", ArmParameterType.ULEB128); + public static final ArmAttributesTag Virtualization_use = addTag(68, "Virtualization_use", ArmParameterType.ULEB128); + public static final ArmAttributesTag MPextension_use2 = addTag(70, "MPextension_use", ArmParameterType.ULEB128); + + private static ArmAttributesTag addTag(int value, String name, ArmParameterType type) { + ArmAttributesTag tag = new ArmAttributesTag(value, name, type); + + if (!valueMap.containsKey(tag.getValue())) { + valueMap.put(tag.getValue(), tag); + } + if (!nameMap.containsKey(tag.getName())) { + nameMap.put(tag.getName(), tag); + } + tags.add(tag); + return tag; + } + + public static List getTags() { + return Collections.unmodifiableList(tags); + } + + public static ArmAttributesTag getByName(String name) { + return nameMap.get(name); + } + + public static ArmAttributesTag getByValue(int value) { + if(valueMap.containsKey(value)) { + return valueMap.get(value); + } else { + ArmAttributesTag pseudoTag = new ArmAttributesTag(value, "Unknown " + value, getParameterType(value)); + return pseudoTag; + } + } + + private static ArmParameterType getParameterType(int value) { + // ARM IHI 0045E, 2.2.6 Coding extensibility and compatibility + ArmAttributesTag tag = getByValue(value); + if (tag == null) { + if ((value % 2) == 0) { + return ArmParameterType.ULEB128; + } else { + return ArmParameterType.NTBS; + } + } else { + return tag.getParameterType(); + } + } +} diff --git a/src/main/java/nl/lxtreme/binutils/elf/ArmEabiAttributes.java b/src/main/java/nl/lxtreme/binutils/elf/ArmEabiAttributes.java new file mode 100644 index 0000000..3f298ef --- /dev/null +++ b/src/main/java/nl/lxtreme/binutils/elf/ArmEabiAttributes.java @@ -0,0 +1,48 @@ +/* + * BinUtils - access various binary formats from Java + * + * (C) Copyright 2018 - Matthias Bläsing - mblaesing@doppel-helix.eu + * + * Licensed under Apache License v2. + */ +package nl.lxtreme.binutils.elf; + +import java.nio.ByteBuffer; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class ArmEabiAttributes +{ + private Map fileAttributes = Collections.EMPTY_MAP; + + public ArmEabiAttributes(ByteBuffer buffer) { + while (buffer.position() < buffer.limit()) { + int pos = buffer.position(); + int subsectionTag = ArmParameterType.ULEB128.readFromByteBuffer(buffer).intValue(); + int length = buffer.getInt(); + if (subsectionTag == ArmAeabiAttributesTag.File.getValue()) { + fileAttributes = parseFileAttribute(buffer); + } + buffer.position(pos + length); + } + } + + public Map getFileAttributes() { + return fileAttributes; + } + + public T getFileAttribute(ArmAeabiAttributesTag tag) { + return (T) fileAttributes.get(tag); + } + + private static Map parseFileAttribute(ByteBuffer bb) { + Map result = new HashMap<>(); + while (bb.position() < bb.limit()) { + int tagValue = ArmParameterType.ULEB128.readFromByteBuffer(bb).intValue(); + ArmAeabiAttributesTag tag = ArmAeabiAttributesTag.getByValue(tagValue); + result.put(tag, tag.getParameterType().readFromByteBuffer(bb)); + } + return result; + } +} diff --git a/src/main/java/nl/lxtreme/binutils/elf/ArmParameterType.java b/src/main/java/nl/lxtreme/binutils/elf/ArmParameterType.java new file mode 100644 index 0000000..56ac802 --- /dev/null +++ b/src/main/java/nl/lxtreme/binutils/elf/ArmParameterType.java @@ -0,0 +1,80 @@ +/* + * BinUtils - access various binary formats from Java + * + * (C) Copyright 2018 - Matthias Bläsing - mblaesing@doppel-helix.eu + * + * Licensed under Apache License v2. + */ +package nl.lxtreme.binutils.elf; + +import java.io.UnsupportedEncodingException; +import java.math.BigInteger; +import java.nio.ByteBuffer; + +public abstract class ArmParameterType +{ + + public static final ArmParameterType UINT32 = new ArmParameterType(Integer.class) + { + @Override + public Integer readFromByteBuffer(ByteBuffer bb) + { + return bb.getInt(); + } + }; + public static final ArmParameterType NTBS = new ArmParameterType(String.class) + { + @Override + public String readFromByteBuffer(ByteBuffer bb) + { + int startingPos = bb.position(); + byte currentByte; + do + { + currentByte = bb.get(); + } while (currentByte != '\0' && bb.position() <= bb.limit()); + int terminatingPosition = bb.position(); + byte[] data = new byte[terminatingPosition - startingPos - 1]; + bb.position(startingPos); + bb.get(data); + bb.position(bb.position() + 1); + try + { + return new String(data, "ASCII"); + } catch (UnsupportedEncodingException ex) + { + throw new RuntimeException(ex); + } + } + }; + public static final ArmParameterType ULEB128 = new ArmParameterType(BigInteger.class) + { + @Override + public BigInteger readFromByteBuffer(ByteBuffer bb) + { + BigInteger result = BigInteger.ZERO; + int shift = 0; + while (true) + { + byte b = bb.get(); + result = result.or(BigInteger.valueOf(b & 127).shiftLeft(shift)); + if ((b & 128) == 0) + { + break; + } + shift += 7; + } + return result; + } + }; + + private final Class javaRepresentation; + + public ArmParameterType(Class javaRepresentation) + { + this.javaRepresentation = javaRepresentation; + } + + public abstract T readFromByteBuffer(ByteBuffer bb); + +} diff --git a/src/test/java/nl/lxtreme/binutils/elf/ArmAttributesTest.java b/src/test/java/nl/lxtreme/binutils/elf/ArmAttributesTest.java new file mode 100644 index 0000000..aaf482d --- /dev/null +++ b/src/test/java/nl/lxtreme/binutils/elf/ArmAttributesTest.java @@ -0,0 +1,53 @@ +/* + * BinUtils - access various binary formats from Java + * + * (C) Copyright 2018 - Matthias Bläsing - mblaesing@doppel-helix.eu + * + * Licensed under Apache License v2. + */ +package nl.lxtreme.binutils.elf; + +import java.io.File; +import java.net.URL; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; +import org.junit.Test; + +public class ArmAttributesTest +{ + + @Test + public void testReadingBuildFlags() throws Exception + { + Elf elf = new Elf(getResource("ts_print")); + for (SectionHeader sh : elf.sectionHeaders) + { + if (".ARM.attributes".equals(sh.getName())) + { + ArmAttributes armAttributes = new ArmAttributes(elf.getSection(sh)); + if (armAttributes.hasVendorName(ArmAttributes.AEABI)) + { + ArmEabiAttributes eabi = new ArmEabiAttributes(armAttributes.getByVendorName(ArmAttributes.AEABI)); + assertEquals(0x04, eabi.getFileAttribute(ArmAeabiAttributesTag.CPU_arch).intValue()); + assertEquals(0x01, eabi.getFileAttribute(ArmAeabiAttributesTag.ARM_ISA_use).intValue()); + } + } + } + } + + /** + * @param aName + * @return + * @throws URISyntaxException + */ + private File getResource(String aName) throws Exception + { + URL url = getClass().getClassLoader().getResource(aName); + if ((url != null) && "file".equals(url.getProtocol())) + { + return new File(url.getPath()).getCanonicalFile(); + } + fail("Resource " + aName + " not found!"); + return null; // to keep compiler happy... + } +}