Skip to content

Commit

Permalink
Merge #19
Browse files Browse the repository at this point in the history
19: objdump: use -arch-name instead of -triple r=therealprof a=japaric

infer the arch-name from the output of `rustc --print cfg` is more robust than
just using the target name for the -triple flag.

fixes #17

r? @rust-embedded/tools (anyone)
cc @danc86

Co-authored-by: Jorge Aparicio <[email protected]>
  • Loading branch information
bors[bot] and japaric committed Aug 28, 2018
2 parents 0c397e1 + 85bcdc6 commit e1a5821
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/bin/cargo-objdump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::process;
fn main() {
match cbu::run(
true,
|ctxt| ctxt.objdump(ctxt.tool_args().iter().all(|s| !s.ends_with(".wasm"))),
|ctxt| ctxt.objdump(),
|_ctxt, stdout| stdout.into(),
) {
Err(e) => eprintln!("error: {}", e),
Expand Down
28 changes: 21 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,23 @@ use walkdir::WalkDir;
use config::Config;

mod config;
mod llvm;
mod rustc;

pub type Result<T> = std::result::Result<T, failure::Error>;

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Endian {
Little,
Big,
}

/// Execution context
// TODO this should be some sort of initialize once, read-only singleton
pub struct Context {
/// Directory within the Rust sysroot where the llvm tools reside
bindir: PathBuf,
cfg: rustc::Cfg,
host: String,
/// Regex to find mangled Rust symbols
re: Regex,
Expand Down Expand Up @@ -114,13 +123,16 @@ impl Context {
.stdout,
)?;

let cfg = rustc::Cfg::parse(target.as_ref().map(|s| &**s).unwrap_or(&host))?;

for entry in WalkDir::new(sysroot.trim()).into_iter() {
let entry = entry?;

if entry.file_name() == &*exe("llvm-size") {
let bindir = entry.path().parent().unwrap().to_owned();

return Ok(Context {
cfg,
bindir,
host,
re: Regex::new(r#"_Z.+?E\b"#).expect("BUG: Malformed Regex"),
Expand All @@ -146,14 +158,12 @@ impl Context {
self.tool("llvm-objcopy")
}

pub fn objdump(&self, append_triple: bool) -> Command {
pub fn objdump(&self) -> Command {
let mut objdump = self.tool("llvm-objdump");
if append_triple {
objdump.arg("-triple");
// NOTE assumes that the target name equates its "llvm-target" option. This may not be true
// for custom targets.
objdump.arg(self.target());
}
objdump.args(&[
"-arch-name",
llvm::arch_name(self.rustc_cfg(), self.target()),
]);
objdump
}

Expand Down Expand Up @@ -189,6 +199,10 @@ impl Context {
&self.host
}

fn rustc_cfg(&self) -> &rustc::Cfg {
&self.cfg
}

fn target(&self) -> &str {
self.target.as_ref().unwrap_or(&self.host)
}
Expand Down
88 changes: 88 additions & 0 deletions src/llvm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use {rustc, Endian};

// Here we map Rust arches to LLVM arches
//
// Rust knows these arches as of 1.28 (from librustc_target/abi/call/mod.rs)
//
// - aarch64
// - arm
// - asmjs (emscripten fork only)
// - hexagon
// - mips
// - mips64
// - msp430
// - nvptx
// - nvptx64
// - powerpc
// - riscv32
// - riscv64
// - s390x
// - sparc
// - sparc64
// - wasm32
// - x86
// - x86_64
//
// Rust LLVM knows these arches of 7.0 (from `llvm-objdump -version`)
//
// - aarch64
// - aarch64_be
// - arm
// - arm64
// - armeb
// - hexagon
// - mips
// - mips64
// - mips64el
// - mipsel
// - msp430
// - nvptx
// - nvptx64
// - ppc32
// - ppc64
// - ppc64le
// - riscv32
// - riscv64
// - sparc
// - sparcel
// - sparcv9
// - systemz
// - thumb
// - thumbeb
// - wasm32
// - wasm64
// - x86
// - x86-64
pub fn arch_name<'a>(cfg: &'a rustc::Cfg, target: &'a str) -> &'a str {
let endian = cfg.endian();
let arch = cfg.arch();

if target.starts_with("thumb") {
// no way to tell from `--print cfg` that the target is thumb only so we
// completely rely on the target name here
match endian {
Endian::Little => "thumb",
Endian::Big => "thumbeb",
}
} else {
match (arch, endian) {
// non standard endianness
("aarch64", Endian::Big) => "aarch64_be",
("arm", Endian::Big) => "armeb",
("mips", Endian::Little) => "mipsel",
("mips64", Endian::Little) => "mips64el",
("powerpc64", Endian::Little) => "ppc64le",
("sparc", Endian::Little) => "sparcel",

// names that match
("powerpc", _) => "ppc",
("powerpc64", Endian::Big) => "ppc64",
("sparc64", _) => "sparcv9",
("s390x", _) => "systemz",
("x86_64", _) => "x86-64",

// all the other names match as of 1.28
_ => arch,
}
}
}
71 changes: 71 additions & 0 deletions src/rustc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use std::process::Command;

use failure;

use {Endian, Result};

/// Parsed `rustc --print cfg`
pub struct Cfg {
arch: String,
endian: Endian,
}

impl Cfg {
pub fn arch(&self) -> &str {
&self.arch
}

pub fn endian(&self) -> Endian {
self.endian
}
}

impl Cfg {
pub fn parse(target: &str) -> Result<Self> {
const MSG: &str = "parsing `rustc --print cfg`";

let mut rustc = Command::new("rustc");
rustc.args(&["--target", target]);

let stdout = String::from_utf8(rustc.arg("--print").arg("cfg").output()?.stdout)?;

let mut arch = None;
let mut endian = None;
for line in stdout.lines() {
if line.starts_with("target_arch") {
arch = Some(
line.split('"')
.nth(1)
.map(|s| s.to_owned())
.ok_or_else(|| failure::err_msg(MSG))?,
);
} else if line.starts_with("target_endian") {
endian = Some(if line.ends_with("\"little\"") {
Endian::Little
} else {
Endian::Big
});
}
}

if let (Some(arch), Some(endian)) = (arch, endian) {
Ok(Cfg { arch, endian })
} else {
Err(failure::err_msg(MSG))
}
}
}

#[cfg(test)]
mod tests {
use super::Cfg;
use Endian;

#[test]
fn x86_64() {
let cfg = Cfg::parse("x86_64-unknown-linux-gnu").unwrap();

assert_eq!(cfg.arch, "x86_64");
assert_eq!(cfg.endian, Endian::Little);
}
}

0 comments on commit e1a5821

Please sign in to comment.