Skip to content

rustc_trans doesn't emit alignment information causing llvm to assume abi alignment #39376

Closed
@binarycrusader

Description

@binarycrusader

commit 7bc1054 attempted to fix unaligned loads, but appears to have only resolved part of the problem and may have unintentionally left things a little broken on architectures with strict alignment requirements.

That commit changed bytes_to_words to return &[Unaligned<u32>], but made that type #[repr(packed)].

I'm currently working with a fellow colleague on a port of rust to another architecture and we hit this:

Thread 4 received signal SIGSEGV, Segmentation fault.
[Switching to Thread 2 (LWP 2)]
0xffffffff50037b34 in rustc_metadata::schema::LazySeq<rustc_metadata::index::Index>::lookup (self=0xffffffff7b861df0, bytes=..., def_index=...)
    at /builds/rust.git/src/librustc_metadata/index.rs:73
73              let position = u32::from_le(words[index].get());
(gdb) print words
$37 = &[rustc_metadata::index::Unaligned<u32>] {data_ptr: 0xffffffff793ae6b6, length: 6908}
(gdb) print index
$38 = 5283
(gdb) print words[index]
$39 = rustc_metadata::index::Unaligned<u32> (4092795392)

A disassembly of the call site shows this:

(gdb) disassemble 0xffffffff50037b34-16,+32
Dump of assembler code from 0xffffffff50037b24 to 0xffffffff50037b44:
   0xffffffff50037b24 <rustc_metadata::schema::LazySeq<rustc_metadata::index::Index>::lookup+864>:      nop 
   0xffffffff50037b28 <rustc_metadata::schema::LazySeq<rustc_metadata::index::Index>::lookup+868>:      ldx  [ %fp + 0x627 ], %i0
   0xffffffff50037b2c <rustc_metadata::schema::LazySeq<rustc_metadata::index::Index>::lookup+872>:      ldx  [ %fp + 0x537 ], %i1
   0xffffffff50037b30 <rustc_metadata::schema::LazySeq<rustc_metadata::index::Index>::lookup+876>:      sllx  %i1, 2, %i2
=> 0xffffffff50037b34 <rustc_metadata::schema::LazySeq<rustc_metadata::index::Index>::lookup+880>:      ld  [ %i0 + %i2 ], %i0
   0xffffffff50037b38 <rustc_metadata::schema::LazySeq<rustc_metadata::index::Index>::lookup+884>:      st  %i0, [ %fp + 0x6e7 ]
   0xffffffff50037b3c <rustc_metadata::schema::LazySeq<rustc_metadata::index::Index>::lookup+888>:      st  %i0, [ %fp + 0x7d7 ]
   0xffffffff50037b40 <rustc_metadata::schema::LazySeq<rustc_metadata::index::Index>::lookup+892>:      call  0xffffffff50038054 <rustc_metadata::index::Unaligned<u32>::get<u32>>
(gdb) print/a $i0    
$40 = 0xffffffff793ae6b6
(gdb) print/a $i2
$41 = 0x528c
(gdb) print/a ($i0+$i2)
$42 = 0xffffffff793b3942
(gdb) print/x *($i0+$i2)
$44 = 0xf3f31a00

Now, if I'm not mistaken it looks like it's trying to perform an ld (aka lduw; load unsigned word) and a word is 4 bytes, but the offset of the memory address it's trying to read from is byte-aligned, not word-aligned, due to the #[repr(packed)], which I believe is causing the fault since what seems like a valid value appears to be there.

I suspect this is another case of issue #27060, but while we're waiting for that to be fixed, should the packed directive be removed instead?

I plan to try that fix myself soon, but wanted confirmation that was a reasonable change before attempting it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions