This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 2/3] ppc64le: Use LEP for probe location


PPC64 ELF ABI v2 has a Global Entry Point and a Local Entry Point for
the functions. Debuginfo of ELF contains GEP which is same as entrypc.
While symbol table contains GEP and offset, from which we can calculate
LEP. LEP is used to call function within single CU, when TOC pointer
update is not required. So it's guaranteed that LEP will hit wherever
function is called but GEP may not.

Before Applying patch:

  $ vim uprobe_test.c
    #include <stdio.h>

    void doit(int i)
    {
        printf("i : %d\n", i);
    }

    int main(int argc, char *argv[])
    {
        doit(42);
        return 0;
    }

  $ gcc uprobe_test.c -g -o uprobe_test

  $ sudo ./stap -e 'probe process("uprobe_test").function("doit") \
        {printf("hit %d\n", $i)}' -c ./uprobe_test
    i : 42
    hit 0

After Applying patch:

  $ sudo ./stap -e 'probe process("uprobe_test").function("doit") \
        {printf("hit %d\n", $i)}' -c ./uprobe_test
    i : 42
    hit 42

Fixes: Commit b4c6a4b1cd00 ("Prioritize symbol table lookup for ppc64le")
Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
---
 tapsets.cxx | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/tapsets.cxx b/tapsets.cxx
index e7be711..1b3a1ea 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -1391,6 +1391,55 @@ string path_remove_sysroot(const systemtap_session& sess, const string& path)
   return retval;
 }
 
+/*
+ * Convert 'Global Entry Point' to 'Local Entry Point'.
+ *
+ * if @gep contains next address after prologue, don't change it.
+ *
+ * For ELF ABI v2 on PPC64 LE, we need to adjust sym.st_value corresponding
+ * to the bits of sym.st_other. These bits will tell us what's the offset
+ * of the local entry point from the global entry point.
+ *
+ * st_other field is currently only used with ABIv2 on ppc64
+ */
+static Dwarf_Addr
+get_lep(dwarf_query *q, Dwarf_Addr gep)
+{
+  Dwarf_Addr bias;
+  Dwfl_Module *mod = q->dw.module;
+  Elf* elf = (dwarf_getelf (dwfl_module_getdwarf (mod, &bias))
+             ?: dwfl_module_getelf (mod, &bias));
+
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem);
+  if (em == NULL)
+    throw SEMANTIC_ERROR (_("Couldn't get elf header"));
+
+  if (!(em->e_machine == EM_PPC64) || !((em->e_flags & EF_PPC64_ABI) == 2))
+    return gep;
+
+  int syments = dwfl_module_getsymtab(mod);
+  for (int i = 1; i < syments; ++i)
+    {
+      GElf_Sym sym;
+      GElf_Word section;
+      GElf_Addr addr;
+
+#if _ELFUTILS_PREREQ (0, 158)
+      dwfl_module_getsym_info (mod, i, &sym, &addr, &section, NULL, NULL);
+#else
+      dwfl_module_getsym (mod, i, &sym, &section);
+      addr = sym.st_value;
+#endif
+
+      if (addr == gep && (GELF_ST_TYPE(sym.st_info) == STT_FUNC)
+          && sym.st_other)
+        return gep + PPC64_LOCAL_ENTRY_OFFSET(sym.st_other);
+    }
+
+  return gep;
+}
+
 void
 dwarf_query::add_probe_point(interned_string dw_funcname,
 			     interned_string filename,
@@ -1405,6 +1454,7 @@ dwarf_query::add_probe_point(interned_string dw_funcname,
 
   assert (! has_absolute); // already handled in dwarf_builder::build()
 
+  addr = get_lep(this, addr);
   reloc_addr = dw.relocate_address(addr, reloc_section);
 
   // If we originally used the linkage name, then let's call it that way
-- 
2.1.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]