14e98e3e1Schristos /* Module support. 24e98e3e1Schristos 3*88241920Schristos Copyright 1996-2024 Free Software Foundation, Inc. 44e98e3e1Schristos 54e98e3e1Schristos Contributed by Cygnus Support. 64e98e3e1Schristos 74e98e3e1Schristos This file is part of GDB, the GNU debugger. 84e98e3e1Schristos 94e98e3e1Schristos This program is free software; you can redistribute it and/or modify 104e98e3e1Schristos it under the terms of the GNU General Public License as published by 114e98e3e1Schristos the Free Software Foundation; either version 3 of the License, or 124e98e3e1Schristos (at your option) any later version. 134e98e3e1Schristos 144e98e3e1Schristos This program is distributed in the hope that it will be useful, 154e98e3e1Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 164e98e3e1Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 174e98e3e1Schristos GNU General Public License for more details. 184e98e3e1Schristos 194e98e3e1Schristos You should have received a copy of the GNU General Public License 204e98e3e1Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 214e98e3e1Schristos 224b169a6bSchristos /* This must come before any other includes. */ 234b169a6bSchristos #include "defs.h" 244b169a6bSchristos 254b169a6bSchristos #include <stdlib.h> 264b169a6bSchristos 274b169a6bSchristos #include "libiberty.h" 284b169a6bSchristos 294e98e3e1Schristos #include "sim-main.h" 304e98e3e1Schristos #include "sim-io.h" 314e98e3e1Schristos #include "sim-options.h" 324e98e3e1Schristos #include "sim-assert.h" 334e98e3e1Schristos 344b169a6bSchristos /* List of all early/core modules. 354b169a6bSchristos TODO: Should trim this list by converting to sim_install_* framework. */ 364b169a6bSchristos static MODULE_INSTALL_FN * const early_modules[] = { 374e98e3e1Schristos standard_install, 384e98e3e1Schristos sim_events_install, 394e98e3e1Schristos sim_model_install, 404e98e3e1Schristos sim_core_install, 414e98e3e1Schristos sim_memopt_install, 424e98e3e1Schristos sim_watchpoint_install, 434e98e3e1Schristos }; 444b169a6bSchristos static int early_modules_len = ARRAY_SIZE (early_modules); 454b169a6bSchristos 464b169a6bSchristos /* List of dynamically detected modules. Declared in generated modules.c. */ 474b169a6bSchristos extern MODULE_INSTALL_FN * const sim_modules_detected[]; 484b169a6bSchristos extern const int sim_modules_detected_len; 494e98e3e1Schristos 504e98e3e1Schristos /* Functions called from sim_open. */ 514e98e3e1Schristos 524e98e3e1Schristos /* Initialize common parts before argument processing. */ 534e98e3e1Schristos 544e98e3e1Schristos SIM_RC 554e98e3e1Schristos sim_pre_argv_init (SIM_DESC sd, const char *myname) 564e98e3e1Schristos { 574e98e3e1Schristos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 584e98e3e1Schristos SIM_ASSERT (STATE_MODULES (sd) == NULL); 594e98e3e1Schristos 60ba340e45Schristos STATE_MY_NAME (sd) = lbasename (myname); 614e98e3e1Schristos 624e98e3e1Schristos /* Set the cpu names to default values. */ 634e98e3e1Schristos { 644e98e3e1Schristos int i; 654e98e3e1Schristos for (i = 0; i < MAX_NR_PROCESSORS; ++i) 664e98e3e1Schristos { 674e98e3e1Schristos char *name; 684e98e3e1Schristos if (asprintf (&name, "cpu%d", i) < 0) 694e98e3e1Schristos return SIM_RC_FAIL; 704e98e3e1Schristos CPU_NAME (STATE_CPU (sd, i)) = name; 714e98e3e1Schristos } 724e98e3e1Schristos } 734e98e3e1Schristos 744e98e3e1Schristos sim_config_default (sd); 754e98e3e1Schristos 764b169a6bSchristos /* Install all early configured-in modules. */ 774e98e3e1Schristos if (sim_module_install (sd) != SIM_RC_OK) 784e98e3e1Schristos return SIM_RC_FAIL; 794e98e3e1Schristos 804b169a6bSchristos /* Install all remaining dynamically detected modules. */ 814b169a6bSchristos return sim_module_install_list (sd, sim_modules_detected, 824b169a6bSchristos sim_modules_detected_len); 834e98e3e1Schristos } 844e98e3e1Schristos 854e98e3e1Schristos /* Initialize common parts after argument processing. */ 864e98e3e1Schristos 874e98e3e1Schristos SIM_RC 884e98e3e1Schristos sim_post_argv_init (SIM_DESC sd) 894e98e3e1Schristos { 904e98e3e1Schristos int i; 914e98e3e1Schristos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 924e98e3e1Schristos SIM_ASSERT (STATE_MODULES (sd) != NULL); 934e98e3e1Schristos 944e98e3e1Schristos /* Set the cpu->state backlinks for each cpu. */ 954e98e3e1Schristos for (i = 0; i < MAX_NR_PROCESSORS; ++i) 964e98e3e1Schristos { 974e98e3e1Schristos CPU_STATE (STATE_CPU (sd, i)) = sd; 984e98e3e1Schristos CPU_INDEX (STATE_CPU (sd, i)) = i; 994e98e3e1Schristos } 1004e98e3e1Schristos 1014e98e3e1Schristos if (sim_module_init (sd) != SIM_RC_OK) 1024e98e3e1Schristos return SIM_RC_FAIL; 1034e98e3e1Schristos 1044e98e3e1Schristos return SIM_RC_OK; 1054e98e3e1Schristos } 1064e98e3e1Schristos 1074b169a6bSchristos /* Install a list of modules. 1084b169a6bSchristos If this fails, no modules are left installed. */ 1094b169a6bSchristos SIM_RC 1104b169a6bSchristos sim_module_install_list (SIM_DESC sd, MODULE_INSTALL_FN * const *modules, 1114b169a6bSchristos size_t modules_len) 1124b169a6bSchristos { 1134b169a6bSchristos size_t i; 1144b169a6bSchristos 1154b169a6bSchristos for (i = 0; i < modules_len; ++i) 1164b169a6bSchristos { 1174b169a6bSchristos MODULE_INSTALL_FN *modp = modules[i]; 1184b169a6bSchristos 1194b169a6bSchristos if (modp != NULL && modp (sd) != SIM_RC_OK) 1204b169a6bSchristos { 1214b169a6bSchristos sim_module_uninstall (sd); 1224b169a6bSchristos SIM_ASSERT (STATE_MODULES (sd) == NULL); 1234b169a6bSchristos return SIM_RC_FAIL; 1244b169a6bSchristos } 1254b169a6bSchristos } 1264b169a6bSchristos 1274b169a6bSchristos return SIM_RC_OK; 1284b169a6bSchristos } 1294b169a6bSchristos 1304e98e3e1Schristos /* Install all modules. 1314e98e3e1Schristos If this fails, no modules are left installed. */ 1324e98e3e1Schristos 1334e98e3e1Schristos SIM_RC 1344e98e3e1Schristos sim_module_install (SIM_DESC sd) 1354e98e3e1Schristos { 1364e98e3e1Schristos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 1374e98e3e1Schristos SIM_ASSERT (STATE_MODULES (sd) == NULL); 1384e98e3e1Schristos 1394e98e3e1Schristos STATE_MODULES (sd) = ZALLOC (struct module_list); 1404b169a6bSchristos return sim_module_install_list (sd, early_modules, early_modules_len); 1414e98e3e1Schristos } 1424e98e3e1Schristos 1434e98e3e1Schristos /* Called after all modules have been installed and after argv 1444e98e3e1Schristos has been processed. */ 1454e98e3e1Schristos 1464e98e3e1Schristos SIM_RC 1474e98e3e1Schristos sim_module_init (SIM_DESC sd) 1484e98e3e1Schristos { 1494e98e3e1Schristos struct module_list *modules = STATE_MODULES (sd); 1504e98e3e1Schristos MODULE_INIT_LIST *modp; 1514e98e3e1Schristos 1524e98e3e1Schristos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 1534e98e3e1Schristos SIM_ASSERT (STATE_MODULES (sd) != NULL); 1544e98e3e1Schristos 1554e98e3e1Schristos for (modp = modules->init_list; modp != NULL; modp = modp->next) 1564e98e3e1Schristos { 1574e98e3e1Schristos if ((*modp->fn) (sd) != SIM_RC_OK) 1584e98e3e1Schristos return SIM_RC_FAIL; 1594e98e3e1Schristos } 1604e98e3e1Schristos return SIM_RC_OK; 1614e98e3e1Schristos } 1624e98e3e1Schristos 1634e98e3e1Schristos /* Called when ever the simulator is resumed */ 1644e98e3e1Schristos 1654e98e3e1Schristos SIM_RC 1664e98e3e1Schristos sim_module_resume (SIM_DESC sd) 1674e98e3e1Schristos { 1684e98e3e1Schristos struct module_list *modules = STATE_MODULES (sd); 1694e98e3e1Schristos MODULE_RESUME_LIST *modp; 1704e98e3e1Schristos 1714e98e3e1Schristos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 1724e98e3e1Schristos SIM_ASSERT (STATE_MODULES (sd) != NULL); 1734e98e3e1Schristos 1744e98e3e1Schristos for (modp = modules->resume_list; modp != NULL; modp = modp->next) 1754e98e3e1Schristos { 1764e98e3e1Schristos if ((*modp->fn) (sd) != SIM_RC_OK) 1774e98e3e1Schristos return SIM_RC_FAIL; 1784e98e3e1Schristos } 1794e98e3e1Schristos return SIM_RC_OK; 1804e98e3e1Schristos } 1814e98e3e1Schristos 1824e98e3e1Schristos /* Called when ever the simulator is suspended */ 1834e98e3e1Schristos 1844e98e3e1Schristos SIM_RC 1854e98e3e1Schristos sim_module_suspend (SIM_DESC sd) 1864e98e3e1Schristos { 1874e98e3e1Schristos struct module_list *modules = STATE_MODULES (sd); 1884e98e3e1Schristos MODULE_SUSPEND_LIST *modp; 1894e98e3e1Schristos 1904e98e3e1Schristos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 1914e98e3e1Schristos SIM_ASSERT (STATE_MODULES (sd) != NULL); 1924e98e3e1Schristos 1934e98e3e1Schristos for (modp = modules->suspend_list; modp != NULL; modp = modp->next) 1944e98e3e1Schristos { 1954e98e3e1Schristos if ((*modp->fn) (sd) != SIM_RC_OK) 1964e98e3e1Schristos return SIM_RC_FAIL; 1974e98e3e1Schristos } 1984e98e3e1Schristos return SIM_RC_OK; 1994e98e3e1Schristos } 2004e98e3e1Schristos 2014e98e3e1Schristos /* Uninstall installed modules, called by sim_close. */ 2024e98e3e1Schristos 2034e98e3e1Schristos void 2044e98e3e1Schristos sim_module_uninstall (SIM_DESC sd) 2054e98e3e1Schristos { 2064e98e3e1Schristos struct module_list *modules = STATE_MODULES (sd); 2074e98e3e1Schristos MODULE_UNINSTALL_LIST *modp; 2084e98e3e1Schristos 2094e98e3e1Schristos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 2104e98e3e1Schristos SIM_ASSERT (STATE_MODULES (sd) != NULL); 2114e98e3e1Schristos 2124e98e3e1Schristos /* Uninstall the modules. */ 2134e98e3e1Schristos for (modp = modules->uninstall_list; modp != NULL; modp = modp->next) 2144e98e3e1Schristos (*modp->fn) (sd); 2154e98e3e1Schristos 2164e98e3e1Schristos /* clean-up init list */ 2174e98e3e1Schristos { 2184e98e3e1Schristos MODULE_INIT_LIST *n, *d; 2194e98e3e1Schristos for (d = modules->init_list; d != NULL; d = n) 2204e98e3e1Schristos { 2214e98e3e1Schristos n = d->next; 2224e98e3e1Schristos free (d); 2234e98e3e1Schristos } 2244e98e3e1Schristos } 2254e98e3e1Schristos 2264e98e3e1Schristos /* clean-up resume list */ 2274e98e3e1Schristos { 2284e98e3e1Schristos MODULE_RESUME_LIST *n, *d; 2294e98e3e1Schristos for (d = modules->resume_list; d != NULL; d = n) 2304e98e3e1Schristos { 2314e98e3e1Schristos n = d->next; 2324e98e3e1Schristos free (d); 2334e98e3e1Schristos } 2344e98e3e1Schristos } 2354e98e3e1Schristos 2364e98e3e1Schristos /* clean-up suspend list */ 2374e98e3e1Schristos { 2384e98e3e1Schristos MODULE_SUSPEND_LIST *n, *d; 2394e98e3e1Schristos for (d = modules->suspend_list; d != NULL; d = n) 2404e98e3e1Schristos { 2414e98e3e1Schristos n = d->next; 2424e98e3e1Schristos free (d); 2434e98e3e1Schristos } 2444e98e3e1Schristos } 2454e98e3e1Schristos 2464e98e3e1Schristos /* clean-up uninstall list */ 2474e98e3e1Schristos { 2484e98e3e1Schristos MODULE_UNINSTALL_LIST *n, *d; 2494e98e3e1Schristos for (d = modules->uninstall_list; d != NULL; d = n) 2504e98e3e1Schristos { 2514e98e3e1Schristos n = d->next; 2524e98e3e1Schristos free (d); 2534e98e3e1Schristos } 2544e98e3e1Schristos } 2554e98e3e1Schristos 2564e98e3e1Schristos /* clean-up info list */ 2574e98e3e1Schristos { 2584e98e3e1Schristos MODULE_INFO_LIST *n, *d; 2594e98e3e1Schristos for (d = modules->info_list; d != NULL; d = n) 2604e98e3e1Schristos { 2614e98e3e1Schristos n = d->next; 2624e98e3e1Schristos free (d); 2634e98e3e1Schristos } 2644e98e3e1Schristos } 2654e98e3e1Schristos 2664e98e3e1Schristos free (modules); 2674e98e3e1Schristos STATE_MODULES (sd) = NULL; 2684e98e3e1Schristos } 2694e98e3e1Schristos 2704e98e3e1Schristos /* Called when ever simulator info is needed */ 2714e98e3e1Schristos 2724e98e3e1Schristos void 273*88241920Schristos sim_module_info (SIM_DESC sd, bool verbose) 2744e98e3e1Schristos { 2754e98e3e1Schristos struct module_list *modules = STATE_MODULES (sd); 2764e98e3e1Schristos MODULE_INFO_LIST *modp; 2774e98e3e1Schristos 2784e98e3e1Schristos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 2794e98e3e1Schristos SIM_ASSERT (STATE_MODULES (sd) != NULL); 2804e98e3e1Schristos 2814e98e3e1Schristos for (modp = modules->info_list; modp != NULL; modp = modp->next) 2824e98e3e1Schristos { 2834e98e3e1Schristos (*modp->fn) (sd, verbose); 2844e98e3e1Schristos } 2854e98e3e1Schristos } 2864e98e3e1Schristos 2874e98e3e1Schristos /* Add FN to the init handler list. 2884e98e3e1Schristos init in the same order as the install. */ 2894e98e3e1Schristos 2904e98e3e1Schristos void 2914e98e3e1Schristos sim_module_add_init_fn (SIM_DESC sd, MODULE_INIT_FN fn) 2924e98e3e1Schristos { 2934e98e3e1Schristos struct module_list *modules = STATE_MODULES (sd); 2944e98e3e1Schristos MODULE_INIT_LIST *l = ZALLOC (MODULE_INIT_LIST); 2954e98e3e1Schristos MODULE_INIT_LIST **last; 2964e98e3e1Schristos 2974e98e3e1Schristos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 2984e98e3e1Schristos SIM_ASSERT (STATE_MODULES (sd) != NULL); 2994e98e3e1Schristos 3004e98e3e1Schristos last = &modules->init_list; 3014e98e3e1Schristos while (*last != NULL) 3024e98e3e1Schristos last = &((*last)->next); 3034e98e3e1Schristos 3044e98e3e1Schristos l->fn = fn; 3054e98e3e1Schristos l->next = NULL; 3064e98e3e1Schristos *last = l; 3074e98e3e1Schristos } 3084e98e3e1Schristos 3094e98e3e1Schristos /* Add FN to the resume handler list. 3104e98e3e1Schristos resume in the same order as the install. */ 3114e98e3e1Schristos 3124e98e3e1Schristos void 3134e98e3e1Schristos sim_module_add_resume_fn (SIM_DESC sd, MODULE_RESUME_FN fn) 3144e98e3e1Schristos { 3154e98e3e1Schristos struct module_list *modules = STATE_MODULES (sd); 3164e98e3e1Schristos MODULE_RESUME_LIST *l = ZALLOC (MODULE_RESUME_LIST); 3174e98e3e1Schristos MODULE_RESUME_LIST **last; 3184e98e3e1Schristos 3194e98e3e1Schristos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 3204e98e3e1Schristos SIM_ASSERT (STATE_MODULES (sd) != NULL); 3214e98e3e1Schristos 3224e98e3e1Schristos last = &modules->resume_list; 3234e98e3e1Schristos while (*last != NULL) 3244e98e3e1Schristos last = &((*last)->next); 3254e98e3e1Schristos 3264e98e3e1Schristos l->fn = fn; 3274e98e3e1Schristos l->next = NULL; 3284e98e3e1Schristos *last = l; 3294e98e3e1Schristos } 3304e98e3e1Schristos 3314e98e3e1Schristos /* Add FN to the init handler list. 3324e98e3e1Schristos suspend in the reverse order to install. */ 3334e98e3e1Schristos 3344e98e3e1Schristos void 3354e98e3e1Schristos sim_module_add_suspend_fn (SIM_DESC sd, MODULE_SUSPEND_FN fn) 3364e98e3e1Schristos { 3374e98e3e1Schristos struct module_list *modules = STATE_MODULES (sd); 3384e98e3e1Schristos MODULE_SUSPEND_LIST *l = ZALLOC (MODULE_SUSPEND_LIST); 3394e98e3e1Schristos MODULE_SUSPEND_LIST **last; 3404e98e3e1Schristos 3414e98e3e1Schristos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 3424e98e3e1Schristos SIM_ASSERT (STATE_MODULES (sd) != NULL); 3434e98e3e1Schristos 3444e98e3e1Schristos last = &modules->suspend_list; 3454e98e3e1Schristos while (*last != NULL) 3464e98e3e1Schristos last = &((*last)->next); 3474e98e3e1Schristos 3484e98e3e1Schristos l->fn = fn; 3494e98e3e1Schristos l->next = modules->suspend_list; 3504e98e3e1Schristos modules->suspend_list = l; 3514e98e3e1Schristos } 3524e98e3e1Schristos 3534e98e3e1Schristos /* Add FN to the uninstall handler list. 3544e98e3e1Schristos Uninstall in reverse order to install. */ 3554e98e3e1Schristos 3564e98e3e1Schristos void 3574e98e3e1Schristos sim_module_add_uninstall_fn (SIM_DESC sd, MODULE_UNINSTALL_FN fn) 3584e98e3e1Schristos { 3594e98e3e1Schristos struct module_list *modules = STATE_MODULES (sd); 3604e98e3e1Schristos MODULE_UNINSTALL_LIST *l = ZALLOC (MODULE_UNINSTALL_LIST); 3614e98e3e1Schristos 3624e98e3e1Schristos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 3634e98e3e1Schristos SIM_ASSERT (STATE_MODULES (sd) != NULL); 3644e98e3e1Schristos 3654e98e3e1Schristos l->fn = fn; 3664e98e3e1Schristos l->next = modules->uninstall_list; 3674e98e3e1Schristos modules->uninstall_list = l; 3684e98e3e1Schristos } 3694e98e3e1Schristos 3704e98e3e1Schristos /* Add FN to the info handler list. 3714e98e3e1Schristos Report info in the same order as the install. */ 3724e98e3e1Schristos 3734e98e3e1Schristos void 3744e98e3e1Schristos sim_module_add_info_fn (SIM_DESC sd, MODULE_INFO_FN fn) 3754e98e3e1Schristos { 3764e98e3e1Schristos struct module_list *modules = STATE_MODULES (sd); 3774e98e3e1Schristos MODULE_INFO_LIST *l = ZALLOC (MODULE_INFO_LIST); 3784e98e3e1Schristos MODULE_INFO_LIST **last; 3794e98e3e1Schristos 3804e98e3e1Schristos SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 3814e98e3e1Schristos SIM_ASSERT (STATE_MODULES (sd) != NULL); 3824e98e3e1Schristos 3834e98e3e1Schristos last = &modules->info_list; 3844e98e3e1Schristos while (*last != NULL) 3854e98e3e1Schristos last = &((*last)->next); 3864e98e3e1Schristos 3874e98e3e1Schristos l->fn = fn; 3884e98e3e1Schristos l->next = NULL; 3894e98e3e1Schristos *last = l; 3904e98e3e1Schristos } 391