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 sets x86_64 MAXPAGESIZE to 0x1000, not 0x200000 as ld.bfd does #30239

Closed
emaste opened this issue Nov 3, 2016 · 9 comments
Closed

lld sets x86_64 MAXPAGESIZE to 0x1000, not 0x200000 as ld.bfd does #30239

emaste opened this issue Nov 3, 2016 · 9 comments
Labels
bugzilla Issues migrated from bugzilla lld:ELF

Comments

@emaste
Copy link
Member

emaste commented Nov 3, 2016

Bugzilla Link 30891
Resolution FIXED
Resolved on Feb 06, 2019 02:46
Version unspecified
OS FreeBSD
Blocks #23588
CC @MaskRay

Extended Description

FreeBSD's amd64 (x86_64) kernel linker script uses MAXPAGESIZE to set the physical and virtual addresses for the kernel.

See https://svnweb.freebsd.org/base/head/sys/conf/ldscript.amd64?annotate=303442#l9

After r282560 (https://reviews.llvm.org/rL282560) lld sets MAXPAGESIZE to 0x1000 not 0x200000. The FreeBSD kernel then occupies the physical memory under 640K and the kernel panics on boot when a device that requires a low memory allocation fails.

@llvmbot
Copy link
Collaborator

llvmbot commented Nov 4, 2016

From the description it looks like the linker script should just say

kernphys = 0x200000;

or maybe

kernphys = 0xa0000

Since it is not really trying to reason about the page size. It is trying to make sure there is some free memory before the kernel.

@emaste
Copy link
Member Author

emaste commented Nov 4, 2016

It's actually trying to do both - a driver panics if there is no low (below 640K) memory available which happens as a side effect of kernphys = 0x1000, but the reason it's currently MAXPAGESIZE is so that the kernel physical address is large-page aligned.

@emaste
Copy link
Member Author

emaste commented Nov 21, 2016

Related FreeBSD bug for the driver panic: https://bugs.freebsd.org/214718

@emaste
Copy link
Member Author

emaste commented Nov 21, 2016

Some discussion in https://reviews.llvm.org/D24987 and in the review thread on llvm-commits (some of which seems to be missing from the archives)

Linking a "hello world" with one int in .data using default ld 2.17.50 settings on FreeBSD gives me (omitting PHDR, INTERP, DYNAMIC, etc. sections):

Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x000000000000086c 0x000000000000086c R E 200000
LOAD 0x0000000000000870 0x0000000000600870 0x0000000000600870
0x00000000000001f0 0x00000000000001f8 RW 200000

With ld.bfd from the binutils package, 2.25.1:

LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x000000000000089c 0x000000000000089c R E 200000
LOAD 0x00000000000008a0 0x00000000006008a0 0x00000000006008a0
0x00000000000001f0 0x00000000000001f8 RW 200000

With ld.gold 2.25.1:

LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x00000000000008b0 0x00000000000008b0 R E 1000
LOAD 0x00000000000008b0 0x00000000004018b0 0x00000000004018b0
0x00000000000001f0 0x00000000000001f8 RW 1000

With ld.lld HEAD:

LOAD 0x0000000000000000 0x0000000000010000 0x0000000000010000
0x0000000000000564 0x0000000000000564 R 1000
LOAD 0x0000000000001000 0x0000000000011000 0x0000000000011000
0x0000000000000340 0x0000000000000340 R E 1000
LOAD 0x0000000000002000 0x0000000000012000 0x0000000000012000
0x0000000000001058 0x0000000000001060 RW 1000

@llvmbot
Copy link
Collaborator

llvmbot commented Nov 21, 2016

Some discussion in https://reviews.llvm.org/D24987 and in the review thread
on llvm-commits (some of which seems to be missing from the archives)

Linking a "hello world" with one int in .data using default ld 2.17.50
settings on FreeBSD gives me (omitting PHDR, INTERP, DYNAMIC, etc. sections):

Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x000000000000086c 0x000000000000086c R E 200000
LOAD 0x0000000000000870 0x0000000000600870 0x0000000000600870
0x00000000000001f0 0x00000000000001f8 RW 200000

With ld.bfd from the binutils package, 2.25.1:

LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x000000000000089c 0x000000000000089c R E 200000
LOAD 0x00000000000008a0 0x00000000006008a0 0x00000000006008a0
0x00000000000001f0 0x00000000000001f8 RW 200000

So both use a 2MB page, merge read and executable sections and overlap PT_LOAD.

With ld.gold 2.25.1:

LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x00000000000008b0 0x00000000000008b0 R E 1000
LOAD 0x00000000000008b0 0x00000000004018b0 0x00000000004018b0
0x00000000000001f0 0x00000000000001f8 RW 1000

Same as bfd, but with a 4k page. You can get the 3 LOADs with --rosegment.

With ld.lld HEAD:

LOAD 0x0000000000000000 0x0000000000010000 0x0000000000010000
0x0000000000000564 0x0000000000000564 R 1000
LOAD 0x0000000000001000 0x0000000000011000 0x0000000000011000
0x0000000000000340 0x0000000000000340 R E 1000
LOAD 0x0000000000002000 0x0000000000012000 0x0000000000012000
0x0000000000001058 0x0000000000001060 RW 1000

4k pages, --rosegment, don't overlap segments.

@emaste
Copy link
Member Author

emaste commented Nov 21, 2016

So both [ld.bfd 2.17.50 and ld.bfd 2.25.1] use a 2MB page, merge read
and executable sections and overlap PT_LOAD.

Interesting: the PT_LOAD overlaps on disk, but the run-time page permissions are applied on a 4K page boundary.

PID START END PRT RES PRES REF SHD FL TP PATH
22056 0x400000 0x401000 r-x 1 0 1 0 C--- vn /home/emaste/a.out
22056 0x600000 0x601000 rw- 1 1 1 0 ---- df

With ld.gold 2.25.1:

Same as bfd, but with a 4k page.

The net result ends up the same though, some overlapping content and 4K run-time permissions.

22108 0x400000 0x401000 r-x 1 0 1 0 C--- vn /home/emaste/a.out
22108 0x401000 0x402000 rw- 1 1 1 0 ---- df

You can get the 3 LOADs with --rosegment.

Do you know if ld.gold defaults to enabling this on Linux, out of curiosity?

@emaste
Copy link
Member Author

emaste commented Nov 22, 2016

Proposed FreeBSD change is in https://reviews.freebsd.org/D8610

@llvmbot
Copy link
Collaborator

llvmbot commented Nov 22, 2016

So both [ld.bfd 2.17.50 and ld.bfd 2.25.1] use a 2MB page, merge read
and executable sections and overlap PT_LOAD.

Interesting: the PT_LOAD overlaps on disk, but the run-time page permissions
are applied on a 4K page boundary.

PID START END PRT RES PRES REF SHD FL TP
PATH
22056 0x400000 0x401000 r-x 1 0 1 0 C--- vn
/home/emaste/a.out
22056 0x600000 0x601000 rw- 1 1 1 0 ---- df

Looks 2MiB to me, no?

You can get the 3 LOADs with --rosegment.

Do you know if ld.gold defaults to enabling this on Linux, out of curiosity?

It does not.

@emaste
Copy link
Member Author

emaste commented Nov 22, 2016

PID START END PRT RES PRES REF SHD FL TP
PATH
22056 0x400000 0x401000 r-x 1 0 1 0 C--- vn
/home/emaste/a.out
22056 0x600000 0x601000 rw- 1 1 1 0 ---- df

Looks 2MiB to me, no?

I mean they are aligned to 2MiB from ld.bfd's MAXPAGESIZE, but are 4KiB runtime mappings (END-START), and they have the same content.

@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

2 participants