From 1e93d4c727f632cd5d6cdc90e6d8a21883d6f409 Mon Sep 17 00:00:00 2001 From: David Li Date: Mon, 4 Jan 2016 10:12:15 -0700 Subject: Add rust-elfloader to tree (needs modification for 32-bit ELF) --- Cargo.toml | 3 + src/rust-elfloader/.gitignore | 14 + src/rust-elfloader/.travis.yml | 2 + src/rust-elfloader/AUTHORS | 3 + src/rust-elfloader/Cargo.toml | 9 + src/rust-elfloader/LICENSE | 202 ++++++++++ src/rust-elfloader/README.md | 11 + src/rust-elfloader/src/elf.rs | 848 +++++++++++++++++++++++++++++++++++++++++ src/rust-elfloader/src/lib.rs | 177 +++++++++ 9 files changed, 1269 insertions(+) create mode 100644 src/rust-elfloader/.gitignore create mode 100644 src/rust-elfloader/.travis.yml create mode 100644 src/rust-elfloader/AUTHORS create mode 100644 src/rust-elfloader/Cargo.toml create mode 100644 src/rust-elfloader/LICENSE create mode 100644 src/rust-elfloader/README.md create mode 100644 src/rust-elfloader/src/elf.rs create mode 100644 src/rust-elfloader/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 99470d5..11f646f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,3 +2,6 @@ name = "rustv" version = "0.1.0" authors = ["David Li "] + +[dependencies.elfloader] +path = "src/rust-elfloader" diff --git a/src/rust-elfloader/.gitignore b/src/rust-elfloader/.gitignore new file mode 100644 index 0000000..a93127b --- /dev/null +++ b/src/rust-elfloader/.gitignore @@ -0,0 +1,14 @@ +# Compiled files +*.o +*.so +*.rlib +*.dll +*.swp + +# Executables +*.exe + +# Generated by Cargo +/target/ + +Cargo.lock diff --git a/src/rust-elfloader/.travis.yml b/src/rust-elfloader/.travis.yml new file mode 100644 index 0000000..7b53aa5 --- /dev/null +++ b/src/rust-elfloader/.travis.yml @@ -0,0 +1,2 @@ +language: rust +rust: nightly diff --git a/src/rust-elfloader/AUTHORS b/src/rust-elfloader/AUTHORS new file mode 100644 index 0000000..20695b9 --- /dev/null +++ b/src/rust-elfloader/AUTHORS @@ -0,0 +1,3 @@ +Gerd Zellweger +Christopher Cole +John Kåre Alsaker diff --git a/src/rust-elfloader/Cargo.toml b/src/rust-elfloader/Cargo.toml new file mode 100644 index 0000000..ee5670f --- /dev/null +++ b/src/rust-elfloader/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "elfloader" +version = "0.0.3" +authors = ["Gerd Zellweger ", "Christopher Cole ", "John Kåre Alsaker "] +repository = "https://github.com/gz/rust-elfloader" +license = "Apache-2.0" +description = "A rust library to load ELF files." +keywords = ["elf", "x86", "os"] +readme = "README.md" diff --git a/src/rust-elfloader/LICENSE b/src/rust-elfloader/LICENSE new file mode 100644 index 0000000..e06d208 --- /dev/null +++ b/src/rust-elfloader/LICENSE @@ -0,0 +1,202 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/src/rust-elfloader/README.md b/src/rust-elfloader/README.md new file mode 100644 index 0000000..c49f38c --- /dev/null +++ b/src/rust-elfloader/README.md @@ -0,0 +1,11 @@ +[![Build Status](https://travis-ci.org/gz/rust-elfloader.svg?branch=master)](https://travis-ci.org/gz/rust-elfloader) + +# rust-elfloader + +A library to load and relocate ELF files in memory. +This library depends only on libcore so it can be used in kernel level code, +for example to load user-space programs. + +This library reuses a modified version of the types.rs +file from [rust-elf](https://github.com/cole14/rust-elf) +by Christopher Cole. \ No newline at end of file diff --git a/src/rust-elfloader/src/elf.rs b/src/rust-elfloader/src/elf.rs new file mode 100644 index 0000000..5a1df57 --- /dev/null +++ b/src/rust-elfloader/src/elf.rs @@ -0,0 +1,848 @@ +use core::fmt; + +/// ELF magic number +pub const ELF_MAGIC: &'static [u8] = &[0x7f, 'E' as u8, 'L' as u8, 'F' as u8]; + +/// Represents the ELF file class (32-bit vs 64-bit) +#[derive(Copy, Clone, PartialEq)] +pub struct Class(pub u8); + +/// Invalid ELF file class +pub const ELFCLASSNONE : Class = Class(0); +/// 32-bit ELF file +pub const ELFCLASS32 : Class = Class(1); +/// 64-bit ELF file +pub const ELFCLASS64 : Class = Class(2); + +impl fmt::Debug for Class { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:#x}", self.0) + } +} + +impl fmt::Display for Class { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let str = match *self { + ELFCLASSNONE => "Invalid", + ELFCLASS32 => "32-bit", + ELFCLASS64 => "64-bit", + _ => "Unknown", + }; + write!(f, "{}", str) + } +} + +/// Represents the ELF file data format (little-endian vs big-endian) +#[derive(Copy, Clone, PartialEq)] +pub struct Data(pub u8); + +/// Invalid ELF data format +pub const ELFDATANONE : Data = Data(0); +/// little-endian ELF file +pub const ELFDATA2LSB : Data = Data(1); +/// big-endian ELF file +pub const ELFDATA2MSB : Data = Data(2); + +impl fmt::Debug for Data { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:#x}", self.0) + } +} + +impl fmt::Display for Data { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let str = match *self { + ELFDATANONE => "Invalid", + ELFDATA2LSB => "2's complement, little endian", + ELFDATA2MSB => "2's complement, big endian", + _ => "Unknown", + }; + write!(f, "{}", str) + } +} + +/// Represents the ELF file version +#[derive(Copy, Clone, Eq, PartialEq)] +pub struct Version(pub u8); + +/// Invalid version +pub const EV_NONE : Version = Version(0); +/// Current version +pub const EV_CURRENT : Version = Version(1); + +impl fmt::Debug for Version { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:#x}", self.0) + } +} + +impl fmt::Display for Version { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let str = match *self { + EV_NONE => "Invalid", + EV_CURRENT => "1 (Current)", + _ => "Unknown", + }; + write!(f, "{}", str) + } +} + +/// Represents the ELF file OS ABI +#[derive(Copy, Clone, Eq, PartialEq)] +pub struct OSABI(pub u8); + +/// Defaults to Unix System V +pub const ELFOSABI_NONE : OSABI = OSABI(0); +/// Unix System V +pub const ELFOSABI_SYSV : OSABI = OSABI(0); +/// HP-UX +pub const ELFOSABI_HPUX : OSABI = OSABI(1); +/// NetBSD +pub const ELFOSABI_NETBSD : OSABI = OSABI(2); +/// Linux with GNU extensions +pub const ELFOSABI_LINUX : OSABI = OSABI(3); +/// Solaris +pub const ELFOSABI_SOLARIS : OSABI = OSABI(6); +/// AIX +pub const ELFOSABI_AIX : OSABI = OSABI(7); +/// SGI Irix +pub const ELFOSABI_IRIX : OSABI = OSABI(8); +/// FreeBSD +pub const ELFOSABI_FREEBSD : OSABI = OSABI(9); +/// Compaq TRU64 UNIX +pub const ELFOSABI_TRU64 : OSABI = OSABI(10); +/// Novell Modesto +pub const ELFOSABI_MODESTO : OSABI = OSABI(11); +/// OpenBSD +pub const ELFOSABI_OPENBSD : OSABI = OSABI(12); + +impl fmt::Debug for OSABI { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:#x}", self.0) + } +} + +impl fmt::Display for OSABI { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let str = match *self { + ELFOSABI_SYSV => "UNIX System V", + ELFOSABI_HPUX => "HP-UX", + ELFOSABI_NETBSD => "NetBSD", + ELFOSABI_LINUX => "Linux with GNU extensions", + ELFOSABI_SOLARIS => "Solaris", + ELFOSABI_AIX => "AIX", + ELFOSABI_IRIX => "SGI Irix", + ELFOSABI_FREEBSD => "FreeBSD", + ELFOSABI_TRU64 => "Compaq TRU64 UNIX", + ELFOSABI_MODESTO => "Novell Modesto", + ELFOSABI_OPENBSD => "OpenBSD", + _ => "Unknown", + }; + write!(f, "{}", str) + } +} + +/// Represents the ELF file type (object, executable, shared lib, core) +#[derive(Copy, Clone, Eq, PartialEq)] +pub struct Type(pub u16); +/// No file type +pub const ET_NONE : Type = Type(0); +/// Relocatable object file +pub const ET_REL : Type = Type(1); +/// Executable file +pub const ET_EXEC : Type = Type(2); +/// Shared library +pub const ET_DYN : Type = Type(3); +/// Core file +pub const ET_CORE : Type = Type(4); + +impl fmt::Debug for Type { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:#x}", self.0) + } +} + +impl fmt::Display for Type { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let str = match *self { + ET_NONE => "No file type", + ET_REL => "Relocatable file", + ET_EXEC => "Executable file", + ET_DYN => "Shared object file", + ET_CORE => "Core file", + _ => "Unknown", + }; + write!(f, "{}", str) + } +} + +/// Represents the ELF file machine architecture +#[derive(Copy, Clone, Eq, PartialEq)] +pub struct Machine(pub u16); +pub const EM_NONE : Machine = Machine(0); +pub const EM_M32 : Machine = Machine(1); +pub const EM_SPARC : Machine = Machine(2); +pub const EM_386 : Machine = Machine(3); +pub const EM_68K : Machine = Machine(4); +pub const EM_88K : Machine = Machine(5); +pub const EM_860 : Machine = Machine(7); +pub const EM_MIPS : Machine = Machine(8); +pub const EM_S370 : Machine = Machine(9); +pub const EM_MIPS_RS3_LE : Machine = Machine(10); +pub const EM_PARISC : Machine = Machine(15); +pub const EM_VPP500 : Machine = Machine(17); +pub const EM_SPARC32PLUS : Machine = Machine(18); +pub const EM_960 : Machine = Machine(19); +pub const EM_PPC : Machine = Machine(20); +pub const EM_PPC64 : Machine = Machine(21); +pub const EM_S390 : Machine = Machine(22); +pub const EM_V800 : Machine = Machine(36); +pub const EM_FR20 : Machine = Machine(37); +pub const EM_RH32 : Machine = Machine(38); +pub const EM_RCE : Machine = Machine(39); +pub const EM_ARM : Machine = Machine(40); +pub const EM_FAKE_ALPHA : Machine = Machine(41); +pub const EM_SH : Machine = Machine(42); +pub const EM_SPARCV9 : Machine = Machine(43); +pub const EM_TRICORE : Machine = Machine(44); +pub const EM_ARC : Machine = Machine(45); +pub const EM_H8_300 : Machine = Machine(46); +pub const EM_H8_300H : Machine = Machine(47); +pub const EM_H8S : Machine = Machine(48); +pub const EM_H8_500 : Machine = Machine(49); +pub const EM_IA_64 : Machine = Machine(50); +pub const EM_MIPS_X : Machine = Machine(51); +pub const EM_COLDFIRE : Machine = Machine(52); +pub const EM_68HC12 : Machine = Machine(53); +pub const EM_MMA : Machine = Machine(54); +pub const EM_PCP : Machine = Machine(55); +pub const EM_NCPU : Machine = Machine(56); +pub const EM_NDR1 : Machine = Machine(57); +pub const EM_STARCORE : Machine = Machine(58); +pub const EM_ME16 : Machine = Machine(59); +pub const EM_ST100 : Machine = Machine(60); +pub const EM_TINYJ : Machine = Machine(61); +pub const EM_X86_64 : Machine = Machine(62); +pub const EM_PDSP : Machine = Machine(63); +pub const EM_FX66 : Machine = Machine(66); +pub const EM_ST9PLUS : Machine = Machine(67); +pub const EM_ST7 : Machine = Machine(68); +pub const EM_68HC16 : Machine = Machine(69); +pub const EM_68HC11 : Machine = Machine(70); +pub const EM_68HC08 : Machine = Machine(71); +pub const EM_68HC05 : Machine = Machine(72); +pub const EM_SVX : Machine = Machine(73); +pub const EM_ST19 : Machine = Machine(74); +pub const EM_VAX : Machine = Machine(75); +pub const EM_CRIS : Machine = Machine(76); +pub const EM_JAVELIN : Machine = Machine(77); +pub const EM_FIREPATH : Machine = Machine(78); +pub const EM_ZSP : Machine = Machine(79); +pub const EM_MMIX : Machine = Machine(80); +pub const EM_HUANY : Machine = Machine(81); +pub const EM_PRISM : Machine = Machine(82); +pub const EM_AVR : Machine = Machine(83); +pub const EM_FR30 : Machine = Machine(84); +pub const EM_D10V : Machine = Machine(85); +pub const EM_D30V : Machine = Machine(86); +pub const EM_V850 : Machine = Machine(87); +pub const EM_M32R : Machine = Machine(88); +pub const EM_MN10300 : Machine = Machine(89); +pub const EM_MN10200 : Machine = Machine(90); +pub const EM_PJ : Machine = Machine(91); +pub const EM_OPENRISC : Machine = Machine(92); +pub const EM_ARC_A5 : Machine = Machine(93); +pub const EM_XTENSA : Machine = Machine(94); +pub const EM_AARCH64 : Machine = Machine(183); +pub const EM_TILEPRO : Machine = Machine(188); +pub const EM_MICROBLAZE : Machine = Machine(189); +pub const EM_TILEGX : Machine = Machine(191); + +impl fmt::Debug for Machine { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:#x}", self.0) + } +} + +impl fmt::Display for Machine { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let str = match *self { + EM_NONE => "No machine", + EM_M32 => "AT&T WE 32100", + EM_SPARC => "SUN SPARC", + EM_386 => "Intel 80386", + EM_68K => "Motorola m68k family", + EM_88K => "Motorola m88k family", + EM_860 => "Intel 80860", + EM_MIPS => "MIPS R3000 big-endian", + EM_S370 => "IBM System/370", + EM_MIPS_RS3_LE => "MIPS R3000 little-endian", + EM_PARISC => "HPPA", + EM_VPP500 => "Fujitsu VPP500", + EM_SPARC32PLUS => "Sun's 'v8plus'", + EM_960 => "Intel 80960", + EM_PPC => "PowerPC", + EM_PPC64 => "PowerPC 64-bit", + EM_S390 => "IBM S390", + EM_V800 => "NEC V800 series", + EM_FR20 => "Fujitsu FR20", + EM_RH32 => "TRW RH-32", + EM_RCE => "Motorola RCE", + EM_ARM => "ARM", + EM_FAKE_ALPHA => "Digital Alpha", + EM_SH => "Hitachi SH", + EM_SPARCV9 => "SPARC v9 64-bit", + EM_TRICORE => "Siemens Tricore", + EM_ARC => "Argonaut RISC Core", + EM_H8_300 => "Hitachi H8/300", + EM_H8_300H => "Hitachi H8/300H", + EM_H8S => "Hitachi H8S", + EM_H8_500 => "Hitachi H8/500", + EM_IA_64 => "Intel Merced", + EM_MIPS_X => "Stanford MIPS-X", + EM_COLDFIRE => "Motorola Coldfire", + EM_68HC12 => "Motorola M68HC12", + EM_MMA => "Fujitsu MMA Multimedia Accelerato", + EM_PCP => "Siemens PCP", + EM_NCPU => "Sony nCPU embeeded RISC", + EM_NDR1 => "Denso NDR1 microprocessor", + EM_STARCORE => "Motorola Start*Core processor", + EM_ME16 => "Toyota ME16 processor", + EM_ST100 => "STMicroelectronic ST100 processor", + EM_TINYJ => "Advanced Logic Corp. Tinyj emb.fa", + EM_X86_64 => "AMD x86-64 architecture", + EM_PDSP => "Sony DSP Processor", + EM_FX66 => "Siemens FX66 microcontroller", + EM_ST9PLUS => "STMicroelectronics ST9+ 8/16 mc", + EM_ST7 => "STmicroelectronics ST7 8 bit mc", + EM_68HC16 => "Motorola MC68HC16 microcontroller", + EM_68HC11 => "Motorola MC68HC11 microcontroller", + EM_68HC08 => "Motorola MC68HC08 microcontroller", + EM_68HC05 => "Motorola MC68HC05 microcontroller", + EM_SVX => "Silicon Graphics SVx", + EM_ST19 => "STMicroelectronics ST19 8 bit mc", + EM_VAX => "Digital VAX", + EM_CRIS => "Axis Communications 32-bit embedded processor", + EM_JAVELIN => "Infineon Technologies 32-bit embedded processor", + EM_FIREPATH => "Element 14 64-bit DSP Processor", + EM_ZSP => "LSI Logic 16-bit DSP Processor", + EM_MMIX => "Donald Knuth's educational 64-bit processor", + EM_HUANY => "Harvard University machine-independent object files", + EM_PRISM => "SiTera Prism", + EM_AVR => "Atmel AVR 8-bit microcontroller", + EM_FR30 => "Fujitsu FR30", + EM_D10V => "Mitsubishi D10V", + EM_D30V => "Mitsubishi D30V", + EM_V850 => "NEC v850", + EM_M32R => "Mitsubishi M32R", + EM_MN10300 => "Matsushita MN10300", + EM_MN10200 => "Matsushita MN10200", + EM_PJ => "picoJava", + EM_OPENRISC => "OpenRISC 32-bit embedded processor", + EM_ARC_A5 => "ARC Cores Tangent-A5", + EM_XTENSA => "Tensilica Xtensa Architecture", + EM_AARCH64 => "ARM AARCH64", + EM_TILEPRO => "Tilera TILEPro", + EM_MICROBLAZE => "Xilinx MicroBlaze", + EM_TILEGX => "Tilera TILE-Gx", + _ => "Unknown", + }; + write!(f, "{}", str) + } +} + +/// First 16 bytes of the ELF file header. +#[derive(Copy, Clone, Debug)] +#[repr(C, packed)] +pub struct ElfIdent { + /// Must have value [0x7f, 'E', 'L', 'F']. + pub magic: [u8; 4], + + /// 32-bit vs 64-bit + pub class: Class, + /// little vs big endian + pub data: Data, + /// elf version + pub version: Version, + /// OS ABI + pub osabi: OSABI, + /// Version of the OS ABI + pub abiversion: u8, + // Reserved (should be zero). + pub padding: [u8; 7], +} + +impl fmt::Display for ElfIdent { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let valid_magic = match self.magic == ELF_MAGIC { + true => "valid magic", + _ => "invalid magic" + }; + write!(f, "ElfIdent: {} {} {} {} {}", valid_magic, self.class, self.data, self.version, self.osabi) + } +} + +/// Encapsulates the contents of the ELF File Header +#[derive(Copy, Clone, Debug)] +#[repr(C, packed)] +pub struct FileHeader { + pub ident: ElfIdent, + /// ELF file type + pub elftype: Type, + /// Target machine architecture + pub machine: Machine, + /// ELF version + pub version: u32, + /// Virtual address of program entry point + pub entry: u32, + /// Start of program headers (bytes into file) + pub phoff: u32, + /// Start of section headers (bytes into file) + pub shoff: u32, + pub flags: u32, + /// Size of this header. + pub ehsize: u16, + /// Size of program headers. + pub phentsize: u16, + /// Number of program headers. + pub phnum: u16, + /// Size of section headers. + pub shentsize: u16, + /// Number of section headers. + pub shnum: u16, + /// Section header string table index. + pub shstrndx: u16, +} + +impl fmt::Display for FileHeader { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "FileHeader: [{}] is {} for {} in version {} starts at {:x}", + self.ident, self.elftype, self.machine, + self.version, self.entry) + } +} + +/// Represents ELF Program Header flags +#[derive(Copy, Clone, PartialEq)] +pub struct ProgFlag(pub u32); + +pub const PF_NONE : ProgFlag = ProgFlag(0); +/// Executable program segment +pub const PF_X : ProgFlag = ProgFlag(1); +/// Writable program segment +pub const PF_W : ProgFlag = ProgFlag(2); +/// Readable program segment +pub const PF_R : ProgFlag = ProgFlag(4); + +impl fmt::Debug for ProgFlag { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:#x}", self.0) + } +} + +impl fmt::Display for ProgFlag { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if (self.0 & PF_R.0) != 0 { + try!(write!(f, "R")); + } else { + try!(write!(f, " ")); + } + if (self.0 & PF_W.0) != 0 { + try!(write!(f, "W")); + } else { + try!(write!(f, " ")); + } + if (self.0 & PF_X.0) != 0 { + write!(f, "E") + } else { + write!(f, " ") + } + } +} + +/// Represents ELF Program Header type +#[derive(Copy, Clone, PartialEq)] +pub struct ProgType(pub u32); + +/// Program header table entry unused +pub const PT_NULL : ProgType = ProgType(0); +/// Loadable program segment +pub const PT_LOAD : ProgType = ProgType(1); +/// Dynamic linking information +pub const PT_DYNAMIC : ProgType = ProgType(2); +/// Program interpreter +pub const PT_INTERP : ProgType = ProgType(3); +/// Auxiliary information +pub const PT_NOTE : ProgType = ProgType(4); +/// Unused +pub const PT_SHLIB : ProgType = ProgType(5); +/// The program header table +pub const PT_PHDR : ProgType = ProgType(6); +/// Thread-local storage segment +pub const PT_TLS : ProgType = ProgType(7); +/// GCC .eh_frame_hdr segment +pub const PT_GNU_EH_FRAME : ProgType = ProgType(0x6474e550); +/// Indicates stack executability +pub const PT_GNU_STACK : ProgType = ProgType(0x6474e551); +/// Read-only after relocation +pub const PT_GNU_RELRO : ProgType = ProgType(0x6474e552); + +impl fmt::Debug for ProgType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:#x}", self.0) + } +} + +impl fmt::Display for ProgType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let str = match *self { + PT_NULL => "NULL", + PT_LOAD => "LOAD", + PT_DYNAMIC => "DYNAMIC", + PT_INTERP => "INTERP", + PT_NOTE => "NOTE", + PT_SHLIB => "SHLIB", + PT_PHDR => "PHDR", + PT_TLS => "TLS", + PT_GNU_EH_FRAME => "GNU_EH_FRAME", + PT_GNU_STACK => "GNU_STACK", + PT_GNU_RELRO => "GNU_RELRO", + _ => "Unknown", + }; + write!(f, "{}", str) + } +} + +/// Encapsulates the contents of an ELF Program Header +/// +/// The program header table is an array of program header structures describing +/// the various segments for program execution. +#[derive(Copy, Clone, Debug)] +pub struct ProgramHeader { + /// Program segment type + pub progtype: ProgType, + /// Offset into the ELF file where this segment begins + pub offset: u32, + /// Virtual address where this segment should be loaded + pub vaddr: u32, + /// Physical address where this segment should be loaded + pub paddr: u32, + /// Size of this segment in the file + pub filesz: u32, + /// Size of this segment in memory + pub memsz: u32, + /// Flags for this segment + pub flags: ProgFlag, + /// file and memory alignment + pub align: u32, +} + +impl fmt::Display for ProgramHeader { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Program Header: Type: {} Offset: {:#010x} VirtAddr: {:#010x} PhysAddr: {:#010x} FileSize: {:#06x} MemSize: {:#06x} Flags: {} Align: {:#x}", + self.progtype, self.offset, self.vaddr, self.paddr, self.filesz, + self.memsz, self.flags, self.align) + } +} + +/// Represens ELF Section type +#[derive(Copy, Clone, PartialEq)] +pub struct SectionType(pub u32); + +/// Inactive section with undefined values +pub const SHT_NULL : SectionType = SectionType(0); +/// Information defined by the program, includes executable code and data +pub const SHT_PROGBITS : SectionType = SectionType(1); +/// Section data contains a symbol table +pub const SHT_SYMTAB : SectionType = SectionType(2); +/// Section data contains a string table +pub const SHT_STRTAB : SectionType = SectionType(3); +/// Section data contains relocation entries with explicit addends +pub const SHT_RELA : SectionType = SectionType(4); +/// Section data contains a symbol hash table. Must be present for dynamic linking +pub const SHT_HASH : SectionType = SectionType(5); +/// Section data contains information for dynamic linking +pub const SHT_DYNAMIC : SectionType = SectionType(6); +/// Section data contains information that marks the file in some way +pub const SHT_NOTE : SectionType = SectionType(7); +/// Section data occupies no space in the file but otherwise resembles SHT_PROGBITS +pub const SHT_NOBITS : SectionType = SectionType(8); +/// Section data contains relocation entries without explicit addends +pub const SHT_REL : SectionType = SectionType(9); +/// Section is reserved but has unspecified semantics +pub const SHT_SHLIB : SectionType = SectionType(10); +/// Section data contains a minimal set of dynamic linking symbols +pub const SHT_DYNSYM : SectionType = SectionType(11); +/// Section data contains an array of constructors +pub const SHT_INIT_ARRAY : SectionType = SectionType(14); +/// Section data contains an array of destructors +pub const SHT_FINI_ARRAY : SectionType = SectionType(15); +/// Section data contains an array of pre-constructors +pub const SHT_PREINIT_ARRAY : SectionType = SectionType(16); +/// Section group +pub const SHT_GROUP : SectionType = SectionType(17); +/// Extended symbol table section index +pub const SHT_SYMTAB_SHNDX : SectionType = SectionType(18); +/// Number of reserved SHT_* values +pub const SHT_NUM : SectionType = SectionType(19); +/// Object attributes +pub const SHT_GNU_ATTRIBUTES : SectionType = SectionType(0x6ffffff5); +/// GNU-style hash section +pub const SHT_GNU_HASH : SectionType = SectionType(0x6ffffff6); +/// Pre-link library list +pub const SHT_GNU_LIBLIST : SectionType = SectionType(0x6ffffff7); +/// Version definition section +pub const SHT_GNU_VERDEF : SectionType = SectionType(0x6ffffffd); +/// Version needs section +pub const SHT_GNU_VERNEED : SectionType = SectionType(0x6ffffffe); +/// Version symbol table +pub const SHT_GNU_VERSYM : SectionType = SectionType(0x6fffffff); + +impl fmt::Debug for SectionType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:#x}", self.0) + } +} + +impl fmt::Display for SectionType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let str = match *self { + SHT_NULL => "SHT_NULL", + SHT_PROGBITS => "SHT_PROGBITS", + SHT_SYMTAB => "SHT_SYMTAB", + SHT_STRTAB => "SHT_STRTAB", + SHT_RELA => "SHT_RELA", + SHT_HASH => "SHT_HASH", + SHT_DYNAMIC => "SHT_DYNAMIC", + SHT_NOTE => "SHT_NOTE", + SHT_NOBITS => "SHT_NOBITS", + SHT_REL => "SHT_REL", + SHT_SHLIB => "SHT_SHLIB", + SHT_DYNSYM => "SHT_DYNSYM", + SHT_INIT_ARRAY => "SHT_INIT_ARRAY", + SHT_FINI_ARRAY => "SHT_FINI_ARRAY", + SHT_PREINIT_ARRAY => "SHT_PREINIT_ARRAY", + SHT_GROUP => "SHT_GROUP", + SHT_SYMTAB_SHNDX => "SHT_SYMTAB_SHNDX", + SHT_NUM => "SHT_NUM", + SHT_GNU_ATTRIBUTES => "SHT_GNU_ATTRIBUTES", + SHT_GNU_HASH => "SHT_GNU_HASH", + SHT_GNU_LIBLIST => "SHT_GNU_LIBLIST", + SHT_GNU_VERDEF => "SHT_GNU_VERDEF", + SHT_GNU_VERNEED => "SHT_GNU_VERNEED", + SHT_GNU_VERSYM => "SHT_GNU_VERSYM", + _ => "Unknown", + }; + write!(f, "{}", str) + } +} + +/// +/// Wrapper type for SectionFlag +/// +#[derive(Copy, Clone, PartialEq)] +pub struct SectionFlag(pub u64); + +/// Empty flags +pub const SHF_NONE : SectionFlag = SectionFlag(0); +/// Writable +pub const SHF_WRITE : SectionFlag = SectionFlag(1); +/// Occupies memory during execution +pub const SHF_ALLOC : SectionFlag = SectionFlag(2); +/// Executable +pub const SHF_EXECINSTR : SectionFlag = SectionFlag(4); +/// Might be merged +pub const SHF_MERGE : SectionFlag = SectionFlag(16); +/// Contains nul-terminated strings +pub const SHF_STRINGS : SectionFlag = SectionFlag(32); +/// `sh_info' contains SHT index +pub const SHF_INFO_LINK : SectionFlag = SectionFlag(64); +/// Preserve order after combining +pub const SHF_LINK_ORDER : SectionFlag = SectionFlag(128); +/// Non-standard OS specific handling required +pub const SHF_OS_NONCONFORMING : SectionFlag = SectionFlag(256); +/// Section is member of a group +pub const SHF_GROUP : SectionFlag = SectionFlag(512); +/// Section hold thread-local data +pub const SHF_TLS : SectionFlag = SectionFlag(1024); + +impl fmt::Debug for SectionFlag { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:#x}", self.0) + } +} + +impl fmt::Display for SectionFlag { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:#x}", self.0) + } +} + +// An offset to a null terminated string in the section string table +#[derive(Copy, Clone)] +pub struct StrOffset(pub u32); + +impl fmt::Debug for StrOffset { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:#x}", self.0) + } +} + +impl fmt::Display for StrOffset { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:#x}", self.0) + } +} + +/// Encapsulates the contents of an ELF Section Header +#[derive(Debug)] +pub struct SectionHeader { + /// Section Name + pub name: StrOffset, + /// Section Type + pub shtype: SectionType, + /// Section Flags + pub flags: SectionFlag, + /// in-memory address where this section is loaded + pub addr: u64, + /// Byte-offset into the file where this section starts + pub offset: u64, + /// Section size in bytes + pub size: u64, + /// Defined by section type + pub link: u32, + /// Defined by section type + pub info: u32, + /// address alignment + pub addralign: u64, + /// size of an entry if section data is an array of entries + pub entsize: u64, +} + +impl fmt::Display for SectionHeader { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Section Header: Name: {} Type: {} Flags: {} Addr: {:#010x} Offset: {:#06x} Size: {:#06x} Link: {} Info: {:#x} AddrAlign: {} EntSize: {}", + self.name, self.shtype, self.flags, self.addr, self.offset, + self.size, self.link, self.info, self.addralign, self.entsize) + } +} + +#[derive(Copy, Clone)] +pub struct SymbolType(pub u8); + +/// Unspecified symbol type +pub const STT_NOTYPE : SymbolType = SymbolType(0); +/// Data object symbol +pub const STT_OBJECT : SymbolType = SymbolType(1); +/// Code object symbol +pub const STT_FUNC : SymbolType = SymbolType(2); +/// Section symbol +pub const STT_SECTION : SymbolType = SymbolType(3); +/// File name symbol +pub const STT_FILE : SymbolType = SymbolType(4); +/// Common data object symbol +pub const STT_COMMON : SymbolType = SymbolType(5); +/// Thread-local data object symbol +pub const STT_TLS : SymbolType = SymbolType(6); +/// Indirect code object symbol +pub const STT_GNU_IFUNC : SymbolType = SymbolType(10); + +impl fmt::Display for SymbolType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let str = match *self { + STT_NOTYPE => "unspecified", + STT_OBJECT => "data object", + STT_FUNC => "code object", + STT_SECTION => "section", + STT_FILE => "file name", + STT_COMMON => "common data object", + STT_TLS => "thread-local data object", + STT_GNU_IFUNC => "indirect code object", + _ => "Unknown", + }; + write!(f, "{}", str) + } +} + +#[derive(Copy, Clone)] +pub struct SymbolBind(pub u8); + +/// Local symbol +pub const STB_LOCAL : SymbolBind = SymbolBind(0); +/// Global symbol +pub const STB_GLOBAL : SymbolBind = SymbolBind(1); +/// Weak symbol +pub const STB_WEAK : SymbolBind = SymbolBind(2); +/// Unique symbol +pub const STB_GNU_UNIQUE : SymbolBind = SymbolBind(10); + +impl fmt::Display for SymbolBind { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let str = match *self { + STB_LOCAL => "local", + STB_GLOBAL => "global", + STB_WEAK => "weak", + STB_GNU_UNIQUE => "unique", + _ => "Unknown", + }; + write!(f, "{}", str) + } +} + +#[derive(Copy, Clone)] +pub struct SymbolVis(pub u8); + +/// Default symbol visibility +pub const STV_DEFAULT : SymbolVis = SymbolVis(0); +/// Processor-specific hidden visibility +pub const STV_INTERNAL : SymbolVis = SymbolVis(1); +/// Hidden visibility +pub const STV_HIDDEN : SymbolVis = SymbolVis(2); +/// Protected visibility +pub const STV_PROTECTED : SymbolVis = SymbolVis(3); + +impl fmt::Display for SymbolVis { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let str = match *self { + STV_DEFAULT => "default", + STV_INTERNAL => "internal", + STV_HIDDEN => "hidden", + STV_PROTECTED => "protected", + _ => "Unknown", + }; + write!(f, "{}", str) + } +} + +pub struct Symbol { + /// Symbol name + pub name: StrOffset, + info: u8, + other: u8, + section_index: u16, + /// Symbol value + pub value: u64, + /// Symbol size + pub size: u64, +} + +impl fmt::Display for Symbol { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Symbol: [{}] @ {:#x} size {:#x} in section {}", + self.name, self.value, self.size, self.section_index) + } +} + +impl Symbol { + pub fn sym_type(&self) -> SymbolType { + SymbolType(self.info & 0xf) + } + + pub fn sym_bind(&self) -> SymbolBind { + SymbolBind(self.info >> 4) + } + + pub fn sym_vis(&self) -> SymbolVis { + SymbolVis(self.other & 0x3) + } +} diff --git a/src/rust-elfloader/src/lib.rs b/src/rust-elfloader/src/lib.rs new file mode 100644 index 0000000..e344bcb --- /dev/null +++ b/src/rust-elfloader/src/lib.rs @@ -0,0 +1,177 @@ +#![feature(no_std, core, core_prelude, core_slice_ext, custom_derive)] +#![no_std] + +#![crate_name = "elfloader"] +#![crate_type = "lib"] + +#[cfg(test)] +#[macro_use] +extern crate std; + +pub mod elf; +use core::fmt; +use core::mem::{transmute, size_of}; + +pub type PAddr = u64; +pub type VAddr = usize; + +/// Abstract representation of a loadable ELF binary. +pub struct ElfBinary<'s> { + name: &'s str, + region: &'s [u8], + header: &'s elf::FileHeader, +} + +impl<'s> fmt::Debug for ElfBinary<'s> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{} {}", self.name, self.header) + } +} + +/// Implement this for ELF loading. +pub trait ElfLoader { + /// Allocates a virtual region of size amount of bytes. + fn allocate(&mut self, base: VAddr, size: usize, flags: elf::ProgFlag); + + /// Copies the region into the base. + fn load(&mut self, base: VAddr, region: &'static [u8]); +} + +// T must be a POD for this to be safe +unsafe fn slice_pod(region: &[u8], offset: usize, count: usize) -> &[T] { + assert!(region.len() - offset >= count * size_of::()); + core::slice::from_raw_parts(region[offset..].as_ptr() as *const T, count) +} + +impl<'s> ElfBinary<'s> { + + /// Create a new ElfBinary. + /// Makes sure that the provided region has valid ELF magic byte sequence + /// and is big enough to contain at least the ELF file header + /// otherwise it will return None. + pub fn new(name: &'s str, region: &'s [u8]) -> Option> { + if region.len() >= size_of::() && region.starts_with(elf::ELF_MAGIC) { + let header: &elf::FileHeader = unsafe { &slice_pod(region, 0, 1)[0] }; + return Some(ElfBinary { name: name, region: region, header: header }); + } + + None + } + + /// Print the program headers. + pub fn print_program_headers(&self) { + for p in self.program_headers() { + //log!("pheader = {}", p); + } + } + + /// Create a slice of the program headers. + pub fn program_headers(&self) -> &'s [elf::ProgramHeader] { + let correct_header_size = self.header.phentsize as usize == size_of::(); + let pheader_region_size = self.header.phoff as usize + self.header.phnum as usize * self.header.phentsize as usize; + let big_enough_region = self.region.len() >= pheader_region_size; + + if self.header.phoff == 0 || !correct_header_size || !big_enough_region { + return &[]; + } + + unsafe { + slice_pod(self.region, self.header.phoff as usize, self.header.phnum as usize) + } + } + + // Get the string at offset str_offset in the string table strtab + fn strtab_str(&self, strtab: &'s elf::SectionHeader, str_offset: elf::StrOffset) -> &'s str { + assert!(strtab.shtype == elf::SHT_STRTAB); + let data = self.section_data(strtab); + let offset = str_offset.0 as usize; + let mut end = offset; + while data[end] != 0 { + end += 1; + } + core::str::from_utf8(&data[offset..end]).unwrap() + } + + // Get the name of the section + pub fn symbol_name(&self, symbol: &'s elf::Symbol) -> &'s str { + let strtab = self.section_headers().iter().find(|s| s.shtype == elf::SHT_STRTAB && self.section_name(s) == ".strtab").unwrap(); + self.strtab_str(strtab, symbol.name) + } + + // Get the data of the section + pub fn section_data(&self, section: &'s elf::SectionHeader) -> &'s [u8] { + &self.region[(section.offset as usize)..(section.offset as usize + section.size as usize)] + } + + // Get the name of the section + pub fn section_name(&self, section: &'s elf::SectionHeader) -> &'s str { + self.strtab_str(&self.section_headers()[self.header.shstrndx as usize], section.name) + } + + // Get the symbols of the section + fn section_symbols(&self, section: &'s elf::SectionHeader) -> &'s [elf::Symbol] { + assert!(section.shtype == elf::SHT_SYMTAB); + unsafe { + slice_pod(self.section_data(section), 0, section.size as usize / size_of::()) + } + } + + // Enumerate all the symbols in the file + pub fn for_each_symbol(&self, mut func: F) { + for sym in self.section_headers().iter().filter(|s| s.shtype == elf::SHT_SYMTAB).flat_map(|s| self.section_symbols(s).iter()) { + func(sym); + } + } + + /// Create a slice of the section headers. + pub fn section_headers(&self) -> &'s [elf::SectionHeader] { + let correct_header_size = self.header.shentsize as usize == size_of::(); + let sheader_region_size = self.header.shoff as usize + self.header.shnum as usize * self.header.shentsize as usize; + let big_enough_region = self.region.len() >= sheader_region_size; + + if self.header.shoff == 0 || !correct_header_size || !big_enough_region { + return &[]; + } + + unsafe { + slice_pod(self.region, self.header.shoff as usize, self.header.shnum as usize) + } + } + + /// Can we load the binary on our platform? + fn can_load(&self) -> bool { + let correct_class = self.header.ident.class == elf::ELFCLASS64; + let correct_elfversion = self.header.ident.version == elf::EV_CURRENT; + let correct_data = self.header.ident.data == elf::ELFDATA2LSB; + let correct_osabi = self.header.ident.osabi == elf::ELFOSABI_SYSV || self.header.ident.osabi == elf::ELFOSABI_LINUX; + let correct_type = self.header.elftype == elf::ET_EXEC || self.header.elftype == elf::ET_DYN; + let correct_machine = self.header.machine == elf::EM_X86_64; + + correct_class && correct_data && correct_elfversion && correct_machine && correct_osabi && correct_type + } + + fn load_header(&self, p: &elf::ProgramHeader, loader: &mut ElfLoader) { + let big_enough_region = self.region.len() >= (p.offset + p.filesz) as usize; + if !big_enough_region { + //log!("Unable to load {}", p); + return; + } + + loader.allocate(p.vaddr as usize, p.memsz as usize, p.flags); + let segment: &'static [u8] = unsafe { + core::slice::from_raw_parts( + transmute(&self.region[p.offset as usize]), p.filesz as usize) + }; + loader.load(p.vaddr as usize, segment); + } + + pub fn load(&self, loader: &mut ElfLoader) { + for p in self.program_headers() { + let x = match p.progtype { + elf::PT_LOAD => self.load_header(p, loader), + _ => () + }; + } + } + +} -- cgit v1.2.3