aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Li <li.davidm96@gmail.com>2016-01-04 10:12:15 -0700
committerDavid Li <li.davidm96@gmail.com>2016-01-04 10:12:15 -0700
commit1e93d4c727f632cd5d6cdc90e6d8a21883d6f409 (patch)
treedfe9a4ad686e8fa389eaca24ad1946d377278095
parent01f161fa1ac86e75524bf038e51a236f0dfb22a6 (diff)
Add rust-elfloader to tree (needs modification for 32-bit ELF)
-rw-r--r--Cargo.toml3
-rw-r--r--src/rust-elfloader/.gitignore14
-rw-r--r--src/rust-elfloader/.travis.yml2
-rw-r--r--src/rust-elfloader/AUTHORS3
-rw-r--r--src/rust-elfloader/Cargo.toml9
-rw-r--r--src/rust-elfloader/LICENSE202
-rw-r--r--src/rust-elfloader/README.md11
-rw-r--r--src/rust-elfloader/src/elf.rs848
-rw-r--r--src/rust-elfloader/src/lib.rs177
9 files changed, 1269 insertions, 0 deletions
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 <li.davidm96@gmail.com>"]
+
+[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 <mail@gerdzellweger.com>
+Christopher Cole <chris.cole.09@gmail.com>
+John Kåre Alsaker <john.kare.alsaker@gmail.com>
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 <mail@gerdzellweger.com>", "Christopher Cole <chris.cole.09@gmail.com>", "John Kåre Alsaker <john.kare.alsaker@gmail.com>"]
+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<T>(region: &[u8], offset: usize, count: usize) -> &[T] {
+ assert!(region.len() - offset >= count * size_of::<T>());
+ 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<ElfBinary<'s>> {
+ if region.len() >= size_of::<elf::FileHeader>() && 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::<elf::ProgramHeader>();
+ 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::<elf::Symbol>())
+ }
+ }
+
+ // Enumerate all the symbols in the file
+ pub fn for_each_symbol<F: FnMut(&'s elf::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::<elf::SectionHeader>();
+ 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),
+ _ => ()
+ };
+ }
+ }
+
+}