Skip to content
This repository was archived by the owner on Feb 15, 2026. It is now read-only.

Commit 4468519

Browse files
committed
Initial commit
0 parents  commit 4468519

File tree

4 files changed

+374
-0
lines changed

4 files changed

+374
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/target/
2+
**/*.rs.bk

Cargo.lock

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[package]
2+
name = "rlib_view"
3+
version = "0.1.0"
4+
authors = ["bjorn3 <bjorn3@users.noreply.github.com>"]
5+
6+
[dependencies]

src/main.rs

Lines changed: 362 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,362 @@
1+
#![feature(rustc_private)]
2+
3+
extern crate getopts;
4+
extern crate owning_ref;
5+
extern crate flate2;
6+
7+
extern crate syntax;
8+
extern crate rustc_data_structures;
9+
10+
extern crate rustc;
11+
extern crate rustc_back;
12+
extern crate rustc_errors;
13+
extern crate rustc_metadata;
14+
extern crate rustc_incremental;
15+
extern crate rustc_trans;
16+
extern crate rustc_driver;
17+
extern crate rustc_trans_utils;
18+
19+
use std::path::{Path, PathBuf};
20+
21+
use rustc::ty::TyCtxt;
22+
use rustc::session::Session;
23+
use rustc_metadata::cstore::CrateMetadata;
24+
use rustc_driver::{Compilation, RustcDefaultCalls};
25+
use rustc_driver::driver::CompileController;
26+
27+
fn find_sysroot() -> String {
28+
if let Ok(sysroot) = std::env::var("MIRI_SYSROOT") {
29+
return sysroot;
30+
}
31+
32+
// Taken from https://github.com/Manishearth/rust-clippy/pull/911.
33+
let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
34+
let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
35+
match (home, toolchain) {
36+
(Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
37+
_ => {
38+
option_env!("RUST_SYSROOT")
39+
.expect(
40+
"need to specify RUST_SYSROOT env var or use rustup or multirust",
41+
)
42+
.to_owned()
43+
}
44+
}
45+
}
46+
47+
fn main() {
48+
let rlib = ::std::env::args().skip(1).next().expect("No rlib given");
49+
println!("Reading rlib {}", rlib);
50+
51+
let mut args = ::std::env::args().collect::<Vec<_>>();
52+
let sysroot_flag = String::from("--sysroot");
53+
if !args.contains(&sysroot_flag) {
54+
args.push(sysroot_flag);
55+
args.push(find_sysroot());
56+
}
57+
println!("Rust args: {:?}", args);
58+
rustc_driver::run_compiler(
59+
&args,
60+
&mut MyCompilerCalls(RustcDefaultCalls, rlib.to_string()),
61+
Some(Box::new(MyFileLoader(rlib.to_string())) as Box<_>),
62+
None
63+
);
64+
}
65+
66+
struct MyFileLoader(String);
67+
68+
impl syntax::codemap::FileLoader for MyFileLoader {
69+
fn file_exists(&self, _: &Path) -> bool { true }
70+
fn abs_path(&self, _: &Path) -> Option<PathBuf> { None }
71+
fn read_file(&self, _: &Path) -> Result<String, ::std::io::Error> {
72+
Ok(format!("
73+
#![feature(no_core)]
74+
#![feature(rustc_private)]
75+
#![feature(panic_unwind)]
76+
#![feature(panic_abort)]
77+
#![feature(compiler_builtins_lib)]
78+
#![no_core]
79+
extern crate {};
80+
fn main() {{}}", self.0))
81+
}
82+
}
83+
84+
struct MyCompilerCalls(RustcDefaultCalls, String);
85+
86+
impl<'a> rustc_driver::CompilerCalls<'a> for MyCompilerCalls {
87+
fn build_controller(
88+
&mut self,
89+
sess: &Session,
90+
matches: &getopts::Matches
91+
) -> CompileController<'a> {
92+
let mut control = self.0.build_controller(sess, matches);
93+
control.after_analysis.stop = Compilation::Stop;
94+
control.after_analysis.callback = Box::new(|state|{
95+
let tcx = state.tcx.as_ref().unwrap();
96+
let mut extern_crate = None;
97+
for item in tcx.hir.krate().items.values() {
98+
match item.node {
99+
::rustc::hir::Item_::ItemExternCrate(_) => {
100+
extern_crate = Some(item.id);
101+
break;
102+
}
103+
_ => {}
104+
}
105+
}
106+
let ext_cnum = tcx.extern_mod_stmt_cnum(tcx.hir.local_def_id(extern_crate.unwrap())).unwrap();
107+
let crate_data = tcx.crate_data_as_rc_any(ext_cnum);
108+
let crate_data = crate_data.downcast_ref::<CrateMetadata>().unwrap();
109+
print_metadata(*tcx, crate_data);
110+
});
111+
control
112+
}
113+
}
114+
115+
macro_rules! language_item_table {
116+
( $( $variant:ident,$name:expr,$_method:ident; )* ) => {
117+
fn lang_item_name(lang_item: ::rustc::middle::lang_items::LangItem) -> &'static str {
118+
use rustc::middle::lang_items::LangItem;
119+
match lang_item {
120+
$(
121+
LangItem::$variant => $name
122+
),*
123+
}
124+
}
125+
};
126+
}
127+
128+
// Copied from librustc/middle/lang_items.rs
129+
language_item_table! {
130+
// Variant name, Name, Method name;
131+
CharImplItem, "char", char_impl;
132+
StrImplItem, "str", str_impl;
133+
SliceImplItem, "slice", slice_impl;
134+
SliceU8ImplItem, "slice_u8", slice_u8_impl;
135+
ConstPtrImplItem, "const_ptr", const_ptr_impl;
136+
MutPtrImplItem, "mut_ptr", mut_ptr_impl;
137+
I8ImplItem, "i8", i8_impl;
138+
I16ImplItem, "i16", i16_impl;
139+
I32ImplItem, "i32", i32_impl;
140+
I64ImplItem, "i64", i64_impl;
141+
I128ImplItem, "i128", i128_impl;
142+
IsizeImplItem, "isize", isize_impl;
143+
U8ImplItem, "u8", u8_impl;
144+
U16ImplItem, "u16", u16_impl;
145+
U32ImplItem, "u32", u32_impl;
146+
U64ImplItem, "u64", u64_impl;
147+
U128ImplItem, "u128", u128_impl;
148+
UsizeImplItem, "usize", usize_impl;
149+
F32ImplItem, "f32", f32_impl;
150+
F64ImplItem, "f64", f64_impl;
151+
152+
SizedTraitLangItem, "sized", sized_trait;
153+
UnsizeTraitLangItem, "unsize", unsize_trait;
154+
CopyTraitLangItem, "copy", copy_trait;
155+
CloneTraitLangItem, "clone", clone_trait;
156+
SyncTraitLangItem, "sync", sync_trait;
157+
FreezeTraitLangItem, "freeze", freeze_trait;
158+
159+
DropTraitLangItem, "drop", drop_trait;
160+
161+
CoerceUnsizedTraitLangItem, "coerce_unsized", coerce_unsized_trait;
162+
163+
AddTraitLangItem, "add", add_trait;
164+
SubTraitLangItem, "sub", sub_trait;
165+
MulTraitLangItem, "mul", mul_trait;
166+
DivTraitLangItem, "div", div_trait;
167+
RemTraitLangItem, "rem", rem_trait;
168+
NegTraitLangItem, "neg", neg_trait;
169+
NotTraitLangItem, "not", not_trait;
170+
BitXorTraitLangItem, "bitxor", bitxor_trait;
171+
BitAndTraitLangItem, "bitand", bitand_trait;
172+
BitOrTraitLangItem, "bitor", bitor_trait;
173+
ShlTraitLangItem, "shl", shl_trait;
174+
ShrTraitLangItem, "shr", shr_trait;
175+
AddAssignTraitLangItem, "add_assign", add_assign_trait;
176+
SubAssignTraitLangItem, "sub_assign", sub_assign_trait;
177+
MulAssignTraitLangItem, "mul_assign", mul_assign_trait;
178+
DivAssignTraitLangItem, "div_assign", div_assign_trait;
179+
RemAssignTraitLangItem, "rem_assign", rem_assign_trait;
180+
BitXorAssignTraitLangItem, "bitxor_assign", bitxor_assign_trait;
181+
BitAndAssignTraitLangItem, "bitand_assign", bitand_assign_trait;
182+
BitOrAssignTraitLangItem, "bitor_assign", bitor_assign_trait;
183+
ShlAssignTraitLangItem, "shl_assign", shl_assign_trait;
184+
ShrAssignTraitLangItem, "shr_assign", shr_assign_trait;
185+
IndexTraitLangItem, "index", index_trait;
186+
IndexMutTraitLangItem, "index_mut", index_mut_trait;
187+
188+
UnsafeCellTypeLangItem, "unsafe_cell", unsafe_cell_type;
189+
190+
DerefTraitLangItem, "deref", deref_trait;
191+
DerefMutTraitLangItem, "deref_mut", deref_mut_trait;
192+
193+
FnTraitLangItem, "fn", fn_trait;
194+
FnMutTraitLangItem, "fn_mut", fn_mut_trait;
195+
FnOnceTraitLangItem, "fn_once", fn_once_trait;
196+
197+
GeneratorStateLangItem, "generator_state", gen_state;
198+
GeneratorTraitLangItem, "generator", gen_trait;
199+
200+
EqTraitLangItem, "eq", eq_trait;
201+
OrdTraitLangItem, "ord", ord_trait;
202+
203+
// A number of panic-related lang items. The `panic` item corresponds to
204+
// divide-by-zero and various panic cases with `match`. The
205+
// `panic_bounds_check` item is for indexing arrays.
206+
//
207+
// The `begin_unwind` lang item has a predefined symbol name and is sort of
208+
// a "weak lang item" in the sense that a crate is not required to have it
209+
// defined to use it, but a final product is required to define it
210+
// somewhere. Additionally, there are restrictions on crates that use a weak
211+
// lang item, but do not have it defined.
212+
PanicFnLangItem, "panic", panic_fn;
213+
PanicBoundsCheckFnLangItem, "panic_bounds_check", panic_bounds_check_fn;
214+
PanicFmtLangItem, "panic_fmt", panic_fmt;
215+
216+
ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn;
217+
BoxFreeFnLangItem, "box_free", box_free_fn;
218+
DropInPlaceFnLangItem, "drop_in_place", drop_in_place_fn;
219+
220+
StartFnLangItem, "start", start_fn;
221+
222+
EhPersonalityLangItem, "eh_personality", eh_personality;
223+
EhUnwindResumeLangItem, "eh_unwind_resume", eh_unwind_resume;
224+
MSVCTryFilterLangItem, "msvc_try_filter", msvc_try_filter;
225+
226+
OwnedBoxLangItem, "owned_box", owned_box;
227+
228+
PhantomDataItem, "phantom_data", phantom_data;
229+
230+
NonZeroItem, "non_zero", non_zero;
231+
232+
DebugTraitLangItem, "debug_trait", debug_trait;
233+
234+
// A lang item for each of the 128-bit operators we can optionally lower.
235+
I128AddFnLangItem, "i128_add", i128_add_fn;
236+
U128AddFnLangItem, "u128_add", u128_add_fn;
237+
I128SubFnLangItem, "i128_sub", i128_sub_fn;
238+
U128SubFnLangItem, "u128_sub", u128_sub_fn;
239+
I128MulFnLangItem, "i128_mul", i128_mul_fn;
240+
U128MulFnLangItem, "u128_mul", u128_mul_fn;
241+
I128DivFnLangItem, "i128_div", i128_div_fn;
242+
U128DivFnLangItem, "u128_div", u128_div_fn;
243+
I128RemFnLangItem, "i128_rem", i128_rem_fn;
244+
U128RemFnLangItem, "u128_rem", u128_rem_fn;
245+
I128ShlFnLangItem, "i128_shl", i128_shl_fn;
246+
U128ShlFnLangItem, "u128_shl", u128_shl_fn;
247+
I128ShrFnLangItem, "i128_shr", i128_shr_fn;
248+
U128ShrFnLangItem, "u128_shr", u128_shr_fn;
249+
// And overflow versions for the operators that are checkable.
250+
// While MIR calls these Checked*, they return (T,bool), not Option<T>.
251+
I128AddoFnLangItem, "i128_addo", i128_addo_fn;
252+
U128AddoFnLangItem, "u128_addo", u128_addo_fn;
253+
I128SuboFnLangItem, "i128_subo", i128_subo_fn;
254+
U128SuboFnLangItem, "u128_subo", u128_subo_fn;
255+
I128MuloFnLangItem, "i128_mulo", i128_mulo_fn;
256+
U128MuloFnLangItem, "u128_mulo", u128_mulo_fn;
257+
I128ShloFnLangItem, "i128_shlo", i128_shlo_fn;
258+
U128ShloFnLangItem, "u128_shlo", u128_shlo_fn;
259+
I128ShroFnLangItem, "i128_shro", i128_shro_fn;
260+
U128ShroFnLangItem, "u128_shro", u128_shro_fn;
261+
}
262+
263+
fn print_metadata(tcx: TyCtxt, crate_data: &CrateMetadata) {
264+
use rustc::middle::lang_items::LangItem;
265+
use rustc_metadata::cstore::NativeLibraryKind;
266+
267+
macro_rules! svmeta {
268+
( @one $crate_data:expr; if $name:ident) => {
269+
if $crate_data.$name() {
270+
svmeta!(@print $name, $crate_data.$name());
271+
}
272+
};
273+
( @one $crate_data:expr; if $name:ident ($arg:expr)) => {
274+
if $crate_data.$name($arg) {
275+
svmeta!(@print $name, $crate_data.$name($arg));
276+
}
277+
};
278+
( @one $crate_data:expr; $name:ident) => {
279+
svmeta!(@print $name, $crate_data.$name());
280+
};
281+
( @one $crate_data:expr; $name:ident ($arg:expr)) => {
282+
svmeta!(@print $name, $crate_data.$name($arg));
283+
};
284+
( @one $crate_data:expr; $name:ident . $call:ident) => {
285+
svmeta!(@print $name, $crate_data.$name().$call());
286+
};
287+
( @print $name:ident, $val:expr) => {
288+
let name = stringify!($name);
289+
println!("{:<30}: {}", name, $val);
290+
};
291+
( $crate_data:expr; $( ($($tts:tt)*) )* ) => {
292+
$(
293+
svmeta!(@one $crate_data; $($tts)*);
294+
)*
295+
};
296+
}
297+
//println!("Name: {}", crate_data.name());
298+
//println!("Hash: {}", crate_data.hash());
299+
//println!("Disambiguator: {}", crate_data.disambiguator().to_fingerprint());
300+
svmeta! {
301+
crate_data;
302+
(name)
303+
(hash)
304+
(disambiguator.to_fingerprint)
305+
(needs_allocator(tcx.sess))
306+
(if has_global_allocator)
307+
(if has_default_lib_allocator)
308+
(if is_panic_runtime(tcx.sess))
309+
(if is_compiler_builtins(tcx.sess))
310+
(if is_sanitizer_runtime(tcx.sess))
311+
(if is_profiler_runtime(tcx.sess))
312+
(if is_no_builtins(tcx.sess))
313+
(if has_copy_closures(tcx.sess))
314+
(if has_clone_closures(tcx.sess))
315+
(panic_strategy.desc)
316+
}
317+
318+
println!("\nLang items:");
319+
for lang_item in crate_data.get_lang_items() {
320+
println!(" {}: {}",
321+
lang_item_name(LangItem::from_u32(lang_item.1 as u32).unwrap()),
322+
tcx.absolute_item_path_str(lang_item.0),
323+
);
324+
}
325+
326+
println!("\nExported symbols:");
327+
for def_id in crate_data.get_exported_symbols() {
328+
println!(" {}", tcx.absolute_item_path_str(def_id));
329+
}
330+
331+
println!("\nTrait impls:");
332+
let mut trait_impls = Vec::new();
333+
crate_data.get_implementations_for_trait(None, &mut trait_impls);
334+
for def_id in trait_impls {
335+
println!(" {}", tcx.absolute_item_path_str(def_id));
336+
}
337+
338+
println!("\nDependent rlibs");
339+
for dep in crate_data.root.crate_deps.decode(crate_data) {
340+
println!(" {:<26}: {:?} ({})", dep.name, dep.kind, dep.hash);
341+
}
342+
343+
println!("\nNative libraries:");
344+
for native_lib in crate_data.get_native_libraries(tcx.sess) {
345+
println!(" {:<26}: {}",
346+
native_lib.name,
347+
match native_lib.kind {
348+
NativeLibraryKind::NativeStatic => "static lib",
349+
NativeLibraryKind::NativeStaticNobundle => "static lib, not bundled",
350+
NativeLibraryKind::NativeFramework => "mac os framework",
351+
NativeLibraryKind::NativeUnknown => "<unknown>",
352+
}
353+
);
354+
}
355+
356+
println!("\nDylib dependency formats:");
357+
for dylib_deps in crate_data.get_dylib_dependency_formats() {
358+
let ext_crate_data = tcx.crate_data_as_rc_any(dylib_deps.0);
359+
let ext_crate_data = ext_crate_data.downcast_ref::<CrateMetadata>().unwrap();
360+
println!(" {:<26}: {:?}", ext_crate_data.name(), dylib_deps.1);
361+
}
362+
}

0 commit comments

Comments
 (0)