readelf: Don't allocate string with asprintf, but reuse buffer with sprintf.
authorMark Wielaard <mark@klomp.org>
Sat, 2 Jun 2018 02:24:01 +0000 (04:24 +0200)
committerMark Wielaard <mark@klomp.org>
Mon, 4 Jun 2018 17:03:18 +0000 (19:03 +0200)
Since we are single threaded we can just use a static result buffer for
format_dwarf_addr as long as we make sure to print the result before
calling format_dwarf_addr again. This removes lots of malloc/free calls.

On my machine eu-readelf -N --debug-dump=info libxul.so
goes from 57 seconds to 55 seconds.

Signed-off-by: Mark Wielaard <mark@klomp.org>
src/ChangeLog
src/readelf.c

index 9ee9650..37e2471 100644 (file)
@@ -1,5 +1,25 @@
 2018-06-04  Mark Wielaard  <mark@klomp.org>
 
+       * readelf (format_result): New static char pointer.
+       (format_result_size): New static size_t.
+       (format_dwarf_addr): Calculate max string size, reuse format_result
+       if possible, otherwise realloc. Use sprintf on result, not asprintf.
+       (print_ops): Don't free format_dwarf_addr, make sure result is
+       printed before calling format_dwarf_addr again.
+       (print_debug_addr_section): Likewise.
+       (print_debug_aranges_section): Likewise.
+       (print_debug_rnglists_section): Likewise.
+       (print_debug_ranges_section): Likewise.
+       (print_debug_frame_section): Likewise.
+       (attr_callback): Likewise.
+       (print_decoded_line_section): Likewise.
+       (print_debug_line_section): Likewise.
+       (print_debug_loclists_section): Likewise.
+       (print_debug_loc_section): Likewise.
+       (print_gdb_index_section): Likewsie.
+
+2018-06-04  Mark Wielaard  <mark@klomp.org>
+
        * readelf.c (yes_str): New static char pointer.
        (no_str): Likewise.
        (main): Set yes_str and no_str using gettext.
index 81d1094..8f37f17 100644 (file)
@@ -3695,6 +3695,9 @@ print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
 }
 
 
+static char *format_result = NULL;
+static size_t format_result_size = 0;
+
 static char *
 format_dwarf_addr (Dwfl_Module *dwflmod,
                   int address_size, Dwarf_Addr address, Dwarf_Addr raw)
@@ -3724,56 +3727,71 @@ format_dwarf_addr (Dwfl_Module *dwflmod,
     }
 
   char *result;
+  size_t max_size = ((name != NULL ? strlen (name) : 0)
+                    + (scn != NULL ? strlen (scn) : 0)
+                    + (2 + 8 * 2) * 2 + 6);
+  if (max_size > format_result_size)
+    {
+      max_size *= 2; /* A bit more, so we don't immediately realloc again.  */
+      result = realloc (format_result, max_size);
+      if (result == NULL)
+       error (EXIT_FAILURE, 0, _("memory exhausted"));
+      format_result_size = max_size;
+      format_result = result;
+    }
+  else
+    result = format_result;
+
   if ((name != NULL
        ? (off != 0
          ? (scn != NULL
             ? (address_size == 0
-               ? asprintf (&result,
-                           gettext ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">"),
-                           scn, address, name, off)
-               : asprintf (&result,
-                           gettext ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
-                           scn, 2 + address_size * 2, address,
-                           name, off))
+               ? sprintf (result,
+                          "%s+%#" PRIx64 " <%s+%#" PRIx64 ">",
+                          scn, address, name, off)
+               : sprintf (result,
+                          "%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">",
+                          scn, 2 + address_size * 2, address,
+                          name, off))
             : (address_size == 0
-               ? asprintf (&result,
-                           gettext ("%#" PRIx64 " <%s+%#" PRIx64 ">"),
-                           address, name, off)
-               : asprintf (&result,
-                           gettext ("%#0*" PRIx64 " <%s+%#" PRIx64 ">"),
-                           2 + address_size * 2, address,
-                           name, off)))
+               ? sprintf (result,
+                          "%#" PRIx64 " <%s+%#" PRIx64 ">",
+                          address, name, off)
+               : sprintf (result,
+                          "%#0*" PRIx64 " <%s+%#" PRIx64 ">",
+                          2 + address_size * 2, address,
+                          name, off)))
          : (scn != NULL
             ? (address_size == 0
-               ? asprintf (&result,
-                           gettext ("%s+%#" PRIx64 " <%s>"),
-                           scn, address, name)
-               : asprintf (&result,
-                           gettext ("%s+%#0*" PRIx64 " <%s>"),
-                           scn, 2 + address_size * 2, address, name))
+               ? sprintf (result,
+                          "%s+%#" PRIx64 " <%s>",
+                          scn, address, name)
+               : sprintf (result,
+                          "%s+%#0*" PRIx64 " <%s>",
+                          scn, 2 + address_size * 2, address, name))
             : (address_size == 0
-               ? asprintf (&result,
-                           gettext ("%#" PRIx64 " <%s>"),
-                           address, name)
-               : asprintf (&result,
-                           gettext ("%#0*" PRIx64 " <%s>"),
-                           2 + address_size * 2, address, name))))
+               ? sprintf (result,
+                          "%#" PRIx64 " <%s>",
+                          address, name)
+               : sprintf (result,
+                          "%#0*" PRIx64 " <%s>",
+                          2 + address_size * 2, address, name))))
        : (scn != NULL
          ? (address_size == 0
-            ? asprintf (&result,
-                        gettext ("%s+%#" PRIx64),
-                        scn, address)
-            : asprintf (&result,
-                        gettext ("%s+%#0*" PRIx64),
-                        scn, 2 + address_size * 2, address))
+            ? sprintf (result,
+                       "%s+%#" PRIx64,
+                       scn, address)
+            : sprintf (result,
+                       "%s+%#0*" PRIx64,
+                       scn, 2 + address_size * 2, address))
          : (address_size == 0
-            ? asprintf (&result,
-                        "%#" PRIx64,
-                        address)
-            : asprintf (&result,
-                        "%#0*" PRIx64,
-                        2 + address_size * 2, address)))) < 0)
-    error (EXIT_FAILURE, 0, _("memory exhausted"));
+            ? sprintf (result,
+                       "%#" PRIx64,
+                       address)
+            : sprintf (result,
+                       "%#0*" PRIx64,
+                       2 + address_size * 2, address)))) < 0)
+    error (EXIT_FAILURE, 0, _("sprintf failure"));
 
   return result;
 }
@@ -4355,7 +4373,6 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
          char *a = format_dwarf_addr (dwflmod, 0, addr, addr);
          printf ("%*s[%2" PRIuMAX "] %s %s\n",
                  indent, "", (uintmax_t) offset, op_name, a);
-         free (a);
 
          offset += 1 + addrsize;
          break;
@@ -4501,7 +4518,6 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
            {
              a = format_dwarf_addr (dwflmod, 0, addr, addr);
              printf ("%s\n", a);
-             free (a);
            }
          break;
 
@@ -5287,7 +5303,6 @@ print_debug_addr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
          char *a = format_dwarf_addr (dwflmod, address_size,
                                       addr, addr);
          printf ("%s\n", a);
-         free (a);
        }
       printf ("\n");
 
@@ -5505,16 +5520,14 @@ print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
 
          char *b = format_dwarf_addr (dwflmod, address_size, range_address,
                                       range_address);
+         printf ("   %s", b);
          char *e = format_dwarf_addr (dwflmod, address_size,
                                       range_address + range_length - 1,
                                       range_length);
          if (segment_size != 0)
-           printf (gettext ("   %s..%s (%" PRIx64 ")\n"), b, e,
-                   (uint64_t) segment);
+           printf ("..%s (%" PRIx64 ")\n", e, (uint64_t) segment);
          else
-           printf (gettext ("   %s..%s\n"), b, e);
-         free (b);
-         free (e);
+           printf ("..%s\n", e);
        }
 
     next_table:
@@ -5664,7 +5677,6 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
          else
            printf (gettext (" CU [%6" PRIx64 "] base: %s\n"),
                    dwarf_dieoffset (&cudie), basestr);
-         free (basestr);
        }
       else
        printf (gettext (" Not associated with a CU.\n"));
@@ -5750,7 +5762,6 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
                      a1 = format_dwarf_addr (dwflmod, address_size,
                                              addr, addr);
                      printf ("      %s\n", a1);
-                     free (a1);
                    }
                }
              break;
@@ -5777,12 +5788,10 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
                    {
                      a1 = format_dwarf_addr (dwflmod, address_size,
                                              addr1, addr1);
+                     printf ("      %s..\n", a1);
                      a2 = format_dwarf_addr (dwflmod, address_size,
                                              addr2 - 1, addr2);
-                     printf ("      %s..\n", a1);
                      printf ("      %s\n", a2);
-                     free (a1);
-                     free (a2);
                    }
                }
              break;
@@ -5809,12 +5818,10 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
                      addr2 = addr1 + op2;
                      a1 = format_dwarf_addr (dwflmod, address_size,
                                              addr1, addr1);
+                     printf ("      %s..\n", a1);
                      a2 = format_dwarf_addr (dwflmod, address_size,
                                              addr2 - 1, addr2);
-                     printf ("      %s..\n", a1);
                      printf ("      %s..\n", a2);
-                     free (a1);
-                     free (a2);
                    }
                }
              break;
@@ -5832,12 +5839,10 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
                  op1 += base;
                  op2 += base;
                  a1 = format_dwarf_addr (dwflmod, address_size, op1, op1);
+                 printf ("      %s..\n", a1);
                  a2 = format_dwarf_addr (dwflmod, address_size,
                                          op2 - 1, op2);
-                 printf ("      %s..\n", a1);
                  printf ("      %s\n", a2);
-                 free (a1);
-                 free (a2);
                }
              break;
 
@@ -5860,7 +5865,6 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
                {
                  a1 = format_dwarf_addr (dwflmod, address_size, base, base);
                  printf ("      %s\n", a1);
-                 free (a1);
                }
              break;
 
@@ -5883,12 +5887,10 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
              if (! print_unresolved_addresses)
                {
                  a1 = format_dwarf_addr (dwflmod, address_size, op1, op1);
+                 printf ("      %s..\n", a1);
                  a2 = format_dwarf_addr (dwflmod, address_size,
                                          op2 - 1, op2);
-                 printf ("      %s..\n", a1);
                  printf ("      %s\n", a2);
-                 free (a1);
-                 free (a2);
                }
              break;
 
@@ -5912,13 +5914,12 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
              if (! print_unresolved_addresses)
                {
                  a1 = format_dwarf_addr (dwflmod, address_size, op1, op1);
+                 printf ("      %s..\n", a1);
+
                  op2 = op1 + op2;
                  a2 = format_dwarf_addr (dwflmod, address_size,
                                          op2 - 1, op2);
-                 printf ("      %s..\n", a1);
                  printf ("      %s\n", a2);
-                 free (a1);
-                 free (a2);
                }
              break;
 
@@ -5990,7 +5991,6 @@ print_debug_ranges_section (Dwfl_Module *dwflmod,
          else
            printf (gettext ("\n CU [%6" PRIx64 "] base: %s\n"),
                    dwarf_dieoffset (&cudie), basestr);
-         free (basestr);
        }
       last_cu = cu;
 
@@ -6019,7 +6019,6 @@ print_debug_ranges_section (Dwfl_Module *dwflmod,
        {
          char *b = format_dwarf_addr (dwflmod, address_size, end, end);
          printf (gettext (" [%6tx] base address\n          %s\n"), offset, b);
-         free (b);
          base = end;
        }
       else if (begin == 0 && end == 0) /* End of list entry.  */
@@ -6041,12 +6040,10 @@ print_debug_ranges_section (Dwfl_Module *dwflmod,
            {
              char *b = format_dwarf_addr (dwflmod, address_size, base + begin,
                                           base + begin);
+             printf ("          %s..\n", b);
              char *e = format_dwarf_addr (dwflmod, address_size,
                                           base + end - 1, base + end);
-             printf ("          %s..\n", b);
              printf ("          %s\n", e);
-             free (b);
-             free (e);
            }
 
          first = false;
@@ -6818,7 +6815,6 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
                  "   initial_location:         %s",
                  offset, (uint64_t) unit_length,
                  cie->cie_offset, (uint64_t) cie_id, a);
-         free (a);
          if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
            {
              vma_base = (((uint64_t) shdr->sh_offset
@@ -6986,7 +6982,6 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
            printf ("           %*s%-20s (%s) %s\n",
                    (int) (level * 2), "", dwarf_attr_name (attr),
                    dwarf_form_name (form), a);
-         free (a);
        }
       break;
 
@@ -7331,7 +7326,6 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
          printf ("           %*s%-20s (%s) %" PRIuMAX " (%s)\n",
                  (int) (level * 2), "", dwarf_attr_name (attr),
                  dwarf_form_name (form), (uintmax_t) num, a);
-         free (a);
        }
       else
        {
@@ -7843,7 +7837,6 @@ print_decoded_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
                  (epilogue_begin ? 'E' : ' '),
                  (endseq ? '*' : ' '),
                  disc, isa, lineop, a);
-         free (a);
 
          if (endseq)
            printf("\n");
@@ -8535,7 +8528,6 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
                printf (gettext ("\
  special opcode %u: address+%u = %s, line%+d = %zu\n"),
                        opcode, op_addr_advance, a, line_increment, line);
-             free (a);
            }
          else if (opcode == 0)
            {
@@ -8577,7 +8569,6 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
                  {
                    char *a = format_dwarf_addr (dwflmod, 0, address, address);
                    printf (gettext (" set address to %s\n"), a);
-                   free (a);
                  }
                  break;
 
@@ -8650,7 +8641,6 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
                    else
                      printf (gettext (" advance address by %u to %s\n"),
                              op_addr_advance, a);
-                   free (a);
                  }
                  break;
 
@@ -8710,7 +8700,6 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
                      printf (gettext ("\
  advance address by constant %u to %s\n"),
                              op_addr_advance, a);
-                   free (a);
                  }
                  break;
 
@@ -8728,7 +8717,6 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
                    printf (gettext ("\
  advance address by fixed value %u to %s\n"),
                            u128, a);
-                   free (a);
                  }
                  break;
 
@@ -8895,7 +8883,6 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
          else
            printf (gettext (" CU [%6" PRIx64 "] base: %s\n"),
                    dwarf_dieoffset (&cudie), basestr);
-         free (basestr);
        }
       else
        printf (gettext (" Not associated with a CU.\n"));
@@ -8981,7 +8968,6 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
                      a1 = format_dwarf_addr (dwflmod, address_size,
                                              addr, addr);
                      printf ("      %s\n", a1);
-                     free (a1);
                    }
                }
              break;
@@ -9008,12 +8994,10 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
                    {
                      a1 = format_dwarf_addr (dwflmod, address_size,
                                              addr1, addr1);
+                     printf ("      %s..\n", a1);
                      a2 = format_dwarf_addr (dwflmod, address_size,
                                              addr2 - 1, addr2);
-                     printf ("      %s..\n", a1);
                      printf ("      %s\n", a2);
-                     free (a1);
-                     free (a2);
                    }
                }
              if ((uint64_t) (nexthdr - readp) < 1)
@@ -9048,12 +9032,10 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
                      addr2 = addr1 + op2;
                      a1 = format_dwarf_addr (dwflmod, address_size,
                                              addr1, addr1);
+                     printf ("      %s..\n", a1);
                      a2 = format_dwarf_addr (dwflmod, address_size,
                                              addr2 - 1, addr2);
-                     printf ("      %s..\n", a1);
                      printf ("      %s..\n", a2);
-                     free (a1);
-                     free (a2);
                    }
                }
              if ((uint64_t) (nexthdr - readp) < 1)
@@ -9079,12 +9061,10 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
                  op1 += base;
                  op2 += base;
                  a1 = format_dwarf_addr (dwflmod, address_size, op1, op1);
+                 printf ("      %s..\n", a1);
                  a2 = format_dwarf_addr (dwflmod, address_size,
                                          op2 - 1, op2);
-                 printf ("      %s..\n", a1);
                  printf ("      %s\n", a2);
-                 free (a1);
-                 free (a2);
                }
              if ((uint64_t) (nexthdr - readp) < 1)
                goto invalid_entry;
@@ -9126,7 +9106,6 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
                {
                  a1 = format_dwarf_addr (dwflmod, address_size, base, base);
                  printf ("      %s\n", a1);
-                 free (a1);
                }
              break;
 
@@ -9149,12 +9128,10 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
              if (! print_unresolved_addresses)
                {
                  a1 = format_dwarf_addr (dwflmod, address_size, op1, op1);
+                 printf ("      %s..\n", a1);
                  a2 = format_dwarf_addr (dwflmod, address_size,
                                          op2 - 1, op2);
-                 printf ("      %s..\n", a1);
                  printf ("      %s\n", a2);
-                 free (a1);
-                 free (a2);
                }
              if ((uint64_t) (nexthdr - readp) < 1)
                goto invalid_entry;
@@ -9186,13 +9163,12 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
              if (! print_unresolved_addresses)
                {
                  a1 = format_dwarf_addr (dwflmod, address_size, op1, op1);
+                 printf ("      %s..\n", a1);
+
                  op2 = op1 + op2;
                  a2 = format_dwarf_addr (dwflmod, address_size,
                                          op2 - 1, op2);
-                 printf ("      %s..\n", a1);
                  printf ("      %s\n", a2);
-                 free (a1);
-                 free (a2);
                }
              if ((uint64_t) (nexthdr - readp) < 1)
                goto invalid_entry;
@@ -9274,7 +9250,6 @@ print_debug_loc_section (Dwfl_Module *dwflmod,
        else
          printf (gettext ("\n CU [%6" PRIx64 "] base: %s\n"),
                  dwarf_dieoffset (&cudie), basestr);
-       free (basestr);
        }
       last_cu = cu;
 
@@ -9403,7 +9378,6 @@ print_debug_loc_section (Dwfl_Module *dwflmod,
        {
          char *b = format_dwarf_addr (dwflmod, address_size, end, end);
          printf (gettext (" [%6tx] base address\n          %s\n"), offset, b);
-         free (b);
          base = end;
        }
       else if (begin == 0 && end == 0) /* End of list entry.  */
@@ -9429,12 +9403,10 @@ print_debug_loc_section (Dwfl_Module *dwflmod,
              Dwarf_Addr dae = use_base ? base + end : end;
              char *b = format_dwarf_addr (dwflmod, address_size,
                                           dab, dab);
+             printf ("          %s..\n", b);
              char *e = format_dwarf_addr (dwflmod, address_size,
                                           dae - 1, dae);
-             printf ("          %s..\n", b);
              printf ("          %s\n", e);
-             free (b);
-             free (e);
            }
 
          if (endp - readp <= (ptrdiff_t) len)
@@ -10694,11 +10666,9 @@ print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
       readp += 4;
 
       char *l = format_dwarf_addr (dwflmod, 8, low, low);
+      printf (" [%4zu] %s..", n, l);
       char *h = format_dwarf_addr (dwflmod, 8, high - 1, high);
-      printf (" [%4zu] %s..%s, CU index: %5" PRId32 "\n",
-             n, l, h, idx);
-      free (l);
-      free (h);
+      printf ("%s, CU index: %5" PRId32 "\n", h, idx);
       n++;
     }