moduleLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:39k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* moduleLib.c - object module management library */
  2.  
  3. /* Copyright 1992-1996 Wind River Systems, Inc. */
  4. #include "copyright_wrs.h"
  5.  
  6. /*
  7. modification history
  8. --------------------
  9. 01r,15mar99,c_c  Doc: updated moduleSegAdd () (SPR #6138).
  10. 01q,27sep96,pad  reinstated a line I deleted accidentally.
  11. 01p,11sep96,pad  strengthened group number handling (SPR #7133).
  12. 01o,10oct95,jdi  doc: added .tG Shell to SEE ALSO for moduleShow();
  13.  changed .pG Cross-Dev to .tG; corrections to moduleCreate().
  14. 01n,14mar93,jdi  fixed documentation for moduleDelete().
  15. 01m,15feb93,kdl  changed documentation for moduleFlagsGet().
  16. 01l,12feb93,jmm  changed documentation for moduleDelete ()
  17. 01k,27nov92,jdi  documentation cleanup.
  18. 01j,30oct92,jmm  moduleSegInfoGet() now zeros out info structure (spr 1702)
  19.                  moduleFindByName () gets just the name part of moduleName
  20.      (spr 1718)
  21. 01i,14oct92,jdi  made moduleInit() and moduleTerminate() NOMANUAL.
  22. 01h,12oct92,jdi  fixed mangen problem in moduleCreateHookDelete().
  23. 01g,27aug92,jmm  changed moduleSegInfoGet() to use new MODULE_SEG_INFO struct
  24.                  changed symFlags to flags
  25.  added moduleNameGet(), moduleFlagsGet()
  26.  set ctors and dtors to NULL in moduleInit()
  27. 01f,31jul92,jmm  cleaned up forward declarations
  28. 01e,30jul92,smb  changed format for printf to avoid zero padding.
  29. 01d,28jul92,jmm  made NODE_TO_ID macro portable to i960
  30. 01c,20jul92,jmm  removed checksum() routine (duplicate of routine in cksumLib.c)
  31.                  removed bzero() of segment id from moduleSegGet()
  32.  added check for HIDDEN_MODULE flag to moduleDisplayGeneric()
  33. 01b,18jul92,smb  Changed errno.h to errnoLib.h.
  34. 01a,jmm,01may92  written 
  35. */
  36.  
  37. /*
  38. DESCRIPTION
  39. This library is a class manager, using the standard VxWorks class/object
  40. facilities.  The library is used to keep track of which object modules
  41. have been loaded into VxWorks, to maintain information about object
  42. module segments associated with each module, and to track which
  43. symbols belong to which module.  Tracking modules makes it possible to
  44. list which modules are currently loaded, and to unload them when
  45. they are no longer needed.
  46. The module object contains the following information:
  47.     - name
  48.     - linked list of segments, including base addresses
  49.       and sizes
  50.     - symbol group number
  51.     - format of the object module (a.out, COFF, ECOFF, etc.)
  52.     - the <symFlag> passed to ld() when the module was
  53.       loaded.  (For more information about <symFlag> and the
  54.       loader, see the manual entry for loadLib.)
  55. Multiple modules with the same name are allowed (the same module may
  56. be loaded without first being unloaded) but "find" functions find the
  57. most recently created module.
  58. The symbol group number is a unique number for each module, used to
  59. identify the module's symbols in the symbol table.  This number is
  60. assigned by moduleLib when a module is created.
  61. In general, users will not access these routines directly, with the
  62. exception of moduleShow(), which displays information about currently
  63. loaded modules.  Most calls to this library will be from routines in
  64. loadLib and unldLib.
  65. INCLUDE FILES: moduleLib.h
  66. SEE ALSO: loadLib,
  67. .tG "Cross-Development"
  68. */
  69. #include "vxWorks.h"
  70. #include "classLib.h"
  71. #include "dllLib.h"
  72. #include "errnoLib.h"
  73. #include "moduleLib.h"
  74. #include "objLib.h"
  75. #include "pathLib.h"
  76. #include "semLib.h"
  77. #include "stdio.h"
  78. #include "stdlib.h"
  79. #include "stddef.h"
  80. #include "string.h"
  81. #include "vxLib.h"
  82. #include "loadLib.h"
  83. #define NODE_TO_ID(pNode) (pNode != NULL ? (MODULE_ID) ((char *) pNode - 
  84.          offsetof (MODULE, moduleNode)) : NULL)
  85. typedef struct
  86.     {
  87.     DL_NODE node;
  88.     FUNCPTR func;
  89.     } MODCREATE_HOOK;
  90. /* forward declarations */
  91.  
  92. LOCAL STATUS moduleDestroy (MODULE_ID moduleId, BOOL dealloc);
  93. LOCAL STATUS moduleDisplayGeneric (MODULE_ID moduleId, UINT options);
  94. LOCAL STATUS moduleSegInfoGet (MODULE_ID moduleId,
  95.        MODULE_SEG_INFO *pModSegInfo);
  96. LOCAL BOOL   moduleCheckSegment (SEGMENT_ID segmentId);
  97. LOCAL BOOL   moduleCheckOne (MODULE_ID moduleId, int options);
  98. LOCAL STATUS moduleInsert (MODULE_ID newModule);
  99. /* LOCALS */
  100. static BOOL  moduleLibInitialized = FALSE; /* prevent multiple inits */
  101. LOCAL OBJ_CLASS  moduleClass;
  102. LOCAL DL_LIST   moduleCreateHookList;
  103. LOCAL SEM_ID  moduleCreateHookSem;
  104. LOCAL BOOL   moduleCreateHookInitialized  = FALSE;
  105. LOCAL BOOL    moduleLibDebug  = FALSE;
  106. LOCAL DL_LIST  moduleList; /* list of loaded modules */
  107. LOCAL SEM_ID  moduleListSem; /* semaphore to protect moduleList */
  108. LOCAL SEM_ID  moduleSegSem; /* semaphore to protect all segment lists */
  109. LOCAL FUNCPTR   moduleDisplayRtn;
  110. /* GLOBALS */
  111. CLASS_ID moduleClassId = &moduleClass;
  112. /******************************************************************************
  113. *
  114. * moduleLibInit - initialize object module library
  115. * This routine initializes the object module tracking facility.  It
  116. * should be called once from usrRoot().
  117. * RETURNS: OK or ERROR.
  118. * NOMANUAL
  119. */
  120. STATUS moduleLibInit
  121.     (
  122.     void
  123.     )
  124.     {
  125.     STATUS      returnValue; /* function return value */
  126.     /*
  127.      * If moduleLibInitialized has been set to TRUE, the library's already
  128.      * initialized.  Return OK.
  129.      */
  130.     if (moduleLibInitialized)
  131.         return (OK);
  132.     /* Initialize the module list and its protecting semaphore */
  133.     moduleListSem = semMCreate (SEM_DELETE_SAFE);
  134.     dllInit (&moduleList);
  135.     /* Initialize the semaphore protecting all segment lists */
  136.     moduleSegSem = semMCreate (SEM_DELETE_SAFE);
  137.     /* Initialize the create hook list */
  138.     moduleCreateHookSem = semMCreate (SEM_DELETE_SAFE);
  139.     dllInit (&moduleCreateHookList);
  140.     moduleCreateHookInitialized = TRUE;
  141.     /*
  142.      * Initialize the display routine function pointer.
  143.      * Currently, this is hard-coded to moduleDisplayGeneric().
  144.      * At some future point, when we need to display other object
  145.      * module formats, this will need to be changed.
  146.      */
  147.     moduleDisplayRtn = moduleDisplayGeneric;
  148.     /* Initialize the module class */
  149.     returnValue = classInit (moduleClassId, sizeof (MODULE),
  150.      OFFSET (MODULE, objCore),
  151.      (FUNCPTR) moduleCreate, (FUNCPTR) moduleInit,
  152.      (FUNCPTR) moduleDestroy);
  153.     /* Library has been initialized, return */
  154.     moduleLibInitialized = TRUE;
  155.     return (returnValue);
  156.     }
  157. /******************************************************************************
  158. *
  159. * moduleCreate - create and initialize a module
  160. * This routine creates an object module descriptor.
  161. * The arguments specify the name of the object module file, 
  162. * the object module format, and an argument specifying which symbols
  163. * to add to the symbol table.  See the loadModuleAt() description of <symFlag>
  164. * for possibles <flags> values.
  165. * Space for the new module is dynamically allocated.
  166. * RETURNS: MODULE_ID, or NULL if there is an error.
  167. *
  168. * SEE ALSO: loadModuleAt()
  169. */
  170. MODULE_ID moduleCreate
  171.     (
  172.     char * name,  /* module name */
  173.     int  format,  /* object module format */
  174.     int flags  /* <symFlag> as passed to loader (see loadModuleAt()) */
  175.     )
  176.     {
  177.     MODULE_ID moduleId;
  178.     /* Allocate the object, return NULL if objAlloc() fails */
  179.     moduleId = objAlloc (moduleClassId);
  180.     if (moduleId == NULL)
  181. {
  182. printf ("errno %#xn", errnoGet());
  183.         return (NULL);
  184. }
  185.     /* Call moduleInit() to do the real work */
  186.     if (moduleInit (moduleId, name, format, flags) != OK)
  187. {
  188. objFree (moduleClassId, (char *) moduleId);
  189.         return (NULL);
  190. }
  191.     return (moduleId);
  192.     }
  193. /******************************************************************************
  194. *
  195. * moduleInit - initialize a module
  196. * This routine initializes an object module descriptor.  Instead of
  197. * dynamically allocating the space for the module descriptor,
  198. * moduleInit() takes a pointer to an existing MODULE structure to initialize.
  199. * The other arguments are identical to the moduleCreate() arguments.
  200. * RETURNS: OK, or ERROR.
  201. *
  202. * NOMANUAL
  203. */
  204. STATUS moduleInit
  205.     (
  206.     MODULE_ID moduleId, /* ptr to module to initialize */
  207.     char * name, /* module name */
  208.     int  format, /* object module format */
  209.     int flags /* symFlags as passed to loader */
  210.     )
  211.     {
  212.     static UINT16  nextGroupNumber = 1; /* 1 is VxWorks */
  213.     MODCREATE_HOOK * createHookNode;
  214.     MODULE_ID oldModule; /* ID of previous same module */
  215.     MODULE_ID lastModule; /* ID of last module in list */
  216.     /* Split the name into it's name and path components */
  217.     pathSplit (name, moduleId->path, moduleId->name);
  218.     /* see if the module was loaded earlier */
  219.     semTake (moduleListSem, WAIT_FOREVER);
  220.     if ((oldModule = moduleFindByName (moduleId->name)) != NULL)
  221. {
  222. /* we found an old module, mark it as obsolete */
  223. oldModule->flags |= MODULE_REPLACED;
  224. }
  225.     /*
  226.      * Today, due to a poor/incomplete implementation of the module group
  227.      * concept, only 65534 modules can be loaded in a VxWorks session's life.
  228.      * The group number counter was simply incremented at each load operation.
  229.      * See SPR #7133 for more precisions on the troubles this brought.
  230.      *
  231.      * Reset the next group number counter to the highest value actually
  232.      * available. This is a first step to work around SPR #7133.
  233.      */
  234.     if ((lastModule = NODE_TO_ID (DLL_LAST (&moduleList))) != NULL)
  235. {
  236. nextGroupNumber = lastModule->group;
  237. nextGroupNumber++;
  238. }
  239.     /* Set the module's group number */
  240.     if (nextGroupNumber < MODULE_GROUP_MAX)
  241. {
  242.         moduleId->group = nextGroupNumber++;
  243. /* Add the module to the end of the module list */
  244. dllAdd (&moduleList, &moduleId->moduleNode);
  245. }
  246.     else
  247. {
  248. /*
  249.  * When all group slots are apparently used, we must walk through the
  250.  * module list and try to find a free group number due to previous
  251.  * unloadings. This is the second step to work around SPR #7133.
  252.  */
  253. if (moduleInsert (moduleId) != OK)
  254.     {
  255.             printf ("No free group number. Abort load operation.n");
  256.     errnoSet (S_moduleLib_MAX_MODULES_LOADED);
  257.             return (ERROR);
  258.     }
  259. }
  260.     semGive (moduleListSem);
  261.     
  262.     /* Set the module format and flags */
  263.     moduleId->flags = flags;
  264.     moduleId->format = format;
  265.     moduleId->ctors = NULL;
  266.     moduleId->dtors = NULL;
  267.     /* Initialize the segment list */
  268.     if (dllInit (&moduleId->segmentList) != OK)
  269. return (ERROR);
  270.     
  271.     /* Initialize the object stuff */
  272.     objCoreInit (&moduleId->objCore, moduleClassId);
  273.     /* Call any moduleCreateHook routines */
  274.     semTake (moduleCreateHookSem, WAIT_FOREVER);
  275.     for (createHookNode = (MODCREATE_HOOK *) DLL_FIRST (&moduleCreateHookList);
  276.  createHookNode != NULL;
  277.  createHookNode = (MODCREATE_HOOK *) DLL_NEXT ((DL_NODE *)
  278.        createHookNode))
  279. {
  280. (* createHookNode->func) (moduleId);
  281. }
  282.     semGive (moduleCreateHookSem);
  283.     
  284.     /* If debugging is on, print out the name of the module. */
  285.     if (moduleLibDebug)
  286.         printf ("Module %s, group %d addedn", moduleId->name, moduleId->group);
  287.     return (OK);
  288.     }
  289. /******************************************************************************
  290. *
  291. * moduleInsert - insert the module in list when possible
  292. *
  293. * This routine walks the module list in order to find a hole in the group
  294. * numbering. As soon as a free group number is found, the new module is
  295. * inserted in the list and is given the available group number.  
  296. *
  297. * This routine should be called only when all the group numbers have been
  298. * allocated (i.e. when the group number counter reaches its maximum).
  299. *
  300. * WARNING: the module list semaphore must be taken by the caller.
  301. *
  302. * RETURNS: OK or ERROR if the module could not be inserted.
  303. */
  304. LOCAL STATUS moduleInsert
  305.     (
  306.     MODULE_ID  newModule /* module to insert */
  307.     )
  308.     {
  309.     MODULE_ID  currentModule; /* module pointer */
  310.     MODULE_ID  nextModule; /* module pointer */
  311.     /* Go through the module list and try to insert the new module */
  312.     for (currentModule = NODE_TO_ID (DLL_FIRST (&moduleList));
  313.  currentModule != NULL;
  314.  currentModule = NODE_TO_ID (DLL_NEXT (&currentModule->moduleNode)))
  315. {
  316. nextModule = NODE_TO_ID (DLL_NEXT (&currentModule->moduleNode));
  317. /* Check if we reached the end of the list: this means no room left */
  318. if (nextModule == NULL)
  319.     break;
  320. /* Insert the new module when there is a whole in the group numbers */
  321. if (nextModule->group > (currentModule->group + 1))
  322.     {
  323.     dllInsert (&moduleList, &currentModule->moduleNode,
  324.        &newModule->moduleNode);
  325.     newModule->group = currentModule->group + 1;
  326.     break;
  327.     }
  328. }
  329.     if (nextModule == NULL)
  330. return (ERROR);
  331.     else
  332. return (OK);
  333.     }
  334. /******************************************************************************
  335. *
  336. * moduleTerminate - terminate a module
  337. * This routine terminates a static object module descriptor that was
  338. * initialized with moduleInit().
  339. * RETURNS: OK or ERROR.
  340. * NOMANUAL
  341. */
  342. STATUS moduleTerminate
  343.     (
  344.     MODULE_ID moduleId /* module to terminate */
  345.     )
  346.     {
  347.     return (moduleDestroy (moduleId, FALSE));
  348.     }
  349. /******************************************************************************
  350. *
  351. * moduleDelete - delete module ID information (use unld() to reclaim space)
  352. * This routine deletes a module descriptor, freeing any space that was
  353. * allocated for the use of the module ID.
  354. *
  355. * This routine does not free space allocated for the object module itself --
  356. * this is done by unld().
  357. * RETURNS: OK or ERROR.
  358. */
  359. STATUS moduleDelete
  360.     (
  361.     MODULE_ID moduleId /* module to delete */
  362.     )
  363.     {
  364.     return (moduleDestroy (moduleId, TRUE));
  365.     }
  366. /******************************************************************************
  367. *
  368. * moduleDestroy - destroy module
  369. *
  370. * This is the underlying routine for moduleDelete() and moduleTerminate().
  371. * RETURNS: OK or ERROR.
  372. * NOMANUAL
  373. */
  374. LOCAL STATUS moduleDestroy
  375.     (
  376.     MODULE_ID  moduleId, /* module to destroy */
  377.     BOOL       dealloc /* deallocate memory associated with module */
  378.     )
  379.     {
  380.     SEGMENT_ID pSegment; /* temp. storage for deleting segments */
  381.     /* Make sure moduleId is a real object of class moduleClassId */
  382.     if (OBJ_VERIFY (moduleId, moduleClassId) != OK)  /* validate module id */
  383. {
  384. return (ERROR);
  385. }
  386.     objCoreTerminate (&moduleId->objCore); /* INVALIDATE */
  387.     /* Remove the module from the module list */
  388.     semTake (moduleListSem, WAIT_FOREVER);
  389.     dllRemove (&moduleList, &moduleId->moduleNode);
  390.     semGive (moduleListSem);
  391.     /* Remove any segment records associated with the module. */
  392.     while ((pSegment = moduleSegGet (moduleId)) != NULL)
  393.         free (pSegment);
  394.     /* Deallocate the module id object itself */
  395.     if (dealloc)
  396. if (objFree (moduleClassId, (char *) moduleId) != OK)
  397.     return (ERROR);
  398.     return (OK);
  399.     }
  400. /******************************************************************************
  401. *
  402. * moduleIdFigure - translate a module name or ID to a module ID
  403. *
  404. * Some routines take either a module ID (an integer) or a module name.  This
  405. * routine determines whether the parameter is a module name or a module ID and
  406. * returns the module ID. 
  407. *
  408. * RETURNS: A module ID (type MODULE_ID), or NULL.
  409. *
  410. * NOMANUAL
  411. */
  412. MODULE_ID moduleIdFigure
  413.     (
  414.     void *  moduleNameOrId /* module name or module ID */
  415.     )
  416.     {
  417.     MODULE_ID  moduleId = NULL; /* default is NULL */
  418.     /*
  419.      * Make sure we're not getting a NULL pointer, OBJ_VERIFY doesn't check
  420.      * for that.
  421.      */
  422.     if (moduleNameOrId == NULL)
  423.         return (NULL);
  424.     
  425.     /* If moduleNameOrId is a moduleId, just return it. */
  426.     
  427.     if (OBJ_VERIFY (moduleNameOrId, moduleClassId) == OK)
  428. {
  429. return ((MODULE_ID) moduleNameOrId);
  430. }
  431.     
  432.     /*
  433.      * moduleNameOrId isn't a legitmate object - see if it's the name
  434.      * of a module.  
  435.      */
  436.     if ((moduleId = moduleFindByName (moduleNameOrId)) == NULL)
  437. {
  438. /*
  439.  * It's neither an object module nor a module name.  Set errno and
  440.  * return NULL.
  441.  */
  442. errnoSet (S_moduleLib_MODULE_NOT_FOUND);
  443. return (NULL);
  444. }
  445.     else
  446.         return (moduleId);
  447.     }
  448. /******************************************************************************
  449. *
  450. * moduleShow - show the current status for all the loaded modules
  451. *
  452. * This routine displays a list of the currently loaded modules and
  453. * some information about where the modules are loaded.
  454. * The specific information displayed depends on the format of the object
  455. * modules.  In the case of a.out and ECOFF object modules, moduleShow() displays
  456. * the start of the text, data, and BSS segments.
  457. * If moduleShow() is called with no arguments, a summary list of all
  458. * loaded modules is displayed.  It can also be called with an argument,
  459. * <moduleNameOrId>, which can be either the name of a loaded module or a
  460. * module ID.  If it is called with either of these, more information
  461. * about the specified module will be displayed.
  462. * RETURNS: OK or ERROR.
  463. *
  464. * SEE ALSO:
  465. * .pG "Target Shell,"
  466. * windsh,
  467. * .tG "Shell"
  468. */
  469. STATUS moduleShow
  470.     (
  471.     char *  moduleNameOrId, /* name or ID of the module to show */
  472.     int options /* display options */
  473.     )
  474.     {
  475.     MODULE_ID moduleId;
  476.     static char * moduleShowHdr [] = {"n
  477. MODULE NAME     MODULE ID  GROUP #    TEXT START DATA START  BSS STARTn
  478. --------------- ---------- ---------- ---------- ---------- ----------n"};
  479.     /*
  480.      * If moduleNameOrId isn't NULL, translate it into a module ID, and
  481.      * display information about that specific module.
  482.      * If it is NULL, set moduleId to NULL, and display info about all
  483.      * loaded modules.
  484.      */
  485.     if (moduleNameOrId != NULL)
  486. {
  487.         if ((moduleId = moduleIdFigure (moduleNameOrId)) == NULL)
  488.     {
  489.     /* moduleIdFigure couldn't find a match */
  490.     printf ("Module not foundn");
  491.     return (ERROR);
  492.     }
  493. }
  494.     else
  495.         moduleId = NULL;
  496.     /* print the module display header */
  497.     printf ("%s", moduleShowHdr [MODULE_A_OUT]);
  498.     /*
  499.      * If moduleId is a specific module ID, print information about that
  500.      * specific module.  Otherwise, print the summary.
  501.      */
  502.     if (moduleId != NULL)
  503. {
  504. /*
  505.  * We've got a specific module to show.  If no options are specified,
  506.  * then display all information, otherwise use what's specified.
  507.  */
  508.         moduleDisplayGeneric (moduleId,
  509.       options == 0 ? MODDISPLAY_ALL : options);
  510. }
  511.     else
  512.         {
  513. /* We need to display all the modules. */
  514. semTake (moduleListSem, WAIT_FOREVER);
  515. dllEach (&moduleList, moduleDisplayGeneric,
  516.  options | MODDISPLAY_IS_DLL_NODE);
  517. semGive (moduleListSem);
  518. }
  519.     /*
  520.      * There's nothing that can fail - always return OK
  521.      */
  522.     return (OK);
  523.     }
  524. /******************************************************************************
  525. *
  526. * moduleDisplayGeneric - support routine to show stats for an object module
  527. *
  528. * This routine is normally called via a dllEach() call from moduleShow.
  529. * It prints a single line of information about the specified module.
  530. * Note that the parameter is _not_ of type MODULE_ID, but rather is a
  531. * DL_NODE *.
  532. * RETURNS: TRUE, or FALSE if display should be aborted.
  533. * NOMANUAL
  534. */
  535. LOCAL STATUS moduleDisplayGeneric
  536.     (
  537.     MODULE_ID moduleId, /* pointer to the module node to display */
  538.     UINT options /* display options */
  539.     )
  540.     {
  541.     static char moduleShowFmt[] = "%15s %#10x %10d %#10x %#10x %#10xn";
  542.     MODULE_SEG_INFO segInfo;    /* segment information */
  543.     /* If MODDISPLAY_IS_DLL_NODE is set, need to convert node to module id */
  544.     if (options & MODDISPLAY_IS_DLL_NODE)
  545.         moduleId = NODE_TO_ID (moduleId);
  546.     /* If HIDDEN_MODULE is set, return OK without displaying anything */
  547.     if (moduleId->flags & HIDDEN_MODULE)
  548.         return (TRUE);
  549.     /* Return FALSE if we can't get information about the module segments */
  550.     if (moduleSegInfoGet (moduleId, &segInfo) != OK)
  551. {
  552. printErr ("Can't get information about module %#xn", moduleId);
  553.         return (FALSE);
  554. }
  555.     /*
  556.      * Print out the module summary line.
  557.      * We only want to print the file name, not the entire path.
  558.      */
  559.     printf (moduleShowFmt, moduleId->name, moduleId,
  560.     moduleId->group,
  561.     segInfo.textAddr,
  562.     segInfo.dataAddr,
  563.     segInfo.bssAddr);
  564.     /*
  565.      * Print out all the optional information
  566.      */
  567.     if (options & MODDISPLAY_CODESIZE)
  568. {
  569. /* Print specific information about the size of module's segments */
  570. printf ("nSize of text segment:   %8dn", segInfo.textSize);
  571. printf ("Size of data segment:   %8dn", segInfo.dataSize);
  572. printf ("Size of bss  segment:   %8dn", segInfo.bssSize);
  573. printf ("Total size          :   %8dnn",
  574. segInfo.textSize + segInfo.dataSize
  575. + segInfo.bssSize);
  576. }
  577.     /*
  578.      * Return TRUE to continue displaying modules
  579.      */
  580.     return (TRUE);
  581.     }
  582. /******************************************************************************
  583. *
  584. * moduleSegAdd - add a segment to a module
  585. * This routine adds segment information to an object module descriptor.  The
  586. * specific information recorded depends on the format of the object module.
  587. * The <type> parameter is one of the following:
  588. * .iP SEGMENT_TEXT 25
  589. * The segment is for TEXT.
  590. * .iP SEGMENT_DATA
  591. * The segment is for DATA
  592. * .iP SEGMENT_BSS
  593. * The segment is for BSS
  594. * NOMANUAL
  595. * RETURNS: OK, or ERROR.
  596. */
  597. STATUS moduleSegAdd
  598.     (
  599.     MODULE_ID moduleId, /* module to add segment to*/
  600.     int type, /* segment type */
  601.     void * location, /* segment address */
  602.     int length, /* segment length */
  603.     int flags /* segment flags */
  604.     )
  605.     {
  606.     SEGMENT_ID seg;
  607.     /*
  608.      * Validate module id
  609.      */
  610.     if (OBJ_VERIFY (moduleId, moduleClassId) != OK)
  611. {
  612. return (ERROR);
  613. }
  614.     
  615.     /*
  616.      * Allocate space for the segment record
  617.      */
  618.     seg = (SEGMENT_ID) malloc (sizeof (*seg));
  619.     if (seg == NULL)
  620. {
  621.         return (ERROR);
  622. }
  623.     /*
  624.      * Set the fields of the segment record
  625.      */
  626.     seg->address = location;
  627.     seg->size = length;
  628.     seg->type = type;
  629.     seg->flags = flags;
  630.     seg->checksum = checksum (location, length);
  631.     /*
  632.      * Add the segment to the module's segment list
  633.      */
  634.     semTake (moduleSegSem, WAIT_FOREVER);
  635.     dllAdd (&moduleId->segmentList, (DL_NODE *) seg);
  636.     semGive (moduleSegSem);
  637.     return (OK);
  638.     }
  639. /******************************************************************************
  640. *
  641. * moduleSegGet - get (delete and return) the first segment from a module
  642. * This routine returns information about the first segment of a module
  643. * descriptor, and then deletes the segment from the module.
  644. * RETURNS: A pointer to the segment ID, or NULL if the segment list is empty.
  645. *
  646. * SEE ALSO: moduleSegFirst()
  647. */
  648. SEGMENT_ID moduleSegGet
  649.     (
  650.     MODULE_ID  moduleId /* module to get segment from */
  651.     )
  652.     {
  653.     SEGMENT_ID segmentId;
  654.     /*
  655.      * Validate module id
  656.      */
  657.     if (OBJ_VERIFY (moduleId, moduleClassId) != OK)
  658. {
  659. return (NULL);
  660. }
  661.     
  662.     semTake (moduleSegSem, WAIT_FOREVER);
  663.     segmentId = (SEGMENT_ID) dllGet (&moduleId->segmentList);
  664.     semGive (moduleSegSem);
  665.     return (segmentId);
  666.     }
  667. /******************************************************************************
  668. *
  669. * moduleSegFirst - find the first segment in a module
  670. * This routine returns information about the first segment of a module
  671. * descriptor.
  672. * RETURNS: A pointer to the segment ID, or NULL if the segment list is empty.
  673. *
  674. * SEE ALSO: moduleSegGet()
  675. */
  676. SEGMENT_ID moduleSegFirst
  677.     (
  678.     MODULE_ID  moduleId /* module to get segment from */
  679.     )
  680.     {
  681.     SEGMENT_ID newSegId;
  682.     /*
  683.      * Validate module id
  684.      */
  685.     if (OBJ_VERIFY (moduleId, moduleClassId) != OK)
  686. {
  687. return (NULL);
  688. }
  689.     semTake (moduleSegSem, WAIT_FOREVER);
  690.     newSegId = (SEGMENT_ID) DLL_FIRST (&moduleId->segmentList);
  691.     semGive (moduleSegSem);
  692.     return (newSegId);
  693.     }
  694. /******************************************************************************
  695. *
  696. * moduleSegNext - find the next segment in a module
  697. * This routine returns the segment in the list immediately following
  698. * <segmentId>.
  699. * RETURNS: A pointer to the segment ID, or NULL if there is no next segment.
  700. */
  701. SEGMENT_ID moduleSegNext
  702.     (
  703.     SEGMENT_ID segmentId /* segment whose successor is to be found */
  704.     )
  705.     {
  706.     SEGMENT_ID newSegId;
  707.     semTake (moduleSegSem, WAIT_FOREVER);
  708.     newSegId = (SEGMENT_ID) DLL_NEXT (segmentId);
  709.     semGive (moduleSegSem);
  710.     return (newSegId);
  711.     }
  712. /******************************************************************************
  713. *
  714. * moduleSegEach - call a routine to examine each segment in a module
  715. * This routine calls a user-supplied routine to examine each segment
  716. * associated with a given module.  The routine should be declared as
  717. * follows:
  718. * .CS
  719. *     BOOL routine
  720. *         (
  721. *         SEGMENT_ID   segmentId,   /@ The segment to examine @/
  722. *         MODULE_ID  moduleId,    /@ The associated module @/
  723. *         int  userArg      /@ An arbitrary user-supplied argument @/
  724. *         )
  725. * .CE
  726. * The user routine should return TRUE if moduleSegEach() is to continue
  727. * calling it for the other segments, or FALSE if moduleSegEach() should
  728. * exit.
  729. * RETURNS: NULL if all segments were examined, or the segment ID that
  730. * caused the support routine to return FALSE.
  731. * NOMANUAL
  732. */
  733. SEGMENT_ID moduleSegEach
  734.     (
  735.     MODULE_ID moduleId, /* The module to examine */
  736.     FUNCPTR  routine, /* The routine to call */
  737.     int userArg /* arbitrary user-supplied argument */
  738.     )
  739.     {
  740.     SEGMENT_ID segmentId;
  741.     semTake (moduleSegSem, WAIT_FOREVER);
  742.     for (segmentId = moduleSegFirst (moduleId);
  743.  segmentId != NULL;
  744.  segmentId = moduleSegNext (segmentId))
  745. {
  746. if ((*routine) (segmentId, moduleId, userArg) == FALSE)
  747.     {
  748.     semGive (moduleSegSem);
  749.     return (segmentId);
  750.     }
  751. }
  752.     semGive (moduleSegSem);
  753.     return (NULL);
  754.     }
  755.     
  756. /******************************************************************************
  757. *
  758. * moduleCreateHookAdd - add a routine to be called when a module is added
  759. * This routine adds a specified routine to a list of routines to be
  760. * called when a module is created.  The specified routine should be
  761. * declared as follows:
  762. * .CS
  763. *     void moduleCreateHook
  764. *         (
  765. *         MODULE_ID  moduleId  /@ the module ID @/
  766. *         )
  767. * .CE
  768. * This routine is called after all fields of the module ID have been filled in.
  769. * NOTE:
  770. * Modules do not have information about their object segments when they are
  771. * created.  This information is not available until after the entire load
  772. * process has finished.
  773. * RETURNS: OK or ERROR.
  774. * SEE ALSO: moduleCreateHookDelete()
  775. */
  776. STATUS moduleCreateHookAdd
  777.     (
  778.     FUNCPTR     moduleCreateHookRtn  /* routine called when module is added */
  779.     )
  780.     {
  781.     MODCREATE_HOOK * pHook;        /* pointer to hook node */
  782.     if (!moduleCreateHookInitialized)
  783. {
  784. dllInit (&moduleCreateHookList);
  785. moduleCreateHookInitialized = TRUE;
  786. }
  787.     /* allocate and initialize hook node */
  788.     if ((pHook = (MODCREATE_HOOK *) malloc (sizeof (MODCREATE_HOOK)))
  789. == NULL)
  790. {
  791. return (ERROR);
  792. }
  793.     pHook->func = moduleCreateHookRtn;
  794.     /* add it to end of hook list */
  795.     semTake (moduleCreateHookSem, WAIT_FOREVER);
  796.     dllAdd (&moduleCreateHookList, &pHook->node);
  797.     semGive (moduleCreateHookSem);
  798.     return (OK);
  799.     }
  800. /******************************************************************************
  801. *
  802. * moduleCreateHookDelete - delete a previously added module create hook routine
  803. *
  804. * This routine removes a specified routine from the list of
  805. * routines to be called at each moduleCreate() call.
  806. *
  807. * RETURNS: OK, or ERROR if the routine is not in the table of module create
  808. * hook routines.
  809. *
  810. * SEE ALSO: moduleCreateHookAdd()
  811. */
  812. STATUS moduleCreateHookDelete
  813.     (
  814.     FUNCPTR     moduleCreateHookRtn  /* routine called when module is added */
  815.     )
  816.     {
  817.     MODCREATE_HOOK * pNode;          /* hook node */
  818.     /*
  819.      * Step through the list of create hooks until we find a match
  820.      */
  821.     for (pNode = (MODCREATE_HOOK *) DLL_FIRST (&moduleCreateHookList);
  822.  pNode != NULL;
  823.  pNode = (MODCREATE_HOOK *) DLL_NEXT ((DL_NODE *) pNode))
  824. {
  825. if (pNode->func == moduleCreateHookRtn)
  826.     {
  827.     
  828.     /*
  829.      * We've found the node, delete it and free the space
  830.      */
  831.     dllRemove (&moduleCreateHookList, (DL_NODE *) pNode);
  832.     free (pNode);
  833.     return (OK);
  834.     }
  835. }
  836.     /*
  837.      * We didn't find the node, return ERROR
  838.      */
  839.     errnoSet (S_moduleLib_HOOK_NOT_FOUND);
  840.     return (ERROR);
  841.     }
  842. /******************************************************************************
  843. *
  844. * moduleFindByName - find a module by name
  845. * This routine searches for a module with a name matching <moduleName>.
  846. * RETURNS: MODULE_ID, or NULL if no match is found.
  847. */
  848. MODULE_ID moduleFindByName
  849.     (
  850.     char *  moduleName        /* name of module to find */
  851.     )
  852.     {
  853.     MODULE_ID  moduleId;
  854.     char         splitName [NAME_MAX]; /* name part of moduleName */
  855.     char         splitPath [PATH_MAX]; /* path part of moduleName */
  856.     /* get just the name component of moduleName */
  857.     pathSplit (moduleName, splitPath, splitName);
  858.     /*
  859.      * Go through the module list, check each module against
  860.      * the search parameter(s).
  861.      */
  862.     semTake (moduleListSem, WAIT_FOREVER);
  863.     for (moduleId = NODE_TO_ID (DLL_LAST (&moduleList));
  864.  moduleId != NULL;
  865.  moduleId = NODE_TO_ID (DLL_PREVIOUS (&moduleId->moduleNode)))
  866. {
  867. /*
  868.  * Found the right one, give the list semaphore, return the module id
  869.  */
  870. if (strcmp (moduleId->name, splitName) == 0)
  871.     {
  872.     semGive (moduleListSem);
  873.     return (moduleId);
  874.     }
  875. }
  876.     /*
  877.      * Give back the module list semaphore, and return NULL (nothing found)
  878.      */
  879.     semGive (moduleListSem);
  880.     return (NULL);
  881.     }
  882. /******************************************************************************
  883. *
  884. * moduleFindByNameAndPath - find a module by file name and path
  885. * This routine searches for a module with a name matching <moduleName>
  886. * and path matching <pathName>.
  887. * RETURNS: MODULE_ID, or NULL if no match is found.
  888. */
  889. MODULE_ID moduleFindByNameAndPath
  890.     (
  891.     char *  moduleName, /* file name to find */
  892.     char *  pathName /* path name to find */
  893.     )
  894.     {
  895.     MODULE_ID  moduleId;
  896.     /*
  897.      * Go through the module list, check each module against
  898.      * the search parameter(s).  Take the module list semaphore first.
  899.      */
  900.     semTake (moduleListSem, WAIT_FOREVER);
  901.     
  902.     for (moduleId = NODE_TO_ID (DLL_LAST (&moduleList));
  903.  moduleId != NULL;
  904.  moduleId = NODE_TO_ID (DLL_PREVIOUS (&moduleId->moduleNode)))
  905. {
  906. /*
  907.  * Found the right one, give the semaphore, return the module id
  908.  */
  909. if ((strcmp (moduleId->name, moduleName) == 0) &&
  910.     (strcmp (moduleId->path, pathName) == 0))
  911.     {
  912.     semGive (moduleListSem);
  913.     return (moduleId);
  914.     }
  915. }
  916.     semGive (moduleListSem);
  917.     return (NULL);
  918.     }
  919. /******************************************************************************
  920. *
  921. * moduleFindByGroup - find a module by group number
  922. * This routine searches for a module with a group number matching
  923. * <groupNumber>.
  924. * RETURNS: MODULE_ID, or NULL if no match is found.
  925. */
  926. MODULE_ID moduleFindByGroup
  927.     (
  928.     int  groupNumber /* group number to find */
  929.     )
  930.     {
  931.     MODULE_ID  moduleId;
  932.     /*
  933.      * Go through the module list, check each module against
  934.      * the search parameter(s).  Take the list semaphore first
  935.      */
  936.     semTake (moduleListSem, WAIT_FOREVER);
  937.     for (moduleId = NODE_TO_ID (DLL_LAST (&moduleList));
  938.  moduleId != NULL;
  939.  moduleId = NODE_TO_ID (DLL_PREVIOUS (&moduleId->moduleNode)))
  940. {
  941. /*
  942.  * Found the right one, give the semaphore, return the module id
  943.  */
  944. if (groupNumber == moduleId->group)
  945.     {
  946.     semGive (moduleListSem);
  947.     return (moduleId);
  948.     }
  949. }
  950.     semGive (moduleListSem);
  951.     return (NULL);
  952.     }
  953. /******************************************************************************
  954. *
  955. * moduleEach - call a routine to examine each loaded module
  956. * This routine calls a user-supplied routine to examine each module.
  957. * The routine should be declared as follows:
  958. * .CS
  959. *       BOOL routine
  960. *           (
  961. *           MODULE_ID  moduleId,    /@ The associated module @/
  962. *      int  userArg      /@ An arbitrary user-supplied argument @/
  963. *           )
  964. * .CE
  965. * The user routine should return TRUE if moduleEach() is to continue
  966. * calling it for the remaining modules, or FALSE if moduleEach() should
  967. * exit.
  968. * RETURNS: NULL if all modules were examined, or the module ID that
  969. * caused the support routine to return FALSE.
  970. * NOMANUAL
  971. */
  972. MODULE_ID moduleEach
  973.     (
  974.     FUNCPTR  routine, /* The routine to call */
  975.     int userArg /* arbitrary user-supplied argument */
  976.     )
  977.     {
  978.     MODULE_ID  moduleId;
  979.     semTake (moduleListSem, WAIT_FOREVER);
  980.     for (moduleId = NODE_TO_ID (DLL_LAST (&moduleList));
  981.  moduleId != NULL;
  982.  moduleId = NODE_TO_ID (DLL_PREVIOUS (&moduleId->moduleNode)))
  983. {
  984. /*
  985.  * If the user routine returns false, then return the current
  986.  * module ID
  987.  */
  988. if ((* routine) (moduleId, userArg) == FALSE)
  989.     {
  990.     semGive (moduleListSem);
  991.     return (moduleId);
  992.     }
  993. }
  994.     /* Give back the module list semaphore */
  995.     semGive (moduleListSem);
  996.     return (NULL);
  997.     }
  998. /******************************************************************************
  999. *
  1000. * moduleIdListGet - get a list of loaded modules
  1001. * This routine provides the calling task with a list of all loaded
  1002. * object modules.  An unsorted list of module IDs for no more than
  1003. * <maxModules> modules is put into <idList>.
  1004. * RETURNS: The number of modules put into the ID list, or ERROR.
  1005. */
  1006. int moduleIdListGet
  1007.     (
  1008.     MODULE_ID * idList, /* array of module IDs to be filled in */
  1009.     int maxModules /* max modules <idList> can accommodate */
  1010.     )
  1011.     {
  1012.     MODULE_ID  moduleId; /* current module */
  1013.     int count = 0; /* count of modules put into array */
  1014.     semTake (moduleListSem, WAIT_FOREVER);
  1015.     
  1016.     for (moduleId = NODE_TO_ID (DLL_FIRST (&moduleList));
  1017.  moduleId != NULL && count < maxModules;
  1018.  moduleId = NODE_TO_ID (DLL_NEXT (&moduleId->moduleNode)))
  1019. {
  1020. idList [count++] = moduleId;
  1021. }
  1022.     semGive (moduleListSem);
  1023.     
  1024.     return (count);
  1025.     }
  1026. /******************************************************************************
  1027. *
  1028. * moduleSegInfoGet - get information about the segments of a module
  1029. *
  1030. * This routine fills in a MODULE_SEG_INFO struct with information about the
  1031. * specified module's segments.
  1032. * RETURNS: OK or ERROR
  1033. */
  1034. LOCAL STATUS moduleSegInfoGet
  1035.     (
  1036.     MODULE_ID    moduleId, /* module to query */
  1037.     MODULE_SEG_INFO * pModSegInfo /* ptr to module segment info struct */
  1038.     )
  1039.     {
  1040.     SEGMENT_ID segId; /* loop variable */
  1041.     bzero ((char *) pModSegInfo, sizeof (*pModSegInfo));
  1042.     for (segId = moduleSegFirst (moduleId);
  1043.  segId != NULL;
  1044.  segId = moduleSegNext (segId))
  1045. {
  1046. switch (segId->type)
  1047.     {
  1048.     case SEGMENT_TEXT:
  1049. pModSegInfo->textAddr = segId->address;
  1050. pModSegInfo->textSize = segId->size;
  1051. break;
  1052.     case SEGMENT_DATA:
  1053. pModSegInfo->dataAddr = segId->address;
  1054. pModSegInfo->dataSize = segId->size;
  1055. break;
  1056.     case SEGMENT_BSS:
  1057. pModSegInfo->bssAddr = segId->address;
  1058. pModSegInfo->bssSize = segId->size;
  1059. break;
  1060.     }
  1061. } /* for loop end */
  1062.     
  1063.     return (OK);
  1064.     }
  1065. /******************************************************************************
  1066. *
  1067. * moduleInfoGet - get information about an object module
  1068. * This routine fills in a MODULE_INFO structure with information about the
  1069. * specified module.
  1070. * RETURNS: OK or ERROR.
  1071. */
  1072. STATUS moduleInfoGet
  1073.     (
  1074.     MODULE_ID   moduleId, /* module to return information about */
  1075.     MODULE_INFO * pModuleInfo /* pointer to module info struct */
  1076.     )
  1077.     {
  1078.     /* Validate module id */
  1079.     if (OBJ_VERIFY (moduleId, moduleClassId) != OK)
  1080. {
  1081. return (ERROR);
  1082. }
  1083.     strcpy (pModuleInfo->name, moduleId->name);
  1084.     pModuleInfo->format = moduleId->format;
  1085.     pModuleInfo->group = moduleId->group;
  1086.     return (moduleSegInfoGet (moduleId, &pModuleInfo->segInfo));
  1087.     }
  1088. /******************************************************************************
  1089. *
  1090. * moduleCheckSegment - compare the current checksum to the recorded checksum
  1091. */
  1092. LOCAL BOOL moduleCheckSegment
  1093.     (
  1094.     SEGMENT_ID segmentId /* the segment */
  1095.     )
  1096.     {
  1097.     u_short  cksum;
  1098.     extern u_short  checksum();
  1099.     /*
  1100.      * Compute the new checksum, and compare it to the
  1101.      * old one.
  1102.      */
  1103.     cksum = checksum (segmentId->address, segmentId->size);
  1104.     if (cksum != segmentId->checksum)
  1105. {
  1106. errnoSet (S_moduleLib_BAD_CHECKSUM);
  1107. return (FALSE);
  1108. }
  1109.     else
  1110. return (TRUE);
  1111.     }
  1112. /******************************************************************************
  1113. *
  1114. * moduleCheckOne - verify checksums on a specific module
  1115. */
  1116. LOCAL BOOL moduleCheckOne
  1117.     (
  1118.     MODULE_ID  moduleId, /* module to check */
  1119.     int options /* options */
  1120.     )
  1121.     {
  1122.     SEGMENT_ID segmentId;
  1123.     STATUS returnValue = TRUE;
  1124.     /* If no options are set, default to checking text segments */
  1125.     if (options == 0)
  1126.         options = MODCHECK_TEXT;
  1127.     for (segmentId = moduleSegFirst (moduleId);
  1128.  segmentId != NULL;
  1129.  segmentId = moduleSegNext (segmentId))
  1130. {
  1131. if (segmentId->type & options)
  1132.     {
  1133.     if (moduleCheckSegment (segmentId) == FALSE)
  1134. {
  1135. if (!(options & MODCHECK_NOPRINT))
  1136.     {
  1137.     printf ("Checksum error in segment type %d, ",
  1138.     segmentId->type);
  1139.     printf ("module %#x (%s)n", (int) moduleId,
  1140.     moduleId->name);
  1141.     }
  1142. returnValue = FALSE;
  1143. }
  1144.     }
  1145. }
  1146.     return (returnValue);
  1147.     }
  1148.     
  1149. /******************************************************************************
  1150. *
  1151. * moduleCheck - verify checksums on all modules
  1152. *
  1153. * This routine verifies the checksums on the segments of all loaded
  1154. * modules.  If any of the checksums are incorrect, a message is printed to
  1155. * the console, and the routine returns ERROR.
  1156. *
  1157. * By default, only the text segment checksum is validated.
  1158. *
  1159. * Bits in the <options> parameter may be set to control specific checks:
  1160. * .iP MODCHECK_TEXT
  1161. * Validate the checksum for the TEXT segment (default).
  1162. * .iP MODCHECK_DATA
  1163. * Validate the checksum for the DATA segment.
  1164. * .iP MODCHECK_BSS
  1165. * Validate the checksum for the BSS segment.
  1166. * .iP MODCHECK_NOPRINT
  1167. * Do not print a message (moduleCheck() still returns ERROR on failure.)
  1168. * .LP
  1169. * See the definitions in moduleLib.h
  1170. *
  1171. * RETURNS: OK, or ERROR if the checksum is invalid.
  1172. */
  1173. STATUS moduleCheck
  1174.     (
  1175.     int options /* validation options */
  1176.     )
  1177.     {
  1178.     if (moduleEach (moduleCheckOne, options) == NULL)
  1179.         return (OK);
  1180.     else
  1181.         return (ERROR);
  1182.     }
  1183. /******************************************************************************
  1184. *
  1185. * moduleNameGet - get the name associated with a module ID
  1186. *
  1187. * This routine returns a pointer to the name associated with a module ID.
  1188. *
  1189. * RETURNS: A pointer to the module name, or NULL if the module ID is invalid.
  1190. */
  1191. char * moduleNameGet
  1192.     (
  1193.     MODULE_ID moduleId
  1194.     )
  1195.     {
  1196.     if (OBJ_VERIFY (moduleId, moduleClassId) != OK)  /* validate module id */
  1197. {
  1198. return (NULL);
  1199. }
  1200.     return (moduleId->name);
  1201.     }
  1202. /******************************************************************************
  1203. *
  1204. * moduleFlagsGet - get the flags associated with a module ID
  1205. *
  1206. * This routine returns the flags associated with a module ID.
  1207. *
  1208. * RETURNS: The flags associated with the module ID, or NULL if the module ID
  1209. * is invalid.
  1210. */
  1211. int moduleFlagsGet
  1212.     (
  1213.     MODULE_ID moduleId
  1214.     )
  1215.     {
  1216.     if (OBJ_VERIFY (moduleId, moduleClassId) != OK)  /* validate module id */
  1217. {
  1218. return (NULL);
  1219. }
  1220.     return (moduleId->flags);
  1221.     }