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