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: unassig...@sources.redhat.com ReportedBy: dang...@gcc.gnu.org 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: d...@gsyprf11:~$ 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. _______________________________________________ bug-binutils mailing list bug-binutils@gnu.org http://lists.gnu.org/mailman/listinfo/bug-binutils