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

VxWorks

开发平台:

C/C++

  1. /* unldLib.c - object module unloading library */
  2. /* Copyright 1992-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01r,15may02,jn   improve explanation of shell commands
  8. 01q,18mar02,jn   remove dependence on usrLib (call to ld)
  9. 01p,30oct96,elp  Added syncUnldRtn function pointer (symtbls synchro).
  10. 01o,09aug96,dbt  check segment size in macro IN_TEXT_SEGMENT (SPR #3908).
  11.  Updated copyright.
  12. 01n,10oct95,jdi  doc: added .tG Shell to unld(); changed .pG Cross-Dev to .tG.
  13. 01m,11feb95,jdi  doc format repair.
  14. 01l,02nov93,caf  made unldTextInUse() static, like its prototype.
  15. 01l,20may94,dvs  fixed references to unallocated memory in reld() (SPR 3005)
  16. 01k,25aug93,srh  added call to C++ run-time for static dtors (spr 2341)
  17. 01j,22aug93,jmm  added call to bdall() from unld{ByModuleId} ()
  18. 01i,18aug93,jmm  removed checking of ether hook routines for unld
  19. 01h,13aug93,jmm  added code to test hook routines before unld() (spr 2054)
  20. 01g,25nov92,jdi  documentation cleanup.
  21. 01f,30oct92,jmm  fixed adding "/" separator in reld() (spr 1717)
  22. 01e,16sep92,kdl  added "/" separator when combining path & name in reld().
  23. 01d,02sep92,jmm  changed name of symFlags field in reld()
  24. 01c,29jul92,jmm  cleaned up warning messages
  25. 01b,21jul92,rdc  mods to support text segment write protection.
  26. 01a,26may92,jmm  written
  27. */
  28. /*
  29. DESCRIPTION
  30. This library provides a facility for unloading object modules.  Once an
  31. object module has been loaded into the system (using the facilities
  32. provided by loadLib), it can be removed from the system by calling one
  33. of the unld...() routines in this library.
  34. Unloading of an object module does the following:
  35. .IP (1) 4
  36. It frees the space allocated for text, data,
  37. and BSS segments, unless loadModuleAt() was called with specific
  38. addresses, in which case the user is responsible for freeing the space.
  39. .IP (2)
  40. It removes all symbols associated with the object module from the
  41. system symbol table.
  42. .IP (3)
  43. It removes the module descriptor from the module list.
  44. .LP
  45. Once the module is unloaded, any calls to routines in that module from
  46. other modules will fail unpredictably.  The user is responsible for
  47. ensuring that no modules are unloaded that are used by other modules.
  48. unld() checks the hooks created by the following routines to
  49. ensure none of the unloaded code is in use by a hook:
  50.     taskCreateHookAdd()
  51.     taskDeleteHookAdd()
  52.     taskHookAdd()
  53.     taskSwapHookAdd()
  54.     taskSwitchHookAdd()
  55. However, unld() f2does notfP check the hooks created by these routines:
  56.     etherInputHookAdd()
  57.     etherOutputHookAdd()
  58.     excHookAdd()
  59.     rebootHookAdd()
  60.     moduleCreateHookAdd()
  61. The routines unld() and reld() are 'shell commands'.  That is,
  62. they are designed to be used only in the shell, and not in code
  63. running on the target.  In future releases, calling unld() and 
  64. reld() directly from code may not be supported.
  65. INCLUDE FILES: unldLib.h, moduleLib.h
  66. SEE ALSO: loadLib, moduleLib,
  67. .tG "Cross-Development" 
  68. */
  69. /* LINTLIBRARY */
  70. #include "vxWorks.h"
  71. #include "a_out.h"
  72. #include "errno.h"
  73. #include "ioLib.h"
  74. #include "loadLib.h"
  75. #include "moduleLib.h"
  76. #include "stdio.h"
  77. #include "stdlib.h"
  78. #include "symLib.h"
  79. #include "symbol.h"
  80. #include "sysSymTbl.h"
  81. #include "unldLib.h"
  82. #include "private/vmLibP.h"
  83. #include "string.h"
  84. #include "usrLib.h"
  85. #include "etherLib.h"
  86. #include "private/cplusLibP.h"
  87. #include "private/taskLibP.h"
  88. #include "private/funcBindP.h"
  89. #define IN_TEXT_SEGMENT(adrs, segment) (((void *) (adrs) >= (segment)->address) && 
  90. (((void *) (adrs) <= (void *) (((int) (segment)->address) + (segment)->size))) && 
  91. (segment->size != 0))
  92. /* globals */
  93. FUNCPTR syncUnldRtn = (FUNCPTR)NULL;
  94. /* locals */
  95. /* forward static functions */
  96.  
  97. static BOOL unldSymbols (char *name, int val, SYM_TYPE type, int deleteGroup,
  98.  UINT16 group, SYMBOL *pSymbol);
  99. static STATUS unldTextInUse (MODULE_ID moduleId);
  100.  
  101. /******************************************************************************
  102. *
  103. * unld - unload an object module by specifying a file name or module ID
  104. * This routine unloads the specified object module from the system.  The
  105. * module can be specified by name or by module ID.  For a.out and ECOFF
  106. * format modules, unloading does the following:
  107. * .IP (1) 4
  108. * It frees the space allocated for text, data,
  109. * and BSS segments, unless loadModuleAt() was called with specific
  110. * addresses, in which case the user is responsible for freeing the space.
  111. * .IP (2)
  112. * It removes all symbols associated with the object module from the
  113. * system symbol table.
  114. * .IP (3)
  115. * It removes the module descriptor from the module list.
  116. * .LP
  117. *
  118. * For other modules of other formats, unloading has similar effects.
  119. *
  120. * Before any modules are unloaded, all breakpoints in the system are deleted.
  121. * If you need to keep breakpoints, set the options parameter to
  122. * UNLD_KEEP_BREAKPOINTS.  No breakpoints can be set in code that is unloaded.
  123. * This routine is a 'shell command'.  That is, it is designed to be
  124. * used only in the shell, and not in code running on the target.  In
  125. * future releases, calling unld() directly from code may not be
  126. * supported.
  127. *
  128. * RETURNS: OK or ERROR.
  129. *
  130. * SEE ALSO:
  131. * .pG "Target Shell,"
  132. * windsh,
  133. * .tG "Shell" 
  134. */
  135. STATUS unld
  136.     (
  137.     void * nameOrId, /* name or ID of the object module file */
  138.     int  options
  139.     )
  140.     {
  141.     MODULE_ID  moduleId;
  142.     /* Given the name, find the right module id, then call unldByModuleId(). */
  143.     if (((moduleId = moduleIdFigure (nameOrId))) != NULL)
  144.         return (unldByModuleId (moduleId, options));
  145.     else
  146.         return (ERROR);
  147.     }
  148. /******************************************************************************
  149. *
  150. * unldByModuleId - unload an object module by specifying a module ID
  151. *
  152. * This routine unloads an object module that has a module ID
  153. * matching <moduleId>.
  154. *
  155. * See the manual entries for unld() or unldLib for more information on
  156. * module unloading.
  157. * RETURNS: OK or ERROR.
  158. * SEE ALSO: unld()
  159. */
  160. STATUS unldByModuleId
  161.     (
  162.     MODULE_ID  moduleId,       /* module ID to unload */
  163.     int        options
  164.     )
  165.     {
  166.     SEGMENT_ID  segmentId;
  167.     int  pageSize;
  168.     int  segSize;
  169.     MODULE syncBuf;
  170.     /* store unloaded module info to be able to synchronize host symtbl */
  171.     if (syncUnldRtn != NULL)
  172. memcpy (&syncBuf, moduleId, sizeof (MODULE));
  173.     /* Make sure the text segment isn't in use */
  174.     if (unldTextInUse (moduleId) != OK)
  175.         return (ERROR);
  176.     
  177.     /* Give C++ run-time a chance to call static destructors */
  178.     cplusUnloadFixup (moduleId);
  179.     /* If options isn't set to 1, delete all breakpoints in the system */
  180.     if (_func_bdall != NULL && !(options & UNLD_KEEP_BREAKPOINTS))
  181.         (*_func_bdall) (0);
  182.     
  183.     /* Free all segments */
  184.     while ((segmentId = moduleSegGet (moduleId)))
  185. {
  186. /*
  187.  * If the segment is marked to dynamically free space, do so
  188.  */
  189. if (segmentId->flags & SEG_FREE_MEMORY)
  190.     {
  191.     /* make sure it's not write protected */
  192.     if (segmentId->flags & SEG_WRITE_PROTECTION)
  193. {
  194. pageSize = VM_PAGE_SIZE_GET ();
  195. /* round seg size to intergral num pages */
  196. segSize = segmentId->size / pageSize * pageSize + pageSize;
  197. if (VM_STATE_SET (NULL, segmentId->address, segSize, 
  198.     VM_STATE_MASK_WRITABLE, VM_STATE_WRITABLE) == ERROR)
  199.     return (ERROR);
  200. }
  201.     free (segmentId->address);
  202.     }
  203. free (segmentId);
  204. }
  205.     /*
  206.      * Remove all symbols from the symbol table that match the group
  207.      * ID #.  If they're common symbols, delete their storage space.
  208.      */
  209.     symEach (sysSymTbl, (FUNCPTR) unldSymbols, (int) moduleId->group);
  210.     /* Remove the module itself */
  211.     if (moduleDelete (moduleId) != OK)
  212. {
  213. return (ERROR);
  214. }
  215.     if ((~options & UNLD_SYNC) && (syncUnldRtn != NULL))
  216. (* syncUnldRtn) (&syncBuf);
  217.     return (OK);
  218.     }
  219. /******************************************************************************
  220. *
  221. * unldByNameAndPath - unload an object module by specifying a name and path
  222. *
  223. * This routine unloads an object module specified by <name> and <path>.
  224. *
  225. * See the manual entries for unld() or unldLib for more information on
  226. * module unloading.
  227. * RETURNS: OK or ERROR.
  228. * SEE ALSO: unld()
  229. */
  230. STATUS unldByNameAndPath
  231.     (
  232.     char * name, /* name of the object module to unload */
  233.     char * path, /* path to the object module to unload */
  234.     int    options /* options, currently unused */
  235.     )
  236.     {
  237.     MODULE_ID moduleId;
  238.     /*
  239.      * Given the name and path, find the right module id, then call
  240.      * unldByModuleId().
  241.      */
  242.     if ((moduleId = moduleFindByNameAndPath (name, path)) != NULL)
  243.         return (unldByModuleId (moduleId, options));
  244.     else
  245.         return (ERROR);
  246.     }
  247. /******************************************************************************
  248. *
  249. * unldByGroup - unload an object module by specifying a group number
  250. *
  251. * This routine unloads an object module that has a group number
  252. * matching <group>.
  253. *
  254. * See the manual entries for unld() or unldLib for more information on
  255. * module unloading.
  256. * RETURNS: OK or ERROR.
  257. * SEE ALSO: unld()
  258. */
  259. STATUS unldByGroup
  260.     (
  261.     UINT16 group, /* group number to unload */
  262.     int   options /* options, currently unused */
  263.     )
  264.     {
  265.     MODULE_ID  moduleId;
  266.     /*
  267.      * Given the name, find the right module id, then call unldByModuleId().
  268.      */
  269.     if ((moduleId = moduleFindByGroup (group)) != NULL)
  270.         return (unldByModuleId (moduleId, options));
  271.     else
  272.         return (ERROR);
  273.     }
  274. /******************************************************************************
  275. *
  276. * unldSymbols - support routine for unldByModuleId
  277. *
  278. * This routine is used by unldByModuleId() as an argument to symEach().
  279. * NOMANUAL
  280. */
  281. LOCAL BOOL unldSymbols
  282.     (
  283.     char *  name, /* not used */
  284.     int      val, /* not used */
  285.     SYM_TYPE   type, /* not used */
  286.     int    deleteGroup, /* group number to delete */
  287.     UINT16       group, /* group number of current symbol*/
  288.     SYMBOL *  pSymbol /* a pointer to the symbol itself */
  289.     )
  290.     {
  291.     if (group == deleteGroup)
  292. {
  293. if (symTblRemove (sysSymTbl, pSymbol) != OK)
  294.     {
  295.     printf ("got bad symbol, %#xn", (UINT) pSymbol);
  296.     return (FALSE);
  297.     }
  298. /*
  299.  * if the type is N_COMM, then free the memory associated
  300.  * with the symbol.
  301.  */
  302. if ((pSymbol->type & N_COMM) == N_COMM)
  303.     {
  304.     free (pSymbol->value);
  305.     }
  306. /* free the space allocated for the symbol itself */
  307. symFree (sysSymTbl, pSymbol);
  308.         
  309. }
  310.     return (TRUE);
  311.     }
  312. /******************************************************************************
  313. *
  314. * reld - reload an object module
  315. *
  316. * This routine unloads a specified object module from the system, and
  317. * then calls loadModule() to load a new copy of the same name.
  318. * If the file was originally loaded using a complete pathname, then
  319. * reld() will use the complete name to locate the file.  If
  320. * the file was originally loaded using a partial pathname, then the 
  321. * current working directory must be changed to the working
  322. * directory in use at the time of the original load.
  323. * Valid values for the options parameter are the same as those allowed 
  324. * for the function unld().  
  325. * This routine is a 'shell command'.  That is, it is designed to be
  326. * used only in the shell, and not in code running on the target.  In
  327. * future releases, calling reld() directly from code may not be
  328. * supported.
  329. *
  330. * RETURNS: A module ID (type MODULE_ID), or NULL.
  331. * SEE ALSO: unld()
  332. */
  333. MODULE_ID reld
  334.     (
  335.     void * nameOrId, /* name or ID of the object module file */
  336.     int  options /* options used for unloading           */
  337.     )
  338.     {
  339.     MODULE_ID  moduleId;
  340.     MODULE_ID  newModuleId;
  341.     char fileName [NAME_MAX + PATH_MAX];
  342.     int         fd;
  343.     int flags;
  344.     
  345.     /*
  346.      * Given the name, find the right module id, then call unldByModuleId()
  347.      * and loadModule().
  348.      */
  349.     if (((moduleId = moduleIdFigure (nameOrId))) != NULL)
  350. {
  351. /* build the new file name before destroying module */
  352. strcpy (fileName, moduleId->path);
  353. if (moduleId->path [0] != EOS)
  354.     strcat (fileName, "/");
  355. strcat (fileName, moduleId->name);
  356. flags = moduleId->flags;
  357.         unldByModuleId (moduleId, options);
  358. /* reload module */
  359.         fd = open (fileName, O_RDONLY, 0);
  360.         if (fd == ERROR)
  361.             return (NULL);
  362. newModuleId = loadModule (fd, flags);
  363.         close (fd);
  364. return (newModuleId);
  365. }
  366.     else
  367.         return (NULL);
  368.     }
  369. /******************************************************************************
  370. *
  371. * unldTextSegmentCheck - check that text segment is not in use by hook routine
  372. * unldTextSegmentCheck returns TRUE if the segment is not a text segment,
  373. * or if the text segment is not used by any hook routines.
  374. * RETURNS: TRUE, or FALSE if the text segment is in use by a hook routine.
  375. * NOMANUAL
  376. */
  377. BOOL unldTextSegmentCheck
  378.     (
  379.     SEGMENT_ID   segmentId,
  380.     MODULE_ID  moduleId, 
  381.     int  unused
  382.     )
  383.     {
  384.     int          hookNumber;
  385.     /* If it's not a text segment, just return TRUE */
  386.     
  387.     if (segmentId->type != SEGMENT_TEXT)
  388.         return (TRUE);
  389.     /* The exception hook is a simple variable */
  390.     if (IN_TEXT_SEGMENT (excExcepHook, segmentId))
  391.         return (FALSE);
  392.     /* check the various task hooks */
  393.     for (hookNumber = 0; hookNumber < VX_MAX_TASK_CREATE_RTNS; hookNumber++)
  394.         if (IN_TEXT_SEGMENT (taskCreateTable [hookNumber], segmentId))
  395.     return (FALSE);
  396.     for (hookNumber = 0; hookNumber < VX_MAX_TASK_DELETE_RTNS; hookNumber++)
  397.         if (IN_TEXT_SEGMENT (taskDeleteTable [hookNumber], segmentId))
  398.     return (FALSE);
  399.     
  400.     for (hookNumber = 0; hookNumber < VX_MAX_TASK_SWAP_RTNS; hookNumber++)
  401.         if (IN_TEXT_SEGMENT (taskSwapTable [hookNumber], segmentId))
  402.     return (FALSE);
  403.     
  404.     for (hookNumber = 0; hookNumber < VX_MAX_TASK_SWITCH_RTNS; hookNumber++)
  405.         if (IN_TEXT_SEGMENT (taskSwitchTable [hookNumber], segmentId))
  406.     return (FALSE);
  407.     /* Didn't find anything, return TRUE */
  408.     return (TRUE);
  409.     }
  410.     
  411. /******************************************************************************
  412. *
  413. * unldTextInUse - check to see if text segment is used by a hook
  414. * unldTextSegment checks the system hook routines to see if any of them
  415. * use text that is about to be unloaded.  Modules that have hooks using
  416. * their text cannot be unloaded.
  417. * unldTextSegmentUsed checks the hooks created by the following routines:
  418. * STATUS taskCreateHookAdd
  419. * STATUS taskDeleteHookAdd
  420. * LOCAL STATUS taskHookAdd
  421. * STATUS taskSwapHookAdd
  422. * STATUS taskSwitchHookAdd
  423. * unldTextSegmentUsed DOES NOT check the hooks created by these routines:
  424. *
  425. * STATUS etherInputHookAdd
  426. * etherOutputHookAdd
  427. * void excHookAdd
  428. * STATUS rebootHookAdd
  429. * STATUS moduleCreateHookAdd
  430. * RETURNS:  OK, or ERROR if the text segment is in use.
  431. * NOMANUAL
  432. */
  433. static STATUS unldTextInUse
  434.     (
  435.     MODULE_ID  moduleId       /* module ID to check */
  436.     )
  437.     {
  438.     if (moduleSegEach (moduleId, unldTextSegmentCheck, 0) != NULL)
  439. {
  440. errno = S_unldLib_TEXT_IN_USE;
  441.         return (ERROR);
  442. }
  443.     else
  444.         return (OK);
  445.     }