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
Αυτή η υποβολή περιλαμβάνεται σε:
@@ -1542,7 +1542,7 @@ void Runtime::LoadTools() {
|
||||
}
|
||||
|
||||
// Discover loaded tools.
|
||||
std::vector<os::LibHandle> loaded = os::GetLoadedLibs();
|
||||
std::vector<os::LibHandle> loaded = os::GetLoadedToolsLib();
|
||||
for(auto& handle : loaded) {
|
||||
const uint32_t* order = (const uint32_t*)os::GetExportAddress(handle, "HSA_AMD_TOOL_PRIORITY");
|
||||
if(order) {
|
||||
|
||||
@@ -204,19 +204,95 @@ void* GetExportAddress(LibHandle lib, std::string export_name) {
|
||||
|
||||
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) {
|
||||
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')) {
|
||||
std::vector<std::string>* loadedlib = (std::vector<std::string>*)data;
|
||||
loadedlib->push_back(info->dlpi_name);
|
||||
if (std::string(info->dlpi_name).find("vdso.so") != std::string::npos) return 0;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
std::vector<LibHandle> GetLoadedLibs() {
|
||||
|
||||
std::vector<LibHandle> GetLoadedToolsLib() {
|
||||
std::vector<LibHandle> ret;
|
||||
std::vector<std::string> names;
|
||||
|
||||
/* Iterate through all of the loaded shared libraries in the process */
|
||||
dl_iterate_phdr(callback, &names);
|
||||
|
||||
if (!names.empty()) {
|
||||
|
||||
@@ -86,9 +86,10 @@ void* GetExportAddress(LibHandle lib, std::string export_name);
|
||||
/// @param: lib(Input), library handle which will be unloaded.
|
||||
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
|
||||
std::vector<LibHandle> GetLoadedLibs();
|
||||
std::vector<LibHandle> GetLoadedToolsLib();
|
||||
|
||||
/// @brief: Returns the library's path name.
|
||||
/// @param: lib(Input), libray handle
|
||||
|
||||
Αναφορά σε νέο ζήτημα
Block a user