Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lld has different section attribute merging vs ld.bfd #29763

Closed
emaste opened this issue Sep 16, 2016 · 8 comments
Closed

lld has different section attribute merging vs ld.bfd #29763

emaste opened this issue Sep 16, 2016 · 8 comments
Labels
bugzilla Issues migrated from bugzilla lld:ELF

Comments

@emaste
Copy link
Member

emaste commented Sep 16, 2016

Bugzilla Link 30415
Resolution FIXED
Resolved on Jul 25, 2019 22:24
Version unspecified
OS FreeBSD
Blocks #23588
CC @MaskRay

Extended Description

LLD is not necessarily wrong here and what ld.bfd is doing is arguably a bug, but I'm submitting this PR for tracking one of the few outstanding issues linking FreeBSD/amd64 with LLD while looking for a solution.

We recently migrated to using a linker script instead of the seemingly obsolete -N command line flag for FreeBSD's boot loader components: https://svnweb.freebsd.org/base?view=revision&revision=305353

The linker script is straightforward:


/* $FreeBSD$ /
/
Merge text, data and bss together almost no padding */
OUTPUT_FORMAT("elf32-i386-freebsd")
OUTPUT_ARCH(i386)
ENTRY(_start)
SECTIONS {
. = 0x08048000 + SIZEOF_HEADERS;
.text : { (.text) } =0x90909090 / Pad with nops, if needed */
.data : { *(.data) } PROVIDE(_edata = .);
.bss : { *(.bss) } PROVIDE(_end = .);
}

From this GNU ld produces an object with all sections packed into a single RWE segment:

% readelf -l boot2.out

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

Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000080 0x00002000 0x00002000 0x01456 0x027f8 RWE 0x10
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4

Section to Segment mapping:
Segment Sections...
00 .text .rodata .data .bss
01

while LLD produces an object with separate segments for sections with different permissions.

@llvmbot
Copy link
Collaborator

llvmbot commented Sep 16, 2016

Why is having multiple PT_LOADs a problem?

@llvmbot
Copy link
Collaborator

llvmbot commented Sep 16, 2016

If you want to merge it all in one output section, I think you can do

.all : { *(.text) *(.data) *(.bss) }

@emaste
Copy link
Member Author

emaste commented Sep 16, 2016

Why is having multiple PT_LOADs a problem?

Sorry, multiple PT_LOADs is not a problem per se, but the resulting binary produced by lld is too large.

@emaste
Copy link
Member Author

emaste commented Sep 16, 2016

.all : { *(.text) *(.data) *(.bss) }

With that I end up failing because there's no section for relocations:

mbr.o: In function start': (.text+0xd): relocation truncated to fit: R_386_16 against .text'

@llvmbot
Copy link
Collaborator

llvmbot commented Oct 31, 2016

.all : { *(.text) *(.data) *(.bss) }

With that I end up failing because there's no section for relocations:

mbr.o: In function start': (.text+0xd): relocation truncated to fit: R_386_16 against .text'

Can you check if this is still a problem and upload a cpio if it is?

@emaste
Copy link
Member Author

emaste commented Nov 22, 2016

A little more information:

FreeBSD switched to a linker script for these boot loaders in r305353 (https://svnweb.freebsd.org/base?view=revision&revision=305353, https://reviews.freebsd.org/D7409)

However, it broke one of the loaders when using ld.bfd (https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=213491)
and was reverted in r307954 (https://svnweb.freebsd.org/base?view=revision&revision=307954)

Most of the boot components worked with the linker script version though, and I expect we'll fix the breakage and restore the use of the linker script.

I will try re-applying r305353 and generating a reproduction cpio at some point, but I believe the EFI loaders are more important to fix first and am helping George investigate those first.

@llvmbot
Copy link
Collaborator

llvmbot commented Nov 28, 2016

A little more information:

FreeBSD switched to a linker script for these boot loaders in r305353
(https://svnweb.freebsd.org/base?view=revision&revision=305353,
https://reviews.freebsd.org/D7409)

However, it broke one of the loaders when using ld.bfd
(https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=213491)
and was reverted in r307954
(https://svnweb.freebsd.org/base?view=revision&revision=307954)

Most of the boot components worked with the linker script version though,
and I expect we'll fix the breakage and restore the use of the linker script.

I will try re-applying r305353 and generating a reproduction cpio at some
point, but I believe the EFI loaders are more important to fix first and am
helping George investigate those first.

Note that given that we already support putting ro and rx together because of linker scripts, supporting the original feature might not be a big problem.

@MaskRay
Copy link
Member

MaskRay commented Jul 26, 2019

lld doesn't create one single RWX PT_LOAD now. Closing because the issue has been fixed for a while.

I test on a Linux machine, but the FreeBSD case is similar.

% clang -fuse-ld=lld -m32 a.c a.x -o a # 5008 bytes

Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x00140 0x00140 R 0x4
INTERP 0x000174 0x08048174 0x08048174 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x000000 0x08048000 0x08048000 0x00730 0x00730 R E 0x1000
LOAD 0x000730 0x08048730 0x08048730 0x000d8 0x000d8 RW 0x1000
LOAD 0x000808 0x08048808 0x08048808 0x00020 0x00021 RW 0x1000
DYNAMIC 0x000738 0x08048738 0x08048738 0x000c8 0x000c8 RW 0x4
GNU_RELRO 0x000730 0x08048730 0x08048730 0x000d8 0x01000 R 0x1
GNU_EH_FRAME 0x000378 0x08048378 0x08048378 0x00044 0x00044 R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0
NOTE 0x000188 0x08048188 0x08048188 0x00020 0x00020 R 0x4

After D64903 and D64906 are merged, the non-linker script case will look similar to this layout.

% clang -fuse-ld=bfd -m32 a.c a.x -o a.bfd # 7148 bytes
% readelf -l a.bfd
...
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 R 0x4
INTERP 0x000154 0x08048154 0x08048154 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x000000 0x08048000 0x08048000 0x005dc 0x005dc R E 0x1000
LOAD 0x000f04 0x08049f04 0x08049f04 0x00118 0x0011c RW 0x1000
DYNAMIC 0x000f0c 0x08049f0c 0x08049f0c 0x000f0 0x000f0 RW 0x4
NOTE 0x000168 0x08048168 0x08048168 0x00020 0x00020 R 0x4
GNU_EH_FRAME 0x0004c8 0x080484c8 0x080484c8 0x00034 0x00034 R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10
GNU_RELRO 0x000f04 0x08049f04 0x08049f04 0x000fc 0x000fc R 0x1

Note that given that we already support putting ro and rx together because of linker scripts, supporting the original feature might not be a big problem.

After https://reviews.llvm.org/rLLD281978, we place R and RX sections in the RX PT_LOAD (singleRoRx = true; in ScriptParser.cpp). I actually want to flip this, to improve consistency with the non-linker script case, and to fix issues like llvm/llvm-bugzilla-archive#38784

People who want separate R PT_LOAD and RX PT_LOAD in linker script cases can enable --no-rosegment.

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 10, 2021
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla lld:ELF
Projects
None yet
Development

No branches or pull requests

3 participants