upd
This commit is contained in:
parent
d60cd92a94
commit
138bbb39a9
11 changed files with 253 additions and 44 deletions
113
Cargo.lock
generated
113
Cargo.lock
generated
|
@ -28,6 +28,12 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
|
@ -49,6 +55,12 @@ dependencies = [
|
|||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.33.3"
|
||||
|
@ -64,6 +76,56 @@ dependencies = [
|
|||
"vec_map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"lazy_static",
|
||||
"memoffset",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "elf"
|
||||
version = "0.1.0"
|
||||
|
@ -102,6 +164,25 @@ version = "0.2.97"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
|
@ -144,15 +225,47 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"crossbeam-deque",
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
"lazy_static",
|
||||
"num_cpus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rsld"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"elf",
|
||||
"rayon",
|
||||
"structopt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.8.0"
|
||||
|
|
|
@ -10,3 +10,4 @@ members = ["elf"]
|
|||
anyhow = "1.0.41"
|
||||
structopt = "0.3.21"
|
||||
elf = { path = "elf" }
|
||||
rayon = "1.5.1"
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
CC := clang
|
||||
|
||||
RUST_SOURCES := $(shell find .. -type f -name "*.rs")
|
||||
SOURCES := $(shell find -type f -name "*.c")
|
||||
OBJECTS := $(patsubst %.c, bin/%, $(SOURCES))
|
||||
RSLD := $(shell pwd)/../target/debug/rsld
|
||||
|
||||
CFLAGS := -v -static -fuse-ld=$(shell pwd)/../target/debug/rsld
|
||||
CFLAGS := -v -static -fuse-ld=$(RSLD)
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
bin/%: %.c bin
|
||||
$(RSLD): $(RUST_SOURCES)
|
||||
cargo build
|
||||
|
||||
bin/%: %.c bin $(RSLD)
|
||||
$(CC) $(CFLAGS) -o $@ $<
|
||||
|
||||
bin:
|
||||
|
|
1
elf/src/.ignore
Normal file
1
elf/src/.ignore
Normal file
|
@ -0,0 +1 @@
|
|||
constants.rs
|
|
@ -1,25 +1,32 @@
|
|||
use std::io::Read;
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::constants::*;
|
||||
use crate::header::E_IDENT;
|
||||
use crate::section::*;
|
||||
|
||||
macro_rules! elf {
|
||||
($size:ty) => {
|
||||
use std::io::Write;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Elf {
|
||||
pub header: Header,
|
||||
pub sections: Vec<Section>,
|
||||
}
|
||||
|
||||
impl Elf {
|
||||
pub(crate) fn continue_read<R: Read>(e_ident: E_IDENT, mut r: R) -> Result<Self> {
|
||||
let mut elf: Self = unsafe { MaybeUninit::zeroed().assume_init() };
|
||||
pub(crate) fn continue_read<R: Read>(e_ident: E_IDENT, r: R) -> Result<Self> {
|
||||
let mut elf: Self = Elf::default();
|
||||
elf.header = Header::continue_read(e_ident, r)?;
|
||||
|
||||
Ok(elf)
|
||||
}
|
||||
|
||||
pub fn write<W: Write>(&self, w: W) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use byteordered::{ByteOrdered, Endianness};
|
|||
|
||||
use crate::constants::*;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type E_IDENT = [u8; EI_NIDENT];
|
||||
|
||||
macro_rules! elf_header {
|
||||
|
@ -40,7 +41,7 @@ macro_rules! elf_header {
|
|||
}
|
||||
|
||||
impl Header {
|
||||
pub(crate) fn continue_read<R: Read>(e_ident: E_IDENT, mut r: R) -> Result<Self> {
|
||||
pub(crate) fn continue_read<R: Read>(e_ident: E_IDENT, r: R) -> Result<Self> {
|
||||
let mut header = Header::default();
|
||||
|
||||
header.e_ident = e_ident;
|
||||
|
|
|
@ -5,9 +5,9 @@ extern crate anyhow;
|
|||
pub mod constants;
|
||||
pub mod elf;
|
||||
pub mod header;
|
||||
pub mod section;
|
||||
|
||||
use std::io::{Read, Write};
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
|
@ -42,14 +42,17 @@ impl Default for Elf {
|
|||
|
||||
impl Elf {
|
||||
pub fn read<R: Read>(mut r: R) -> Result<Self> {
|
||||
// read the first 16-bytes of the header to see if it's 32-bit or 64-bit
|
||||
let mut e_ident: E_IDENT = [0u8; EI_NIDENT];
|
||||
r.read_exact(&mut e_ident);
|
||||
r.read_exact(&mut e_ident)?;
|
||||
|
||||
// continue reading, passing the array we already read
|
||||
let res = match e_ident[EI_CLASS] {
|
||||
ELFCLASS32 => Elf::Elf32(elf32::Elf::continue_read(e_ident, r)?),
|
||||
ELFCLASS64 => Elf::Elf64(elf64::Elf::continue_read(e_ident, r)?),
|
||||
n => bail!("invalid class: {}", n),
|
||||
};
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
|
|
2
elf/src/section.rs
Normal file
2
elf/src/section.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
#[derive(Debug)]
|
||||
pub struct Section {}
|
96
src/link.rs
96
src/link.rs
|
@ -1,36 +1,104 @@
|
|||
use std::fs::{File, OpenOptions};
|
||||
use std::os::unix::fs::OpenOptionsExt;
|
||||
use std::fs::File;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use elf::Elf;
|
||||
use anyhow::Result;
|
||||
use elf::{elf32::Elf as Elf32, elf64::Elf as Elf64, Elf};
|
||||
use rayon::prelude::*;
|
||||
|
||||
use crate::{LinkUnit, Opt};
|
||||
|
||||
pub(crate) fn link(opt: &Opt) -> Result<()> {
|
||||
let res = Elf::default();
|
||||
pub(crate) fn link(opt: Opt) -> Result<()> {
|
||||
let output = match opt.out {
|
||||
Some(v) => v,
|
||||
None => bail!("TODO: default output name"),
|
||||
};
|
||||
|
||||
for unit in &opt.units {
|
||||
let accum = opt
|
||||
.units
|
||||
.into_par_iter()
|
||||
.try_fold(|| Accum::default(), sort_all_elfs_by_bitness)
|
||||
.try_reduce(|| Accum::default(), combine_accum)?;
|
||||
|
||||
// call out to the appropriately specialized function
|
||||
if accum.elfs32.is_empty() {
|
||||
bits_64::link(output, accum.elfs64)
|
||||
} else if accum.elfs64.is_empty() {
|
||||
bits_32::link(output, accum.elfs32)
|
||||
} else {
|
||||
// not all ELFs are either 32-bit or 64-bit
|
||||
bail!("not all elfs have the same bitness")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
struct Accum {
|
||||
elfs32: Vec<Elf32>,
|
||||
elfs64: Vec<Elf64>,
|
||||
}
|
||||
|
||||
fn sort_all_elfs_by_bitness(mut accum: Accum, unit: LinkUnit) -> Result<Accum> {
|
||||
match unit {
|
||||
LinkUnit::Path(path) => {
|
||||
let file = File::open(path)?;
|
||||
let elf = Elf::read(&file)?;
|
||||
println!("elf: {:?}", elf);
|
||||
// println!("elf: {:?}", elf);
|
||||
match elf {
|
||||
Elf::Elf32(v) => accum.elfs32.push(v),
|
||||
Elf::Elf64(v) => accum.elfs64.push(v),
|
||||
}
|
||||
_ => {}
|
||||
|
||||
Ok(accum)
|
||||
}
|
||||
|
||||
_ => bail!("lol"),
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(path) = &opt.out {
|
||||
let path = crate::utils::normalize_path(path);
|
||||
fn combine_accum(mut a: Accum, b: Accum) -> Result<Accum> {
|
||||
// TODO: early check to make sure at least one of these are 0
|
||||
Ok(Accum {
|
||||
elfs32: {
|
||||
a.elfs32.extend(b.elfs32);
|
||||
a.elfs32
|
||||
},
|
||||
elfs64: {
|
||||
a.elfs64.extend(b.elfs64);
|
||||
a.elfs64
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
macro_rules! link {
|
||||
() => {
|
||||
use std::fs::OpenOptions;
|
||||
use std::os::unix::fs::OpenOptionsExt;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
|
||||
pub fn link(output: PathBuf, elfs: Vec<Elf>) -> Result<()> {
|
||||
let res = Elf::default();
|
||||
println!("Hellosu {:?}", elfs);
|
||||
|
||||
let path = crate::utils::normalize_path(&output);
|
||||
let file = OpenOptions::new()
|
||||
.create(true)
|
||||
.write(true)
|
||||
.mode(0o755)
|
||||
.open(&path)
|
||||
.with_context(|| format!("could not create output file {:?}", path))?;
|
||||
res.write(file);
|
||||
println!("wrote to {:?}", path);
|
||||
}
|
||||
|
||||
res.write(file)?;
|
||||
Ok(())
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
mod bits_32 {
|
||||
pub type Elf = elf::elf32::Elf;
|
||||
link! {}
|
||||
}
|
||||
|
||||
mod bits_64 {
|
||||
pub type Elf = elf::elf64::Elf;
|
||||
link! {}
|
||||
}
|
||||
|
|
18
src/main.rs
18
src/main.rs
|
@ -1,3 +1,6 @@
|
|||
#[macro_use]
|
||||
extern crate anyhow;
|
||||
|
||||
mod link;
|
||||
mod utils;
|
||||
|
||||
|
@ -13,14 +16,14 @@ struct Opt {
|
|||
emulate: String,
|
||||
out: Option<PathBuf>,
|
||||
link_includes: Vec<PathBuf>,
|
||||
link_to: Vec<String>,
|
||||
units: Vec<LinkUnit>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum LinkUnit {
|
||||
Lib(String),
|
||||
Path(PathBuf),
|
||||
Group(Vec<PathBuf>),
|
||||
Group(Vec<LinkUnit>),
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
|
@ -54,18 +57,23 @@ fn main() -> Result<()> {
|
|||
let path = PathBuf::from(arg.trim_start_matches("-L"));
|
||||
opt.link_includes.push(path);
|
||||
} else if arg.starts_with("-l") {
|
||||
opt.link_to.push(arg.trim_start_matches("-l").to_owned());
|
||||
let name = arg.trim_start_matches("-l").to_owned();
|
||||
if let Some(curr_group) = curr_group.as_mut() {
|
||||
curr_group.push(LinkUnit::Lib(name));
|
||||
} else {
|
||||
opt.units.push(LinkUnit::Lib(name));
|
||||
}
|
||||
} else {
|
||||
let path = PathBuf::from(&arg);
|
||||
if let Some(curr_group) = curr_group.as_mut() {
|
||||
curr_group.push(path);
|
||||
curr_group.push(LinkUnit::Path(path));
|
||||
} else {
|
||||
opt.units.push(LinkUnit::Path(path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
link::link(&opt)?;
|
||||
link::link(opt)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::path::{Component, Path, PathBuf};
|
||||
|
||||
pub fn normalize_path(path: &Path) -> PathBuf {
|
||||
let mut components = path.components().peekable();
|
||||
pub fn normalize_path(path: impl AsRef<Path>) -> PathBuf {
|
||||
let mut components = path.as_ref().components().peekable();
|
||||
let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() {
|
||||
components.next();
|
||||
PathBuf::from(c.as_os_str())
|
||||
|
|
Loading…
Reference in a new issue