Fixes hang due to change in order of initialization of libraries
Fixes hang due to change in order of initialization of libraries
that have cyclical dependencies and they call hsa_init() during their
initialization phase.
This implementation looks for a symbol called "HSA_AMD_TOOL_PRIORITY"
across all loaded shared libraries using dynamic section entries of the
loaded lib instead of using dlopen and dlsym for the same purpose.
Change-Id: I4865f2fd18dd186ec311a432ec38fbb5583805d2
[ROCm/ROCR-Runtime commit: 8aac885318]
This commit is contained in:
@@ -1542,7 +1542,7 @@ void Runtime::LoadTools() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Discover loaded tools.
|
// Discover loaded tools.
|
||||||
std::vector<os::LibHandle> loaded = os::GetLoadedLibs();
|
std::vector<os::LibHandle> loaded = os::GetLoadedToolsLib();
|
||||||
for(auto& handle : loaded) {
|
for(auto& handle : loaded) {
|
||||||
const uint32_t* order = (const uint32_t*)os::GetExportAddress(handle, "HSA_AMD_TOOL_PRIORITY");
|
const uint32_t* order = (const uint32_t*)os::GetExportAddress(handle, "HSA_AMD_TOOL_PRIORITY");
|
||||||
if(order) {
|
if(order) {
|
||||||
|
|||||||
@@ -204,19 +204,95 @@ void* GetExportAddress(LibHandle lib, std::string export_name) {
|
|||||||
|
|
||||||
void CloseLib(LibHandle lib) { dlclose(*(void**)&lib); }
|
void CloseLib(LibHandle lib) { dlclose(*(void**)&lib); }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief Look for a symbol called "HSA_AMD_TOOL_PRIORITY" across all loaded
|
||||||
|
* shared libraries, and if found, store the name of the library
|
||||||
|
*
|
||||||
|
* @param[in]: info A dl_phdr_info struct pointer, which contains information
|
||||||
|
* about library's load address, header, and name.
|
||||||
|
*
|
||||||
|
* @param[in]: size integer size of dl_phdr_info struct
|
||||||
|
*
|
||||||
|
* @param[out]: data copy of the data argument to dl_phdr_iterate call
|
||||||
|
*
|
||||||
|
* @retval:: Return 0 on Success. If callback returns a non-zero value,
|
||||||
|
* dl_iterate_phdr() will stop processing, even if there are unprocessed
|
||||||
|
* shared objects.
|
||||||
|
*/
|
||||||
|
|
||||||
static int callback(struct dl_phdr_info* info, size_t size, void* data) {
|
static int callback(struct dl_phdr_info* info, size_t size, void* data) {
|
||||||
|
std::vector<std::string>* loadedToolsLib = (std::vector<std::string>*)data;
|
||||||
|
assert(loadedToolsLib != nullptr);
|
||||||
|
/*
|
||||||
|
* Check if lib name is not empty and its not a "vdso.so" lib,
|
||||||
|
* The vDSO is a special shared object file that is built into the Linux kernel.
|
||||||
|
* It is not a regular shared library and thus does not have all the properties
|
||||||
|
* of regular shared libraries. The way the vDSO is loaded and organized in memory
|
||||||
|
* is different from regular shared libraries and it's not guaranteed that it
|
||||||
|
* will have a specific segment or section. Hence its skipped.
|
||||||
|
*/
|
||||||
|
|
||||||
if ((info) && (info->dlpi_name[0] != '\0')) {
|
if ((info) && (info->dlpi_name[0] != '\0')) {
|
||||||
std::vector<std::string>* loadedlib = (std::vector<std::string>*)data;
|
if (std::string(info->dlpi_name).find("vdso.so") != std::string::npos) return 0;
|
||||||
loadedlib->push_back(info->dlpi_name);
|
|
||||||
|
/*
|
||||||
|
* Iterate through the program headers of the loaded lib and check for PT_DYNAMIC program
|
||||||
|
* header. If the PT_DYNAMIC program header is found, use dlpi_addr and dlpi_phdr members
|
||||||
|
* of dl_phdr_info struct to get the address of the dynamic section of the loaded
|
||||||
|
* library in memory
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (int i = 0; i < info->dlpi_phnum; i++) {
|
||||||
|
if (info->dlpi_phdr[i].p_type == PT_DYNAMIC) {
|
||||||
|
Elf64_Dyn* dyn_section = (Elf64_Dyn*)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
|
||||||
|
|
||||||
|
char* strings = nullptr;
|
||||||
|
Elf64_Xword limit = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The dynamic section is searched for DT_STRTAB (address of string table),
|
||||||
|
* and DT_STRSZ (size of string table)
|
||||||
|
* DT_NULL - Marks the end of the _DYNAMIC array
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (int j = 0;; j++) {
|
||||||
|
if (dyn_section[j].d_tag == DT_NULL) break;
|
||||||
|
|
||||||
|
if (dyn_section[j].d_tag == DT_STRTAB) strings = (char*)(dyn_section[j].d_un.d_ptr);
|
||||||
|
|
||||||
|
if (dyn_section[j].d_tag == DT_STRSZ) limit = dyn_section[j].d_un.d_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strings == nullptr) debug_print("String table not found");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hacky lookup, if string and symbol tables are found,
|
||||||
|
* iterate through the strings in string table and check if
|
||||||
|
* any string matches "HSA_AMD_TOOL_PRIORITY".
|
||||||
|
* If yes, then add the name of the library to the vector of
|
||||||
|
* lib names
|
||||||
|
*/
|
||||||
|
if (strings != nullptr) {
|
||||||
|
char* end = strings + limit;
|
||||||
|
while (strings < end) {
|
||||||
|
if (strcmp(strings, "HSA_AMD_TOOL_PRIORITY") == 0) {
|
||||||
|
loadedToolsLib->push_back(info->dlpi_name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
strings += (strlen(strings) + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<LibHandle> GetLoadedLibs() {
|
std::vector<LibHandle> GetLoadedToolsLib() {
|
||||||
|
|
||||||
std::vector<LibHandle> ret;
|
std::vector<LibHandle> ret;
|
||||||
std::vector<std::string> names;
|
std::vector<std::string> names;
|
||||||
|
|
||||||
|
/* Iterate through all of the loaded shared libraries in the process */
|
||||||
dl_iterate_phdr(callback, &names);
|
dl_iterate_phdr(callback, &names);
|
||||||
|
|
||||||
if (!names.empty()) {
|
if (!names.empty()) {
|
||||||
|
|||||||
@@ -86,9 +86,10 @@ void* GetExportAddress(LibHandle lib, std::string export_name);
|
|||||||
/// @param: lib(Input), library handle which will be unloaded.
|
/// @param: lib(Input), library handle which will be unloaded.
|
||||||
void CloseLib(LibHandle lib);
|
void CloseLib(LibHandle lib);
|
||||||
|
|
||||||
/// @brief: Lists libraries in the process
|
/// @brief: Lists loaded tool libraries that contain
|
||||||
|
/// symbol HSA_AMD_TOOL_PRIORITY
|
||||||
/// @return: List of library handles
|
/// @return: List of library handles
|
||||||
std::vector<LibHandle> GetLoadedLibs();
|
std::vector<LibHandle> GetLoadedToolsLib();
|
||||||
|
|
||||||
/// @brief: Returns the library's path name.
|
/// @brief: Returns the library's path name.
|
||||||
/// @param: lib(Input), libray handle
|
/// @param: lib(Input), libray handle
|
||||||
|
|||||||
Reference in New Issue
Block a user