]> sourceware.org Git - systemtap.git/commitdiff
Put generated debug_hdr in _stp_section, add sec_load_offset for adjustment.
authorMark Wielaard <mjw@redhat.com>
Mon, 5 Jul 2010 19:14:42 +0000 (21:14 +0200)
committerMark Wielaard <mjw@redhat.com>
Mon, 5 Jul 2010 19:25:01 +0000 (21:25 +0200)
Make sure to adjust .debug_frame addresses to section load address.
Which means keeping track of the (synthetic) .debug_frame_hdr index
per section. For now keep track of "magic sections". Will need to
be extended to track all loadable code sections as we do for symbol
tables. See http://sourceware.org/ml/systemtap/2010-q3/msg00012.html

* runtime/sym.h (_stp_module): Remove dwarf_module_base. Move debug_hdr
  and debug_hdr_len from here to ...
  (_stp_section): ... here. And add sec_load_offset.
* runtime/unwind.c (adjustStartLoc): Don't use m->dwarf_module_base,
  use s->sec_load_offset.
  (_stp_search_unwind_hdr): Use s->debug_hdr and s->debug_hdr_len.
* translate.cxx (create_debug_frame_hdr): Accept and set debug_frame_off.
  (get_unwind_data): Likewise.
  (dump_unwindsyms): Keep track of debug_frame_off. Output debug_frame_hdr
  per _stp_section if section is ".dynamic", ".absolute", ".text", or
  "_stext".

runtime/sym.h
runtime/unwind.c
translate.cxx

index bf69dab91e8b1edb176dc1b67d30064fbc463950..55d02d5c6a1536fc58fc49bff0019dba420fb840 100644 (file)
@@ -61,8 +61,13 @@ struct _stp_section {
        unsigned long size; /* length of the address space module covers. */
        struct _stp_symbol *symbols;  /* ordered by address */
        unsigned num_symbols;
-};
 
+       /* Synthesized index for .debug_frame table, keep section
+          offset to adjust addresses relative to load address. */
+       void *debug_hdr;
+       uint32_t debug_hdr_len;
+       unsigned long sec_load_offset;
+};
 
 struct _stp_module {
         const char* name;
@@ -70,26 +75,17 @@ struct _stp_module {
        struct _stp_section *sections;
        unsigned num_sections;
 
-       /* This is the base address for the dwfl module (adjusted for
-        * dwbias) as we read it in the translator. This is normally
-        * zero for shared libraries, but not for prelinked libraries.
-        * We adjust the addresses read from the .debug_frame unwind
-        * data against the actual and (prelinked) load addresses.
-        * into the module. See adjustStartLoc() in unwind.c.
-        */
-       unsigned long dwarf_module_base;
-
-       /* the stack unwind data for this module */
+       /* The .eh_frame unwind data for this module.
+          Note index for .debug_frame (hdr) is per section. */
        void *debug_frame;
-       void *debug_hdr;
        void *eh_frame;
        void *unwind_hdr;       
        uint32_t debug_frame_len;
-       uint32_t debug_hdr_len;
        uint32_t eh_frame_len;
        uint32_t unwind_hdr_len;
        unsigned long eh_frame_addr; /* Orig load address (offset) .eh_frame */
        unsigned long unwind_hdr_addr; /* same for .eh_frame_hdr */
+
        /* build-id information */
        unsigned char *build_id_bits;
        unsigned long  build_id_offset;
index 4aeac3c95fc5f25e0b4ab62ec294e932da0d49dd..18e7f1066cafce7965c173df296854ec09865595 100644 (file)
@@ -547,7 +547,7 @@ adjustStartLoc (unsigned long startLoc, struct task_struct *tsk,
   if (is_ehframe)
     return startLoc + vm_addr;
   else
-    return startLoc + vm_addr - m->dwarf_module_base;
+    return startLoc + vm_addr - s->sec_load_offset;
 }
 
 /* If we previously created an unwind header, then use it now to binary search */
@@ -557,7 +557,7 @@ static u32 *_stp_search_unwind_hdr(unsigned long pc, struct task_struct *tsk,
                                   struct _stp_section *s,
                                   int is_ehframe)
 {
-       const u8 *ptr, *end, *hdr = is_ehframe ? m->unwind_hdr: m->debug_hdr;
+       const u8 *ptr, *end, *hdr = is_ehframe ? m->unwind_hdr: s->debug_hdr;
        unsigned long startLoc;
        u32 *fde = NULL;
        unsigned num, tableSize, t2;
@@ -587,7 +587,7 @@ static u32 *_stp_search_unwind_hdr(unsigned long pc, struct task_struct *tsk,
                return NULL;
        }
        ptr = hdr + 4;
-       end = hdr + (is_ehframe ? m->unwind_hdr_len : m->debug_hdr_len);
+       end = hdr + (is_ehframe ? m->unwind_hdr_len : s->debug_hdr_len);
        {
                // XXX Can the header validity be checked just once?
                unsigned long eh = read_ptr_sect(&ptr, end, hdr[1], 0,
index f2049e286c672d64e082eea9a5a6e3dbd2a51d81..5fdc37c65d6c10ba901ba1c6740557f3605923fb 100644 (file)
@@ -4663,8 +4663,9 @@ static void create_debug_frame_hdr (const unsigned char e_ident[],
                                    Elf_Data *debug_frame,
                                    void **debug_frame_hdr,
                                    size_t *debug_frame_hdr_len,
+                                   Dwarf_Addr *debug_frame_off,
                                    systemtap_session& session,
-                                   const string& modname)
+                                   Dwfl_Module *mod)
 {
   *debug_frame_hdr = NULL;
   *debug_frame_hdr_len = 0;
@@ -4707,13 +4708,29 @@ static void create_debug_frame_hdr (const unsigned char e_ident[],
        {
          // Warn, but continue, backtracing will be slow...
           if (session.verbose > 2 && ! session.suppress_warnings)
-           session.print_warning ("Problem creating debug frame hdr for "
-                                  + modname + ", " + dwarf_errmsg (-1));
+           {
+             const char *modname = dwfl_module_info (mod, NULL,
+                                                     NULL, NULL, NULL,
+                                                     NULL, NULL, NULL);
+             session.print_warning("Problem creating debug frame hdr for "
+                                   + lex_cast_qstring(modname)
+                                   + ", " + dwarf_errmsg (-1));
+           }
          return;
        }
       off = next_off;
     }
 
+  if (fdes.size() > 0)
+    {
+      it = fdes.begin();
+      Dwarf_Addr first_addr = (*it).first;
+      int res = dwfl_module_relocate_address (mod, &first_addr);
+      dwfl_assert ("create_debug_frame_hdr, dwfl_module_relocate_address",
+                  res >= 0);
+      *debug_frame_off = (*it).first - first_addr;
+    }
+
   size_t total_size = 4 + (2 * size) + (2 * size * fdes.size());
   uint8_t *hdr = (uint8_t *) malloc(total_size);
   *debug_frame_hdr = hdr;
@@ -4759,9 +4776,10 @@ static void get_unwind_data (Dwfl_Module *m,
                             void **eh_frame_hdr, size_t *eh_frame_hdr_len,
                             void **debug_frame_hdr,
                             size_t *debug_frame_hdr_len,
+                            Dwarf_Addr *debug_frame_off,
                             Dwarf_Addr *eh_frame_hdr_addr,
                             systemtap_session& session,
-                            const string& modname)
+                            Dwfl_Module *mod)
 {
   Dwarf_Addr start, bias = 0;
   GElf_Ehdr *ehdr, ehdr_mem;
@@ -4829,7 +4847,7 @@ static void get_unwind_data (Dwfl_Module *m,
   if (*debug_frame != NULL && *debug_len > 0)
     create_debug_frame_hdr (ehdr->e_ident, data,
                            debug_frame_hdr, debug_frame_hdr_len,
-                           session, modname);
+                           debug_frame_off, session, mod);
 }
 
 static int
@@ -5069,6 +5087,7 @@ dump_unwindsyms (Dwfl_Module *m,
   size_t debug_len = 0;
   void *debug_frame_hdr = NULL;
   size_t debug_frame_hdr_len = 0;
+  Dwarf_Addr debug_frame_off = 0;
   void *eh_frame = NULL;
   void *eh_frame_hdr = NULL;
   size_t eh_len = 0;
@@ -5077,8 +5096,8 @@ dump_unwindsyms (Dwfl_Module *m,
   Dwarf_Addr eh_frame_hdr_addr = 0;
   get_unwind_data (m, &debug_frame, &eh_frame, &debug_len, &eh_len, &eh_addr,
                    &eh_frame_hdr, &eh_frame_hdr_len, &debug_frame_hdr,
-                   &debug_frame_hdr_len, &eh_frame_hdr_addr,
-                  c->session, modname);
+                   &debug_frame_hdr_len, &debug_frame_off, &eh_frame_hdr_addr,
+                   c->session, m);
   if (debug_frame != NULL && debug_len > 0)
     {
       c->output << "#if defined(STP_USE_DWARF_UNWINDER) && defined(STP_NEED_UNWIND_DATA)\n";
@@ -5103,30 +5122,6 @@ dump_unwindsyms (Dwfl_Module *m,
       c->output << "#endif /* STP_USE_DWARF_UNWINDER && STP_NEED_UNWIND_DATA */\n";
     }
 
-  if (debug_frame_hdr != NULL && debug_frame_hdr_len > 0)
-    {
-      c->output << "#if defined(STP_USE_DWARF_UNWINDER) && defined(STP_NEED_UNWIND_DATA)\n";
-      c->output << "static uint8_t _stp_module_" << stpmod_idx
-               << "_debug_frame_hdr[] = \n";
-      c->output << "  {";
-      if (debug_frame_hdr_len > MAX_UNWIND_TABLE_SIZE)
-        {
-          if (! c->session.suppress_warnings)
-            c->session.print_warning ("skipping module " + modname + " debug_frame_hdr table (too big: " +
-                                      lex_cast(debug_frame_hdr_len) + " > " + lex_cast(MAX_UNWIND_TABLE_SIZE) + ")");
-        }
-      else
-        for (size_t i = 0; i < debug_frame_hdr_len; i++)
-          {
-            int h = ((uint8_t *)debug_frame_hdr)[i];
-            c->output << "0x" << hex << h << dec << ",";
-            if ((i + 1) % 16 == 0)
-              c->output << "\n" << "   ";
-          }
-      c->output << "};\n";
-      c->output << "#endif /* STP_USE_DWARF_UNWINDER && STP_NEED_UNWIND_DATA */\n";
-    }
-
   if (eh_frame != NULL && eh_len > 0)
     {
       c->output << "#if defined(STP_USE_DWARF_UNWINDER) && defined(STP_NEED_UNWIND_DATA)\n";
@@ -5207,6 +5202,45 @@ dump_unwindsyms (Dwfl_Module *m,
       c->output << "#endif /* STP_NEED_SYMBOL_DATA */\n";
 
       c->output << "};\n";
+
+      /* For now output debug_frame index only in "magic" sections. */
+      string secname = seclist[secidx].first;
+      if (secname == ".dynamic" || secname == ".absolute"
+         || secname == ".text" || secname == "_stext")
+       {
+         if (debug_frame_hdr != NULL && debug_frame_hdr_len > 0)
+           {
+             c->output << "#if defined(STP_USE_DWARF_UNWINDER)"
+                       << " && defined(STP_NEED_UNWIND_DATA)\n";
+             c->output << "static uint8_t _stp_module_" << stpmod_idx
+                       << "_debug_frame_hdr_" << secidx << "[] = \n";
+             c->output << "  {";
+             if (debug_frame_hdr_len > MAX_UNWIND_TABLE_SIZE)
+               {
+                 if (! c->session.suppress_warnings)
+                   c->session.print_warning ("skipping module "
+                                             + modname
+                                             + ", section" + secname
+                                             + " debug_frame_hdr table"
+                                             + " (too big: "
+                                             + lex_cast(debug_frame_hdr_len)
+                                             + " > "
+                                             + lex_cast(MAX_UNWIND_TABLE_SIZE)
+                                             + ")");
+               }
+             else
+               for (size_t i = 0; i < debug_frame_hdr_len; i++)
+                 {
+                   int h = ((uint8_t *)debug_frame_hdr)[i];
+                   c->output << "0x" << hex << h << dec << ",";
+                   if ((i + 1) % 16 == 0)
+                     c->output << "\n" << "   ";
+                 }
+             c->output << "};\n";
+             c->output << "#endif /* STP_USE_DWARF_UNWINDER"
+                       << " && STP_NEED_UNWIND_DATA */\n";
+           }
+       }
     }
 
   c->output << "static struct _stp_section _stp_module_" << stpmod_idx<< "_sections[] = {\n";
@@ -5220,8 +5254,42 @@ dump_unwindsyms (Dwfl_Module *m,
                 << ".name = " << lex_cast_qstring(seclist[secidx].first) << ",\n"
                 << ".size = 0x" << hex << seclist[secidx].second << dec << ",\n"
                 << ".symbols = _stp_module_" << stpmod_idx << "_symbols_" << secidx << ",\n"
-                << ".num_symbols = " << addrmap[secidx].size() << "\n"
-                << "},\n";
+                << ".num_symbols = " << addrmap[secidx].size() << ",\n";
+
+      /* For now output debug_frame index only in "magic" sections. */
+      string secname = seclist[secidx].first;
+      if (debug_frame_hdr && (secname == ".dynamic" || secname == ".absolute"
+                             || secname == ".text" || secname == "_stext"))
+       {
+         c->output << "#if defined(STP_USE_DWARF_UNWINDER)"
+                   << " && defined(STP_NEED_UNWIND_DATA)\n";
+
+          c->output << ".debug_hdr = "
+                   << "_stp_module_" << stpmod_idx
+                   << "_debug_frame_hdr_" << secidx << ",\n";
+          c->output << ".debug_hdr_len = " << debug_frame_hdr_len << ", \n";
+
+         Dwarf_Addr dwbias = 0;
+         dwfl_module_getdwarf (m, &dwbias);
+         c->output << ".sec_load_offset = 0x"
+                   << hex << debug_frame_off - dwbias << dec << "\n";
+
+         c->output << "#else\n";
+         c->output << ".debug_hdr = NULL,\n";
+         c->output << ".debug_hdr_len = 0,\n";
+         c->output << ".sec_load_offset = 0\n";
+         c->output << "#endif /* STP_USE_DWARF_UNWINDER"
+                   << " && STP_NEED_UNWIND_DATA */\n";
+
+       }
+      else
+       {
+         c->output << ".debug_hdr = NULL,\n";
+         c->output << ".debug_hdr_len = 0,\n";
+         c->output << ".sec_load_offset = 0\n";
+       }
+
+       c->output << "},\n";
     }
   c->output << "};\n";
 
@@ -5237,11 +5305,9 @@ dump_unwindsyms (Dwfl_Module *m,
   c->output << "static struct _stp_module _stp_module_" << stpmod_idx << " = {\n";
   c->output << ".name = " << lex_cast_qstring (mainname) << ", \n";
   c->output << ".path = " << lex_cast_qstring (mainpath) << ",\n";
-  Dwarf_Addr dwbias = 0;
-  dwfl_module_getdwarf (m, &dwbias);
-  c->output << ".dwarf_module_base = 0x" << hex << (base - dwbias) << ", \n";
-  c->output << ".eh_frame_addr = 0x" << eh_addr << ", \n";
-  c->output << ".unwind_hdr_addr = 0x" << eh_frame_hdr_addr << dec << ", \n";
+  c->output << ".eh_frame_addr = 0x" << hex << eh_addr << dec << ", \n";
+  c->output << ".unwind_hdr_addr = 0x" << hex << eh_frame_hdr_addr
+           << dec << ", \n";
 
   if (debug_frame != NULL)
     {
@@ -5249,17 +5315,6 @@ dump_unwindsyms (Dwfl_Module *m,
       c->output << ".debug_frame = "
                << "_stp_module_" << stpmod_idx << "_debug_frame, \n";
       c->output << ".debug_frame_len = " << debug_len << ", \n";
-      if (debug_frame_hdr)
-        {
-          c->output << ".debug_hdr = "
-                    << "_stp_module_" << stpmod_idx << "_debug_frame_hdr, \n";
-          c->output << ".debug_hdr_len = " << debug_frame_hdr_len << ", \n";
-        }
-      else
-        {
-          c->output << ".debug_hdr = NULL,\n";
-          c->output << ".debug_hdr_len = 0,\n";
-        }
       c->output << "#else\n";
     }
 
This page took 0.045969 seconds and 5 git commands to generate.