From 5f783494f17c023079b80c9f35f9da258830888d Mon Sep 17 00:00:00 2001 From: Laurent Morichetti Date: Tue, 28 Jan 2020 09:53:11 -0800 Subject: [PATCH] Return a file URI for elf images in shared objects Iterate the loaded shared objects to see if the given elf image binary is part of a loaded segment. Change-Id: I074cacd99eb5b59f883f4ce2bd901e0e35a660b8 --- runtime/hsa-runtime/loader/executable.cpp | 70 +++++++++++++++++++++-- 1 file changed, 65 insertions(+), 5 deletions(-) diff --git a/runtime/hsa-runtime/loader/executable.cpp b/runtime/hsa-runtime/loader/executable.cpp index 6299983af8..cdfa20774e 100644 --- a/runtime/hsa-runtime/loader/executable.cpp +++ b/runtime/hsa-runtime/loader/executable.cpp @@ -42,14 +42,18 @@ #include "executable.hpp" +#include +#include +#include +#include + #include #include #include +#include #include #include #include -#include -#include #include "inc/amd_hsa_elf.h" #include "inc/amd_hsa_kernel_code.h" #include "core/inc/amd_hsa_code.hpp" @@ -1859,9 +1863,65 @@ hsa_status_t ExecutableImpl::Freeze(const char *options) { std::stringstream ss; uint64_t elf_begin = lco->getElfData(); uint64_t elf_size = lco->getElfSize(); - ss << "file:///proc/" << getpid() << "/mem#" - << "offset=" << std::hex << std::showbase << elf_begin << "&" - << "size=" << elf_size; + + struct args { + ElfW(Addr) mem_addr; + size_t callback_num; + const char *file_name; + size_t file_offset; + } data{ elf_begin, 0 }; + + // Iterate the loaded shared objects program headers to see if the elf binary + // is allocated in a mapped file. + if (dl_iterate_phdr([](struct dl_phdr_info *info, size_t size, void *ptr) -> int { + struct args *data = (struct args *) ptr; + const ElfW(Addr) reladdr = data->mem_addr - info->dlpi_addr; + + int n = info->dlpi_phnum; + while (--n >= 0) { + if (info->dlpi_phdr[n].p_type == PT_LOAD + && reladdr - info->dlpi_phdr[n].p_vaddr >= 0 + && reladdr - info->dlpi_phdr[n].p_vaddr < info->dlpi_phdr[n].p_memsz) { + // The first callback is always the program executable. + if (!info->dlpi_name[0] && data->callback_num == 0) { + static char argv0[PATH_MAX] = {0}; + if (!argv0[0] && readlink("/proc/self/exe", argv0, sizeof(argv0)) == -1) + return 0; + data->file_name = argv0; + } else { + data->file_name = info->dlpi_name; + } + + data->file_offset = reladdr - info->dlpi_phdr[n].p_vaddr + info->dlpi_phdr[n].p_offset; + return 1; + } + } + + ++data->callback_num; + return 0; + }, &data)) { + unsigned char c; + + ss.fill('0'); + ss << "file://"; + + while ((c = *data.file_name++) != '\0') { + // %-encode the file name + if (isalnum(c) || c == '/' || c == '-' || c == '_' || c == '.' || c == '~') { + ss << c; + } else { + ss << std::uppercase; + ss << '%' << std::hex << std::setw(2) << static_cast(c); + ss << std::nouppercase; + } + } + ss << "#offset=" << std::dec << data.file_offset + << "&size=" << std::dec << elf_size; + } else { + ss << "file:///proc/" << getpid() << "/mem#" + << "offset=" << std::hex << std::showbase << elf_begin << "&" + << "size=" << std::dec << elf_size; + } lco->r_debug_info.l_addr = lco->getDelta(); lco->r_debug_info.l_name = strdup(ss.str().c_str()); lco->r_debug_info.l_prev = nullptr;