Skip to content

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

@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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions