Skip to content

Commit a28c085

Browse files
authored
Merge pull request rust-lang#174 from wasmerio/reloc-past-the-end
Don't increment the iterator while a Section/Relocation/Symbol is using it.
2 parents 777ef66 + 09c4e96 commit a28c085

File tree

3 files changed

+244
-16
lines changed

3 files changed

+244
-16
lines changed

src/object_file.rs

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ impl Drop for ObjectFile {
4848
pub struct SectionIterator {
4949
section_iterator: LLVMSectionIteratorRef,
5050
object_file: LLVMObjectFileRef,
51+
before_first: bool,
5152
}
5253

5354
impl SectionIterator {
@@ -56,7 +57,8 @@ impl SectionIterator {
5657

5758
SectionIterator {
5859
section_iterator,
59-
object_file
60+
object_file,
61+
before_first: true
6062
}
6163
}
6264
}
@@ -65,7 +67,14 @@ impl Iterator for SectionIterator {
6567
type Item = Section;
6668

6769
fn next(&mut self) -> Option<Self::Item> {
68-
// REVIEW: Should it compare against 1? End checking order might also be off
70+
if self.before_first {
71+
self.before_first = false;
72+
} else {
73+
unsafe {
74+
LLVMMoveToNextSection(self.section_iterator);
75+
}
76+
}
77+
6978
let at_end = unsafe {
7079
LLVMIsSectionIteratorAtEnd(self.object_file, self.section_iterator) == 1
7180
};
@@ -76,10 +85,6 @@ impl Iterator for SectionIterator {
7685

7786
let section = Section::new(self.section_iterator, self.object_file);
7887

79-
unsafe {
80-
LLVMMoveToNextSection(self.section_iterator)
81-
}
82-
8388
Some(section)
8489
}
8590
}
@@ -151,6 +156,7 @@ pub struct RelocationIterator {
151156
relocation_iterator: LLVMRelocationIteratorRef,
152157
section_iterator: LLVMSectionIteratorRef,
153158
object_file: LLVMObjectFileRef,
159+
before_first: bool,
154160
}
155161

156162
impl RelocationIterator {
@@ -161,6 +167,7 @@ impl RelocationIterator {
161167
relocation_iterator,
162168
section_iterator,
163169
object_file,
170+
before_first: true
164171
}
165172
}
166173
}
@@ -169,7 +176,14 @@ impl Iterator for RelocationIterator {
169176
type Item = Relocation;
170177

171178
fn next(&mut self) -> Option<Self::Item> {
172-
// REVIEW: Should it compare against 1? End checking order might also be off
179+
if self.before_first {
180+
self.before_first = false;
181+
} else {
182+
unsafe {
183+
LLVMMoveToNextRelocation(self.relocation_iterator)
184+
}
185+
}
186+
173187
let at_end = unsafe {
174188
LLVMIsRelocationIteratorAtEnd(self.section_iterator, self.relocation_iterator) == 1
175189
};
@@ -180,10 +194,6 @@ impl Iterator for RelocationIterator {
180194

181195
let relocation = Relocation::new(self.relocation_iterator, self.object_file);
182196

183-
unsafe {
184-
LLVMMoveToNextRelocation(self.relocation_iterator)
185-
}
186-
187197
Some(relocation)
188198
}
189199
}
@@ -249,6 +259,7 @@ impl Relocation {
249259
pub struct SymbolIterator {
250260
symbol_iterator: LLVMSymbolIteratorRef,
251261
object_file: LLVMObjectFileRef,
262+
before_first: bool,
252263
}
253264

254265
impl SymbolIterator {
@@ -258,6 +269,7 @@ impl SymbolIterator {
258269
SymbolIterator {
259270
symbol_iterator,
260271
object_file,
272+
before_first: true
261273
}
262274
}
263275
}
@@ -266,7 +278,14 @@ impl Iterator for SymbolIterator {
266278
type Item = Symbol;
267279

268280
fn next(&mut self) -> Option<Self::Item> {
269-
// REVIEW: Should it compare against 1? End checking order might also be off
281+
if self.before_first {
282+
self.before_first = false;
283+
} else {
284+
unsafe {
285+
LLVMMoveToNextSymbol(self.symbol_iterator)
286+
}
287+
}
288+
270289
let at_end = unsafe {
271290
LLVMIsSymbolIteratorAtEnd(self.object_file, self.symbol_iterator) == 1
272291
};
@@ -277,10 +296,6 @@ impl Iterator for SymbolIterator {
277296

278297
let symbol = Symbol::new(self.symbol_iterator);
279298

280-
unsafe {
281-
LLVMMoveToNextSymbol(self.symbol_iterator)
282-
}
283-
284299
Some(symbol)
285300
}
286301
}

tests/all/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ mod test_context;
1212
mod test_execution_engine;
1313
mod test_instruction_values;
1414
mod test_module;
15+
mod test_object_file;
1516
mod test_passes;
1617
mod test_targets;
1718
mod test_tari_example;

tests/all/test_object_file.rs

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
extern crate inkwell;
2+
3+
use self::inkwell::context::Context;
4+
use self::inkwell::module::Module;
5+
use self::inkwell::targets::{
6+
CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetMachine,
7+
};
8+
use self::inkwell::types::IntType;
9+
use self::inkwell::values::BasicValue;
10+
use self::inkwell::OptimizationLevel;
11+
12+
#[llvm_versions(7.0..=latest)]
13+
fn get_host_cpu_name() -> String {
14+
TargetMachine::get_host_cpu_name().to_string()
15+
}
16+
#[llvm_versions(7.0..=latest)]
17+
fn get_host_cpu_features() -> String {
18+
TargetMachine::get_host_cpu_features().to_string()
19+
}
20+
#[llvm_versions(4.0..=latest)]
21+
fn ptr_sized_int_type<'ctx>(
22+
target_machine: &TargetMachine,
23+
context: &'ctx Context,
24+
) -> IntType<'ctx> {
25+
let target_data = target_machine.get_target_data();
26+
target_data.ptr_sized_int_type_in_context(&context, None)
27+
}
28+
#[llvm_versions(4.0..=latest)]
29+
fn apply_target_to_module<'ctx>(target_machine: &TargetMachine, module: &Module) {
30+
module.set_triple(&target_machine.get_triple());
31+
module.set_data_layout(&target_machine.get_target_data().get_data_layout());
32+
}
33+
34+
#[llvm_versions(3.6..7.0)]
35+
fn get_host_cpu_name() -> String {
36+
"".to_string()
37+
}
38+
#[llvm_versions(3.6..7.0)]
39+
fn get_host_cpu_features() -> String {
40+
"".to_string()
41+
}
42+
#[llvm_versions(3.6..4.0)]
43+
fn ptr_sized_int_type<'ctx>(
44+
_target_machine: &TargetMachine,
45+
context: &'ctx Context,
46+
) -> IntType<'ctx> {
47+
context.i64_type()
48+
}
49+
#[llvm_versions(3.6..4.0)]
50+
fn apply_target_to_module(target_machine: &TargetMachine, module: &Module) {
51+
module.set_triple(&target_machine.get_triple());
52+
}
53+
54+
fn get_native_target_machine() -> TargetMachine {
55+
Target::initialize_native(&InitializationConfig::default())
56+
.expect("Failed to initialize native target");
57+
let target_triple = TargetMachine::get_default_triple();
58+
let target = Target::from_triple(&target_triple).unwrap();
59+
target
60+
.create_target_machine(
61+
&target_triple,
62+
&get_host_cpu_name(),
63+
&get_host_cpu_features(),
64+
OptimizationLevel::None,
65+
RelocMode::Default,
66+
CodeModel::Default,
67+
)
68+
.unwrap()
69+
}
70+
71+
#[test]
72+
fn test_section_iterator() {
73+
let target_machine = get_native_target_machine();
74+
75+
let context = Context::create();
76+
let mut module = context.create_module("test_section_iterator");
77+
78+
let gv_a = module.add_global(context.i8_type(), None, "a");
79+
gv_a.set_initializer(&context.i8_type().const_zero().as_basic_value_enum());
80+
gv_a.set_section("A");
81+
82+
let gv_b = module.add_global(context.i16_type(), None, "b");
83+
gv_b.set_initializer(&context.i16_type().const_zero().as_basic_value_enum());
84+
gv_b.set_section("B");
85+
86+
let gv_c = module.add_global(context.i32_type(), None, "c");
87+
gv_c.set_initializer(&context.i32_type().const_zero().as_basic_value_enum());
88+
gv_c.set_section("C");
89+
90+
apply_target_to_module(&target_machine, &module);
91+
92+
let memory_buffer = target_machine
93+
.write_to_memory_buffer(&mut module, FileType::Object)
94+
.unwrap();
95+
let object_file = memory_buffer.create_object_file().unwrap();
96+
97+
let mut has_section_a = false;
98+
let mut has_section_b = false;
99+
let mut has_section_c = false;
100+
for section in object_file.get_sections() {
101+
if let Some(name) = section.get_name() {
102+
match name.to_str().unwrap() {
103+
"A" => {
104+
assert!(!has_section_a);
105+
has_section_a = true;
106+
assert_eq!(section.size(), 1);
107+
}
108+
"B" => {
109+
assert!(!has_section_b);
110+
has_section_b = true;
111+
assert_eq!(section.size(), 2);
112+
}
113+
"C" => {
114+
assert!(!has_section_c);
115+
has_section_c = true;
116+
assert_eq!(section.size(), 4);
117+
}
118+
_ => {}
119+
}
120+
}
121+
}
122+
assert!(has_section_a);
123+
assert!(has_section_b);
124+
assert!(has_section_c);
125+
}
126+
127+
#[test]
128+
fn test_symbol_iterator() {
129+
let target_machine = get_native_target_machine();
130+
131+
let context = Context::create();
132+
let mut module = context.create_module("test_symbol_iterator");
133+
module
134+
.add_global(context.i8_type(), None, "a")
135+
.set_initializer(&context.i8_type().const_zero().as_basic_value_enum());
136+
module
137+
.add_global(context.i16_type(), None, "b")
138+
.set_initializer(&context.i16_type().const_zero().as_basic_value_enum());
139+
module
140+
.add_global(context.i32_type(), None, "c")
141+
.set_initializer(&context.i32_type().const_zero().as_basic_value_enum());
142+
apply_target_to_module(&target_machine, &module);
143+
144+
let memory_buffer = target_machine
145+
.write_to_memory_buffer(&mut module, FileType::Object)
146+
.unwrap();
147+
let object_file = memory_buffer.create_object_file().unwrap();
148+
149+
let mut has_symbol_a = false;
150+
let mut has_symbol_b = false;
151+
let mut has_symbol_c = false;
152+
for symbol in object_file.get_symbols() {
153+
if let Some(name) = symbol.get_name() {
154+
match name.to_str().unwrap() {
155+
"a" => {
156+
assert!(!has_symbol_a);
157+
has_symbol_a = true;
158+
assert_eq!(symbol.size(), 1);
159+
}
160+
"b" => {
161+
assert!(!has_symbol_b);
162+
has_symbol_b = true;
163+
assert_eq!(symbol.size(), 2);
164+
}
165+
"c" => {
166+
assert!(!has_symbol_c);
167+
has_symbol_c = true;
168+
assert_eq!(symbol.size(), 4);
169+
}
170+
_ => {}
171+
}
172+
}
173+
}
174+
assert!(has_symbol_a);
175+
assert!(has_symbol_b);
176+
assert!(has_symbol_c);
177+
}
178+
179+
#[test]
180+
fn test_reloc_iterator() {
181+
let target_machine = get_native_target_machine();
182+
183+
let context = Context::create();
184+
let intptr_t = ptr_sized_int_type(&target_machine, &context);
185+
186+
let mut module = context.create_module("test_reloc_iterator");
187+
let x_ptr = module
188+
.add_global(context.i8_type(), None, "x")
189+
.as_pointer_value();
190+
let x_plus_4 = x_ptr
191+
.const_to_int(intptr_t)
192+
.const_add(intptr_t.const_int(4, false));
193+
module
194+
.add_global(intptr_t, None, "a")
195+
.set_initializer(&x_plus_4);
196+
197+
apply_target_to_module(&target_machine, &module);
198+
199+
let memory_buffer = target_machine
200+
.write_to_memory_buffer(&mut module, FileType::Object)
201+
.unwrap();
202+
let object_file = memory_buffer.create_object_file().unwrap();
203+
204+
let mut found_relocation = false;
205+
for section in object_file.get_sections() {
206+
for _ in section.get_relocations() {
207+
found_relocation = true;
208+
// We don't stop the traversal here, so as to exercise the iterators.
209+
}
210+
}
211+
assert!(found_relocation);
212+
}

0 commit comments

Comments
 (0)