@@ -35,11 +35,21 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
35
35
assert_eq ! ( offset as usize as u64 , offset) ;
36
36
let offset = offset as usize ;
37
37
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) ) ;
39
46
}
40
47
let ptr_offset = read_target_uint (
41
48
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) ) ,
43
53
) . expect ( "const_alloc_to_llvm: could not read relocation pointer" ) as u64 ;
44
54
llvals. push ( cx. scalar_to_backend (
45
55
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
51
61
) ) ;
52
62
next_offset = offset + pointer_size;
53
63
}
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) ) ;
56
74
}
57
75
58
76
cx. const_struct ( & llvals, true )
@@ -437,7 +455,23 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
437
455
//
438
456
// We could remove this hack whenever we decide to drop macOS 10.10 support.
439
457
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 {
441
475
CStr :: from_bytes_with_nul_unchecked ( b"__DATA,__thread_bss\0 " )
442
476
} else {
443
477
CStr :: from_bytes_with_nul_unchecked ( b"__DATA,__thread_data\0 " )
@@ -456,10 +490,17 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
456
490
section. as_str ( ) . as_ptr ( ) as * const _ ,
457
491
section. as_str ( ) . len ( ) as c_uint ,
458
492
) ;
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 ( ) ) ;
459
500
let alloc = llvm:: LLVMMDStringInContext (
460
501
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 ,
463
504
) ;
464
505
let data = [ section, alloc] ;
465
506
let meta = llvm:: LLVMMDNodeInContext ( self . llcx , data. as_ptr ( ) , 2 ) ;
0 commit comments