New user self-registration is disabled due to spam. For an account please email bugs-admin@lists.llvm.org with your e-mail address and full name.

Bug 43212 - After r360593, badly aligned offsets when using -N (aka --omagic)
Summary: After r360593, badly aligned offsets when using -N (aka --omagic)
Status: RESOLVED FIXED
Alias: None
Product: lld
Classification: Unclassified
Component: ELF (show other bugs)
Version: unspecified
Hardware: PC All
: P normal
Assignee: Unassigned LLVM Bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-09-03 12:23 PDT by Dimitry Andric
Modified: 2019-09-05 10:57 PDT (History)
7 users (show)

See Also:
Fixed By Commit(s):


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Dimitry Andric 2019-09-03 12:23:18 PDT
While attempting to build FreeBSD head with clang and lld 9.0.0, I ran into an error message from our elftoolchain-based objcopy, when stripping a boot loader related binary which was linked with lld:

objcopy: elf_update() failed: Layout constraint violation

The problem turns out to be the alignment of the .rodata section:

$ readelf -lSW /usr/obj/share/dim/src/freebsd/clang900-import/amd64.amd64/stand/i386/gptboot/gptboot.out
There are 19 section headers, starting at offset 0x2e454:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        00000000 000094 00a504 00  AX  0   0  4
  [ 2] .rodata           PROGBITS        0000a508 00a59c 0038fb 00 AMS  0   0  8
...
Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000094 0x00000000 0x00000000 0x0df3c 0x0df3c RWE 0x8
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0

E.g., .rodata starts at offset 0xa59c, while its alignment is supposed to be 8 bytes. Similarly, the LOAD segment has an offset of 0x94, while its alignment is 8 bytes.

This problem started occurring after https://reviews.llvm.org/rLLD360593 ("[ELF] Full support for -n (--nmagic) and -N (--omagic) via common page").  Before this change, the -N option got largely ignored, which is why we never saw this issue before.

Minimal test case:

$ cat align-test.s
        .text
        .globl  _start
_start:
        xor     %eax,%eax
        retl

        .rodata
        .align 8
        .quad 42

$ cc -m32 -c align-test.s

$ readelf -S align-test.o
There are 5 section headers, starting at offset 0x88:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .strtab           STRTAB          00000000 000060 000026 00      0   0  1
  [ 2] .text             PROGBITS        00000000 000034 000003 00  AX  0   0  4
  [ 3] .rodata           PROGBITS        00000000 000038 000008 00   A  0   0  8
  [ 4] .symtab           SYMTAB          00000000 000040 000020 10      1   1  4

################################################################
# with ld.lld r360592, everything is page-aligned, even while -N is used:

$ ~/llvm/trunk-r360592/bin/ld.lld -m elf_i386_fbsd -N -Ttext 0x0 -o align-test-r360592.out align-test.o

$ readelf -lS align-test-r360592.out

Elf file type is EXEC (Executable file)
Entry point 0x0
There are 2 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x001000 0x00000000 0x00000000 0x01000 0x01000 RWE 0x1000
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0

 Section to Segment mapping:
  Segment Sections...
   00     .text .rodata
   01
There are 7 section headers, starting at offset 0x20a4:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        00000000 001000 000003 00  AX  0   0  4
  [ 2] .rodata           PROGBITS        00000008 001008 000008 00   A  0   0  8
  [ 3] .comment          PROGBITS        00000000 002000 000047 01  MS  0   0  1
  [ 4] .symtab           SYMTAB          00000000 002048 000020 10      6   1  4
  [ 5] .shstrtab         STRTAB          00000000 002068 000032 00      0   0  1
  [ 6] .strtab           STRTAB          00000000 00209a 000008 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

################################################################
# with ld.lld r360593, -N does much more, but messes up the offsets:

$ ~/llvm/trunk-r360593/bin/ld.lld -m elf_i386_fbsd -N -Ttext 0x0 -o align-test-r360593.out align-test.o

$ readelf -lS align-test-r360593.out

Elf file type is EXEC (Executable file)
Entry point 0x0
There are 2 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000094 0x00000000 0x00000000 0x00010 0x00010 RWE 0x8
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0

 Section to Segment mapping:
  Segment Sections...
   00     .text .rodata
   01
There are 7 section headers, starting at offset 0x148:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        00000000 000094 000003 00  AX  0   0  4
  [ 2] .rodata           PROGBITS        00000008 00009c 000008 00   A  0   0  8
  [ 3] .comment          PROGBITS        00000000 0000a4 000047 01  MS  0   0  1
  [ 4] .symtab           SYMTAB          00000000 0000ec 000020 10      6   1  4
  [ 5] .shstrtab         STRTAB          00000000 00010c 000032 00      0   0  1
  [ 6] .strtab           STRTAB          00000000 00013e 000008 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)
Comment 1 Dimitry Andric 2019-09-03 12:25:29 PDT
Not sure if this should block 9.0, it's probably overkill, and we're already at rc3 ... :-/
Comment 2 Rui Ueyama 2019-09-04 02:03:55 PDT
I confirmed the issue and trying to fix it. It looks like a regression of the -N option, and it can cause a real issue due to unaligned accesses. If a fix is executed only when -N is given and is small, we may want to cherry-pick it to the LLVM9 tree.
Comment 3 Peter Smith 2019-09-04 03:05:10 PDT
As I remember it -n and -N disable page alignment by setting the max and common page size to 1. At a first guess there is some place in the code where there is an alignment done exclusively on pagesize and not max(os->alignment, pagesize) that is triggering a problem.
Comment 4 Fangrui Song 2019-09-05 09:27:33 PDT
ruiu fixed it in D67152/r371013.

dim, you may add it to the 9.0.1 wish list (once there is a tracking bug for 9.0.1)?
Comment 5 Dimitry Andric 2019-09-05 10:57:02 PDT
(In reply to Fangrui Song from comment #4)
> ruiu fixed it in D67152/r371013.
> 
> dim, you may add it to the 9.0.1 wish list (once there is a tracking bug for
> 9.0.1)?

Thanks, I will do that.  I have already pulled it into FreeBSD's import branch for 9.0.0, here: https://svnweb.freebsd.org/changeset/base/351879

Note that this also needs http://reviews.llvm.org/rLLD369828 as a prerequisite.