bug-binutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Bug ld/12376] New: File offsets for PT_LOAD segments and resulting ineq


From: danglin at gcc dot gnu.org
Subject: [Bug ld/12376] New: File offsets for PT_LOAD segments and resulting inequivalent memory aliases
Date: Sat, 8 Jan 2011 19:22:44 +0000

http://sourceware.org/bugzilla/show_bug.cgi?id=12376

           Summary: File offsets for PT_LOAD segments and resulting
                    inequivalent memory aliases
           Product: binutils
           Version: unspecified
            Status: NEW
          Severity: normal
          Priority: P2
         Component: ld
        AssignedTo: address@hidden
        ReportedBy: address@hidden


By default, the linker places sections in sequential order in executable
files for ELF targets like hppa-unknown-linux-gnu.  The glibc dynamic
linker uses mmap with MAP_FIXED to map PT_LOAD segments in the executable
file to the virtual address ranges specified in the program headers.
At the boundary between segments, we may have two different virtual
address pages with different protections mapping to the same physical
address page.

This results in two inequivalent aliases to the same physical page.  This
is inefficient, and certain hardware can lead to cache corruption and
segmentation faults.  For example, the HP PA8800 and PA8900 processors
do not support inequivalent aliases.

The issue can be seen with the following simple program:

int main () { return 0; }

Compiling with gcc -o xxx3 xxx3.c, I see with readelf:

ELF Header:
  Magic:   7f 45 4c 46 01 02 01 03 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, big endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - Linux
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           HPPA
  Version:                           0x1
  Entry point address:               0x10354
  Start of program headers:          52 (bytes into file)
  Start of section headers:          2880 (bytes into file)
  Flags:                             0x210, PA-RISC 1.1
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         7
  Size of section headers:           40 (bytes)
  Number of section headers:         31
  Section header string table index: 28

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf
Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0 
0
  [ 1] .interp           PROGBITS        00010114 000114 00000d 00   A  0   0 
1
  [ 2] .note.ABI-tag     NOTE            00010124 000124 000020 00   A  0   0 
4
  [ 3] .note.gnu.build-i NOTE            00010144 000144 000000 00   A  0   0 
4
  [ 4] .hash             HASH            00010144 000144 000034 04   A  5   0 
4
  [ 5] .dynsym           DYNSYM          00010178 000178 000080 10   A  6   1 
4
  [ 6] .dynstr           STRTAB          000101f8 0001f8 000080 00   A  0   0 
1
  [ 7] .gnu.version      VERSYM          00010278 000278 000010 02   A  5   0 
2
  [ 8] .gnu.version_r    VERNEED         00010288 000288 000020 00   A  6   1 
4
  [ 9] .rela.dyn         RELA            000102a8 0002a8 00000c 0c   A  5   0 
4
  [10] .rela.plt         RELA            000102b4 0002b4 000048 0c   A  5  23 
4
  [11] .init             PROGBITS        000102fc 0002fc 000048 00  AX  0   0 
4
  [12] .text             PROGBITS        00010344 000344 0003e0 00  AX  0   0 
4
  [13] .fini             PROGBITS        00010724 000724 000028 00  AX  0   0 
4
  [14] .rodata           PROGBITS        0001074c 00074c 000018 00   A  0   0 
4
  [15] .PARISC.unwind    PROGBITS        00010764 000764 0000e0 04   A  0  12 
4
  [16] .eh_frame_hdr     PROGBITS        00010844 000844 000014 00   A  0   0 
4
  [17] .eh_frame         PROGBITS        00010858 000858 000034 00   A  0   0 
4
  [18] .ctors            PROGBITS        0001188c 00088c 000008 00  WA  0   0 
4
  [19] .dtors            PROGBITS        00011894 000894 000008 00  WA  0   0 
4
  [20] .jcr              PROGBITS        0001189c 00089c 000004 00  WA  0   0 
4
  [21] .dynamic          DYNAMIC         000118a0 0008a0 0000c8 08  WA  6   0 
4
  [22] .data             PROGBITS        00011968 000968 000008 00  WA  0   0 
4
  [23] .plt              PROGBITS        00011970 000970 00004c 08 WAX  0   0 
4
  [24] .got              PROGBITS        000119bc 0009bc 00001c 04  WA  0   0 
4
  [25] .bss              NOBITS          000119d8 0009d8 000014 00  WA  0   0 
4
  [26] .note             NOTE            00000000 0009d8 000028 00      0   0 
1
  [27] .comment          PROGBITS        00000000 000a00 000038 01  MS  0   0 
1
  [28] .shstrtab         STRTAB          00000000 000a38 000106 00      0   0 
1
  [29] .symtab           SYMTAB          00000000 001018 0004c0 10     30  56 
4
  [30] .strtab           STRTAB          00000000 0014d8 0002b1 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)

There are no section groups in this file.

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x00010034 0x00010034 0x000e0 0x000e0 R E 0x4
  INTERP         0x000114 0x00010114 0x00010114 0x0000d 0x0000d R   0x1
      [Requesting program interpreter: /lib/ld.so.1]
  LOAD           0x000000 0x00010000 0x00010000 0x0088c 0x0088c R E 0x1000
  LOAD           0x00088c 0x0001188c 0x0001188c 0x0014c 0x00160 RWE 0x1000
  DYNAMIC        0x0008a0 0x000118a0 0x000118a0 0x000c8 0x000c8 RW  0x4
  NOTE           0x000124 0x00010124 0x00010124 0x00020 0x00020 R   0x4
  GNU_EH_FRAME   0x000844 0x00010844 0x00010844 0x00014 0x00014 R   0x4

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .interp 
   02     .interp .note.ABI-tag .hash .dynsym .dynstr .gnu.version
.gnu.version_r .rela.dyn .rela.plt .init .text .fini .rodata .PARISC.unwind
.eh_frame_hdr .eh_frame 
   03     .ctors .dtors .jcr .dynamic .data .plt .got .bss 
   04     .dynamic 
   05     .note.ABI-tag 
   06     .eh_frame_hdr 

As can be seen, the .ctors section follows .eh_frame in the file with
only an adjustment for its alignment.  It is not page aligned in the file.

If we now look at how it is mapped into memory by the dynamic loader and
linux kernel, we see the following:

address@hidden:~$ cat /proc/26767/maps
00010000-00011000 r-xp 00000000 08:30 6615849                           
/home2/dave/inequiv/xxx3
00011000-00012000 rwxp 00000000 08:30 6615849                           
/home2/dave/inequiv/xxx3
40000000-40005000 rw-p 00000000 00:00 0 
40175000-40195000 r-xp 00000000 08:03 2502157                           
/lib/ld-2.11.2.so
40195000-40199000 rwxp 0001f000 08:03 2502157                           
/lib/ld-2.11.2.so
40199000-4019a000 rwxp 00000000 00:00 0 
403ee000-40547000 r-xp 00000000 08:03 2502172                           
/lib/libc-2.11.2.so
40547000-4054e000 rwxp 00158000 08:03 2502172                           
/lib/libc-2.11.2.so
4054e000-40550000 rwxp 00000000 00:00 0 
fdf00000-fdf23000 rwxp 00000000 00:00 0                                 
[stack]

As can be seen in the first two maps, we have two maps pointing to the same
page in the file xxx3.  These in fact point to the same page in physical
memory.  So, the second map can apparently write to the address range
protected in the first map.  However, my main concern is the inequivalent
aliases to physical memory.

The Open Group rationale for mmap mentions the following issues:

"If an application requests a mapping that would overlay existing mappings in
the process, it might be desirable that an implementation detect this and
inform the application. However, the default, portable (not MAP_FIXED)
operation does not overlay existing mappings. On the other hand, if the program
specifies a fixed address mapping (which requires some implementation knowledge
to determine a suitable address, if the function is supported at all), then the
program is presumed to be successfully managing its own address space and
should be trusted when it asks to map over existing data structures.
Furthermore, it is also desirable to make as few system calls as possible, and
it might be considered onerous to require an munmap() before an mmap() to the
same address range. This volume of IEEE Std 1003.1-2001 specifies that the new
mappings replace any existing mappings, following existing practice in this
regard.

It is not expected, when the Memory Protection option is supported, that all
hardware implementations are able to support all combinations of permissions at
all addresses. When this option is supported, implementations are required to
disallow write access to mappings without write permission and to disallow
access to mappings without any access permission. Other than these
restrictions, implementations may allow access types other than those requested
by the application. For example, if the application requests only PROT_WRITE,
the implementation may also allow read access. A call to mmap() fails if the
implementation cannot support allowing all the access requested by the
application. For example, some implementations cannot support a request for
both write access and execute access simultaneously. All implementations
supporting the Memory Protection option must support requests for no access,
read access, write access, and both read and write access. Strictly conforming
code must only rely on the required checks. These restrictions allow for
portability across a wide range of hardware."

My impression from this is that it is not up to the kernel to detect
overlapping
maps.  As far as the linker goes, I can see two options:

1) Adjust hppalinux.sh to modify TEXT_ADDR and SHLIB_TEXT_ADDR.  I need to
   add 0x400000 (4 MB) to make the addresses equivalent.  This rather chews
   up the virtual address space for shared libraries.

2) Align the PT_LOAD segments in the file.  I'm not sure how to do this
   at the moment.  Currently, maxpagesize is 0x1000, so this might not be
   a too onerous increase in file size.  On the otherhand, maxpagesize
   probably should be 0x10000.

-- 
Configure bugmail: http://sourceware.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]