xref: /netbsd-src/external/gpl3/gdb/dist/sim/common/sim-module.c (revision 88241920d21b339bf319c0e979ffda80c49a2936)
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