From bdf5540dc510bb7cfaca1b9045533cd558954681 Mon Sep 17 00:00:00 2001 From: Andrew Jeffery Date: Thu, 10 May 2018 16:07:18 +0930 Subject: meta-python: Make python-pyflame cope with prelinked ELFs Signed-off-by: Andrew Jeffery Signed-off-by: Khem Raj --- ...mbol-Account-for-prelinked-shared-objects.patch | 134 +++++++++++++++++++++ .../python/python-pyflame_1.6.6.bb | 1 + 2 files changed, 135 insertions(+) create mode 100644 meta-python/recipes-devtools/python/python-pyflame-1.6.6/0001-symbol-Account-for-prelinked-shared-objects.patch (limited to 'meta-python') diff --git a/meta-python/recipes-devtools/python/python-pyflame-1.6.6/0001-symbol-Account-for-prelinked-shared-objects.patch b/meta-python/recipes-devtools/python/python-pyflame-1.6.6/0001-symbol-Account-for-prelinked-shared-objects.patch new file mode 100644 index 0000000000..3eefc9cb98 --- /dev/null +++ b/meta-python/recipes-devtools/python/python-pyflame-1.6.6/0001-symbol-Account-for-prelinked-shared-objects.patch @@ -0,0 +1,134 @@ +From 007965d341349679607699d005c4af811b2c419a Mon Sep 17 00:00:00 2001 +From: Andrew Jeffery +Date: Fri, 4 May 2018 11:23:53 +0930 +Subject: [PATCH] symbol: Account for prelinked shared objects + +Some projects, such as those derived from Yocto, tend to prelink their +binaries and libraries to reduce runtime overhead. Currently this trips +up pyflame in its symbol address calculations, and leads to ptrace +failures due to spurious addresses: + + $ pyflame -t python -c "print 'foo'" + Unexpected ptrace(2) exception: Failed to PTRACE_PEEKDATA (pid 1482, addr 0x9f9b1d70): Input/output error + Unexpected ptrace(2) exception: Failed to PTRACE_PEEKDATA (pid 1482, addr 0x9f9b1d70): Input/output error + Unexpected ptrace(2) exception: Failed to PTRACE_PEEKDATA (pid 1482, addr 0x9f9b1d70): Input/output error + Unexpected ptrace(2) exception: Failed to PTRACE_PEEKDATA (pid 1482, addr 0x9f9b1d70): Input/output error + Unexpected ptrace(2) exception: Failed to PTRACE_PEEKDATA (pid 1482, addr 0x9f9b1d70): Input/output error + ... + +Add support for reading a prelinked base p_vaddr out of the ELF and +adjust the PyAddresses values accordingly. + +Signed-off-by: Andrew Jeffery +--- + src/symbol.cc | 15 +++++++++++++++ + src/symbol.h | 29 ++++++++++++++++++++++++++++- + 2 files changed, 43 insertions(+), 1 deletion(-) + +diff --git a/src/symbol.cc b/src/symbol.cc +index 125174efeeb5..39c3e8132dd1 100644 +--- a/src/symbol.cc ++++ b/src/symbol.cc +@@ -166,6 +166,17 @@ PyABI ELF::WalkTable(int sym, int str, PyAddresses *addrs) { + return abi; + } + ++addr_t ELF::GetBaseAddress() { ++ int32_t phnum = hdr()->e_phnum; ++ int32_t i; ++ for (i = 0; i < phnum && phdr(i)->p_type != PT_LOAD; i++) { ++ } ++ if (i == phnum) { ++ throw FatalException("Failed to find PT_LOAD entry in program headers"); ++ } ++ return phdr(i)->p_vaddr; ++} ++ + PyAddresses ELF::GetAddresses(PyABI *abi) { + PyAddresses addrs; + PyABI detected_abi = WalkTable(dynsym_, dynstr_, &addrs); +@@ -176,6 +187,10 @@ PyAddresses ELF::GetAddresses(PyABI *abi) { + if (abi != nullptr) { + *abi = detected_abi; + } ++ // Handle prelinked shared objects ++ if (hdr()->e_type == ET_DYN) { ++ return addrs - GetBaseAddress(); ++ } + return addrs; + } + } // namespace pyflame +diff --git a/src/symbol.h b/src/symbol.h +index 124853bcc1c1..bb92b9a2604b 100644 +--- a/src/symbol.h ++++ b/src/symbol.h +@@ -28,15 +28,19 @@ + + #if USE_ELF64 + #define ehdr_t Elf64_Ehdr ++#define phdr_t Elf64_Phdr + #define shdr_t Elf64_Shdr + #define dyn_t Elf64_Dyn + #define sym_t Elf64_Sym ++#define addr_t Elf64_Addr + #define ARCH_ELFCLASS ELFCLASS64 + #else + #define ehdr_t Elf32_Ehdr ++#define phdr_t Elf32_Phdr + #define shdr_t Elf32_Shdr + #define dyn_t Elf32_Dyn + #define sym_t Elf32_Sym ++#define addr_t Elf32_Addr + #define ARCH_ELFCLASS ELFCLASS32 + #endif + +@@ -67,8 +71,18 @@ struct PyAddresses { + interp_head_hint(0), + pie(false) {} + ++ PyAddresses operator-(const unsigned long base) const { ++ PyAddresses res(*this); ++ res.tstate_addr = this->tstate_addr == 0 ? 0 : this->tstate_addr - base; ++ res.interp_head_addr = ++ this->interp_head_addr == 0 ? 0 : this->interp_head_addr - base; ++ res.interp_head_fn_addr = ++ this->interp_head_fn_addr == 0 ? 0 : this->interp_head_fn_addr - base; ++ return res; ++ } ++ + PyAddresses operator+(const unsigned long base) const { +- PyAddresses res; ++ PyAddresses res(*this); + res.tstate_addr = this->tstate_addr == 0 ? 0 : this->tstate_addr + base; + res.interp_head_addr = + this->interp_head_addr == 0 ? 0 : this->interp_head_addr + base; +@@ -113,6 +127,9 @@ class ELF { + // ABI. + PyAddresses GetAddresses(PyABI *abi); + ++ // Extract the base load address from the Program Header table ++ addr_t GetBaseAddress(); ++ + private: + void *addr_; + size_t length_; +@@ -122,6 +139,16 @@ class ELF { + return reinterpret_cast(addr_); + } + ++ inline const phdr_t *phdr(int idx) const { ++ if (idx < 0) { ++ std::ostringstream ss; ++ ss << "Illegal phdr index: " << idx; ++ throw FatalException(ss.str()); ++ } ++ return reinterpret_cast(p() + hdr()->e_phoff + ++ idx * hdr()->e_phentsize); ++ } ++ + inline const shdr_t *shdr(int idx) const { + if (idx < 0) { + std::ostringstream ss; +-- +2.14.1 + diff --git a/meta-python/recipes-devtools/python/python-pyflame_1.6.6.bb b/meta-python/recipes-devtools/python/python-pyflame_1.6.6.bb index 7a6d3b0996..abf3ed7fee 100644 --- a/meta-python/recipes-devtools/python/python-pyflame_1.6.6.bb +++ b/meta-python/recipes-devtools/python/python-pyflame_1.6.6.bb @@ -1,3 +1,4 @@ require python-pyflame.inc SRC_URI += "file://0001-ptrace-Abstract-over-user_regs_struct-name-which-dif.patch" +SRC_URI += "file://0001-symbol-Account-for-prelinked-shared-objects.patch" -- cgit 1.2.3-korg