1/* Solaris host-specific hook definitions. 2 Copyright (C) 2004-2015 Free Software Foundation, Inc. 3 4 This file is part of GCC. 5 6 GCC is free software; you can redistribute it and/or modify it 7 under the terms of the GNU General Public License as published 8 by the Free Software Foundation; either version 3, or (at your 9 option) any later version. 10 11 GCC is distributed in the hope that it will be useful, but WITHOUT 12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GCC; see the file COPYING3. If not see 18 <http://www.gnu.org/licenses/>. */ 19 20#include "config.h" 21#include "system.h" 22#include "coretypes.h" 23#include "hosthooks.h" 24#include "hosthooks-def.h" 25 26 27#undef HOST_HOOKS_GT_PCH_GET_ADDRESS 28#define HOST_HOOKS_GT_PCH_GET_ADDRESS sol_gt_pch_get_address 29#undef HOST_HOOKS_GT_PCH_USE_ADDRESS 30#define HOST_HOOKS_GT_PCH_USE_ADDRESS sol_gt_pch_use_address 31 32/* Before Solaris 11, the mmap ADDR parameter is mostly ignored without 33 MAP_FIXED set. Before we give up, search the desired address space with 34 mincore to see if the space is really free. */ 35 36static void * 37mmap_fixed (void *addr, size_t len, int prot, int flags, int fd, off_t off) 38{ 39 void *base; 40 41 base = mmap ((caddr_t) addr, len, prot, flags, fd, off); 42 43 if (base != addr) 44 { 45 size_t page_size = getpagesize(); 46 char one_byte; 47 size_t i; 48 49 if (base != (void *) MAP_FAILED) 50 munmap ((caddr_t) base, len); 51 52 errno = 0; 53 for (i = 0; i < len; i += page_size) 54 if (mincore ((char *)addr + i, page_size, (char *) &one_byte) == -1 55 && errno == ENOMEM) 56 continue; /* The page is not mapped. */ 57 else 58 break; 59 60 if (i >= len) 61 base = mmap ((caddr_t) addr, len, prot, flags | MAP_FIXED, fd, off); 62 } 63 64 return base; 65} 66 67/* For various ports, try to guess a fixed spot in the vm space 68 that's probably free. Based on McDougall, Mauro, Solaris Internals, 2nd 69 ed., p.460-461, fig. 9-3, 9-4, 9-5. */ 70#if defined(__sparcv9__) 71/* This low to avoid VA hole on UltraSPARC I/II. */ 72# define TRY_EMPTY_VM_SPACE 0x70000000000 73#elif defined(__sparc__) 74# define TRY_EMPTY_VM_SPACE 0x80000000 75#elif defined(__x86_64__) 76# define TRY_EMPTY_VM_SPACE 0x80000000000 77#elif defined(__i386__) 78# define TRY_EMPTY_VM_SPACE 0xB0000000 79#else 80# define TRY_EMPTY_VM_SPACE 0 81#endif 82 83/* Determine a location where we might be able to reliably allocate 84 SIZE bytes. FD is the PCH file, though we should return with the 85 file unmapped. */ 86 87static void * 88sol_gt_pch_get_address (size_t size, int fd) 89{ 90 void *addr; 91 92 addr = mmap_fixed ((caddr_t) TRY_EMPTY_VM_SPACE, size, 93 PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); 94 95 /* If we failed the map, that means there's *no* free space. */ 96 if (addr == (void *) MAP_FAILED) 97 return NULL; 98 /* Unmap the area before returning. */ 99 munmap ((caddr_t) addr, size); 100 101 return addr; 102} 103 104/* Map SIZE bytes of FD+OFFSET at BASE. Return 1 if we succeeded at 105 mapping the data at BASE, -1 if we couldn't. */ 106 107static int 108sol_gt_pch_use_address (void *base, size_t size, int fd, size_t offset) 109{ 110 void *addr; 111 112 /* We're called with size == 0 if we're not planning to load a PCH 113 file at all. This allows the hook to free any static space that 114 we might have allocated at link time. */ 115 if (size == 0) 116 return -1; 117 118 addr = mmap_fixed ((caddr_t) base, size, 119 PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, offset); 120 121 return addr == base ? 1 : -1; 122} 123 124 125const struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER; 126