]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Color code output of nm and objdump
authorUlrich Drepper <drepper@gmail.com>
Sat, 21 Jan 2012 23:14:39 +0000 (18:14 -0500)
committerUlrich Drepper <drepper@gmail.com>
Sat, 21 Jan 2012 23:14:39 +0000 (18:14 -0500)
lib/ChangeLog
lib/Makefile.am
lib/color.c [new file with mode: 0644]
lib/system.h
libcpu/ChangeLog
libcpu/i386_disasm.c
src/ChangeLog
src/nm.c
src/objdump.c

index a6fec3094614d204c18b1d5fdd39c3fe9c6731f2..47e831ea89c2cdb6a6f24a3cf9ff53a7d56c5420 100644 (file)
@@ -1,3 +1,10 @@
+2012-01-21  Ulrich Drepper  <drepper@gmail.com>
+
+       * Makefile.am (libeu_a_SOURCES): Add color.c.
+       * system.h: Declare color_argp.  Define color_enum.  Declare
+       color_* variables.
+       * color.c: New file.
+
 2011-10-02  Ulrich Drepper  <drepper@gmail.com>
 
        * system.h: Declare __cxa_demangle.
index 50d55c56ccdc99f48e9d4db9b9b419dc85265fab..4ea143616a01577c66d38086c7caeda6ce8faa37 100644 (file)
@@ -1,6 +1,6 @@
 ## Process this file with automake to create Makefile.in
 ##
-## Copyright (C) 1996-2010 Red Hat, Inc.
+## Copyright (C) 1996-2011 Red Hat, Inc.
 ## This file is part of Red Hat elfutils.
 ##
 ## Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -30,8 +30,9 @@ INCLUDES += -I$(srcdir)/../libelf
 
 noinst_LIBRARIES = libeu.a
 
-libeu_a_SOURCES = xstrndup.c xmalloc.c next_prime.c \
-                 crc32.c crc32_file.c md5.c sha1.c
+libeu_a_SOURCES = xstrdup.c xstrndup.c xmalloc.c next_prime.c \
+                 crc32.c crc32_file.c md5.c sha1.c \
+                 color.c
 
 noinst_HEADERS = fixedsizehash.h system.h dynamicsizehash.h list.h md5.h \
                 sha1.h eu-config.h
diff --git a/lib/color.c b/lib/color.c
new file mode 100644 (file)
index 0000000..ff82448
--- /dev/null
@@ -0,0 +1,227 @@
+/* Handling of color output.
+   Copyright (C) 2011 Red Hat, Inc.
+   This file is part of Red Hat elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2011.
+
+   Red Hat elfutils is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by the
+   Free Software Foundation; version 2 of the License.
+
+   Red Hat elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Red Hat elfutils; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+   Red Hat elfutils is an included package of the Open Invention Network.
+   An included package of the Open Invention Network is a package for which
+   Open Invention Network licensees cross-license their patents.  No patent
+   license is granted, either expressly or impliedly, by designation as an
+   included package.  Should you wish to participate in the Open Invention
+   Network licensing program, please visit www.openinventionnetwork.com
+   <http://www.openinventionnetwork.com>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <argp.h>
+#include <error.h>
+#include <libintl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "system.h"
+
+
+/* Prototype for option handler.  */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+/* Option values.  */
+#define OPT_COLOR 0x100100
+
+/* Definitions of arguments for argp functions.  */
+static const struct argp_option options[] =
+{
+  { "color", OPT_COLOR, "WHEN", OPTION_ARG_OPTIONAL,
+    N_("colorize the output.  WHEN defaults to 'always' or can be 'auto' or 'never'"), 0 },
+
+  { NULL, 0, NULL, 0, NULL, 0 }
+};
+
+/* Parser data structure.  */
+const struct argp color_argp =
+  {
+    options, parse_opt, NULL, NULL, NULL, NULL, NULL
+  };
+
+/* Coloring mode.  */
+enum color_enum color_mode;
+
+/* Colors to use for the various components.  */
+char *color_address = "";
+char *color_bytes = "";
+char *color_mnemonic = "";
+char *color_operand = NULL;
+char *color_operand1 = "";
+char *color_operand2 = "";
+char *color_operand3 = "";
+char *color_label = "";
+char *color_undef = "";
+char *color_undef_tls = "";
+char *color_undef_weak = "";
+char *color_symbol = "";
+char *color_tls = "";
+char *color_weak = "";
+
+const char color_off[] = "\e[0m";
+
+
+/* Handle program arguments.  */
+static error_t
+parse_opt (int key, char *arg,
+          struct argp_state *state __attribute__ ((unused)))
+{
+  switch (key)
+    {
+    case OPT_COLOR:
+      if (arg == NULL)
+       color_mode = color_always;
+      else
+       {
+         static const struct
+         {
+           const char str[7];
+           enum color_enum mode;
+         } values[] =
+             {
+               { "always", color_always },
+               { "yes", color_always },
+               { "force", color_always },
+               { "never", color_never },
+               { "no", color_never },
+               { "none", color_never },
+               { "auto", color_auto },
+               { "tty", color_auto },
+               { "if-tty", color_auto }
+             };
+         const int nvalues = sizeof (values) / sizeof (values[0]);
+         int i;
+         for (i = 0; i < nvalues; ++i)
+           if (strcmp (arg, values[i].str) == 0)
+             {
+               color_mode = values[i].mode;
+               if (color_mode == color_auto)
+                 color_mode
+                   = isatty (STDOUT_FILENO) ? color_always : color_never;
+               break;
+             }
+         if (i == nvalues)
+           {
+             error (0, 0, dgettext ("elfutils", "\
+%s: invalid argument '%s' for '--color'\n\
+valid arguments are:\n\
+  - 'always', 'yes', 'force'\n\
+  - 'never', 'no', 'none'\n\
+  - 'auto', 'tty', 'if-tty'\n"),
+                    program_invocation_short_name, arg);
+             argp_help (&color_argp, stderr, ARGP_HELP_SEE,
+                        program_invocation_short_name);
+             exit (EXIT_FAILURE);
+           }
+       }
+
+      if (color_mode == color_always)
+       {
+         const char *env = getenv ("ELFUTILS_COLORS");
+         if (env != NULL)
+           {
+             do
+               {
+                 const char *start = env;
+                 while (*env != '=' && *env != '\0')
+                   ++env;
+                 if (*env == '=' && env != start)
+                   {
+                     size_t name_len = env - start;
+                     const char *val = ++env;
+                     env = strchrnul (env, ':');
+                     if (val != env)
+                       {
+                         static const struct
+                         {
+                           unsigned char len;
+                           const char name[sizeof (char *) - 1];
+                           char **varp;
+                         } known[] =
+                             {
+#define E(name, var) { sizeof (#name) - 1, #name,  &color_##var }
+                               E (a, address),
+                               E (b, bytes),
+                               E (m, mnemonic),
+                               E (o, operand),
+                               E (o1, operand1),
+                               E (o1, operand2),
+                               E (o1, operand3),
+                               E (l, label),
+                               E (u, undef),
+                               E (ut, undef_tls),
+                               E (uw, undef_weak),
+                               E (sy, symbol),
+                               E (st, tls),
+                               E (sw, weak),
+                             };
+                         const size_t nknown = (sizeof (known)
+                                                / sizeof (known[0]));
+
+                         for (size_t i = 0; i < nknown; ++i)
+                           if (name_len == known[i].len
+                               && memcmp (start, known[i].name, name_len) == 0)
+                             {
+                               if (asprintf (known[i].varp, "\e[%.*sm",
+                                             (int) (env - val), val) < 0)
+                                 error (EXIT_FAILURE, errno,
+                                        gettext ("cannot allocate memory"));
+                               break;
+                             }
+                       }
+                     if (*env == ':')
+                       ++env;
+                   }
+               }
+             while (*env != '\0');
+
+             if (color_operand != NULL)
+               {
+                 if (color_operand1[0] == '\0')
+                   color_operand1 = color_operand;
+                 if (color_operand2[0] == '\0')
+                   color_operand2 = color_operand;
+                 if (color_operand3[0] == '\0')
+                   color_operand3 = color_operand;
+               }
+           }
+#if 0
+         else
+           {
+             // XXX Just for testing.
+             color_address = xstrdup ("\e[38;5;166;1m");
+             color_bytes = xstrdup ("\e[38;5;141m");
+             color_mnemonic = xstrdup ("\e[38;5;202;1m");
+             color_operand1 = xstrdup ("\e[38;5;220m");
+             color_operand2 = xstrdup ("\e[38;5;48m");
+             color_operand3 = xstrdup ("\e[38;5;112m");
+             color_label = xstrdup ("\e[38;5;21m");
+           }
+#endif
+       }
+      break;
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
index 8e32c3a1f77b593501827ffcff61e23463d5a599..3f9f0af5837fe7b7064d06c2091d9d94f8ea968a 100644 (file)
@@ -49,6 +49,7 @@
 #ifndef LIB_SYSTEM_H
 #define LIB_SYSTEM_H   1
 
+#include <argp.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <endian.h>
@@ -107,4 +108,37 @@ extern int crc32_file (int fd, uint32_t *resp);
 extern char *__cxa_demangle (const char *mangled_name, char *output_buffer,
                             size_t *length, int *status);
 
+
+
+/* Color handling.  */
+
+/* Command line parser.  */
+extern const struct argp color_argp;
+
+/* Coloring mode.  */
+enum color_enum
+  {
+    color_never = 0,
+    color_always,
+    color_auto
+  } __attribute__ ((packed));
+extern enum color_enum color_mode;
+
+/* Colors to use for the various components.  */
+extern char *color_address;
+extern char *color_bytes;
+extern char *color_mnemonic;
+extern char *color_operand1;
+extern char *color_operand2;
+extern char *color_operand3;
+extern char *color_label;
+extern char *color_undef;
+extern char *color_undef_tls;
+extern char *color_undef_weak;
+extern char *color_symbol;
+extern char *color_tls;
+extern char *color_weak;
+
+extern const char color_off[];
+
 #endif /* system.h */
index 52a073abfe8f3cba733316deb13d52a8293de434..76340a136d717195a144d54fe10bed4a9a708b02 100644 (file)
@@ -1,3 +1,8 @@
+2012-01-21  Ulrich Drepper  <drepper@gmail.com>
+
+       * i386_disasm.c (ADD_NSTRING): Define.
+       (i386_disasm): Print color codes in the appropriate places.
+
 2011-10-16  Roland McGrath  <roland@hack.frob.com>
 
        * Makefile.am (libcpu_i386_a_SOURCES): Add i386_dis.h.
index c6bb0a584f80b39e55da256f2a34dd338bac2534..6d58f0ea96f9ac676a62fb65f4543c83df696957 100644 (file)
@@ -1,5 +1,5 @@
 /* Disassembler for x86.
-   Copyright (C) 2007, 2008, 2009 Red Hat, Inc.
+   Copyright (C) 2007, 2008, 2009, 2011 Red Hat, Inc.
    This file is part of Red Hat elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2007.
 
@@ -292,12 +292,19 @@ struct output_data
   } while (0)
 
 #define ADD_STRING(str) \
+  do {                                                                       \
+    const char *_str0 = (str);                                               \
+    size_t _len0 = strlen (_str0);                                           \
+    ADD_NSTRING (_str0, _len0);                                                      \
+  } while (0)
+
+#define ADD_NSTRING(str, len) \
   do {                                                                       \
     const char *_str = (str);                                                \
-    size_t _len = strlen (_str);                                             \
+    size_t _len = (len);                                                     \
     if (unlikely (bufcnt + _len > bufsize))                                  \
       goto enomem;                                                           \
-    memcpy (buf + bufcnt, str, _len);                                        \
+    memcpy (buf + bufcnt, _str, _len);                                       \
     bufcnt += _len;                                                          \
   } while (0)
 
@@ -615,6 +622,10 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr,
 
          unsigned long string_end_idx = 0;
          fmt = save_fmt;
+         const char *deferred_start = NULL;
+         size_t deferred_len = 0;
+         // XXX Can we get this from color.c?
+         static const char color_off[] = "\e[0m";
          while (*fmt != '\0')
            {
              if (*fmt != '%')
@@ -657,6 +668,22 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr,
                          goto do_ret;
                        }
                    }
+                 else if (ch == '\e' && *fmt == '[')
+                   {
+                     deferred_start = fmt - 1;
+                     do
+                       ++fmt;
+                     while (*fmt != 'm' && *fmt != '\0');
+
+                     if (*fmt == 'm')
+                       {
+                         deferred_len = ++fmt - deferred_start;
+                         continue;
+                       }
+
+                     fmt = deferred_start + 1;
+                     deferred_start = NULL;
+                   }
                  ADD_CHAR (ch);
                  continue;
                }
@@ -672,6 +699,7 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr,
                  prec = prec * 10 + (*fmt - '0');
 
              size_t start_idx = bufcnt;
+             size_t non_printing = 0;
              switch (*fmt++)
                {
                  char mnebuf[16];
@@ -796,6 +824,12 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr,
                  else
                    str = mnestr.str + mneidx[instrtab[cnt].mnemonic];
 
+                 if (deferred_start != NULL)
+                   {
+                     ADD_NSTRING (deferred_start, deferred_len);
+                     non_printing += deferred_len;
+                   }
+
                  ADD_STRING (str);
 
                  switch (instrtab[cnt].suffix)
@@ -879,6 +913,12 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr,
                      abort ();
                    }
 
+                 if (deferred_start != NULL)
+                   {
+                     ADD_STRING (color_off);
+                     non_printing += strlen (color_off);
+                   }
+
                  string_end_idx = bufcnt;
                  break;
 
@@ -886,6 +926,12 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr,
                  if (prec == 1 && instrtab[cnt].fct1 != 0)
                    {
                      /* First parameter.  */
+                     if (deferred_start != NULL)
+                       {
+                         ADD_NSTRING (deferred_start, deferred_len);
+                         non_printing += deferred_len;
+                       }
+
                      if (instrtab[cnt].str1 != 0)
                        ADD_STRING (op1_str
                                    + op1_str_idx[instrtab[cnt].str1 - 1]);
@@ -902,11 +948,23 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr,
                      if (r > 0)
                        goto enomem;
 
+                     if (deferred_start != NULL)
+                       {
+                         ADD_STRING (color_off);
+                         non_printing += strlen (color_off);
+                       }
+
                      string_end_idx = bufcnt;
                    }
                  else if (prec == 2 && instrtab[cnt].fct2 != 0)
                    {
                      /* Second parameter.  */
+                     if (deferred_start != NULL)
+                       {
+                         ADD_NSTRING (deferred_start, deferred_len);
+                         non_printing += deferred_len;
+                       }
+
                      if (instrtab[cnt].str2 != 0)
                        ADD_STRING (op2_str
                                    + op2_str_idx[instrtab[cnt].str2 - 1]);
@@ -923,11 +981,23 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr,
                      if (r > 0)
                        goto enomem;
 
+                     if (deferred_start != NULL)
+                       {
+                         ADD_STRING (color_off);
+                         non_printing += strlen (color_off);
+                       }
+
                      string_end_idx = bufcnt;
                    }
                  else if (prec == 3 && instrtab[cnt].fct3 != 0)
                    {
                      /* Third parameter.  */
+                     if (deferred_start != NULL)
+                       {
+                         ADD_NSTRING (deferred_start, deferred_len);
+                         non_printing += deferred_len;
+                       }
+
                      if (instrtab[cnt].str3 != 0)
                        ADD_STRING (op3_str
                                    + op3_str_idx[instrtab[cnt].str3 - 1]);
@@ -948,6 +1018,12 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr,
                      if (r > 0)
                        goto enomem;
 
+                     if (deferred_start != NULL)
+                       {
+                         ADD_STRING (color_off);
+                         non_printing += strlen (color_off);
+                       }
+
                      string_end_idx = bufcnt;
                    }
                  else
@@ -960,12 +1036,18 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr,
 
                case 'a':
                  /* Pad to requested column.  */
-                 while (bufcnt < (size_t) width)
+                 while (bufcnt - non_printing < (size_t) width)
                    ADD_CHAR (' ');
                  width = 0;
                  break;
 
                case 'l':
+                 if (deferred_start != NULL)
+                   {
+                     ADD_NSTRING (deferred_start, deferred_len);
+                     non_printing += deferred_len;
+                   }
+
                  if (output_data.labelbuf != NULL
                      && output_data.labelbuf[0] != '\0')
                    {
@@ -1005,11 +1087,21 @@ i386_disasm (const uint8_t **startp, const uint8_t *end, GElf_Addr addr,
 
                      output_data.symaddr_use = addr_none;
                    }
+                 if (deferred_start != NULL)
+                   {
+                     ADD_STRING (color_off);
+                     non_printing += strlen (color_off);
+                   }
                  break;
+
+               default:
+                 abort ();
                }
 
+             deferred_start = NULL;
+
              /* Pad according to the specified width.  */
-             while (bufcnt + prefix_size < start_idx + width)
+             while (bufcnt + prefix_size - non_printing < start_idx + width)
                ADD_CHAR (' ');
              prefix_size = 0;
            }
index b4dcca9b0f0ccf867741707d30e82e92d130f972..e9d52208e3a015ca90a010e89c119ce726d1ef0e 100644 (file)
@@ -1,3 +1,17 @@
+2012-01-21  Ulrich Drepper  <drepper@gmail.com>
+
+       * nm.c (argp_children): Define.
+       (argp): Hook up argp_children.
+       (handle_ar): Optimize puts call.
+       (show_symbols_bsd): Use positional parameters to also print color
+       codes.  Don't print STT_FILE symbols.
+       * objdump.c (options): Improve help text.
+       (argp_children): Define.
+       (argp): Hook up argp_children.
+       (disasm_info): Add elements for color codes.
+       (disasm_output): Print color codes as well.
+       (show_disasm): Set up disasm_info data for callback.
+
 2012-01-20  Roland McGrath  <roland@hack.frob.com>
 
        * arlib-argp.c (arlib_deterministic_output): Initialize from
index dd69a00e14278db1a9f5d9f27ec3b3cbd83805d5..dc6403f2771ffa4f938e91a8d8be371c715ac060 100644 (file)
--- a/src/nm.c
+++ b/src/nm.c
@@ -118,10 +118,17 @@ static const char args_doc[] = N_("[FILE...]");
 /* Prototype for option handler.  */
 static error_t parse_opt (int key, char *arg, struct argp_state *state);
 
+/* Parser children.  */
+static struct argp_child argp_children[] =
+  {
+    { &color_argp, 0, N_("Output formatting"), 2 },
+    { NULL, 0, NULL, 0}
+  };
+
 /* Data structure to communicate with argp functions.  */
 static struct argp argp =
 {
-  options, parse_opt, args_doc, doc, NULL, NULL, NULL
+  options, parse_opt, args_doc, doc, argp_children, NULL, NULL
 };
 
 
@@ -267,7 +274,7 @@ print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
 Copyright (C) %s Red Hat, Inc.\n\
 This is free software; see the source for copying conditions.  There is NO\n\
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2009");
+"), "2011");
   fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
 }
 
@@ -458,7 +465,7 @@ handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
          Elf_Arhdr *arhdr = NULL;
          size_t arhdr_off = 0; /* Note: 0 is no valid offset.  */
 
-         puts (gettext("\nArchive index:"));
+         fputs_unlocked (gettext("\nArchive index:\n"), stdout);
 
          while (arsym->as_off != 0)
            {
@@ -930,15 +937,15 @@ show_symbols_bsd (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx,
 
   static const char *const fmtstrs[] =
     {
-      [radix_hex] = "%0*" PRIx64 " %c%s %s\n",
-      [radix_decimal] = "%*" PRId64 " %c%s %s\n",
-      [radix_octal] = "%0*" PRIo64 " %c%s %s\n"
+      [radix_hex] = "%8$s%2$0*1$" PRIx64 "%10$s %9$s%3$c%4$s %5$s",
+      [radix_decimal] = "%8$s%*" PRId64 "%10$s %9$s%3$c%4$s %5$s",
+      [radix_octal] = "%8$s%2$0*1$" PRIo64 "%10$s %9$s%3$c%4$s %5$s"
     };
   static const char *const sfmtstrs[] =
     {
-      [radix_hex] = "%2$0*1$" PRIx64 " %7$0*6$" PRIx64 " %3$c%4$s %5$s\n",
-      [radix_decimal] = "%2$*1$" PRId64 " %7$*6$" PRId64 " %3$c%4$s %5$s\n",
-      [radix_octal] = "%2$0*1$" PRIo64 " %7$0*6$" PRIo64 " %3$c%4$s %5$s\n"
+      [radix_hex] = "%8$s%2$0*1$" PRIx64 "%10$s %7$0*6$" PRIx64 " %9$s%3$c%4$s %5$s",
+      [radix_decimal] = "%8$s%2$*1$" PRId64 "%10$s %7$*6$" PRId64 " %9$s%3$c%4$s %5$s",
+      [radix_octal] = "%8$s%2$0*1$" PRIo64 "%10$s %7$0*6$" PRIo64 " %9$s%3$c%4$s %5$s"
     };
 
 #ifdef USE_DEMANGLE
@@ -959,6 +966,10 @@ show_symbols_bsd (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx,
       if (symstr[0] == '\0')
        continue;
 
+      /* We do not print the entries for files.  */
+      if (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_FILE)
+       continue;
+
 #ifdef USE_DEMANGLE
       /* Demangle if necessary.  */
       if (demangle)
@@ -979,28 +990,53 @@ show_symbols_bsd (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx,
          putchar_unlocked (':');
        }
 
+      bool is_tls = GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_TLS;
+      bool is_weak = GELF_ST_BIND (syms[cnt].sym.st_info) == STB_WEAK;
+      const char *marker = (mark_special
+                           ? (is_tls ? "@" : (is_weak ? "*" : " ")) : "");
+
       if (syms[cnt].sym.st_shndx == SHN_UNDEF)
-       printf ("%*s U%s %s\n",
-               digits, "",
-               mark_special
-               ? (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_TLS
-                  ? "@"
-                  : (GELF_ST_BIND (syms[cnt].sym.st_info) == STB_WEAK
-                     ? "*" : " "))
-               : "",
-               symstr);
+       {
+         const char *color = "";
+         if (color_mode)
+           {
+             if (is_tls)
+               color = color_undef_tls;
+             else if (is_weak)
+               color = color_undef_weak;
+             else
+               color = color_undef;
+           }
+
+         printf ("%*s %sU%s %s", digits, "", color, marker, symstr);
+       }
       else
-       printf (print_size ? sfmtstrs[radix] : fmtstrs[radix],
-               digits, syms[cnt].sym.st_value,
-               class_type_char (elf, ehdr, &syms[cnt].sym),
-               mark_special
-               ? (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_TLS
-                  ? "@"
-                  : (GELF_ST_BIND (syms[cnt].sym.st_info) == STB_WEAK
-                     ? "*" : " "))
-               : "",
-               symstr,
-               digits, (uint64_t) syms[cnt].sym.st_size);
+       {
+         const char *color = "";
+         if (color_mode)
+           {
+             if (is_tls)
+               color = color_tls;
+             else if (is_weak)
+               color = color_weak;
+             else
+               color = color_symbol;
+           }
+
+         printf (print_size && syms[cnt].sym.st_size != 0
+                 ? sfmtstrs[radix] : fmtstrs[radix],
+                 digits, syms[cnt].sym.st_value,
+                 class_type_char (elf, ehdr, &syms[cnt].sym), marker,
+                 symstr,
+                 digits, (uint64_t) syms[cnt].sym.st_size,
+                 color_mode ? color_address : "",
+                 color,
+                 color_mode ? color_off : "");
+       }
+
+      if (color_mode)
+       fputs_unlocked (color_off, stdout);
+      putchar_unlocked ('\n');
     }
 
 #ifdef USE_DEMANGLE
index 1234c794ec557cc3649d54508cbf5c74f79c3cb9..e683a29fe6f63a2609710e2719d5c4b73d63120a 100644 (file)
@@ -1,5 +1,5 @@
 /* Print information from ELF file in human-readable form.
-   Copyright (C) 2005, 2006, 2007, 2009 Red Hat, Inc.
+   Copyright (C) 2005, 2006, 2007, 2009, 2011 Red Hat, Inc.
    This file is part of Red Hat elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2005.
 
@@ -65,7 +65,7 @@ static const struct argp_option options[] =
   { "disassemble", 'd', NULL, 0,
     N_("Display assembler code of executable sections"), 0 },
 
-  { NULL, 0, NULL, 0, N_("Output option selection:"), 0 },
+  { NULL, 0, NULL, 0, N_("Output content selection:"), 0 },
   { "section", 'j', "NAME", 0,
     N_("Only display information for section NAME."), 0 },
 
@@ -82,10 +82,17 @@ static const char args_doc[] = N_("[FILE...]");
 /* Prototype for option handler.  */
 static error_t parse_opt (int key, char *arg, struct argp_state *state);
 
+/* Parser children.  */
+static struct argp_child argp_children[] =
+  {
+    { &color_argp, 0, N_("Output formatting"), 2 },
+    { NULL, 0, NULL, 0}
+  };
+
 /* Data structure to communicate with argp functions.  */
-static struct argp argp =
+static const struct argp argp =
 {
-  options, parse_opt, args_doc, doc, NULL, NULL, NULL
+  options, parse_opt, args_doc, doc, argp_children, NULL, NULL
 };
 
 
@@ -128,6 +135,7 @@ static bool print_full_content;
 /* If true print disassembled output..  */
 static bool print_disasm;
 
+
 int
 main (int argc, char *argv[])
 {
@@ -182,7 +190,7 @@ print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
 Copyright (C) %s Red Hat, Inc.\n\
 This is free software; see the source for copying conditions.  There is NO\n\
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "20089");
+"), "2011");
   fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
 }
 
@@ -499,7 +507,7 @@ show_relocs (Ebl *ebl, const char *fname, uint32_t shstrndx)
 
       if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
        {
-         if  (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
+         if  (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
            continue;
 
          GElf_Shdr destshdr_mem;
@@ -570,7 +578,7 @@ show_full_content (Ebl *ebl, const char *fname, uint32_t shstrndx)
 
       if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0)
        {
-         if  (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
+         if  (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
            continue;
 
          printf (gettext ("Contents of section %s:\n"),
@@ -632,6 +640,8 @@ struct disasm_info
   GElf_Addr addr;
   const uint8_t *cur;
   const uint8_t *last_end;
+  const char *address_color;
+  const char *bytes_color;
 };
 
 
@@ -642,10 +652,20 @@ disasm_output (char *buf, size_t buflen, void *arg)
 {
   struct disasm_info *info = (struct disasm_info *) arg;
 
-  printf ("%8" PRIx64 ":   ", (uint64_t) info->addr);
+  if (info->address_color != NULL)
+    printf ("%s%8" PRIx64 "%s:   ",
+           info->address_color, (uint64_t) info->addr, color_off);
+  else
+    printf ("%8" PRIx64 ":   ", (uint64_t) info->addr);
+
+  if (info->bytes_color != NULL)
+    fputs_unlocked (info->bytes_color, stdout);
   size_t cnt;
   for (cnt = 0; cnt < (size_t) MIN (info->cur - info->last_end, 8); ++cnt)
     printf (" %02" PRIx8, info->last_end[cnt]);
+  if (info->bytes_color != NULL)
+    fputs_unlocked (color_off, stdout);
+
   printf ("%*s %.*s\n",
          (int) (8 - cnt) * 3 + 1, "", (int) buflen, buf);
 
@@ -655,9 +675,18 @@ disasm_output (char *buf, size_t buflen, void *arg)
      Print the rest on a separate, following line.  */
   if (info->cur - info->last_end > 8)
     {
-      printf ("%8" PRIx64 ":   ", (uint64_t) info->addr);
+      if (info->address_color != NULL)
+       printf ("%s%8" PRIx64 "%s:   ",
+               info->address_color, (uint64_t) info->addr, color_off);
+      else
+       printf ("%8" PRIx64 ":   ", (uint64_t) info->addr);
+
+      if (info->bytes_color != NULL)
+       fputs_unlocked (info->bytes_color, stdout);
       for (; cnt < (size_t) (info->cur - info->last_end); ++cnt)
        printf (" %02" PRIx8, info->last_end[cnt]);
+      if (info->bytes_color != NULL)
+       fputs_unlocked (color_off, stdout);
       putchar_unlocked ('\n');
       info->addr += info->cur - info->last_end - 8;
     }
@@ -687,7 +716,7 @@ show_disasm (Ebl *ebl, const char *fname, uint32_t shstrndx)
       if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0
          && (shdr->sh_flags & SHF_EXECINSTR) != 0)
        {
-         if  (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
+         if  (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
            continue;
 
          Elf_Data *data = elf_getdata (scn, NULL);
@@ -700,10 +729,32 @@ show_disasm (Ebl *ebl, const char *fname, uint32_t shstrndx)
          struct disasm_info info;
          info.addr = shdr->sh_addr;
          info.last_end = info.cur = data->d_buf;
+         char *fmt;
+         if (color_mode)
+           {
+             info.address_color = color_address;
+             info.bytes_color = color_bytes;
+
+             if (asprintf (&fmt, "%s%%7m %s%%.1o,%s%%.2o,%s%%.3o%%34a %s%%l",
+                           color_mnemonic ?: "",
+                           color_operand1 ?: "",
+                           color_operand2 ?: "",
+                           color_operand3 ?: "",
+                           color_label ?: "") < 0)
+               error (EXIT_FAILURE, errno, _("cannot allocate memory"));
+           }
+         else
+           {
+             info.address_color = info.bytes_color = NULL;
+
+             fmt = "%7m %.1o,%.2o,%.3o%34a %l";
+           }
 
          disasm_cb (ctx, &info.cur, info.cur + data->d_size, info.addr,
-                    "%7m %.1o,%.2o,%.3o%34a %l", disasm_output, &info,
-                    NULL /* XXX */);
+                    fmt, disasm_output, &info, NULL /* XXX */);
+
+         if (color_mode)
+           free (fmt);
        }
     }