1169689Skan/* HP-UX host-specific hook definitions. 2169689Skan Copyright (C) 2004, 2005 Free Software Foundation, Inc. 3169689Skan 4169689Skan This file is part of GCC. 5169689Skan 6169689Skan GCC is free software; you can redistribute it and/or modify it 7169689Skan under the terms of the GNU General Public License as published 8169689Skan by the Free Software Foundation; either version 2, or (at your 9169689Skan option) any later version. 10169689Skan 11169689Skan GCC is distributed in the hope that it will be useful, but WITHOUT 12169689Skan ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13169689Skan or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14169689Skan License for more details. 15169689Skan 16169689Skan You should have received a copy of the GNU General Public License 17169689Skan along with GCC; see the file COPYING. If not, write to the 18169689Skan Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, 19169689Skan MA 02110-1301, USA. */ 20169689Skan 21169689Skan#include "config.h" 22169689Skan#include "system.h" 23169689Skan#include "coretypes.h" 24169689Skan#include <sys/mman.h> 25169689Skan#include <unistd.h> 26169689Skan#include "hosthooks.h" 27169689Skan#include "hosthooks-def.h" 28169689Skan 29169689Skan#ifndef MAP_FAILED 30169689Skan#define MAP_FAILED (void *)-1L 31169689Skan#endif 32169689Skan 33169689Skanstatic void *hpux_gt_pch_get_address (size_t, int); 34169689Skanstatic int hpux_gt_pch_use_address (void *, size_t, int, size_t); 35169689Skan 36169689Skan#undef HOST_HOOKS_GT_PCH_GET_ADDRESS 37169689Skan#define HOST_HOOKS_GT_PCH_GET_ADDRESS hpux_gt_pch_get_address 38169689Skan#undef HOST_HOOKS_GT_PCH_USE_ADDRESS 39169689Skan#define HOST_HOOKS_GT_PCH_USE_ADDRESS hpux_gt_pch_use_address 40169689Skan 41169689Skan/* For various ports, try to guess a fixed spot in the vm space 42169689Skan that's probably free. */ 43169689Skan#if (defined(__hppa__) || defined(__ia64__)) && defined(__LP64__) 44169689Skan# define TRY_EMPTY_VM_SPACE 0x8000000000000000 45169689Skan#elif defined(__hppa__) || defined(__ia64__) 46169689Skan# define TRY_EMPTY_VM_SPACE 0x60000000 47169689Skan#else 48169689Skan# define TRY_EMPTY_VM_SPACE 0 49169689Skan#endif 50169689Skan 51169689Skan/* Determine a location where we might be able to reliably allocate 52169689Skan SIZE bytes. FD is the PCH file, though we should return with the 53169689Skan file unmapped. */ 54169689Skan 55169689Skanstatic void * 56169689Skanhpux_gt_pch_get_address (size_t size, int fd) 57169689Skan{ 58169689Skan void *addr; 59169689Skan 60169689Skan addr = mmap ((void *)TRY_EMPTY_VM_SPACE, size, PROT_READ | PROT_WRITE, 61169689Skan MAP_PRIVATE, fd, 0); 62169689Skan 63169689Skan /* If we failed the map, that means there's *no* free space. */ 64169689Skan if (addr == (void *) MAP_FAILED) 65169689Skan return NULL; 66169689Skan /* Unmap the area before returning. */ 67169689Skan munmap (addr, size); 68169689Skan 69169689Skan return addr; 70169689Skan} 71169689Skan 72169689Skan/* Map SIZE bytes of FD+OFFSET at BASE. Return 1 if we succeeded at 73169689Skan mapping the data at BASE, -1 if we couldn't. 74169689Skan 75169689Skan It's not possibly to reliably mmap a file using MAP_PRIVATE to 76169689Skan a specific START address on either hpux or linux. First we see 77169689Skan if mmap with MAP_PRIVATE works. If it does, we are off to the 78169689Skan races. If it doesn't, we try an anonymous private mmap since the 79169689Skan kernel is more likely to honor the BASE address in anonymous maps. 80169689Skan We then copy the data to the anonymous private map. This assumes 81169689Skan of course that we don't need to change the data in the PCH file 82169689Skan after it is created. 83169689Skan 84169689Skan This approach obviously causes a performance penalty but there is 85169689Skan little else we can do given the current PCH implementation. */ 86169689Skan 87169689Skanstatic int 88169689Skanhpux_gt_pch_use_address (void *base, size_t size, int fd, size_t offset) 89169689Skan{ 90169689Skan void *addr; 91169689Skan 92169689Skan /* We're called with size == 0 if we're not planning to load a PCH 93169689Skan file at all. This allows the hook to free any static space that 94169689Skan we might have allocated at link time. */ 95169689Skan if (size == 0) 96169689Skan return -1; 97169689Skan 98169689Skan /* Try to map the file with MAP_PRIVATE. */ 99169689Skan addr = mmap (base, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, offset); 100169689Skan 101169689Skan if (addr == base) 102169689Skan return 1; 103169689Skan 104169689Skan if (addr != (void *) MAP_FAILED) 105169689Skan munmap (addr, size); 106169689Skan 107169689Skan /* Try to make an anonymous private mmap at the desired location. */ 108169689Skan addr = mmap (base, size, PROT_READ | PROT_WRITE, 109169689Skan MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 110169689Skan 111169689Skan if (addr != base) 112169689Skan { 113169689Skan if (addr != (void *) MAP_FAILED) 114169689Skan munmap (addr, size); 115169689Skan return -1; 116169689Skan } 117169689Skan 118169689Skan if (lseek (fd, offset, SEEK_SET) == (off_t)-1) 119169689Skan return -1; 120169689Skan 121169689Skan while (size) 122169689Skan { 123169689Skan ssize_t nbytes; 124169689Skan 125169689Skan nbytes = read (fd, base, MIN (size, SSIZE_MAX)); 126169689Skan if (nbytes <= 0) 127169689Skan return -1; 128169689Skan base = (char *) base + nbytes; 129169689Skan size -= nbytes; 130169689Skan } 131169689Skan 132169689Skan return 1; 133169689Skan} 134169689Skan 135169689Skan 136169689Skanconst struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER; 137