Created
March 22, 2023 15:06
-
-
Save alexanderankin/143f49820d12d3e76397fcbfd722bc8b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import lombok.*; | |
| import lombok.experimental.Accessors; | |
| import java.nio.ByteBuffer; | |
| import java.nio.file.Files; | |
| import java.nio.file.Path; | |
| import java.util.Arrays; | |
| import java.util.Map; | |
| import java.util.function.Function; | |
| import java.util.stream.Collectors; | |
| public class ElfReader { | |
| @SneakyThrows | |
| public static void main(String[] args) { | |
| ByteBuffer byteBuffer = ByteBuffer.wrap(Files.readAllBytes(Path.of("/usr/bin/cat"))); | |
| ElfHeader elfHeader = new ElfReader() | |
| .parseHeader(byteBuffer); | |
| // System.out.println(elfHeader); | |
| System.out.println(elfHeader.toReport()); | |
| } | |
| static byte[] copy(ByteBuffer byteBuffer) { | |
| if (!byteBuffer.hasArray()) { | |
| int position = byteBuffer.position(); | |
| byteBuffer.position(0); | |
| byte[] copy = new byte[byteBuffer.remaining()]; | |
| byteBuffer.get(copy); | |
| byteBuffer.position(position); | |
| return copy; | |
| } | |
| return Arrays.copyOfRange(byteBuffer.array(), | |
| byteBuffer.arrayOffset(), | |
| byteBuffer.limit()); | |
| } | |
| ElfHeader parseHeader(ByteBuffer byteBuffer) { | |
| ByteBuffer eIdent = byteBuffer.slice(0, 16); | |
| ElfIdent elfIdent = new ElfIdent().setValue(eIdent); | |
| if (elfIdent.eiClass() == null) throw new UnsupportedOperationException("unknown value"); | |
| ElfHeaderBody body = switch (elfIdent.eiClass()) { | |
| case CLASS64 -> new ElfHeaderBody64().setByteBuffer(byteBuffer.slice(16, 36)); | |
| case CLASS32 -> new ElfHeaderBody32().setByteBuffer(byteBuffer.slice(16, 36)); | |
| case NONE -> throw new UnsupportedOperationException("not sure how to handle"); | |
| }; | |
| // ElfHeaderBody64 body1 = (ElfHeaderBody64) body; | |
| // ByteBuffer.wrap(copy(body1.byteBuffer)).order(ByteOrder.LITTLE_ENDIAN).getShort(2); | |
| // short i = body1.byteBuffer.getShort(4); | |
| // ElfMachine elfMachine = ElfMachine.valueOf(i); | |
| // System.out.println(elfMachine); | |
| return new ElfHeader() | |
| .setElfIdent(elfIdent) | |
| .setElfHeaderBody(body) | |
| ; | |
| } | |
| /** | |
| * This member identifies the object file type. | |
| */ | |
| @AllArgsConstructor | |
| @ToString | |
| @Getter | |
| enum ElfType { | |
| //<editor-fold desc="members"> | |
| /** | |
| * No file type | |
| */ | |
| ET_NONE(0), | |
| /** | |
| * Relocatable file | |
| */ | |
| ET_REL(1), | |
| /** | |
| * Executable file | |
| */ | |
| ET_EXEC(2), | |
| /** | |
| * Shared object file | |
| */ | |
| ET_DYN(3), | |
| /** | |
| * Core file | |
| */ | |
| ET_CORE(4), | |
| /** | |
| * Operating system-specific | |
| */ | |
| ET_LOOS(0xfe00), | |
| /** | |
| * Operating system-specific | |
| */ | |
| ET_HIOS(0xfeff), | |
| /** | |
| * Processor-specific | |
| */ | |
| ET_LOPROC(0xff00), | |
| /** | |
| * Processor-specific | |
| */ | |
| ET_HIPROC(0xffff), | |
| //</editor-fold> | |
| ; | |
| private static final Map<Integer, ElfType> byCode = | |
| Arrays.stream(values()) | |
| .collect(Collectors.toMap(ElfType::getCode, | |
| Function.identity())); | |
| private final int code; | |
| public static ElfType valueOf(int code) { | |
| return byCode.get(code); | |
| } | |
| } | |
| /** | |
| * This member's value specifies the required architecture for an individual file. | |
| */ | |
| @AllArgsConstructor | |
| @ToString | |
| @Getter | |
| enum ElfMachine { | |
| //<editor-fold desc="members"> | |
| /** | |
| * No machine | |
| */ | |
| EM_NONE(0), | |
| /** | |
| * AT&T WE 32100 | |
| */ | |
| EM_M32(1), | |
| /** | |
| * SPARC | |
| */ | |
| EM_SPARC(2), | |
| /** | |
| * Intel 80386 | |
| */ | |
| EM_386(3), | |
| /** | |
| * Motorola 68000 | |
| */ | |
| EM_68K(4), | |
| /** | |
| * Motorola 88000 | |
| */ | |
| EM_88K(5), | |
| /** | |
| * Intel 80860 | |
| */ | |
| EM_860(7), | |
| /** | |
| * MIPS I Architecture | |
| */ | |
| EM_MIPS(8), | |
| /** | |
| * IBM System/370 Processor | |
| */ | |
| EM_S370(9), | |
| /** | |
| * MIPS RS3000 Little-endian | |
| */ | |
| EM_MIPS_RS3_LE(10), | |
| /** | |
| * Hewlett-Packard PA-RISC | |
| */ | |
| EM_PARISC(15), | |
| /** | |
| * Fujitsu VPP500 | |
| */ | |
| EM_VPP500(17), | |
| /** | |
| * Enhanced instruction set SPARC | |
| */ | |
| EM_SPARC32PLUS(18), | |
| /** | |
| * Intel 80960 | |
| */ | |
| EM_960(19), | |
| /** | |
| * PowerPC | |
| */ | |
| EM_PPC(20), | |
| /** | |
| * 64-bit PowerPC | |
| */ | |
| EM_PPC64(21), | |
| /** | |
| * IBM System/390 Processor | |
| */ | |
| EM_S390(22), | |
| /** | |
| * NEC V800 | |
| */ | |
| EM_V800(36), | |
| /** | |
| * Fujitsu FR20 | |
| */ | |
| EM_FR20(37), | |
| /** | |
| * TRW RH-32 | |
| */ | |
| EM_RH32(38), | |
| /** | |
| * Motorola RCE | |
| */ | |
| EM_RCE(39), | |
| /** | |
| * Advanced RISC Machines ARM | |
| */ | |
| EM_ARM(40), | |
| /** | |
| * Digital Alpha | |
| */ | |
| EM_ALPHA(41), | |
| /** | |
| * Hitachi SH | |
| */ | |
| EM_SH(42), | |
| /** | |
| * SPARC Version 9 | |
| */ | |
| EM_SPARCV9(43), | |
| /** | |
| * Siemens TriCore embedded processor | |
| */ | |
| EM_TRICORE(44), | |
| /** | |
| * Argonaut RISC Core, Argonaut Technologies Inc. | |
| */ | |
| EM_ARC(45), | |
| /** | |
| * Hitachi H8/300 | |
| */ | |
| EM_H8_300(46), | |
| /** | |
| * Hitachi H8/300H | |
| */ | |
| EM_H8_300H(47), | |
| /** | |
| * Hitachi H8S | |
| */ | |
| EM_H8S(48), | |
| /** | |
| * Hitachi H8/500 | |
| */ | |
| EM_H8_500(49), | |
| /** | |
| * Intel IA-64 processor architecture | |
| */ | |
| EM_IA_64(50), | |
| /** | |
| * Stanford MIPS-X | |
| */ | |
| EM_MIPS_X(51), | |
| /** | |
| * Motorola ColdFire | |
| */ | |
| EM_COLDFIRE(52), | |
| /** | |
| * Motorola M68HC12 | |
| */ | |
| EM_68HC12(53), | |
| /** | |
| * Fujitsu MMA Multimedia Accelerator | |
| */ | |
| EM_MMA(54), | |
| /** | |
| * Siemens PCP | |
| */ | |
| EM_PCP(55), | |
| /** | |
| * Sony nCPU embedded RISC processor | |
| */ | |
| EM_NCPU(56), | |
| /** | |
| * Denso NDR1 microprocessor | |
| */ | |
| EM_NDR1(57), | |
| /** | |
| * Motorola Star*Core processor | |
| */ | |
| EM_STARCORE(58), | |
| /** | |
| * Toyota ME16 processor | |
| */ | |
| EM_ME16(59), | |
| /** | |
| * STMicroelectronics ST100 processor | |
| */ | |
| EM_ST100(60), | |
| /** | |
| * Advanced Logic Corp. TinyJ embedded processor family | |
| */ | |
| EM_TINYJ(61), | |
| /** | |
| * AMD x86-64 architecture | |
| */ | |
| EM_X86_64(62), | |
| /** | |
| * Sony DSP Processor | |
| */ | |
| EM_PDSP(63), | |
| /** | |
| * Digital Equipment Corp. PDP-10 | |
| */ | |
| EM_PDP10(64), | |
| /** | |
| * Digital Equipment Corp. PDP-11 | |
| */ | |
| EM_PDP11(65), | |
| /** | |
| * Siemens FX66 microcontroller | |
| */ | |
| EM_FX66(66), | |
| /** | |
| * STMicroelectronics ST9+ 8/16 bit microcontroller | |
| */ | |
| EM_ST9PLUS(67), | |
| /** | |
| * STMicroelectronics ST7 8-bit microcontroller | |
| */ | |
| EM_ST7(68), | |
| /** | |
| * Motorola MC68HC16 Microcontroller | |
| */ | |
| EM_68HC16(69), | |
| /** | |
| * Motorola MC68HC11 Microcontroller | |
| */ | |
| EM_68HC11(70), | |
| /** | |
| * Motorola MC68HC08 Microcontroller | |
| */ | |
| EM_68HC08(71), | |
| /** | |
| * Motorola MC68HC05 Microcontroller | |
| */ | |
| EM_68HC05(72), | |
| /** | |
| * Silicon Graphics SVx | |
| */ | |
| EM_SVX(73), | |
| /** | |
| * STMicroelectronics ST19 8-bit microcontroller | |
| */ | |
| EM_ST19(74), | |
| /** | |
| * Digital VAX | |
| */ | |
| EM_VAX(75), | |
| /** | |
| * Axis Communications 32-bit embedded processor | |
| */ | |
| EM_CRIS(76), | |
| /** | |
| * Infineon Technologies 32-bit embedded processor | |
| */ | |
| EM_JAVELIN(77), | |
| /** | |
| * Element 14 64-bit DSP Processor | |
| */ | |
| EM_FIREPATH(78), | |
| /** | |
| * LSI Logic 16-bit DSP Processor | |
| */ | |
| EM_ZSP(79), | |
| /** | |
| * Donald Knuth's educational 64-bit processor | |
| */ | |
| EM_MMIX(80), | |
| /** | |
| * Harvard University machine-independent object files | |
| */ | |
| EM_HUANY(81), | |
| /** | |
| * SiTera Prism | |
| */ | |
| EM_PRISM(82), | |
| /** | |
| * Atmel AVR 8-bit microcontroller | |
| */ | |
| EM_AVR(83), | |
| /** | |
| * Fujitsu FR30 | |
| */ | |
| EM_FR30(84), | |
| /** | |
| * Mitsubishi D10V | |
| */ | |
| EM_D10V(85), | |
| /** | |
| * Mitsubishi D30V | |
| */ | |
| EM_D30V(86), | |
| /** | |
| * NEC v850 | |
| */ | |
| EM_V850(87), | |
| /** | |
| * Mitsubishi M32R | |
| */ | |
| EM_M32R(88), | |
| /** | |
| * Matsushita MN10300 | |
| */ | |
| EM_MN10300(89), | |
| /** | |
| * Matsushita MN10200 | |
| */ | |
| EM_MN10200(90), | |
| /** | |
| * picoJava | |
| */ | |
| EM_PJ(91), | |
| /** | |
| * OpenRISC 32-bit embedded processor | |
| */ | |
| EM_OPENRISC(92), | |
| /** | |
| * ARC Cores Tangent-A5 | |
| */ | |
| EM_ARC_A5(93), | |
| /** | |
| * Tensilica Xtensa Architecture | |
| */ | |
| EM_XTENSA(94), | |
| /** | |
| * Alphamosaic VideoCore processor | |
| */ | |
| EM_VIDEOCORE(95), | |
| /** | |
| * Thompson Multimedia General Purpose Processor | |
| */ | |
| EM_TMM_GPP(96), | |
| /** | |
| * National Semiconductor 32000 series | |
| */ | |
| EM_NS32K(97), | |
| /** | |
| * Tenor Network TPC processor | |
| */ | |
| EM_TPC(98), | |
| /** | |
| * Trebia SNP 1000 processor | |
| */ | |
| EM_SNP1K(99), | |
| /** | |
| * STMicroelectronics (www.st.com) ST200 microcontroller | |
| */ | |
| EM_ST200(100), | |
| //</editor-fold> | |
| /** | |
| * Reserved for future use (was EM_486) | |
| */ | |
| RESERVED_WAS_EM_486(6), | |
| /** | |
| * Reserved for future use | |
| */ | |
| reserved(null), | |
| ; | |
| private static final Map<Integer, ElfMachine> values = | |
| Arrays.stream(values()) | |
| .filter(e -> null != e.getCode()) | |
| .collect(Collectors.toMap(ElfMachine::getCode, | |
| Function.identity())); | |
| final Integer code; | |
| public static ElfMachine valueOf(int code) { | |
| ElfMachine elfMachine = values.get(code); | |
| if (elfMachine != null) return elfMachine; | |
| if (code >= 11 && code <= 14) return reserved; | |
| if (code == 16) return reserved; | |
| if (code >= 23 && code <= 35) return reserved; | |
| return null; | |
| } | |
| } | |
| interface ElfHeaderBody { | |
| ByteBuffer getByteBuffer(); | |
| } | |
| /** | |
| * <pre> | |
| * #define EI_NIDENT 16 | |
| * | |
| * typedef struct { | |
| * unsigned char e_ident[EI_NIDENT]; | |
| * Elf32_Half e_type; | |
| * Elf32_Half e_machine; | |
| * Elf32_Word e_version; | |
| * Elf32_Addr e_entry; | |
| * Elf32_Off e_phoff; | |
| * Elf32_Off e_shoff; | |
| * Elf32_Word e_flags; | |
| * Elf32_Half e_ehsize; | |
| * Elf32_Half e_phentsize; | |
| * Elf32_Half e_phnum; | |
| * Elf32_Half e_shentsize; | |
| * Elf32_Half e_shnum; | |
| * Elf32_Half e_shstrndx; | |
| * } Elf32_Ehdr; | |
| * | |
| * typedef struct { | |
| * unsigned char e_ident[EI_NIDENT]; | |
| * Elf64_Half e_type; | |
| * Elf64_Half e_machine; | |
| * Elf64_Word e_version; | |
| * Elf64_Addr e_entry; | |
| * Elf64_Off e_phoff; | |
| * Elf64_Off e_shoff; | |
| * Elf64_Word e_flags; | |
| * Elf64_Half e_ehsize; | |
| * Elf64_Half e_phentsize; | |
| * Elf64_Half e_phnum; | |
| * Elf64_Half e_shentsize; | |
| * Elf64_Half e_shnum; | |
| * Elf64_Half e_shstrndx; | |
| * } Elf64_Ehdr; | |
| * </pre> | |
| */ | |
| @Accessors(chain = true) | |
| @Data | |
| static class ElfHeader { | |
| ElfIdent elfIdent; | |
| ElfHeaderBody elfHeaderBody; | |
| public String toReport() { | |
| var _class = elfIdent.eiClass(); | |
| var data = elfIdent.eiData(); | |
| var version = elfIdent.eiVersion(); | |
| var osAbi = elfIdent.eiOsAbi(); | |
| var abiVersion = elfIdent.eiAbiVersion(); | |
| var type = elfHeaderBody.getByteBuffer(); | |
| var machine = "null"; | |
| var versionNum = "null"; | |
| var entryPointAddress = "null"; | |
| var startOfProgramHeaders = "null"; | |
| var startOfSectionHeaders = "null"; | |
| var flags = "null"; | |
| var sizeOfThisHeader = "null"; | |
| var sizeOfProgramHeaders = "null"; | |
| var numberOfProgramHeaders = "null"; | |
| var sizeOfSectionHeaders = "null"; | |
| var numberOfSectionHeaders = "null"; | |
| var sectionHeaderStringTableIndex = "null"; | |
| String magic = elfIdent.bytesHex(); | |
| return """ | |
| ELF Header: | |
| Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 | |
| Magic: %s | |
| Class: ELF64 | |
| Class: %s | |
| Data: 2's complement, little endian | |
| Data: %s | |
| Version: 1 (current) | |
| Version: %s | |
| OS/ABI: UNIX - System V | |
| OS/ABI: %s | |
| ABI Version: 0 | |
| ABI Version: %s | |
| Type: DYN (Shared object file) | |
| Type: %s | |
| Machine: Advanced Micro Devices X86-64 | |
| Machine: %s | |
| Version: 0x1 | |
| Version: %s | |
| Entry point address: 0x31f0 | |
| Entry point address: %s | |
| Start of program headers: 64 (bytes into file) | |
| Start of program headers: %s | |
| Start of section headers: 41496 (bytes into file) | |
| Start of section headers: %s | |
| Flags: 0x0 | |
| Flags: %s | |
| Size of this header: 64 (bytes) | |
| Size of this header: %s | |
| Size of program headers: 56 (bytes) | |
| Size of program headers: %s | |
| Number of program headers: 13 | |
| Number of program headers: %s | |
| Size of section headers: 64 (bytes) | |
| Size of section headers: %s | |
| Number of section headers: 30 | |
| Number of section headers: %s | |
| Section header string table index: 29 | |
| Section header string table index: %s | |
| """.formatted( | |
| magic, | |
| _class, | |
| data, | |
| version, | |
| osAbi, | |
| abiVersion, | |
| type, | |
| machine, | |
| versionNum, | |
| entryPointAddress, | |
| startOfProgramHeaders, | |
| startOfSectionHeaders, | |
| flags, | |
| sizeOfThisHeader, | |
| sizeOfProgramHeaders, | |
| numberOfProgramHeaders, | |
| sizeOfSectionHeaders, | |
| numberOfSectionHeaders, | |
| sectionHeaderStringTableIndex); | |
| } | |
| } | |
| @Accessors(chain = true) | |
| @Data | |
| static abstract class ElfHeaderBodyBase implements ElfHeaderBody { | |
| protected ByteBuffer byteBuffer; | |
| } | |
| @EqualsAndHashCode(callSuper = true) | |
| @Accessors(chain = true) | |
| @Data | |
| static class ElfHeaderBody32 extends ElfHeaderBodyBase { | |
| } | |
| @EqualsAndHashCode(callSuper = true) | |
| @Accessors(chain = true) | |
| @Data | |
| static class ElfHeaderBody64 extends ElfHeaderBodyBase { | |
| @ToString.Include | |
| short e_type() { | |
| return byteBuffer.getShort(0); | |
| } | |
| @ToString.Include | |
| short e_machine() { | |
| return byteBuffer.getShort(2); | |
| } | |
| @ToString.Include /*Word*/ int e_version() { | |
| return byteBuffer.getInt(4); | |
| } | |
| @ToString.Include /*Addr*/ int e_entry() { | |
| return byteBuffer.getInt(8); | |
| } | |
| @ToString.Include /*Off*/ int e_phoff() { | |
| return byteBuffer.getInt(12); | |
| } | |
| @ToString.Include /*Off*/ int e_shoff() { | |
| return byteBuffer.getInt(16); | |
| } | |
| @ToString.Include /*Word*/ int e_flags() { | |
| return byteBuffer.getInt(20); | |
| } | |
| @ToString.Include | |
| short e_ehsize() { | |
| return byteBuffer.getShort(24); | |
| } | |
| @ToString.Include | |
| short e_phentsize() { | |
| return byteBuffer.getShort(26); | |
| } | |
| @ToString.Include | |
| short e_phnum() { | |
| return byteBuffer.getShort(28); | |
| } | |
| @ToString.Include | |
| short e_shentsize() { | |
| return byteBuffer.getShort(30); | |
| } | |
| @ToString.Include | |
| short e_shnum() { | |
| return byteBuffer.getShort(32); | |
| } | |
| @ToString.Include | |
| short e_shstrndx() { | |
| return byteBuffer.getShort(34); | |
| } | |
| } | |
| @Accessors(chain = true) | |
| @Data | |
| static class ElfIdent { | |
| public static final int EI_NIDENT = 16; | |
| public static final byte[] ELF_MAGIC_NUMBER = new byte[]{127, 'E', 'L', 'F'}; | |
| // 16 chars | |
| ByteBuffer value; | |
| byte[] magicNumber() { | |
| return copy(value.slice(0, 4)); | |
| } | |
| boolean magicNumberIsElf() { | |
| return Arrays.equals(ELF_MAGIC_NUMBER, magicNumber()); | |
| } | |
| public String bytesHex() { | |
| StringBuilder magic = new StringBuilder(); | |
| ByteBuffer mn = value.slice(); | |
| while (mn.hasRemaining()) { | |
| String part = Integer.toHexString(mn.get()); | |
| magic | |
| .append(part.length() == 1 ? "0" : "") | |
| .append(part) | |
| .append(" "); | |
| } | |
| return magic.toString(); | |
| } | |
| byte eiClassValue() { | |
| return value.get(4); | |
| } | |
| @ToString.Include | |
| EiClass eiClass() { | |
| return EiClass.valueOf(eiClassValue()); | |
| } | |
| byte eiDataValue() { | |
| return value.get(5); | |
| } | |
| @ToString.Include | |
| EiData eiData() { | |
| return EiData.valueOf(eiDataValue()); | |
| } | |
| /** | |
| * Byte e_ident[EI_VERSION] specifies the ELF header version number. | |
| * Currently, this value must be EV_CURRENT, as explained above | |
| * for e_version. | |
| * | |
| * @return version | |
| */ | |
| @ToString.Include | |
| byte eiVersion() { | |
| return value.get(6); | |
| } | |
| byte eiOsAbiValue() { | |
| return value.get(7); | |
| } | |
| @ToString.Include | |
| EiOsAbi eiOsAbi() { | |
| return EiOsAbi.valueOf(eiOsAbiValue()); | |
| } | |
| /** | |
| * Byte e_ident[EI_ABIVERSION] identifies the version of the ABI to | |
| * which the object is targeted. This field is used to | |
| * distinguish among incompatible versions of an ABI. The | |
| * interpretation of this version number is dependent on the ABI | |
| * identified by the EI_OSABI field. If no values are specified | |
| * for the EI_OSABI field by the processor supplement or no | |
| * version values are specified for the ABI determined by a | |
| * particular value of the EI_OSABI byte, the value 0 shall be | |
| * used for the EI_ABIVERSION byte; it indicates unspecified. | |
| */ | |
| @ToString.Include | |
| byte eiAbiVersion() { | |
| return value.get(8); | |
| } | |
| /** | |
| * This value marks the beginning of the unused bytes in e_ident. | |
| * These bytes are reserved and set to zero; programs that read | |
| * object files should ignore them. The value of EI_PAD will | |
| * change in the future if currently unused bytes are given meanings. | |
| */ | |
| byte eiPad() { | |
| return value.get(9); | |
| } | |
| /** | |
| * EI_CLASS | |
| * <p> | |
| * The next byte, e_ident[EI_CLASS], identifies the file's class, or capacity. | |
| */ | |
| @AllArgsConstructor | |
| @Getter | |
| enum EiClass { | |
| /** | |
| * Invalid class | |
| */ | |
| NONE(0, "NONE"), | |
| /** | |
| * 32-bit objects | |
| */ | |
| CLASS32(1, "ELF32"), | |
| /** | |
| * 64-bit objects | |
| */ | |
| CLASS64(2, "ELF64"), | |
| ; | |
| private static final Map<Integer, EiClass> byCode = | |
| Arrays.stream(values()) | |
| .collect(Collectors.toMap(EiClass::getCode, | |
| Function.identity())); | |
| final int code; | |
| final String binUtilsName; | |
| public static EiClass valueOf(int code) { | |
| return byCode.get(code); | |
| } | |
| @Override | |
| public String toString() { | |
| return binUtilsName; | |
| } | |
| } | |
| /** | |
| * EI_DATA | |
| * <p> | |
| * Byte e_ident[EI_DATA] specifies the encoding of both the data | |
| * structures used by object file container and data contained in | |
| * object file sections. The following encodings are currently defined. | |
| * <p> | |
| * Other values are reserved and will be assigned to new encodings as necessary. | |
| */ | |
| @AllArgsConstructor | |
| @Getter | |
| enum EiData { | |
| /** | |
| * Invalid class | |
| */ | |
| NONE(0, "NONE"), | |
| /** | |
| * Encoding ELFDATA2LSB specifies 2's complement values, | |
| * with the least significant byte occupying the lowest address. | |
| */ | |
| LSB(1, "2's complement, little endian"), | |
| /** | |
| * Encoding ELFDATA2MSB specifies 2's complement values, | |
| * with the most significant byte occupying the lowest address. | |
| */ | |
| MSB(2, "2's complement, big endian"), | |
| ; | |
| private static final Map<Integer, EiData> byCode = | |
| Arrays.stream(values()) | |
| .collect(Collectors.toMap(EiData::getCode, | |
| Function.identity())); | |
| final int code; | |
| final String binUtilsName; | |
| public static EiData valueOf(int code) { | |
| return byCode.get(code); | |
| } | |
| @Override | |
| public String toString() { | |
| return binUtilsName; | |
| } | |
| } | |
| /** | |
| * EI_OSABI | |
| * <p> | |
| * Byte e_ident[EI_OSABI] identifies the OS- or ABI-specific ELF | |
| * extensions used by this file. Some fields in other ELF | |
| * structures have flags and values that have operating system | |
| * and/or ABI specific meanings; the interpretation of those | |
| * fields is determined by the value of this byte. If the object | |
| * file does not use any extensions, it is recommended that this | |
| * byte be set to 0. If the value for this byte is 64 through | |
| * 255, its meaning depends on the value of the e_machine header | |
| * member. The ABI processor supplement for an architecture can | |
| * define its own associated set of values for this byte in this | |
| * range. If the processor supplement does not specify a set of | |
| * values, one of the following values shall be used, where 0 can | |
| * also be taken to mean unspecified. | |
| */ | |
| @AllArgsConstructor | |
| @ToString | |
| @Getter | |
| enum EiOsAbi { | |
| //<editor-fold desc="members"> | |
| /** | |
| * No extensions or unspecified | |
| */ | |
| NONE(0), | |
| /** | |
| * Hewlett-Packard HP-UX | |
| */ | |
| HPUX(1), | |
| /** | |
| * NetBSD | |
| */ | |
| NETBSD(2), | |
| /** | |
| * Linux | |
| */ | |
| LINUX(3), | |
| /** | |
| * Sun Solaris | |
| */ | |
| SOLARIS(6), | |
| /** | |
| * AIX | |
| */ | |
| AIX(7), | |
| /** | |
| * IRIX | |
| */ | |
| IRIX(8), | |
| /** | |
| * FreeBSD | |
| */ | |
| FREEBSD(9), | |
| /** | |
| * Compaq TRU64 UNIX | |
| */ | |
| TRU64(10), | |
| /** | |
| * Novell Modesto | |
| */ | |
| MODESTO(11), | |
| /** | |
| * Open BSD | |
| */ | |
| OPENBSD(12), | |
| /** | |
| * Open VMS | |
| */ | |
| OPENVMS(13), | |
| /** | |
| * Hewlett-Packard Non-Stop Kernel | |
| */ | |
| NSK(14), | |
| //</editor-fold> | |
| /** | |
| * Architecture-specific value range 64-255 | |
| */ | |
| ARCH_SPECIFIC(null), | |
| ; | |
| private static final Map<Integer, EiOsAbi> byCode = | |
| Arrays.stream(values()) | |
| .filter(e -> e.getCode() != null) | |
| .collect(Collectors.toMap(EiOsAbi::getCode, | |
| Function.identity())); | |
| final Integer code; | |
| public static EiOsAbi valueOf(int code) { | |
| EiOsAbi eiData = byCode.get(code); | |
| if (eiData != null) return eiData; | |
| if (code >= 64 && code <= 255) return ARCH_SPECIFIC; | |
| return null; | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment