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