Skip to content

Commit df58fcf

Browse files
committed
Fix codegen with explicit allocation byte access
1 parent 7b941e3 commit df58fcf

File tree

1 file changed

+48
-7
lines changed

1 file changed

+48
-7
lines changed

src/librustc_codegen_llvm/consts.rs

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,21 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
3535
assert_eq!(offset as usize as u64, offset);
3636
let offset = offset as usize;
3737
if offset > next_offset {
38-
llvals.push(cx.const_bytes(&alloc.bytes[next_offset..offset]));
38+
// This `inspect` is okay since we have check that it is not within a relocation, it is
39+
// within the bounds of the allocation, and it doesn't affect interpreter execution (we
40+
// inspect the result after interpreter execution). Any undef byte is replaced with
41+
// some arbitrary byte value.
42+
//
43+
// FIXME: relay undef bytes to codegen as undef const bytes
44+
let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(next_offset..offset);
45+
llvals.push(cx.const_bytes(bytes));
3946
}
4047
let ptr_offset = read_target_uint(
4148
dl.endian,
42-
&alloc.bytes[offset..(offset + pointer_size)],
49+
// This `inspect` is okay since it is within the bounds of the allocation, it doesn't
50+
// affect interpreter execution (we inspect the result after interpreter execution),
51+
// and we properly interpret the relocation as a relocation pointer offset.
52+
alloc.inspect_with_undef_and_ptr_outside_interpreter(offset..(offset + pointer_size)),
4353
).expect("const_alloc_to_llvm: could not read relocation pointer") as u64;
4454
llvals.push(cx.scalar_to_backend(
4555
Pointer::new(alloc_id, Size::from_bytes(ptr_offset)).into(),
@@ -51,8 +61,16 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
5161
));
5262
next_offset = offset + pointer_size;
5363
}
54-
if alloc.bytes.len() >= next_offset {
55-
llvals.push(cx.const_bytes(&alloc.bytes[next_offset ..]));
64+
if alloc.len() >= next_offset {
65+
let range = next_offset..alloc.len();
66+
// This `inspect` is okay since we have check that it is after all relocations, it is
67+
// within the bounds of the allocation, and it doesn't affect interpreter execution (we
68+
// inspect the result after interpreter execution). Any undef byte is replaced with some
69+
// arbitrary byte value.
70+
//
71+
// FIXME: relay undef bytes to codegen as undef const bytes
72+
let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(range);
73+
llvals.push(cx.const_bytes(bytes));
5674
}
5775

5876
cx.const_struct(&llvals, true)
@@ -437,7 +455,23 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
437455
//
438456
// We could remove this hack whenever we decide to drop macOS 10.10 support.
439457
if self.tcx.sess.target.target.options.is_like_osx {
440-
let sect_name = if alloc.bytes.iter().all(|b| *b == 0) {
458+
assert_eq!(alloc.relocations.len(), 0);
459+
460+
let is_zeroed = {
461+
// Treats undefined bytes as if they were defined with the byte value that
462+
// happens to be currently assigned in mir. This is valid since reading
463+
// undef bytes may yield arbitrary values.
464+
//
465+
// FIXME: ignore undef bytes even with representation `!= 0`.
466+
//
467+
// The `inspect` method is okay here because we checked relocations, and
468+
// because we are doing this access to inspect the final interpreter state
469+
// (not as part of the interpreter execution).
470+
alloc.inspect_with_undef_and_ptr_outside_interpreter(0..alloc.len())
471+
.iter()
472+
.all(|b| *b == 0)
473+
};
474+
let sect_name = if is_zeroed {
441475
CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_bss\0")
442476
} else {
443477
CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_data\0")
@@ -456,10 +490,17 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
456490
section.as_str().as_ptr() as *const _,
457491
section.as_str().len() as c_uint,
458492
);
493+
assert!(alloc.relocations.is_empty());
494+
495+
// The `inspect` method is okay here because we checked relocations, and
496+
// because we are doing this access to inspect the final interpreter state (not
497+
// as part of the interpreter execution).
498+
let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(
499+
0..alloc.len());
459500
let alloc = llvm::LLVMMDStringInContext(
460501
self.llcx,
461-
alloc.bytes.as_ptr() as *const _,
462-
alloc.bytes.len() as c_uint,
502+
bytes.as_ptr() as *const _,
503+
bytes.len() as c_uint,
463504
);
464505
let data = [section, alloc];
465506
let meta = llvm::LLVMMDNodeInContext(self.llcx, data.as_ptr(), 2);

0 commit comments

Comments
 (0)