Blame SOURCES/rhbz1376515.patch

9201c6
From fced4ba337a4eddb4163994834a122e62c6efdfb Mon Sep 17 00:00:00 2001
9201c6
From: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
9201c6
Date: Wed, 14 Sep 2016 13:32:51 +0530
9201c6
Subject: [PATCH 1/2] ppc64le: Store correct function entry address in
9201c6
 symbol_table
9201c6
9201c6
PPC64 ELF ABI v2 has a Global Entry Point and a Local Entry Point for
9201c6
the functions. Debuginfo of ELF contains GEP which is same as entrypc
9201c6
while symbol table contains GEP and offset, from which we can calculate
9201c6
LEP. LEP is used to call function within single CU, when TOC pointer
9201c6
update is not required. Placing a probe on LEP catches call from both
9201c6
the GEP and the LEP but, by default, systemtap probes on GEP.
9201c6
9201c6
For ppc64le, Systemtap stores LEP in symbol table and prioritize symbol
9201c6
table over debuginfo. But, storing LEP in symbol table has couple of
9201c6
regression effect. As LEP is only required at a time of adding a probe,
9201c6
don't store it in symbol table.
9201c6
9201c6
No need to prioritize symbol table as well because debuginfo and symbol
9201c6
table both will contain Global Entry Point.
9201c6
9201c6
Revert commit b4c6a4b1cd00 ("Prioritize symbol table lookup for ppc64le")
9201c6
partially.
9201c6
9201c6
Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
9201c6
---
9201c6
 tapsets.cxx | 62 +------------------------------------------------------------
9201c6
 1 file changed, 1 insertion(+), 61 deletions(-)
9201c6
9201c6
diff --git a/tapsets.cxx b/tapsets.cxx
9201c6
index 4167678..a887e1f 100644
9201c6
--- a/tapsets.cxx
9201c6
+++ b/tapsets.cxx
9201c6
@@ -2134,18 +2134,6 @@ query_dwarf_inline_instance (Dwarf_Die * die, dwarf_query * q)
9201c6
     }
9201c6
 }
9201c6
 
9201c6
-static bool
9201c6
-is_filtered_func_exists (func_info_map_t const& filtered, func_info *fi)
9201c6
-{
9201c6
-  for (unsigned i = 0; i < filtered.size(); i++)
9201c6
-    {
9201c6
-      if ((filtered[i].entrypc == fi->entrypc) && (filtered[i].name == fi->name))
9201c6
-        return true;
9201c6
-    }
9201c6
-
9201c6
-  return false;
9201c6
-}
9201c6
-
9201c6
 static int
9201c6
 query_dwarf_func (Dwarf_Die * func, dwarf_query * q)
9201c6
 {
9201c6
@@ -2198,37 +2186,7 @@ query_dwarf_func (Dwarf_Die * func, dwarf_query * q)
9201c6
           q->dw.function_line (&func.decl_line);
9201c6
 
9201c6
           Dwarf_Addr entrypc;
9201c6
-
9201c6
-          func.entrypc = 0;
9201c6
-          Dwarf_Addr bias;
9201c6
-          Dwfl_Module *mod = q->dw.module;
9201c6
-          Elf* elf = (dwarf_getelf (dwfl_module_getdwarf (mod, &bias))
9201c6
-                     ?: dwfl_module_getelf (mod, &bias));
9201c6
-
9201c6
-          GElf_Ehdr ehdr_mem;
9201c6
-          GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem);
9201c6
-          if (em == NULL) throw SEMANTIC_ERROR (_("Couldn't get elf header"));
9201c6
-
9201c6
-          /* Giving priority to sym_table for ppc64*/
9201c6
-          if ((em->e_machine == EM_PPC64) && ((em->e_flags & EF_PPC64_ABI) == 2)
9201c6
-              && (q->dw.mod_info->sym_table))
9201c6
-            {
9201c6
-              /* The linkage name is the best match for the symbol table. */
9201c6
-              const string& linkage_name = dwarf_linkage_name(&func.die)
9201c6
-                ?: dwarf_diename(&func.die) ?: (string)func.name;
9201c6
-
9201c6
-              set<func_info *> fis = q->dw.mod_info->sym_table->lookup_symbol(linkage_name);
9201c6
-              for (set<func_info*>::iterator it=fis.begin(); it!=fis.end() ; ++it)
9201c6
-                {
9201c6
-                  func.entrypc = (*it)->entrypc;
9201c6
-                  if (is_filtered_func_exists(q->filtered_functions, &func))
9201c6
-                    continue;
9201c6
-                  q->filtered_functions.push_back(func);
9201c6
-                }
9201c6
-            }
9201c6
-
9201c6
-          /* If not ppc64 or not found in sym_table, try it directly. */
9201c6
-          if (!func.entrypc && q->dw.function_entrypc (&entrypc))
9201c6
+          if (q->dw.function_entrypc (&entrypc))
9201c6
             {
9201c6
               func.entrypc = entrypc;
9201c6
               q->filtered_functions.push_back (func);
9201c6
@@ -8448,13 +8406,6 @@ symbol_table::get_from_elf()
9201c6
   int syments = dwfl_module_getsymtab(mod);
9201c6
   assert(syments);
9201c6
   prepare_section_rejection(mod);
9201c6
-  Dwarf_Addr bias;
9201c6
-  Elf* elf = (dwarf_getelf (dwfl_module_getdwarf (mod, &bias))
9201c6
-              ?: dwfl_module_getelf (mod, &bias));
9201c6
-
9201c6
-  GElf_Ehdr ehdr_mem;
9201c6
-  GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem);
9201c6
-  if (em == NULL) throw SEMANTIC_ERROR (_("Couldn't get elf header"));
9201c6
 
9201c6
   for (int i = 1; i < syments; ++i)
9201c6
     {
9201c6
@@ -8487,18 +8438,7 @@ symbol_table::get_from_elf()
9201c6
         continue;
9201c6
       interned_string name = n;
9201c6
 
9201c6
-     /*
9201c6
-      * For ELF ABI v2 on PPC64 LE, we need to adjust sym.st_value corresponding
9201c6
-      * to the bits of sym.st_other. These bits will tell us what's the offset
9201c6
-      * of the local entry point from the global entry point.
9201c6
-      *
9201c6
-      * st_other field is currently only used with ABIv2 on ppc64
9201c6
-      */
9201c6
       Dwarf_Addr entrypc = addr;
9201c6
-      if ((em->e_machine == EM_PPC64) && ((em->e_flags & EF_PPC64_ABI) == 2)
9201c6
-          && (GELF_ST_TYPE(sym.st_info) == STT_FUNC) && sym.st_other)
9201c6
-        entrypc += PPC64_LOCAL_ENTRY_OFFSET(sym.st_other);
9201c6
-
9201c6
       if (GELF_ST_TYPE(sym.st_info) == STT_FUNC)
9201c6
         add_symbol(name, (GELF_ST_BIND(sym.st_info) == STB_WEAK),
9201c6
                    reject, addr, entrypc);
9201c6
-- 
9201c6
1.8.3.1
9201c6
9201c6
From 1b83a55a0272f2eb0bdcd5809fb630e1f369d400 Mon Sep 17 00:00:00 2001
9201c6
From: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
9201c6
Date: Wed, 14 Sep 2016 13:36:00 +0530
9201c6
Subject: [PATCH 2/2] ppc64le: Fix LEP usage for probing
9201c6
9201c6
PPC64 ELF ABI v2 has a Global Entry Point and a Local Entry Point for
9201c6
the functions. Debuginfo of ELF contains GEP which is same as entrypc
9201c6
while symbol table contains GEP and offset, from which we can calculate
9201c6
LEP. LEP is used to call function within single CU, when TOC pointer
9201c6
update is not required. Placing a probe on LEP catches call from both
9201c6
the GEP and the LEP but, by default, systemtap probes on GEP.
9201c6
9201c6
Commit b4c6a4b1cd00 ("Prioritize symbol table lookup for ppc64le") solve
9201c6
this issue by storing LEP in symbol table and prioritizing symbol table
9201c6
over debuginfo for ppc64le.
9201c6
9201c6
But there are few regression effect of this patch. Couple of examples
9201c6
are given below.
9201c6
9201c6
1. If target program is compiled without optimization and user is
9201c6
interested in function parameter, systemtap should probe after function
9201c6
prologue. But above patch forces probe on LEP and which result in garbage
9201c6
value of function parameter will get recorded.
9201c6
9201c6
  $ make verbose=1 installcheck RUNTESTFLAGS='at_var.exp -v --debug'
9201c6
    ...
9201c6
    # of expected passes        1
9201c6
    # of unexpected failures    1
9201c6
9201c6
2. Probe on shared library function with parameter is failing at Pass 2.
9201c6
9201c6
  $ make verbose=1 installcheck RUNTESTFLAGS='exelib.exp -v --debug'
9201c6
    ...
9201c6
    # of expected passes        10
9201c6
    # of unexpected failures    64
9201c6
9201c6
3. When symbol_name with offset is used to register kprobe, kernel itself
9201c6
will find LEP and adds offset to it. Systemtap using LEP to find offset
9201c6
is resulting in offset being added two times.
9201c6
  GEP + lep_offset (by systemtap) + lep_offset (by kernel)
9201c6
9201c6
This can be solved by calculating LEP only at a time of adding a probe.
9201c6
That will make effect of LEP local to that area and won't have any
9201c6
regression effect.
9201c6
9201c6
After applying patch:
9201c6
9201c6
  $ make verbose=1 installcheck RUNTESTFLAGS='at_var.exp -v --debug'
9201c6
    ...
9201c6
    # of expected passes        2
9201c6
9201c6
  $ make verbose=1 installcheck RUNTESTFLAGS='exelib.exp -v --debug'
9201c6
    ...
9201c6
    # of expected passes        74
9201c6
9201c6
Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
9201c6
---
9201c6
 tapsets.cxx | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
9201c6
 1 file changed, 59 insertions(+), 1 deletion(-)
9201c6
9201c6
diff --git a/tapsets.cxx b/tapsets.cxx
9201c6
index a887e1f..30aebb9 100644
9201c6
--- a/tapsets.cxx
9201c6
+++ b/tapsets.cxx
9201c6
@@ -1376,6 +1376,59 @@ string path_remove_sysroot(const systemtap_session& sess, const string& path)
9201c6
   return retval;
9201c6
 }
9201c6
 
9201c6
+/*
9201c6
+ * Convert 'Global Entry Point' to 'Local Entry Point'.
9201c6
+ *
9201c6
+ * if @gep contains next address after prologue, don't change it.
9201c6
+ *
9201c6
+ * For ELF ABI v2 on PPC64 LE, we need to adjust sym.st_value corresponding
9201c6
+ * to the bits of sym.st_other. These bits will tell us what's the offset
9201c6
+ * of the local entry point from the global entry point.
9201c6
+ *
9201c6
+ * st_other field is currently only used with ABIv2 on ppc64
9201c6
+ */
9201c6
+static Dwarf_Addr
9201c6
+get_lep(dwarf_query *q, Dwarf_Addr gep)
9201c6
+{
9201c6
+  Dwarf_Addr bias;
9201c6
+  Dwfl_Module *mod = q->dw.module;
9201c6
+  Elf* elf = (dwarf_getelf (dwfl_module_getdwarf (mod, &bias))
9201c6
+             ?: dwfl_module_getelf (mod, &bias));
9201c6
+
9201c6
+  GElf_Ehdr ehdr_mem;
9201c6
+  GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem);
9201c6
+  if (em == NULL)
9201c6
+    throw SEMANTIC_ERROR (_("Couldn't get elf header"));
9201c6
+
9201c6
+  if (!(em->e_machine == EM_PPC64) || !((em->e_flags & EF_PPC64_ABI) == 2))
9201c6
+    return gep;
9201c6
+
9201c6
+  int syments = dwfl_module_getsymtab(mod);
9201c6
+  for (int i = 1; i < syments; ++i)
9201c6
+    {
9201c6
+      GElf_Sym sym;
9201c6
+      GElf_Word section;
9201c6
+      GElf_Addr addr;
9201c6
+
9201c6
+#if _ELFUTILS_PREREQ (0, 158)
9201c6
+      dwfl_module_getsym_info (mod, i, &sym, &addr, &section, NULL, NULL);
9201c6
+#else
9201c6
+      dwfl_module_getsym (mod, i, &sym, &section);
9201c6
+      addr = sym.st_value;
9201c6
+#endif
9201c6
+
9201c6
+      /*
9201c6
+       * Symbol table contains module_bias + offset. Substract module_bias
9201c6
+       * to compare offset with gep.
9201c6
+       */
9201c6
+      if ((addr - bias) == gep && (GELF_ST_TYPE(sym.st_info) == STT_FUNC)
9201c6
+          && sym.st_other)
9201c6
+        return gep + PPC64_LOCAL_ENTRY_OFFSET(sym.st_other);
9201c6
+    }
9201c6
+
9201c6
+  return gep;
9201c6
+}
9201c6
+
9201c6
 void
9201c6
 dwarf_query::add_probe_point(interned_string dw_funcname,
9201c6
 			     interned_string filename,
9201c6
@@ -1384,12 +1437,14 @@ dwarf_query::add_probe_point(interned_string dw_funcname,
9201c6
 			     Dwarf_Addr addr)
9201c6
 {
9201c6
   interned_string reloc_section; // base section for relocation purposes
9201c6
+  Dwarf_Addr orig_addr = addr;
9201c6
   Dwarf_Addr reloc_addr; // relocated
9201c6
   interned_string module = dw.module_name; // "kernel" or other
9201c6
   interned_string funcname = dw_funcname;
9201c6
 
9201c6
   assert (! has_absolute); // already handled in dwarf_builder::build()
9201c6
 
9201c6
+  addr = get_lep(this, addr);
9201c6
   reloc_addr = dw.relocate_address(addr, reloc_section);
9201c6
 
9201c6
   // If we originally used the linkage name, then let's call it that way
9201c6
@@ -1455,7 +1510,10 @@ dwarf_query::add_probe_point(interned_string dw_funcname,
9201c6
 
9201c6
 	      symbol_table *sym_table = mi->sym_table;
9201c6
 	      func_info *symbol = sym_table->get_func_containing_address(addr);
9201c6
-	      Dwarf_Addr offset = addr - symbol->addr;
9201c6
+
9201c6
+	      // Do not use LEP to find offset here. When 'symbol_name'
9201c6
+	      // is used to register probe, kernel itself will find LEP.
9201c6
+	      Dwarf_Addr offset = orig_addr - symbol->addr;
9201c6
 	      results.push_back (new dwarf_derived_probe(funcname, filename,
9201c6
 							 line, module,
9201c6
 							 reloc_section, addr,
9201c6
-- 
9201c6
1.8.3.1
9201c6