summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@gmail.com>2012-01-21 18:14:39 -0500
committerUlrich Drepper <drepper@gmail.com>2012-01-21 18:14:39 -0500
commitc6b3d0c27833c8e0936cb6b8973e8578e3a9421f (patch)
treea6a9b80d84878e0bfeaf4137dd15e78effbc3162
parent5bdee8e7af380c17a3b1d76e3a16764c81fe23c1 (diff)
Color code output of nm and objdump
-rw-r--r--lib/ChangeLog7
-rw-r--r--lib/Makefile.am7
-rw-r--r--lib/color.c227
-rw-r--r--lib/system.h34
-rw-r--r--libcpu/ChangeLog5
-rw-r--r--libcpu/i386_disasm.c102
-rw-r--r--src/ChangeLog14
-rw-r--r--src/nm.c94
-rw-r--r--src/objdump.c75
9 files changed, 516 insertions, 49 deletions
diff --git a/lib/ChangeLog b/lib/ChangeLog
index a6fec309..47e831ea 100644
--- a/lib/ChangeLog
+++ b/lib/ChangeLog
@@ -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.
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 50d55c56..4ea14361 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -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
index 00000000..ff824485
--- /dev/null
+++ b/lib/color.c
@@ -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;
+}
diff --git a/lib/system.h b/lib/system.h
index 8e32c3a1..3f9f0af5 100644
--- a/lib/system.h
+++ b/lib/system.h
@@ -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 */
diff --git a/libcpu/ChangeLog b/libcpu/ChangeLog
index 52a073ab..76340a13 100644
--- a/libcpu/ChangeLog
+++ b/libcpu/ChangeLog
@@ -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.
diff --git a/libcpu/i386_disasm.c b/libcpu/i386_disasm.c
index c6bb0a58..6d58f0ea 100644
--- a/libcpu/i386_disasm.c
+++ b/libcpu/i386_disasm.c
@@ -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.
@@ -293,11 +293,18 @@ struct output_data
#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;
}
diff --git a/src/ChangeLog b/src/ChangeLog
index b4dcca9b..e9d52208 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -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
diff --git a/src/nm.c b/src/nm.c
index dd69a00e..dc6403f2 100644
--- 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
diff --git a/src/objdump.c b/src/objdump.c
index 1234c794..e683a29f 100644
--- a/src/objdump.c
+++ b/src/objdump.c
@@ -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);
}
}