1/* BEGIN LICENSE BLOCK 2 * Version: CMPL 1.1 3 * 4 * The contents of this file are subject to the Cisco-style Mozilla Public 5 * License Version 1.1 (the "License"); you may not use this file except 6 * in compliance with the License. You may obtain a copy of the License 7 * at www.eclipse-clp.org/license. 8 * 9 * Software distributed under the License is distributed on an "AS IS" 10 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 11 * the License for the specific language governing rights and limitations 12 * under the License. 13 * 14 * The Original Code is The ECLiPSe Constraint Logic Programming System. 15 * The Initial Developer of the Original Code is Cisco Systems, Inc. 16 * Portions created by the Initial Developer are 17 * Copyright (C) 1995-2006 Cisco Systems, Inc. All Rights Reserved. 18 * 19 * Contributor(s): Kees Schuerman, ECRC 20 * 21 * END LICENSE BLOCK */ 22 23/********************************************************************** 24** File: addrmap.c 25** Author: Kees Schuerman 26** Description: Address Space Map 27** 28* 29* The program displays the address map of the machine 30* using the following categories: 31* 32* FREE The area is not mapped and can be mapped. 33* If the flag ADDR_FLAGS_WRITECHECK is specified, 34* it is also writable, otherwise this is not certain. 35* MAPPED This area is already mapped to this process. 36* UNAVAILABLE This are is not mapped to this process and cannot 37* be mapped, i.e. it is probably being used by 38* other processes 39* 40***********************************************************************/ 41 42#include "config.h" 43 44#ifdef HAVE_MMAP 45#include <sys/types.h> 46#include <sys/stat.h> 47#include <sys/mman.h> 48#include <fcntl.h> 49#include <signal.h> 50#include <setjmp.h> 51 52#ifdef SBRK_UNDEF 53extern char *sbrk(); 54#endif 55extern void exit(int); 56 57#ifdef HAVE_UNISTD_H 58#include <unistd.h> 59#endif 60 61#define ADDR_UNAVAILABLE 0 62#define ADDR_MAPPED 1 63#define ADDR_FREE 2 64#define ADDR_FREE_VAR 3 65#define ADDR_TRY -1 66 67#define ADDR_FLAGS_WRITECHECK 1 68#define ADDR_FLAGS_SHARED 2 69 70#ifndef MAP_NORESERVE 71#define MAP_NORESERVE 0 72#endif 73#ifndef MAP_VARIABLE 74#define MAP_VARIABLE 0 75#endif 76#ifndef MAP_FAILED 77#define MAP_FAILED ((caddr_t) (-1)) 78#endif 79#if defined(MAP_ANONYMOUS) || defined(MAP_ANON) 80# ifndef MAP_FILE 81# define MAP_FILE 0 82# endif 83# ifndef MAP_ANONYMOUS 84# define MAP_ANONYMOUS MAP_ANON 85# endif 86#endif 87 88extern char *shared_mem_base(void); 89 90typedef struct addr_range { 91 struct addr_range * next; 92 char * addr; 93 unsigned size; 94 unsigned state; 95} addr_range_t; 96 97static jmp_buf addr_env; 98 99static addr_range_t * addr_spc_map; 100static addr_range_t * addr_range; 101static char * addr_range_addr; 102 103static void _addr_map(char *from, char *to, long int increment), 104 _addr_init(char *from), 105 _write_address(char *a), 106 _write_range(char *from, char *to, int state); 107 108#ifdef HAVE_SIGACTION 109typedef struct sigaction sig_action_t; 110#else 111#ifdef HAVE_SIGVEC 112typedef struct sigvec sig_action_t; 113#define sa_handler sv_handler 114#define sa_mask sv_mask 115#define sa_flags sv_flags 116#else 117typedef struct { 118 RETSIGTYPE (*sa_handler)(); 119 int sa_mask; 120 int sa_flags; 121} sig_action_t; 122#endif 123#endif 124 125static sig_action_t sigsegv_act; 126static sig_action_t sigbus_act; 127 128static unsigned long addr_pagesize; 129static int addr_map_fd; 130static long addr_increment; 131 132static volatile char * addr = 0; 133static volatile int addr_state = ADDR_FREE; 134static volatile int addr_flags = 0; 135static volatile int addr_map_mode = MAP_FIXED; 136 137ec_layout(int flags, char *from, char *to, long int increment) 138{ 139 140 if (flags & ADDR_FLAGS_SHARED) 141 write(2, "\nshared\n", 8); 142 else if (flags & ADDR_FLAGS_WRITECHECK) 143 write(2, "\nwrite check\n", 13); 144 addr_flags = flags; 145 _addr_init(from); 146 _addr_map(from, to, increment); 147} 148 149static void 150_addr_init(char *from) 151{ 152#if defined(HAVE_SYSCONF) && defined(SYSCONF_PAGE) 153 addr_pagesize = sysconf(SYSCONF_PAGE); 154#else 155#ifdef HAVE_GETPAGESIZE 156 addr_pagesize = getpagesize(); 157#else 158 addr_pagesize = 4096; 159#endif 160#endif 161 162 if (addr_flags & ADDR_FLAGS_SHARED) { 163 (void) unlink("heap.map"); 164 addr_map_fd = open("heap.map", O_RDWR|O_CREAT|O_EXCL, 0700); 165 if (addr_map_fd == -1 || 166 ftruncate(addr_map_fd, (off_t) addr_pagesize) == -1) { 167 (void) write(2, "AdrMap: Cannot use the map file\n", 32); 168 exit(-1); 169 } 170 } else 171#ifdef MAP_ANONYMOUS 172 addr_map_fd = -1; 173#else 174 if ((addr_map_fd = open("/dev/zero", O_RDWR)) == -1) { 175 (void) write(2, "AdrMap: Cannot open /dev/zero\n", 31); 176 exit(-1); 177 } 178#endif 179 180 addr_spc_map = (addr_range_t *) 0; 181 182 addr = addr_range_addr = from; 183 addr_range = (addr_range_t *) 0; 184} 185 186/*ARGSUSED*/ 187static void 188_sigsegv_handler(int sig) 189{ 190 int addr_state_save; 191 int map_flags, map_prot; 192 caddr_t map_result; 193#ifdef HAVE_SIGPROCMASK 194 sigset_t sig_mask; 195 196 (void) sigemptyset(&sig_mask); 197 (void) sigaddset(&sig_mask, sig); 198 (void) sigprocmask(SIG_UNBLOCK, &sig_mask, (sigset_t *) 0); 199#else 200 int sig_mask; 201 202 sig_mask = ~sigmask(sig); 203 (void) sigblock(sig_mask); 204#endif 205 206 map_prot = PROT_READ|PROT_WRITE; 207 if(addr_flags & ADDR_FLAGS_SHARED) { 208 map_prot |= PROT_EXEC; 209 map_flags = 210#ifdef MAP_ANONYMOUS 211 MAP_FILE| 212#endif 213 MAP_SHARED|MAP_NORESERVE|addr_map_mode; 214 } else { 215 map_flags = 216#ifdef MAP_ANONYMOUS 217 MAP_ANONYMOUS| 218#endif 219 MAP_PRIVATE|addr_map_mode; 220 } 221 map_result = mmap((caddr_t) addr, 222 (size_t) addr_pagesize, 223 map_prot, 224 map_flags, 225 addr_map_fd, 226 (off_t) 0); 227 if ((addr_state != ADDR_TRY) && map_result == addr) { 228 if (addr_flags & ADDR_FLAGS_WRITECHECK && 229 !(addr_flags & ADDR_FLAGS_SHARED)) { 230 addr_state_save = addr_state; 231 addr_state = ADDR_TRY; 232 *addr = 0xff; 233 addr_state = addr_state_save; 234 } 235 (void) munmap((caddr_t) addr,(size_t) addr_pagesize); 236 if (addr_state != ADDR_FREE) { 237 if (addr_range_addr != addr) 238 _write_range(addr_range_addr, (char *) addr, addr_state); 239 addr_range_addr = (char *) addr; 240 } 241 addr_state = ADDR_FREE; 242 } 243 else if (addr_state != ADDR_UNAVAILABLE) { 244 if (addr_range_addr != addr) 245 _write_range(addr_range_addr, (char *) addr, addr_state); 246 addr_range_addr = (char *) addr; 247 addr_state = ADDR_UNAVAILABLE; 248 } 249 250 addr += addr_increment; 251 252 longjmp(addr_env,0); 253} 254 255 256static void 257_save_handler(int sig, sig_action_t *action) 258{ 259#ifdef HAVE_SIGACTION 260 (void) sigaction(sig, 261 (struct sigaction *) 0, 262 action); 263#else 264#ifdef HAVE_SIGVEC 265 (void) sigvec(sig, (struct sigvec *) 0, action); 266#else 267 /* no flags for signal() */ 268#endif 269#endif 270} 271 272static void 273_install_handler(int sig, sig_action_t *action) 274{ 275 sig_action_t act; 276 int res; 277 278 act.sa_handler = _sigsegv_handler; 279#ifdef HAVE_SIGACTION 280 (void) sigemptyset(&act.sa_mask); 281#ifdef SA_RESETHAND 282 act.sa_flags = action->sa_flags & ~SA_RESETHAND; 283#else 284 act.sa_flags = action->sa_flags; 285#endif 286 res = sigaction(sig, &act, (struct sigaction *) 0); 287#else 288#ifdef HAVE_SIGVEC 289 act.sa_mask = 0; 290 act.sa_flags = action->sa_flags & ~SV_RESETHAND; 291 res = sigvec(sig, &act, (struct sigvec *) 0); 292#else 293 action->sa_handler = (RETSIGTYPE (*)()) signal(sig, act.sa_handler); 294#endif 295#endif 296 if (res < 0) 297 exit(-1); 298} 299 300 301static void 302_restore_handler(int sig, sig_action_t *action) 303{ 304 int res; 305 306#ifdef HAVE_SIGACTION 307 res = sigaction(sig, action, (struct sigaction *) 0); 308#else 309#ifdef HAVE_SIGVEC 310 res = sigvec(sig, action, (struct sigvec *) 0); 311#else 312 res = signal(sig, action->sa_handler); 313#endif 314#endif 315 if (res < 0) 316 exit(-1); 317} 318 319 320static void 321_addr_map(char *from, char *to, long int increment) 322{ 323 char byte; 324 325 addr_increment = (increment == 0) ? addr_pagesize: increment; 326 (void) write(2, "page size = ", 12); 327 _write_address((char *) addr_pagesize); 328 if (from != (char *) 0 || to != (char *) 0 || increment != 0) { 329 (void) write(2, "\nstep = ", 14); 330 _write_address((char *) addr_increment); 331 (void) write(2, "\nstart = ", 14); 332 _write_address(from); 333 (void) write(2, "\nend = ", 14); 334 _write_address(to); 335 } 336 (void) write(2, "\n\n", 2); 337 338 _save_handler(SIGSEGV, &sigsegv_act); 339 _save_handler(SIGBUS, &sigbus_act); 340 341 _install_handler(SIGSEGV, &sigsegv_act); 342 _install_handler(SIGBUS, &sigbus_act); 343 344 (void) setjmp(addr_env); 345 346 while (1) { 347 if (to != (char *) 0 && addr + addr_increment > to || 348 ((unsigned long) (addr - (char *) 0)) > 349 ((unsigned long) ((addr + addr_increment) - (char *) 0))) { 350 _write_range(addr_range_addr, (char *) addr + addr_increment, addr_state); 351 352 _restore_handler(SIGSEGV, &sigsegv_act); 353 _restore_handler(SIGBUS, &sigbus_act); 354 if (addr_flags & ADDR_FLAGS_SHARED) { 355 (void) close(addr_map_fd); 356 (void) unlink("heap.map"); 357 } 358 return; 359 } 360 byte = *addr; 361 if (addr_state != ADDR_MAPPED) { 362 if (addr_range_addr != addr) 363 _write_range(addr_range_addr, (char *) addr, addr_state); 364 addr_range_addr = (char *) addr; 365 addr_state = ADDR_MAPPED; 366 } 367 addr += addr_increment; 368 } 369} 370 371/* Output the address without allocating any memory */ 372static void 373_write_address(char *a) 374{ 375 char buf[2*sizeof(char *)]; 376 int i; 377 int c; 378 int n = 2*sizeof(char *); 379 380 for (i = 0; i < n; i++) { 381 c = ((unsigned long) a & ((unsigned long) 0xf << 4 * (n - i - 1))) >> 4 * (n - i - 1); 382 if (c < 10) 383 buf[i] = c + '0'; 384 else 385 buf[i] = c - 10 + 'a'; 386 } 387 (void) write(2, buf, n); 388} 389 390static void 391_write_range(char *from, char *to, int state) 392{ 393 unsigned long size = (to-from); 394 _write_address(from); 395 (void) write(2, " <-> ", 5); 396 _write_address(to); 397 (void) write(2, " (", 2); 398 _write_address((char*) size); 399 (void) write(2, ") ", 2); 400 switch (state) { 401 case ADDR_FREE: 402 (void) write(2, "FREE\n", 5); 403 break; 404 405 case ADDR_FREE_VAR: 406 (void) write(2, "FREE for MAP_VARIABLE\n", 22); 407 break; 408 409 case ADDR_MAPPED: 410 (void) write(2, "MAPPED\n", 7); 411 break; 412 413 case ADDR_UNAVAILABLE: 414 (void) write(2, "UNAVAILABLE\n", 12); 415 break; 416 417 } 418} 419#endif /* HAVE_MMAP */ 420