LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 30891 - lld sets x86_64 MAXPAGESIZE to 0x1000, not 0x200000 as ld.bfd does
Summary: lld sets x86_64 MAXPAGESIZE to 0x1000, not 0x200000 as ld.bfd does
Status: RESOLVED FIXED
Alias: None
Product: lld
Classification: Unclassified
Component: ELF (show other bugs)
Version: unspecified
Hardware: PC FreeBSD
: P normal
Assignee: Unassigned LLVM Bugs
URL:
Keywords:
Depends on:
Blocks: 23214
  Show dependency tree
 
Reported: 2016-11-02 18:18 PDT by emaste
Modified: 2019-02-06 02:46 PST (History)
4 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 emaste 2016-11-02 18:18:10 PDT
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.
Comment 1 Rafael Ávila de Espíndola 2016-11-04 15:08:12 PDT
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.
Comment 2 emaste 2016-11-04 15:14:23 PDT
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.
Comment 3 emaste 2016-11-21 14:18:48 PST
Related FreeBSD bug for the driver panic: https://bugs.freebsd.org/214718
Comment 4 emaste 2016-11-21 14:34:37 PST
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
Comment 5 Rafael Ávila de Espíndola 2016-11-21 14:43:27 PST
(In reply to comment #4)
> 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.
Comment 6 emaste 2016-11-21 14:52:30 PST
(In reply to comment #5)
> 
> 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?
Comment 7 emaste 2016-11-21 17:14:13 PST
Proposed FreeBSD change is in https://reviews.freebsd.org/D8610
Comment 8 Rafael Ávila de Espíndola 2016-11-22 07:19:14 PST
(In reply to comment #6)
> (In reply to comment #5)
> > 
> > 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.
Comment 9 emaste 2016-11-22 07:28:17 PST
(In reply to comment #8)
> >   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.