Skip to content

Commit 75c24b9

Browse files
authored
Merge pull request rust-lang#758 from bjorn3/object_write
Add object::write as alternative object file writer
2 parents 8243a37 + 1901571 commit 75c24b9

File tree

10 files changed

+307
-95
lines changed

10 files changed

+307
-95
lines changed

.travis.yml

+3
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,6 @@ env:
2121
- RUST_BACKTRACE=1
2222
# Reduce amount of benchmark runs as they are slow.
2323
- COMPILE_RUNS=2 RUN_RUNS=2
24+
jobs:
25+
- "CG_CLIF_COMPILE_FLAGS="
26+
- "CG_CLIF_COMPILE_FLAGS='--features backend_object'"

Cargo.lock

+15
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+5
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,15 @@ edition = "2018"
99
[lib]
1010
crate-type = ["dylib"]
1111

12+
[features]
13+
backend_object = ["object/write", "cranelift-object"]
14+
1215
[dependencies]
1316
# These have to be in sync with each other
1417
cranelift = { git = "https://github.com/CraneStation/cranelift.git" }
1518
cranelift-module = { git = "https://github.com/CraneStation/cranelift.git" }
1619
cranelift-faerie = { git = "https://github.com/CraneStation/cranelift.git" }
20+
cranelift-object = { git = "https://github.com/CraneStation/cranelift.git", optional = true }
1721
target-lexicon = "0.8.1"
1822
faerie = "0.11.0"
1923

@@ -36,6 +40,7 @@ features = ["compression", "read", "std"] # We don't need WASM support
3640
#cranelift-module = { path = "../cranelift/cranelift-module" }
3741
#cranelift-simplejit = { path = "../cranelift/cranelift-simplejit" }
3842
#cranelift-faerie = { path = "../cranelift/cranelift-faerie" }
43+
#cranelift-object = { path = "../cranelift/cranelift-object" }
3944

4045
#[patch.crates-io]
4146
#gimli = { path = "../" }

src/backend.rs

+222
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
use std::collections::HashMap;
2+
3+
use rustc::session::Session;
4+
5+
use cranelift_module::{FuncId, Module};
6+
7+
use faerie::*;
8+
#[cfg(feature = "backend_object")]
9+
use object::{SectionKind, RelocationKind, RelocationEncoding};
10+
#[cfg(feature = "backend_object")]
11+
use object::write::*;
12+
use cranelift_faerie::{FaerieBackend, FaerieBuilder, FaerieProduct, FaerieTrapCollection};
13+
14+
#[cfg(feature = "backend_object")]
15+
use cranelift_object::*;
16+
17+
use gimli::SectionId;
18+
19+
use crate::debuginfo::{DebugReloc, DebugRelocName};
20+
21+
pub trait WriteMetadata {
22+
fn add_rustc_section(&mut self, symbol_name: String, data: Vec<u8>, is_like_osx: bool);
23+
}
24+
25+
impl WriteMetadata for faerie::Artifact {
26+
fn add_rustc_section(&mut self, symbol_name: String, data: Vec<u8>, is_like_osx: bool) {
27+
self
28+
.declare(".rustc", faerie::Decl::section(faerie::SectionKind::Data))
29+
.unwrap();
30+
self
31+
.define_with_symbols(".rustc", data, {
32+
let mut map = std::collections::BTreeMap::new();
33+
// FIXME implement faerie elf backend section custom symbols
34+
// For MachO this is necessary to prevent the linker from throwing away the .rustc section,
35+
// but for ELF it isn't.
36+
if is_like_osx {
37+
map.insert(
38+
symbol_name,
39+
0,
40+
);
41+
}
42+
map
43+
})
44+
.unwrap();
45+
}
46+
}
47+
48+
#[cfg(feature = "backend_object")]
49+
impl WriteMetadata for object::write::Object {
50+
fn add_rustc_section(&mut self, symbol_name: String, data: Vec<u8>, _is_like_osx: bool) {
51+
let segment = self.segment_name(object::write::StandardSegment::Data).to_vec();
52+
let section_id = self.add_section(segment, b".rustc".to_vec(), object::SectionKind::Data);
53+
let offset = self.append_section_data(section_id, &data, 1);
54+
// For MachO and probably PE this is necessary to prevent the linker from throwing away the
55+
// .rustc section. For ELF this isn't necessary, but it also doesn't harm.
56+
self.add_symbol(object::write::Symbol {
57+
name: symbol_name.into_bytes(),
58+
value: offset,
59+
size: data.len() as u64,
60+
kind: object::SymbolKind::Data,
61+
scope: object::SymbolScope::Dynamic,
62+
weak: false,
63+
section: Some(section_id),
64+
});
65+
}
66+
}
67+
68+
pub trait WriteDebugInfo {
69+
type SectionId;
70+
71+
fn add_debug_section(&mut self, name: SectionId, data: Vec<u8>) -> Self::SectionId;
72+
fn add_debug_reloc(
73+
&mut self,
74+
section_map: &HashMap<SectionId, Self::SectionId>,
75+
symbol_map: &indexmap::IndexMap<FuncId, String>,
76+
from: &Self::SectionId,
77+
reloc: &DebugReloc,
78+
);
79+
}
80+
81+
impl WriteDebugInfo for FaerieProduct {
82+
type SectionId = SectionId;
83+
84+
fn add_debug_section(&mut self, id: SectionId, data: Vec<u8>) -> SectionId {
85+
self.artifact.declare_with(id.name(), Decl::section(faerie::SectionKind::Debug), data).unwrap();
86+
id
87+
}
88+
89+
fn add_debug_reloc(
90+
&mut self,
91+
_section_map: &HashMap<SectionId, Self::SectionId>,
92+
symbol_map: &indexmap::IndexMap<FuncId, String>,
93+
from: &Self::SectionId,
94+
reloc: &DebugReloc,
95+
) {
96+
self
97+
.artifact
98+
.link_with(
99+
faerie::Link {
100+
from: from.name(),
101+
to: match reloc.name {
102+
DebugRelocName::Section(id) => id.name(),
103+
DebugRelocName::Symbol(index) => &symbol_map.get_index(index).unwrap().1,
104+
},
105+
at: u64::from(reloc.offset),
106+
},
107+
faerie::Reloc::Debug {
108+
size: reloc.size,
109+
addend: reloc.addend as i32,
110+
},
111+
)
112+
.expect("faerie relocation error");
113+
}
114+
}
115+
116+
#[cfg(feature = "backend_object")]
117+
impl WriteDebugInfo for ObjectProduct {
118+
type SectionId = (object::write::SectionId, object::write::SymbolId);
119+
120+
fn add_debug_section(
121+
&mut self,
122+
id: SectionId,
123+
data: Vec<u8>,
124+
) -> (object::write::SectionId, object::write::SymbolId) {
125+
let segment = self.object.segment_name(StandardSegment::Debug).to_vec();
126+
let name = id.name().as_bytes().to_vec();
127+
let section_id = self.object.add_section(segment, name, SectionKind::Debug);
128+
self.object.section_mut(section_id).set_data(data, 1);
129+
let symbol_id = self.object.section_symbol(section_id);
130+
(section_id, symbol_id)
131+
}
132+
133+
fn add_debug_reloc(
134+
&mut self,
135+
section_map: &HashMap<SectionId, Self::SectionId>,
136+
symbol_map: &indexmap::IndexMap<FuncId, String>,
137+
from: &Self::SectionId,
138+
reloc: &DebugReloc,
139+
) {
140+
let symbol = match reloc.name {
141+
DebugRelocName::Section(id) => section_map.get(&id).unwrap().1,
142+
DebugRelocName::Symbol(id) => {
143+
self.function_symbol(*symbol_map.get_index(id).unwrap().0)
144+
}
145+
};
146+
self.object.add_relocation(from.0, Relocation {
147+
offset: u64::from(reloc.offset),
148+
symbol,
149+
kind: RelocationKind::Absolute,
150+
encoding: RelocationEncoding::Generic,
151+
size: reloc.size * 8,
152+
addend: reloc.addend,
153+
}).unwrap();
154+
}
155+
}
156+
157+
pub trait Emit {
158+
fn emit(self) -> Vec<u8>;
159+
}
160+
161+
impl Emit for FaerieProduct {
162+
fn emit(self) -> Vec<u8> {
163+
self.artifact.emit().unwrap()
164+
}
165+
}
166+
167+
#[cfg(feature = "backend_object")]
168+
impl Emit for ObjectProduct {
169+
fn emit(self) -> Vec<u8> {
170+
self.object.write().unwrap()
171+
}
172+
}
173+
174+
#[cfg(not(feature = "backend_object"))]
175+
pub fn with_object(sess: &Session, name: &str, f: impl FnOnce(&mut Artifact)) -> Vec<u8> {
176+
let mut metadata_artifact = faerie::Artifact::new(
177+
crate::build_isa(sess, true).triple().clone(),
178+
name.to_string(),
179+
);
180+
f(&mut metadata_artifact);
181+
metadata_artifact.emit().unwrap()
182+
}
183+
184+
#[cfg(feature = "backend_object")]
185+
pub fn with_object(sess: &Session, name: &str, f: impl FnOnce(&mut Object)) -> Vec<u8> {
186+
let triple = crate::build_isa(sess, true).triple().clone();
187+
let mut metadata_object =
188+
object::write::Object::new(triple.binary_format, triple.architecture);
189+
metadata_object.add_file_symbol(name.as_bytes().to_vec());
190+
f(&mut metadata_object);
191+
metadata_object.write().unwrap()
192+
}
193+
194+
pub type Backend = impl cranelift_module::Backend<Product: Emit + WriteDebugInfo>;
195+
196+
#[cfg(not(feature = "backend_object"))]
197+
pub fn make_module(sess: &Session, name: String) -> Module<Backend> {
198+
let module: Module<FaerieBackend> = Module::new(
199+
FaerieBuilder::new(
200+
crate::build_isa(sess, true),
201+
name + ".o",
202+
FaerieTrapCollection::Disabled,
203+
cranelift_module::default_libcall_names(),
204+
)
205+
.unwrap(),
206+
);
207+
module
208+
}
209+
210+
#[cfg(feature = "backend_object")]
211+
pub fn make_module(sess: &Session, name: String) -> Module<Backend> {
212+
let module: Module<ObjectBackend> = Module::new(
213+
ObjectBuilder::new(
214+
crate::build_isa(sess, true),
215+
name + ".o",
216+
ObjectTrapCollection::Disabled,
217+
cranelift_module::default_libcall_names(),
218+
)
219+
.unwrap(),
220+
);
221+
module
222+
}

src/base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub fn trans_fn<'clif, 'tcx, B: Backend + 'static>(
1717
let mut debug_context = cx
1818
.debug_context
1919
.as_mut()
20-
.map(|debug_context| FunctionDebugContext::new(tcx, debug_context, mir, &name, &sig));
20+
.map(|debug_context| FunctionDebugContext::new(tcx, debug_context, mir, func_id, &name, &sig));
2121

2222
// Make FunctionBuilder
2323
let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig);

0 commit comments

Comments
 (0)