xref: /openbsd-src/gnu/gcc/gcc/config/host-hpux.c (revision 404b540a9034ac75a6199ad1a32d1bbc7a0d4210)
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