diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index 0077df3cf5e..26eb870cfc0 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -35,11 +35,21 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll assert_eq!(offset as usize as u64, offset); let offset = offset as usize; if offset > next_offset { - llvals.push(cx.const_bytes(&alloc.bytes[next_offset..offset])); + // This `inspect` is okay since we have check that it is not within a relocation, it is + // within the bounds of the allocation, and it doesn't affect interpreter execution (we + // inspect the result after interpreter execution). Any undef byte is replaced with + // some arbitrary byte value. + // + // FIXME: relay undef bytes to codegen as undef const bytes + let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(next_offset..offset); + llvals.push(cx.const_bytes(bytes)); } let ptr_offset = read_target_uint( dl.endian, - &alloc.bytes[offset..(offset + pointer_size)], + // This `inspect` is okay since it is within the bounds of the allocation, it doesn't + // affect interpreter execution (we inspect the result after interpreter execution), + // and we properly interpret the relocation as a relocation pointer offset. + alloc.inspect_with_undef_and_ptr_outside_interpreter(offset..(offset + pointer_size)), ).expect("const_alloc_to_llvm: could not read relocation pointer") as u64; llvals.push(cx.scalar_to_backend( 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 )); next_offset = offset + pointer_size; } - if alloc.bytes.len() >= next_offset { - llvals.push(cx.const_bytes(&alloc.bytes[next_offset ..])); + if alloc.len() >= next_offset { + let range = next_offset..alloc.len(); + // This `inspect` is okay since we have check that it is after all relocations, it is + // within the bounds of the allocation, and it doesn't affect interpreter execution (we + // inspect the result after interpreter execution). Any undef byte is replaced with some + // arbitrary byte value. + // + // FIXME: relay undef bytes to codegen as undef const bytes + let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(range); + llvals.push(cx.const_bytes(bytes)); } cx.const_struct(&llvals, true) @@ -437,7 +455,23 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { // // We could remove this hack whenever we decide to drop macOS 10.10 support. if self.tcx.sess.target.target.options.is_like_osx { - let sect_name = if alloc.bytes.iter().all(|b| *b == 0) { + assert_eq!(alloc.relocations.len(), 0); + + let is_zeroed = { + // Treats undefined bytes as if they were defined with the byte value that + // happens to be currently assigned in mir. This is valid since reading + // undef bytes may yield arbitrary values. + // + // FIXME: ignore undef bytes even with representation `!= 0`. + // + // The `inspect` method is okay here because we checked relocations, and + // because we are doing this access to inspect the final interpreter state + // (not as part of the interpreter execution). + alloc.inspect_with_undef_and_ptr_outside_interpreter(0..alloc.len()) + .iter() + .all(|b| *b == 0) + }; + let sect_name = if is_zeroed { CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_bss\0") } else { CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_data\0") @@ -456,10 +490,17 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { section.as_str().as_ptr() as *const _, section.as_str().len() as c_uint, ); + assert!(alloc.relocations.is_empty()); + + // The `inspect` method is okay here because we checked relocations, and + // because we are doing this access to inspect the final interpreter state (not + // as part of the interpreter execution). + let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter( + 0..alloc.len()); let alloc = llvm::LLVMMDStringInContext( self.llcx, - alloc.bytes.as_ptr() as *const _, - alloc.bytes.len() as c_uint, + bytes.as_ptr() as *const _, + bytes.len() as c_uint, ); let data = [section, alloc]; let meta = llvm::LLVMMDNodeInContext(self.llcx, data.as_ptr(), 2);