Bug 24490 - -z max-page-size=0x200000 -z separate-code creates huge binary
Summary: -z max-page-size=0x200000 -z separate-code creates huge binary
Status: NEW
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.33
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-04-26 15:18 UTC by H.J. Lu
Modified: 2024-01-14 18:58 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description H.J. Lu 2019-04-26 15:18:55 UTC
[hjl@gnu-cfl-1 max-page-size]$ cat foo.c
int data = 3;

int
foo (void)
{
  return data;
}
[hjl@gnu-cfl-1 max-page-size]$ make
gcc -g -Wall -fpic   -c -o foo.o foo.c
./ld -z max-page-size=0x200000 -m elf_x86_64 -z separate-code -shared -o libfoo2.so foo.o
readelf -lW libfoo2.so

Elf file type is DYN (Shared object file)
Entry point 0x200000
There are 9 program headers, starting at offset 64

Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x0002e8 0x0002e8 R   0x200000
  LOAD           0x200000 0x0000000000200000 0x0000000000200000 0x00000f 0x00000f R E 0x200000
  LOAD           0x400000 0x0000000000400000 0x0000000000400000 0x000068 0x000068 R   0x200000
  LOAD           0x400f08 0x0000000000600f08 0x0000000000600f08 0x000114 0x000114 RW  0x200000
  DYNAMIC        0x400f08 0x0000000000600f08 0x0000000000600f08 0x0000f0 0x0000f0 RW  0x8
  NOTE           0x400000 0x0000000000400000 0x0000000000400000 0x000030 0x000030 R   0x8
  GNU_PROPERTY   0x400000 0x0000000000400000 0x0000000000400000 0x000030 0x000030 R   0x8
  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x10
  GNU_RELRO      0x400f08 0x0000000000600f08 0x0000000000600f08 0x0000f8 0x0000f8 R   0x1

 Section to Segment mapping:
  Segment Sections...
   00     .hash .gnu.hash .dynsym .dynstr .rela.dyn 
   01     .text 
   02     .note.gnu.property .eh_frame 
   03     .dynamic .got .got.plt .data 
   04     .dynamic 
   05     .note.gnu.property 
   06     .note.gnu.property 
   07     
   08     .dynamic .got 
ls -l libfoo2.so
-rwxrwxr-x 1 hjl hjl 4201160 Apr 26 08:14 libfoo2.so
[hjl@gnu-cfl-1 max-page-size]$ 

Since all PT_LOAD segments are very small, they can be fit into a
single 4K or 2MB page.  Ld should use the smallest of minpagesize
and maxpagesize which can cover the whole PT_LOAD segment.
Comment 1 Alan Modra 2019-05-02 05:05:49 UTC
If you specify -z max-page-size=0x200000 then there is an expectation that the binary produced will work with an actual hardware page size of 0x200000.  If ld were instead to use minpagesize then the binary may not even run when the hardware page size is 0x200000, and certainly won't have the page protection you expect with -z separate-code.

I don't see any way around this.  As ld.text says of -z separate-code:
"Create separate code @code{PT_LOAD} segment header in the object.  This
specifies a memory segment that should contain only instructions and must
be in wholly disjoint pages from any other data."  The presumption here is that data can't appear in the text memory pages.  So you can't use tricks like that done between rodata and data by DATA_SEGMENT_ALIGN (ie. starting rw data at the end of ro data but on the next page in order to save disk), because that allows part of rw data to leak into ro data and vice versa.
Comment 2 H.J. Lu 2019-05-02 21:43:40 UTC
On targets where the maximum page size is optional and only the minimum
page size is required, we can set p_align to the minimum page size if
the segment is less than the maximum page size.  At run-time, these
segments can be aligned at the maximum page size, but their p_align
is the minimum page size.
Comment 3 Fangrui Song 2019-06-17 06:06:14 UTC
Two R-- PT_LOAD segments are wasteful. Is it possible to move .rodata .eh_frame .eh_frame_hdr etc before the R-E PT_LOAD?