1/* Simulator memory option handling. 2 Copyright (C) 1996-1999, 2007 Free Software Foundation, Inc. 3 Contributed by Cygnus Support. 4 5This file is part of GDB, the GNU debugger. 6 7This program is free software; you can redistribute it and/or modify 8it under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 3 of the License, or 10(at your option) any later version. 11 12This program is distributed in the hope that it will be useful, 13but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15GNU General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20#include "cconfig.h" 21 22#include "sim-main.h" 23#include "sim-assert.h" 24#include "sim-options.h" 25 26#ifdef HAVE_STRING_H 27#include <string.h> 28#else 29#ifdef HAVE_STRINGS_H 30#include <strings.h> 31#endif 32#endif 33#ifdef HAVE_STDLIB_H 34#include <stdlib.h> 35#endif 36#ifdef HAVE_ERRNO_H 37#include <errno.h> 38#endif 39#ifdef HAVE_FCNTL_H 40#include <fcntl.h> 41#endif 42#ifdef HAVE_SYS_MMAN_H 43#include <sys/mman.h> 44#endif 45#ifdef HAVE_SYS_STAT_H 46#include <sys/stat.h> 47#endif 48#ifdef HAVE_UNISTD_H 49#include <unistd.h> 50#endif 51 52/* Memory fill byte. */ 53static unsigned8 fill_byte_value; 54static int fill_byte_flag = 0; 55 56/* Memory mapping; see OPTION_MEMORY_MAPFILE. */ 57static int mmap_next_fd = -1; 58 59/* Memory command line options. */ 60 61enum { 62 OPTION_MEMORY_DELETE = OPTION_START, 63 OPTION_MEMORY_REGION, 64 OPTION_MEMORY_SIZE, 65 OPTION_MEMORY_INFO, 66 OPTION_MEMORY_ALIAS, 67 OPTION_MEMORY_CLEAR, 68 OPTION_MEMORY_FILL, 69 OPTION_MEMORY_MAPFILE 70}; 71 72static DECLARE_OPTION_HANDLER (memory_option_handler); 73 74static const OPTION memory_options[] = 75{ 76 { {"memory-delete", required_argument, NULL, OPTION_MEMORY_DELETE }, 77 '\0', "ADDRESS|all", "Delete memory at ADDRESS (all addresses)", 78 memory_option_handler }, 79 { {"delete-memory", required_argument, NULL, OPTION_MEMORY_DELETE }, 80 '\0', "ADDRESS", NULL, 81 memory_option_handler }, 82 83 { {"memory-region", required_argument, NULL, OPTION_MEMORY_REGION }, 84 '\0', "ADDRESS,SIZE[,MODULO]", "Add a memory region", 85 memory_option_handler }, 86 87 { {"memory-alias", required_argument, NULL, OPTION_MEMORY_ALIAS }, 88 '\0', "ADDRESS,SIZE{,ADDRESS}", "Add memory shadow", 89 memory_option_handler }, 90 91 { {"memory-size", required_argument, NULL, OPTION_MEMORY_SIZE }, 92 '\0', "<size>[in bytes, Kb (k suffix), Mb (m suffix) or Gb (g suffix)]", 93 "Add memory at address zero", memory_option_handler }, 94 95 { {"memory-fill", required_argument, NULL, OPTION_MEMORY_FILL }, 96 '\0', "VALUE", "Fill subsequently added memory regions", 97 memory_option_handler }, 98 99 { {"memory-clear", no_argument, NULL, OPTION_MEMORY_CLEAR }, 100 '\0', NULL, "Clear subsequently added memory regions", 101 memory_option_handler }, 102 103#if defined(HAVE_MMAP) && defined(HAVE_MUNMAP) 104 { {"memory-mapfile", required_argument, NULL, OPTION_MEMORY_MAPFILE }, 105 '\0', "FILE", "Memory-map next memory region from file", 106 memory_option_handler }, 107#endif 108 109 { {"memory-info", no_argument, NULL, OPTION_MEMORY_INFO }, 110 '\0', NULL, "List configurable memory regions", 111 memory_option_handler }, 112 { {"info-memory", no_argument, NULL, OPTION_MEMORY_INFO }, 113 '\0', NULL, NULL, 114 memory_option_handler }, 115 116 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL } 117}; 118 119 120static sim_memopt * 121do_memopt_add (SIM_DESC sd, 122 int level, 123 int space, 124 address_word addr, 125 address_word nr_bytes, 126 unsigned modulo, 127 sim_memopt **entry, 128 void *buffer) 129{ 130 void *fill_buffer; 131 unsigned fill_length; 132 void *free_buffer; 133 unsigned long free_length; 134 135 if (buffer != NULL) 136 { 137 /* Buffer already given. sim_memory_uninstall will free it. */ 138 sim_core_attach (sd, NULL, 139 level, access_read_write_exec, space, 140 addr, nr_bytes, modulo, NULL, buffer); 141 142 free_buffer = buffer; 143 free_length = 0; 144 fill_buffer = buffer; 145 fill_length = (modulo == 0) ? nr_bytes : modulo; 146 } 147 else 148 { 149 /* Allocate new well-aligned buffer, just as sim_core_attach(). */ 150 void *aligned_buffer; 151 int padding = (addr % sizeof (unsigned64)); 152 unsigned long bytes = (modulo == 0 ? nr_bytes : modulo) + padding; 153 154 free_buffer = NULL; 155 free_length = bytes; 156 157#ifdef HAVE_MMAP 158 /* Memory map or malloc(). */ 159 if (mmap_next_fd >= 0) 160 { 161 /* Check that given file is big enough. */ 162 struct stat s; 163 int rc; 164 165 /* Some kernels will SIGBUS the application if mmap'd file 166 is not large enough. */ 167 rc = fstat (mmap_next_fd, &s); 168 if (rc < 0 || s.st_size < bytes) 169 { 170 sim_io_error (sd, 171 "Error, cannot confirm that mmap file is large enough " 172 "(>= %ld bytes)\n", bytes); 173 } 174 175 free_buffer = mmap (0, bytes, PROT_READ|PROT_WRITE, MAP_SHARED, mmap_next_fd, 0); 176 if (free_buffer == 0 || free_buffer == (char*)-1) /* MAP_FAILED */ 177 { 178 sim_io_error (sd, "Error, cannot mmap file (%s).\n", 179 strerror(errno)); 180 } 181 } 182#endif 183 184 /* Need heap allocation? */ 185 if (free_buffer == NULL) 186 { 187 /* If filling with non-zero value, do not use clearing allocator. */ 188 if (fill_byte_flag && fill_byte_value != 0) 189 free_buffer = xmalloc (bytes); /* don't clear */ 190 else 191 free_buffer = zalloc (bytes); /* clear */ 192 } 193 194 aligned_buffer = (char*) free_buffer + padding; 195 196 sim_core_attach (sd, NULL, 197 level, access_read_write_exec, space, 198 addr, nr_bytes, modulo, NULL, aligned_buffer); 199 200 fill_buffer = aligned_buffer; 201 fill_length = (modulo == 0) ? nr_bytes : modulo; 202 203 /* If we just used a clearing allocator, and are about to fill with 204 zero, truncate the redundant fill operation. */ 205 206 if (fill_byte_flag && fill_byte_value == 0) 207 fill_length = 1; /* avoid boundary length=0 case */ 208 } 209 210 if (fill_byte_flag) 211 { 212 ASSERT (fill_buffer != 0); 213 memset ((char*) fill_buffer, fill_byte_value, fill_length); 214 } 215 216 while ((*entry) != NULL) 217 entry = &(*entry)->next; 218 (*entry) = ZALLOC (sim_memopt); 219 (*entry)->level = level; 220 (*entry)->space = space; 221 (*entry)->addr = addr; 222 (*entry)->nr_bytes = nr_bytes; 223 (*entry)->modulo = modulo; 224 (*entry)->buffer = free_buffer; 225 226 /* Record memory unmapping info. */ 227 if (mmap_next_fd >= 0) 228 { 229 (*entry)->munmap_length = free_length; 230 close (mmap_next_fd); 231 mmap_next_fd = -1; 232 } 233 else 234 (*entry)->munmap_length = 0; 235 236 return (*entry); 237} 238 239static SIM_RC 240do_memopt_delete (SIM_DESC sd, 241 int level, 242 int space, 243 address_word addr) 244{ 245 sim_memopt **entry = &STATE_MEMOPT (sd); 246 sim_memopt *alias; 247 while ((*entry) != NULL 248 && ((*entry)->level != level 249 || (*entry)->space != space 250 || (*entry)->addr != addr)) 251 entry = &(*entry)->next; 252 if ((*entry) == NULL) 253 { 254 sim_io_eprintf (sd, "Memory at 0x%lx not found, not deleted\n", 255 (long) addr); 256 return SIM_RC_FAIL; 257 } 258 /* delete any buffer */ 259 if ((*entry)->buffer != NULL) 260 { 261#ifdef HAVE_MUNMAP 262 if ((*entry)->munmap_length > 0) 263 munmap ((*entry)->buffer, (*entry)->munmap_length); 264 else 265#endif 266 zfree ((*entry)->buffer); 267 } 268 269 /* delete it and its aliases */ 270 alias = *entry; 271 *entry = (*entry)->next; 272 while (alias != NULL) 273 { 274 sim_memopt *dead = alias; 275 alias = alias->alias; 276 sim_core_detach (sd, NULL, dead->level, dead->space, dead->addr); 277 zfree (dead); 278 } 279 return SIM_RC_OK; 280} 281 282 283static char * 284parse_size (char *chp, 285 address_word *nr_bytes, 286 unsigned *modulo) 287{ 288 /* <nr_bytes>[K|M|G] [ "%" <modulo> ] */ 289 *nr_bytes = strtoul (chp, &chp, 0); 290 switch (*chp) 291 { 292 case '%': 293 *modulo = strtoul (chp + 1, &chp, 0); 294 break; 295 case 'g': case 'G': /* Gigabyte suffix. */ 296 *nr_bytes <<= 10; 297 /* Fall through. */ 298 case 'm': case 'M': /* Megabyte suffix. */ 299 *nr_bytes <<= 10; 300 /* Fall through. */ 301 case 'k': case 'K': /* Kilobyte suffix. */ 302 *nr_bytes <<= 10; 303 /* Check for a modulo specifier after the suffix. */ 304 ++ chp; 305 if (* chp == 'b' || * chp == 'B') 306 ++ chp; 307 if (* chp == '%') 308 *modulo = strtoul (chp + 1, &chp, 0); 309 break; 310 } 311 return chp; 312} 313 314static char * 315parse_ulong_value (char *chp, 316 unsigned long *value) 317{ 318 *value = strtoul (chp, &chp, 0); 319 return chp; 320} 321 322static char * 323parse_addr (char *chp, 324 int *level, 325 int *space, 326 address_word *addr) 327{ 328 /* [ <space> ": " ] <addr> [ "@" <level> ] */ 329 *addr = (unsigned long) strtoul (chp, &chp, 0); 330 if (*chp == ':') 331 { 332 *space = *addr; 333 *addr = (unsigned long) strtoul (chp + 1, &chp, 0); 334 } 335 if (*chp == '@') 336 { 337 *level = strtoul (chp + 1, &chp, 0); 338 } 339 return chp; 340} 341 342 343static SIM_RC 344memory_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt, 345 char *arg, int is_command) 346{ 347 switch (opt) 348 { 349 350 case OPTION_MEMORY_DELETE: 351 if (strcasecmp (arg, "all") == 0) 352 { 353 while (STATE_MEMOPT (sd) != NULL) 354 do_memopt_delete (sd, 355 STATE_MEMOPT (sd)->level, 356 STATE_MEMOPT (sd)->space, 357 STATE_MEMOPT (sd)->addr); 358 return SIM_RC_OK; 359 } 360 else 361 { 362 int level = 0; 363 int space = 0; 364 address_word addr = 0; 365 parse_addr (arg, &level, &space, &addr); 366 return do_memopt_delete (sd, level, space, addr); 367 } 368 369 case OPTION_MEMORY_REGION: 370 { 371 char *chp = arg; 372 int level = 0; 373 int space = 0; 374 address_word addr = 0; 375 address_word nr_bytes = 0; 376 unsigned modulo = 0; 377 /* parse the arguments */ 378 chp = parse_addr (chp, &level, &space, &addr); 379 if (*chp != ',') 380 { 381 sim_io_eprintf (sd, "Missing size for memory-region\n"); 382 return SIM_RC_FAIL; 383 } 384 chp = parse_size (chp + 1, &nr_bytes, &modulo); 385 /* old style */ 386 if (*chp == ',') 387 modulo = strtoul (chp + 1, &chp, 0); 388 /* try to attach/insert it */ 389 do_memopt_add (sd, level, space, addr, nr_bytes, modulo, 390 &STATE_MEMOPT (sd), NULL); 391 return SIM_RC_OK; 392 } 393 394 case OPTION_MEMORY_ALIAS: 395 { 396 char *chp = arg; 397 int level = 0; 398 int space = 0; 399 address_word addr = 0; 400 address_word nr_bytes = 0; 401 unsigned modulo = 0; 402 sim_memopt *entry; 403 /* parse the arguments */ 404 chp = parse_addr (chp, &level, &space, &addr); 405 if (*chp != ',') 406 { 407 sim_io_eprintf (sd, "Missing size for memory-region\n"); 408 return SIM_RC_FAIL; 409 } 410 chp = parse_size (chp + 1, &nr_bytes, &modulo); 411 /* try to attach/insert the main record */ 412 entry = do_memopt_add (sd, level, space, addr, nr_bytes, modulo, 413 &STATE_MEMOPT (sd), 414 NULL); 415 /* now attach all the aliases */ 416 while (*chp == ',') 417 { 418 int a_level = level; 419 int a_space = space; 420 address_word a_addr = addr; 421 chp = parse_addr (chp + 1, &a_level, &a_space, &a_addr); 422 do_memopt_add (sd, a_level, a_space, a_addr, nr_bytes, modulo, 423 &entry->alias, entry->buffer); 424 } 425 return SIM_RC_OK; 426 } 427 428 case OPTION_MEMORY_SIZE: 429 { 430 int level = 0; 431 int space = 0; 432 address_word addr = 0; 433 address_word nr_bytes = 0; 434 unsigned modulo = 0; 435 /* parse the arguments */ 436 parse_size (arg, &nr_bytes, &modulo); 437 /* try to attach/insert it */ 438 do_memopt_add (sd, level, space, addr, nr_bytes, modulo, 439 &STATE_MEMOPT (sd), NULL); 440 return SIM_RC_OK; 441 } 442 443 case OPTION_MEMORY_CLEAR: 444 { 445 fill_byte_value = (unsigned8) 0; 446 fill_byte_flag = 1; 447 return SIM_RC_OK; 448 break; 449 } 450 451 case OPTION_MEMORY_FILL: 452 { 453 unsigned long fill_value; 454 parse_ulong_value (arg, &fill_value); 455 if (fill_value > 255) 456 { 457 sim_io_eprintf (sd, "Missing fill value between 0 and 255\n"); 458 return SIM_RC_FAIL; 459 } 460 fill_byte_value = (unsigned8) fill_value; 461 fill_byte_flag = 1; 462 return SIM_RC_OK; 463 break; 464 } 465 466 case OPTION_MEMORY_MAPFILE: 467 { 468 if (mmap_next_fd >= 0) 469 { 470 sim_io_eprintf (sd, "Duplicate memory-mapfile option\n"); 471 return SIM_RC_FAIL; 472 } 473 474 mmap_next_fd = open (arg, O_RDWR); 475 if (mmap_next_fd < 0) 476 { 477 sim_io_eprintf (sd, "Cannot open file `%s': %s\n", 478 arg, strerror(errno)); 479 return SIM_RC_FAIL; 480 } 481 482 return SIM_RC_OK; 483 } 484 485 case OPTION_MEMORY_INFO: 486 { 487 sim_memopt *entry; 488 sim_io_printf (sd, "Memory maps:\n"); 489 for (entry = STATE_MEMOPT (sd); entry != NULL; entry = entry->next) 490 { 491 sim_memopt *alias; 492 sim_io_printf (sd, " memory"); 493 if (entry->alias == NULL) 494 sim_io_printf (sd, " region "); 495 else 496 sim_io_printf (sd, " alias "); 497 if (entry->space != 0) 498 sim_io_printf (sd, "0x%lx:", (long) entry->space); 499 sim_io_printf (sd, "0x%08lx", (long) entry->addr); 500 if (entry->level != 0) 501 sim_io_printf (sd, "@0x%lx", (long) entry->level); 502 sim_io_printf (sd, ",0x%lx", 503 (long) entry->nr_bytes); 504 if (entry->modulo != 0) 505 sim_io_printf (sd, "%%0x%lx", (long) entry->modulo); 506 for (alias = entry->alias; 507 alias != NULL; 508 alias = alias->next) 509 { 510 if (alias->space != 0) 511 sim_io_printf (sd, "0x%lx:", (long) alias->space); 512 sim_io_printf (sd, ",0x%08lx", (long) alias->addr); 513 if (alias->level != 0) 514 sim_io_printf (sd, "@0x%lx", (long) alias->level); 515 } 516 sim_io_printf (sd, "\n"); 517 } 518 return SIM_RC_OK; 519 break; 520 } 521 522 default: 523 sim_io_eprintf (sd, "Unknown memory option %d\n", opt); 524 return SIM_RC_FAIL; 525 526 } 527 528 return SIM_RC_FAIL; 529} 530 531 532/* "memory" module install handler. 533 534 This is called via sim_module_install to install the "memory" subsystem 535 into the simulator. */ 536 537static MODULE_INIT_FN sim_memory_init; 538static MODULE_UNINSTALL_FN sim_memory_uninstall; 539 540SIM_RC 541sim_memopt_install (SIM_DESC sd) 542{ 543 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 544 sim_add_option_table (sd, NULL, memory_options); 545 sim_module_add_uninstall_fn (sd, sim_memory_uninstall); 546 sim_module_add_init_fn (sd, sim_memory_init); 547 return SIM_RC_OK; 548} 549 550 551/* Uninstall the "memory" subsystem from the simulator. */ 552 553static void 554sim_memory_uninstall (SIM_DESC sd) 555{ 556 sim_memopt **entry = &STATE_MEMOPT (sd); 557 sim_memopt *alias; 558 559 while ((*entry) != NULL) 560 { 561 /* delete any buffer */ 562 if ((*entry)->buffer != NULL) 563 { 564#ifdef HAVE_MUNMAP 565 if ((*entry)->munmap_length > 0) 566 munmap ((*entry)->buffer, (*entry)->munmap_length); 567 else 568#endif 569 zfree ((*entry)->buffer); 570 } 571 572 /* delete it and its aliases */ 573 alias = *entry; 574 575 /* next victim */ 576 *entry = (*entry)->next; 577 578 while (alias != NULL) 579 { 580 sim_memopt *dead = alias; 581 alias = alias->alias; 582 sim_core_detach (sd, NULL, dead->level, dead->space, dead->addr); 583 zfree (dead); 584 } 585 } 586} 587 588 589static SIM_RC 590sim_memory_init (SIM_DESC sd) 591{ 592 /* Reinitialize option modifier flags, in case they were left 593 over from a previous sim startup event. */ 594 fill_byte_flag = 0; 595 mmap_next_fd = -1; 596 597 return SIM_RC_OK; 598} 599