Skip to content

Commit

Permalink
Fix #641, add flags to OS_ModuleLoad
Browse files Browse the repository at this point in the history
Add flags to indicate symbol visibility for OS_ModuleLoad().

By default (flags=0) symbols will have global visibility,
which should be the same as existing behavior.
  • Loading branch information
jphickey committed Nov 4, 2020
1 parent 1a82657 commit d068af0
Show file tree
Hide file tree
Showing 18 changed files with 475 additions and 82 deletions.
59 changes: 58 additions & 1 deletion src/os/inc/osapi-os-loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,44 @@
** Defines
*/

/**
* @brief Requests OS_ModuleLoad() to add the symbols to the global symbol table
*
* When supplied as the "flags" argument to OS_ModuleLoad(), this indicates
* that the symbols in the loaded module should be added to the global symbol
* table. This will make symbols in this library available for use when
* resolving symbols in future module loads.
*
* This is the default mode of operation for OS_ModuleLoad().
*
* @note On some operating systems, use of this option may make it difficult
* to unload the module in the future, if the symbols are in use by other entities.
*
*/
#define OS_MODULE_FLAG_GLOBAL_SYMBOLS 0x00

/**
* @brief Requests OS_ModuleLoad() to keep the symbols local/private to this module
*
* When supplied as the "flags" argument to OS_ModuleLoad(), this indicates
* that the symbols in the loaded module should NOT be added to the global
* symbol table. This means the symbols in the loaded library will not available
* to for use by other modules.
*
* Use this option is recommended for cases where no other entities will need
* to reference symbols within this module. This helps ensure that the module
* can be more safely unloaded in the future, by preventing other modules from
* binding to it. It also helps reduce the likelihood of symbol name conflicts
* among modules.
*
* @note To look up symbols within a module loaded with this flag, use
* OS_SymbolLookupInModule() instead of OS_SymbolLookup(). Also note that
* references obtained using this method are not tracked by the OS; the
* application must ensure that all references obtained in this manner have
* been cleaned up/released before unloading the module.
*/
#define OS_MODULE_FLAG_LOCAL_SYMBOLS 0x01

/*
** Typedefs
*/
Expand Down Expand Up @@ -105,6 +143,25 @@ typedef const struct
*/
int32 OS_SymbolLookup(cpuaddr *symbol_address, const char *symbol_name);

/*-------------------------------------------------------------------------------------*/
/**
* @brief Find the Address of a Symbol within a module
*
* This is similar to OS_SymbolLookup() but for a specific module ID.
* This should be used to look up a symbol in a module that has been
* loaded with the #OS_MODULE_FLAG_LOCAL_SYMBOLS flag.
*
* @param[in] module_id Module ID that should contain the symbol
* @param[out] symbol_address Set to the address of the symbol
* @param[in] symbol_name Name of the symbol to look up
*
* @return Execution status, see @ref OSReturnCodes
* @retval #OS_SUCCESS @copybrief OS_SUCCESS
* @retval #OS_ERROR if the symbol could not be found
* @retval #OS_INVALID_POINTER if one of the pointers passed in are NULL
*/
int32 OS_ModuleSymbolLookup(osal_id_t module_id, cpuaddr *SymbolAddress, const char *SymbolName);

/*-------------------------------------------------------------------------------------*/
/**
* @brief Dumps the system symbol table to a file
Expand Down Expand Up @@ -138,7 +195,7 @@ int32 OS_SymbolTableDump(const char *filename, uint32 size_limit);
* @retval #OS_ERR_NO_FREE_IDS if the module table is full
* @retval #OS_ERR_NAME_TAKEN if the name is in use
*/
int32 OS_ModuleLoad(osal_id_t *module_id, const char *module_name, const char *filename);
int32 OS_ModuleLoad(osal_id_t *module_id, const char *module_name, const char *filename, uint32 flags);

/*-------------------------------------------------------------------------------------*/
/**
Expand Down
4 changes: 2 additions & 2 deletions src/os/inc/osapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ extern "C"
#define OS_ERR_INCORRECT_OBJ_STATE (-35) /**< @brief Incorrect object state */
#define OS_ERR_INCORRECT_OBJ_TYPE (-36) /**< @brief Incorrect object type */
#define OS_ERR_STREAM_DISCONNECTED (-37) /**< @brief Stream disconnected */
#define OS_ERR_OPERATION_NOT_SUPPORTED (-38) /**< @brief Requested operation is not support on the supplied object(s) \
*/
#define OS_ERR_OPERATION_NOT_SUPPORTED (-38) /**< @brief Requested operation is not support on the supplied object(s) */

/**@}*/

/*
Expand Down
20 changes: 17 additions & 3 deletions src/os/portable/os-impl-no-symtab.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,31 @@

/*----------------------------------------------------------------
*
* Function: OS_SymbolLookup_Impl
* Function: OS_GlobalSymbolLookup_Impl
*
* Purpose: Implemented per internal OSAL API
* See prototype for argument/return detail
*
*-----------------------------------------------------------------*/
int32 OS_SymbolLookup_Impl(cpuaddr *SymbolAddress, const char *SymbolName)
int32 OS_GlobalSymbolLookup_Impl(cpuaddr *SymbolAddress, const char *SymbolName)
{
return OS_ERR_NOT_IMPLEMENTED;

} /* end OS_SymbolLookup_Impl */
} /* end OS_GlobalSymbolLookup_Impl */

/*----------------------------------------------------------------
*
* Function: OS_ModuleSymbolLookup_Impl
*
* Purpose: Implemented per internal OSAL API
* See prototype for argument/return detail
*
*-----------------------------------------------------------------*/
int32 OS_ModuleSymbolLookup_Impl(uint32 local_id, cpuaddr *SymbolAddress, const char *SymbolName)
{
return OS_ERR_NOT_IMPLEMENTED;

} /* end OS_ModuleSymbolLookup_Impl */

/*----------------------------------------------------------------
*
Expand Down
31 changes: 30 additions & 1 deletion src/os/portable/os-impl-posix-dl-loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,38 @@
int32 OS_ModuleLoad_Impl(uint32 module_id, const char *translated_path)
{
int32 status = OS_ERROR;
int dl_mode;

/*
* RTLD_NOW should instruct dlopen() to resolve all the symbols in the
* module immediately, as opposed to waiting until they are used.
* The latter (lazy mode) is non-deterministic - a resolution error on
* a rarely-used symbol could cause a random failure far in the future.
*/
dl_mode = RTLD_NOW;

if ((OS_module_table[module_id].flags & OS_MODULE_FLAG_LOCAL_SYMBOLS) != 0)
{
/*
* Do not add the symbols in this module to the global symbol table.
* This mode helps prevent any unanticipated references into this
* module, which can in turn prevent unloading via dlclose().
*/
dl_mode |= RTLD_LOCAL;
}
else
{
/*
* Default mode - add symbols to the global symbol table, so they
* will be available to resolve symbols in future module loads.
* However, any such references will prevent unloading of this
* module via dlclose().
*/
dl_mode |= RTLD_GLOBAL;
}

dlerror();
OS_impl_module_table[module_id].dl_handle = dlopen(translated_path, RTLD_NOW | RTLD_GLOBAL);
OS_impl_module_table[module_id].dl_handle = dlopen(translated_path, dl_mode);
if (OS_impl_module_table[module_id].dl_handle != NULL)
{
status = OS_SUCCESS;
Expand Down
81 changes: 64 additions & 17 deletions src/os/portable/os-impl-posix-dl-symtab.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,12 @@
* Otherwise, check if the C library provides an "RTLD_DEFAULT" symbol -
* This symbol is not POSIX standard but many implementations do provide it.
*
* Lastly, if nothing else works, use NULL. This is technically undefined
* behavior per POSIX, but most implementations do seem to interpret this
* as referring to the complete process (base executable + all loaded modules).
* Lastly, if nothing no special handle that indicates the global symbol
* table is defined, then OS_GlobalSymbolLookup_Impl() will return
* OS_ERR_NOT_IMPLEMENTED rather than relying on undefined behavior.
*/
#ifndef OSAL_DLSYM_DEFAULT_HANDLE
#ifdef RTLD_DEFAULT
#define OSAL_DLSYM_DEFAULT_HANDLE RTLD_DEFAULT
#else
#define OSAL_DLSYM_DEFAULT_HANDLE NULL
#endif
#if !defined(OSAL_DLSYM_GLOBAL_HANDLE) && defined(RTLD_DEFAULT)
#define OSAL_DLSYM_GLOBAL_HANDLE RTLD_DEFAULT
#endif

/****************************************************************************************
Expand All @@ -78,23 +74,25 @@

/*----------------------------------------------------------------
*
* Function: OS_SymbolLookup_Impl
* Function: OS_GenericSymbolLookup_Impl
*
* Purpose: Implemented per internal OSAL API
* See prototype for argument/return detail
*
*-----------------------------------------------------------------*/
int32 OS_SymbolLookup_Impl(cpuaddr *SymbolAddress, const char *SymbolName)
int32 OS_GenericSymbolLookup_Impl(void *dl_handle, cpuaddr *SymbolAddress, const char *SymbolName)
{
int32 status = OS_ERROR;
const char *dlError; /* Pointer to error string */
void * Function;
void *Function;
int32 status;

status = OS_ERROR;

/*
* call dlerror() to clear any prior error that might have occurred.
*/
dlerror();
Function = dlsym(OSAL_DLSYM_DEFAULT_HANDLE, SymbolName);
Function = dlsym(dl_handle, SymbolName);
dlError = dlerror();

/*
Expand All @@ -110,16 +108,65 @@ int32 OS_SymbolLookup_Impl(cpuaddr *SymbolAddress, const char *SymbolName)
* and as such all valid symbols should be non-NULL, so NULL is considered
* an error even if the C library doesn't consider this an error.
*/
if (dlError == NULL && Function != NULL)
if (dlError != NULL)
{
OS_DEBUG("Error: %s: %s\n", SymbolName, dlError);
}
else if (Function == NULL)
{
*SymbolAddress = (cpuaddr)Function;
status = OS_SUCCESS;
/* technically not an error per POSIX, but in practice should not happen */
OS_DEBUG("Error: %s: dlsym() returned NULL\n", SymbolName);
}
else
{
status = OS_SUCCESS;
}

*SymbolAddress = (cpuaddr)Function;

return status;
}

/*----------------------------------------------------------------
*
* Function: OS_GlobalSymbolLookup_Impl
*
* Purpose: Implemented per internal OSAL API
* See prototype for argument/return detail
*
*-----------------------------------------------------------------*/
int32 OS_GlobalSymbolLookup_Impl(cpuaddr *SymbolAddress, const char *SymbolName)
{
int32 status;

#ifdef OSAL_DLSYM_DEFAULT_HANDLE
status = OS_GenericSymbolLookup_Impl(OSAL_DLSYM_DEFAULT_HANDLE, SymbolAddress, SymbolName);
#else
status = OS_ERR_NOT_IMPLEMENTED;
#endif

return status;

} /* end OS_SymbolLookup_Impl */

/*----------------------------------------------------------------
*
* Function: OS_ModuleSymbolLookup_Impl
*
* Purpose: Implemented per internal OSAL API
* See prototype for argument/return detail
*
*-----------------------------------------------------------------*/
int32 OS_ModuleSymbolLookup_Impl(uint32 local_id, cpuaddr *SymbolAddress, const char *SymbolName)
{
int32 status;

status = OS_GenericSymbolLookup_Impl(OS_impl_module_table[local_id].dl_handle, SymbolAddress, SymbolName);

return status;

} /* end OS_ModuleSymbolLookup_Impl */

/*----------------------------------------------------------------
*
* Function: OS_SymbolTableDump_Impl
Expand Down
16 changes: 13 additions & 3 deletions src/os/shared/inc/os-shared-module.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,25 @@ int32 OS_ModuleUnload_Impl(uint32 module_id);
------------------------------------------------------------------*/
int32 OS_ModuleGetInfo_Impl(uint32 module_id, OS_module_prop_t *module_prop);

/*----------------------------------------------------------------
Function: OS_GlobalSymbolLookup_Impl
Purpose: Find the Address of a Symbol in the global symbol table.
The address of the symbol will be stored in the pointer that is passed in.
Returns: OS_SUCCESS on success, or relevant error code
------------------------------------------------------------------*/
int32 OS_GlobalSymbolLookup_Impl(cpuaddr *SymbolAddress, const char *SymbolName);

/*----------------------------------------------------------------
Function: OS_SymbolLookup_Impl
Purpose: Find the Address of a Symbol
Purpose: Find the Address of a Symbol within a specific module.
The address of the symbol will be stored in the pointer that is passed in.
Returns: OS_SUCCESS on success, or relevant error code
------------------------------------------------------------------*/
int32 OS_SymbolLookup_Impl(cpuaddr *SymbolAddress, const char *SymbolName);
int32 OS_ModuleSymbolLookup_Impl(uint32 local_id, cpuaddr *SymbolAddress, const char *SymbolName);

/*----------------------------------------------------------------
Function: OS_SymbolTableDump_Impl
Expand All @@ -109,6 +119,6 @@ int32 OS_SymbolTableDump_Impl(const char *filename, uint32 size_limit);
* These need to be exposed for unit testing
*/
int32 OS_ModuleLoad_Static(const char *ModuleName);
int32 OS_SymbolLookup_Static(cpuaddr *SymbolAddress, const char *SymbolName);
int32 OS_SymbolLookup_Static(cpuaddr *SymbolAddress, const char *SymbolName, const char *ModuleName);

#endif /* INCLUDE_OS_SHARED_MODULE_H_ */
Loading

0 comments on commit d068af0

Please sign in to comment.