1*404b540aSrobert /* HP-UX host-specific hook definitions.
2*404b540aSrobert Copyright (C) 2004, 2005 Free Software Foundation, Inc.
3*404b540aSrobert
4*404b540aSrobert This file is part of GCC.
5*404b540aSrobert
6*404b540aSrobert GCC is free software; you can redistribute it and/or modify it
7*404b540aSrobert under the terms of the GNU General Public License as published
8*404b540aSrobert by the Free Software Foundation; either version 2, or (at your
9*404b540aSrobert option) any later version.
10*404b540aSrobert
11*404b540aSrobert GCC is distributed in the hope that it will be useful, but WITHOUT
12*404b540aSrobert ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13*404b540aSrobert or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14*404b540aSrobert License for more details.
15*404b540aSrobert
16*404b540aSrobert You should have received a copy of the GNU General Public License
17*404b540aSrobert along with GCC; see the file COPYING. If not, write to the
18*404b540aSrobert Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
19*404b540aSrobert MA 02110-1301, USA. */
20*404b540aSrobert
21*404b540aSrobert #include "config.h"
22*404b540aSrobert #include "system.h"
23*404b540aSrobert #include "coretypes.h"
24*404b540aSrobert #include <sys/mman.h>
25*404b540aSrobert #include <unistd.h>
26*404b540aSrobert #include "hosthooks.h"
27*404b540aSrobert #include "hosthooks-def.h"
28*404b540aSrobert
29*404b540aSrobert #ifndef MAP_FAILED
30*404b540aSrobert #define MAP_FAILED (void *)-1L
31*404b540aSrobert #endif
32*404b540aSrobert
33*404b540aSrobert static void *hpux_gt_pch_get_address (size_t, int);
34*404b540aSrobert static int hpux_gt_pch_use_address (void *, size_t, int, size_t);
35*404b540aSrobert
36*404b540aSrobert #undef HOST_HOOKS_GT_PCH_GET_ADDRESS
37*404b540aSrobert #define HOST_HOOKS_GT_PCH_GET_ADDRESS hpux_gt_pch_get_address
38*404b540aSrobert #undef HOST_HOOKS_GT_PCH_USE_ADDRESS
39*404b540aSrobert #define HOST_HOOKS_GT_PCH_USE_ADDRESS hpux_gt_pch_use_address
40*404b540aSrobert
41*404b540aSrobert /* For various ports, try to guess a fixed spot in the vm space
42*404b540aSrobert that's probably free. */
43*404b540aSrobert #if (defined(__hppa__) || defined(__ia64__)) && defined(__LP64__)
44*404b540aSrobert # define TRY_EMPTY_VM_SPACE 0x8000000000000000
45*404b540aSrobert #elif defined(__hppa__) || defined(__ia64__)
46*404b540aSrobert # define TRY_EMPTY_VM_SPACE 0x60000000
47*404b540aSrobert #else
48*404b540aSrobert # define TRY_EMPTY_VM_SPACE 0
49*404b540aSrobert #endif
50*404b540aSrobert
51*404b540aSrobert /* Determine a location where we might be able to reliably allocate
52*404b540aSrobert SIZE bytes. FD is the PCH file, though we should return with the
53*404b540aSrobert file unmapped. */
54*404b540aSrobert
55*404b540aSrobert static void *
hpux_gt_pch_get_address(size_t size,int fd)56*404b540aSrobert hpux_gt_pch_get_address (size_t size, int fd)
57*404b540aSrobert {
58*404b540aSrobert void *addr;
59*404b540aSrobert
60*404b540aSrobert addr = mmap ((void *)TRY_EMPTY_VM_SPACE, size, PROT_READ | PROT_WRITE,
61*404b540aSrobert MAP_PRIVATE, fd, 0);
62*404b540aSrobert
63*404b540aSrobert /* If we failed the map, that means there's *no* free space. */
64*404b540aSrobert if (addr == (void *) MAP_FAILED)
65*404b540aSrobert return NULL;
66*404b540aSrobert /* Unmap the area before returning. */
67*404b540aSrobert munmap (addr, size);
68*404b540aSrobert
69*404b540aSrobert return addr;
70*404b540aSrobert }
71*404b540aSrobert
72*404b540aSrobert /* Map SIZE bytes of FD+OFFSET at BASE. Return 1 if we succeeded at
73*404b540aSrobert mapping the data at BASE, -1 if we couldn't.
74*404b540aSrobert
75*404b540aSrobert It's not possibly to reliably mmap a file using MAP_PRIVATE to
76*404b540aSrobert a specific START address on either hpux or linux. First we see
77*404b540aSrobert if mmap with MAP_PRIVATE works. If it does, we are off to the
78*404b540aSrobert races. If it doesn't, we try an anonymous private mmap since the
79*404b540aSrobert kernel is more likely to honor the BASE address in anonymous maps.
80*404b540aSrobert We then copy the data to the anonymous private map. This assumes
81*404b540aSrobert of course that we don't need to change the data in the PCH file
82*404b540aSrobert after it is created.
83*404b540aSrobert
84*404b540aSrobert This approach obviously causes a performance penalty but there is
85*404b540aSrobert little else we can do given the current PCH implementation. */
86*404b540aSrobert
87*404b540aSrobert static int
hpux_gt_pch_use_address(void * base,size_t size,int fd,size_t offset)88*404b540aSrobert hpux_gt_pch_use_address (void *base, size_t size, int fd, size_t offset)
89*404b540aSrobert {
90*404b540aSrobert void *addr;
91*404b540aSrobert
92*404b540aSrobert /* We're called with size == 0 if we're not planning to load a PCH
93*404b540aSrobert file at all. This allows the hook to free any static space that
94*404b540aSrobert we might have allocated at link time. */
95*404b540aSrobert if (size == 0)
96*404b540aSrobert return -1;
97*404b540aSrobert
98*404b540aSrobert /* Try to map the file with MAP_PRIVATE. */
99*404b540aSrobert addr = mmap (base, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, offset);
100*404b540aSrobert
101*404b540aSrobert if (addr == base)
102*404b540aSrobert return 1;
103*404b540aSrobert
104*404b540aSrobert if (addr != (void *) MAP_FAILED)
105*404b540aSrobert munmap (addr, size);
106*404b540aSrobert
107*404b540aSrobert /* Try to make an anonymous private mmap at the desired location. */
108*404b540aSrobert addr = mmap (base, size, PROT_READ | PROT_WRITE,
109*404b540aSrobert MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
110*404b540aSrobert
111*404b540aSrobert if (addr != base)
112*404b540aSrobert {
113*404b540aSrobert if (addr != (void *) MAP_FAILED)
114*404b540aSrobert munmap (addr, size);
115*404b540aSrobert return -1;
116*404b540aSrobert }
117*404b540aSrobert
118*404b540aSrobert if (lseek (fd, offset, SEEK_SET) == (off_t)-1)
119*404b540aSrobert return -1;
120*404b540aSrobert
121*404b540aSrobert while (size)
122*404b540aSrobert {
123*404b540aSrobert ssize_t nbytes;
124*404b540aSrobert
125*404b540aSrobert nbytes = read (fd, base, MIN (size, SSIZE_MAX));
126*404b540aSrobert if (nbytes <= 0)
127*404b540aSrobert return -1;
128*404b540aSrobert base = (char *) base + nbytes;
129*404b540aSrobert size -= nbytes;
130*404b540aSrobert }
131*404b540aSrobert
132*404b540aSrobert return 1;
133*404b540aSrobert }
134*404b540aSrobert
135*404b540aSrobert
136*404b540aSrobert const struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER;
137