From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 00FDD3856DDA for ; Wed, 10 Aug 2022 14:24:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 00FDD3856DDA Received: from mail-wm1-f71.google.com (mail-wm1-f71.google.com [209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-20-OgboPSR8Of2DGgN5THanVw-1; Wed, 10 Aug 2022 10:24:48 -0400 X-MC-Unique: OgboPSR8Of2DGgN5THanVw-1 Received: by mail-wm1-f71.google.com with SMTP id r5-20020a1c4405000000b003a534ec2570so1156246wma.7 for ; Wed, 10 Aug 2022 07:24:48 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc; bh=pDvo6MRi71cRW23dtVsG+Lit9/EGRSBG+7Zb8/J6sKk=; b=zRWw8VVpiNiRPwvyOZIEK54Yo5dh6uIolI5fL6tOWAOPcDGSJ7RfMPT9E0lplcxWo4 CfJZ1kSpYYM+YL+JQD4WcCX2ce/wBfLEtnru9spzjr0tzsCPHX0Y/YJ9GhOP6RFdHz1E h8Q0Xqb32GR4P3LGwxakOFBKF9pVa4OLDOHkItjCBooYXfNNCSIGyPiydQZHfT5ZMkMw UPunDqVRiMcZuZUaoq/VANtumuWZMjPeoEKbwaWI1B2Ecwy2TNtCBKV/VoqxoxebiM2+ mPhBPJ2l6LMJhlLsSXY+nx4f8k2E+SmcY22C4Gpl3azu+JoVzfkLe2i6U0B9akpwtye7 riMw== X-Gm-Message-State: ACgBeo3/wZ7QvxQtWilwaNsx4fvmJmDeI91DXLyVMVPvCvfYTNyH/M1F L/2s443rdbXmRc3Po/wDJaBUG3abjVMJQb7+lH9G/LRJ/jHF0+6bJIwOu91sII8RNIaxgLv514g uVJJsxcjAAoNuF6NQ/TLOqJKmclgkQhkTGTus4S8YlVgUE9DNTgvW+xjOG+IpxmNiUo7fWw== X-Received: by 2002:a05:600c:5028:b0:3a5:56d7:24b1 with SMTP id n40-20020a05600c502800b003a556d724b1mr2716558wmr.26.1660141487064; Wed, 10 Aug 2022 07:24:47 -0700 (PDT) X-Google-Smtp-Source: AA6agR5UcOTF0IdVZnWWoUB0xppt0P6RZ3NllTtQ4hIBiOFFg3w7qZoClPRu4/l7IvSViZBjC4gg9Q== X-Received: by 2002:a05:600c:5028:b0:3a5:56d7:24b1 with SMTP id n40-20020a05600c502800b003a556d724b1mr2716541wmr.26.1660141486570; Wed, 10 Aug 2022 07:24:46 -0700 (PDT) Received: from localhost (15.72.115.87.dyn.plus.net. [87.115.72.15]) by smtp.gmail.com with ESMTPSA id w8-20020a5d6088000000b002185631adf0sm16292327wrt.23.2022.08.10.07.24.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 10 Aug 2022 07:24:46 -0700 (PDT) From: Andrew Burgess To: binutils@sourceware.org Cc: Andrew Burgess Subject: [PATCH 3/3] objdump: allow the disassembler colors to be customized Date: Wed, 10 Aug 2022 15:24:39 +0100 Message-Id: X-Mailer: git-send-email 2.25.4 In-Reply-To: References: MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII"; x-default=true X-Spam-Status: No, score=-10.4 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_BARRACUDACENTRAL, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 10 Aug 2022 14:24:53 -0000 This commit extends the use of OBJDUMP_COLORS to allow all the disassembler colors to be controlled by the user. The approach used is to have the environment variable OBJDUMP_COLORS contain a simple map of a two letter code to the appropriate escape sequence to use. For example: OBJDUMP_COLORS="sy=38;5;162:rg=38;5;215" Makes use of color 162 for symbol names (sy) and color 215 for register names (rg). Both of these colors are from the 256 color space. Any styles not mentioned in OBJDUMP_COLORS will use their default colors. Building on the previous commit, OBJDUMP_COLORS can still control the default styling mode, for example: OBJDUMP_COLORS="extended:sy=38;5;162:rg=38;5;215" With the addition of the 'extended:' prefix, unless told otherwise by a command line argument, objdump will use the 256 extended-colors by default for styling, and symbol names and register names will use the modified colors. I don't know if this style of environment encoded settings will be acceptable or not. The alternative would be some kind of configuration file system. My inspiration for the approach I propose here is the LS_COLORS variable used by `ls`. * doc/binutils.texi (objdump): Extend the description of OBJDUMP_COLORS environment variable. * objdump.c (disasm_styles): New global. (objdump_find_disasm_styles_entry): New function. (objdump_fill_styles_array): New function. (objdump_color_for_disassembler_style): Complete rewrite, return strings from disasm_styles array. (objdump_styled_sprintf): Update to account for changes to objdump_color_for_disassembler_style. --- binutils/doc/binutils.texi | 73 +++++++++++- binutils/objdump.c | 237 ++++++++++++++++++++++++++----------- 2 files changed, 238 insertions(+), 72 deletions(-) diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi index 6606d2c51ac..3955cc954ae 100644 --- a/binutils/doc/binutils.texi +++ b/binutils/doc/binutils.texi @@ -3017,20 +3017,81 @@ The environment variable @code{OBJDUMP_COLORS} can be used to control the colors objdump uses for it's disassembler output. +The format of @code{OBJDUMP_COLORS} is given by @var{} +in: + +@smallexample + ::= ":" + | + | + + ::= "OFF" | "B" | "X" + + ::= + | ":" + + ::= "=" + + ::= "ad" | "ao" | "as" | "cm" | "im" + | "mn" | "rg" | "sm" | "sy" | "tx" +@end smallexample + When objdump disassembles to a terminal, and the @option{--disassembler-color} argument is not used, objdump will, by default, behave as if @option{--disassembler-color=color} had been used. -If @code{OBJDUMP_COLORS} is set to @code{off} then objdump will behave -as if @option{--disassembler-color=off} was given by default. +If @var{} is set to @code{off} then objdump will +behave as if @option{--disassembler-color=off} was given by default. -If @code{OBJDUMP_COLORS} is set to @code{color} then objdump will -behave as if @option{--disassembler-color=color} was given by default. +If @var{} is set to @code{color} then objdump will behave +as if @option{--disassembler-color=color} was given by default. -If @code{OBJDUMP_COLORS} is set to @code{extended} then objdump will -behave as if @option{--disassembler-color=extended-color} was given by +If @var{} is set to @code{extended} then objdump will behave +as if @option{--disassembler-color=extended-color} was given by default. + +Each @var{} is a two letter sequence that identifies a +particular part of the disassembler output, the valid codes are: + +@itemize @bullet +@item ad +The style used to for numerical addresses. +@item ao +The style used for numerical address offsets. +@item as +The style used for assembler directives. +@item cm +The style used for comments. +@item im +The style used for numerical immediates. +@item mn +The style used for the primary instruction mnemonic. +@item rg +The style used for register names. +@item sm +The style used for any secondary mnemonics within an instruction. +@item sy +The style used for symbol names. +@item tx +The style used for anything that is not covered by any of the above +styles. This style should not usually be modified, this will leave +this text styled the same as the rest of objdump's output. +@end itemize + +Each @var{} associates a @var{} with an +@var{}. Each escape string is a series of digits and +@code{;} characters, and will be used as part of an escape sequence to +add styling to the disassembler output. Each @var{} +has @code{\033[} added as a prefix, and @code{m} added as a suffix to +create the complete escape sequence. + +Alternatively, if an @var{} is empty then no styling is +added to this element of the disassembler output. + +Any styles specified in the @var{} override the +corresponding style in the objdump output. Any style not specified in +the @var{} will retain its default styling. @c man end @ignore diff --git a/binutils/objdump.c b/binutils/objdump.c index 1231cda3657..56fe051b62b 100644 --- a/binutils/objdump.c +++ b/binutils/objdump.c @@ -2184,79 +2184,186 @@ objdump_default_disassembler_color_mode (void) return mode; } -/* Return an integer greater than, or equal to zero, representing the color - for STYLE, or -1 if no color should be used. */ +/* An array of strings, one for each entry in enum disassembler_style. + Each string here is either NULL or something that can be used in an + escape sequence to style the disassembler output. */ +static const char *disasm_styles[10] = { NULL }; -static int -objdump_color_for_disassembler_style (enum disassembler_style style) +/* CODE should be a string starting 'XX=' where 'XX' is a two letter style + code. This function returns a pointer to the entry in the global + disasm_styles array that corresponds to 'XX', or NULL if there is no + suitable entry. + + Code must not be NULL. If this function returns non-NULL then CODE is + guaranteed to start with the 3 character pattern 'XX=', but nothing is + guaranteed after that. + + Care is taken to ensure we don't index outside the bounds of + disasm_style, which might happen if new styles have been added and + disasm_styles has not been extended correctly. */ + +static const char ** +objdump_find_disasm_styles_entry (const char *code) { - int color = -1; + enum disassembler_style style; + unsigned int style_idx; + + if (strncmp ("ad=", code, 3) == 0) + style = dis_style_address; + else if (strncmp ("ao=", code, 3) == 0) + style = dis_style_address_offset; + else if (strncmp ("as=", code, 3) == 0) + style = dis_style_assembler_directive; + else if (strncmp ("cm=", code, 3) == 0) + style = dis_style_comment_start; + else if (strncmp ("im=", code, 3) == 0) + style = dis_style_immediate; + else if (strncmp ("mn=", code, 3) == 0) + style = dis_style_mnemonic; + else if (strncmp ("rg=", code, 3) == 0) + style = dis_style_register; + else if (strncmp ("sm=", code, 3) == 0) + style = dis_style_sub_mnemonic; + else if (strncmp ("sy=", code, 3) == 0) + style = dis_style_symbol; + else if (strncmp ("tx=", code, 3) == 0) + style = dis_style_text; + else + return NULL; - if (style == dis_style_comment_start) - disassembler_in_comment = true; + style_idx = (unsigned int) style; + if (style_idx > (sizeof (disasm_styles) / sizeof (disasm_styles[0]))) + return NULL; + + return &disasm_styles[style_idx]; +} + +/* This function should be called at most once, before we first try to use + the global disasm_styles array. This function fills the disasm_styles + array with suitable strings based on which disassembler-color arguments + the user passed to objdump, as well as the OBJDUMP_COLORS environment + variable, if this is set. */ +static void +objdump_fill_styles_array (void) +{ if (disassembler_color == on) { - if (disassembler_in_comment) - return color; - - switch (style) - { - case dis_style_symbol: - color = 32; - break; - case dis_style_assembler_directive: - case dis_style_sub_mnemonic: - case dis_style_mnemonic: - color = 33; - break; - case dis_style_register: - color = 34; - break; - case dis_style_address: - case dis_style_address_offset: - case dis_style_immediate: - color = 35; - break; - default: - case dis_style_text: - color = -1; - break; - } + /* The defaults colors for --disassembler-color=color. */ + disasm_styles[(unsigned int) dis_style_address] = "35"; + disasm_styles[(unsigned int) dis_style_address_offset] = "35"; + disasm_styles[(unsigned int) dis_style_assembler_directive] = "33"; + disasm_styles[(unsigned int) dis_style_comment_start] = NULL; + disasm_styles[(unsigned int) dis_style_immediate] = "35"; + disasm_styles[(unsigned int) dis_style_mnemonic] = "33"; + disasm_styles[(unsigned int) dis_style_register] = "34"; + disasm_styles[(unsigned int) dis_style_sub_mnemonic] = "33"; + disasm_styles[(unsigned int) dis_style_symbol] = "32"; + disasm_styles[(unsigned int) dis_style_text] = NULL; } else if (disassembler_color == extended) { - if (disassembler_in_comment) - return 250; + /* The defaults colors for --disassembler-color=extended-color. */ + disasm_styles[(unsigned int) dis_style_address] = "38;5;134"; + disasm_styles[(unsigned int) dis_style_address_offset] = "38;5;134"; + disasm_styles[(unsigned int) dis_style_assembler_directive] = "38;5;142"; + disasm_styles[(unsigned int) dis_style_comment_start] = "38;5;250"; + disasm_styles[(unsigned int) dis_style_immediate] = "38;5;134"; + disasm_styles[(unsigned int) dis_style_mnemonic] = "38;5;142"; + disasm_styles[(unsigned int) dis_style_register] = "38;5;27"; + disasm_styles[(unsigned int) dis_style_sub_mnemonic] = "38;5;142"; + disasm_styles[(unsigned int) dis_style_symbol] = "38;5;40"; + disasm_styles[(unsigned int) dis_style_text] = NULL; + } + else if (disassembler_color != off) + bfd_fatal (_("disassembly color not correctly selected")); - switch (style) + if (disassembler_color != off) + { + const char *env_var = getenv (objdump_colors_var); + if (env_var != NULL) { - case dis_style_symbol: - color = 40; - break; - case dis_style_assembler_directive: - case dis_style_sub_mnemonic: - case dis_style_mnemonic: - color = 142; - break; - case dis_style_register: - color = 27; - break; - case dis_style_address: - case dis_style_address_offset: - case dis_style_immediate: - color = 134; - break; - default: - case dis_style_text: - color = -1; - break; + /* Create a copy of the colors environment variable. The + disasm_styles array will point directly into our copy, which + we will modify to insert '\0' at appropriate places. */ + static char *env_colors = NULL; + env_colors = strdup (env_var); + const char **style_entry; + char *ptr; + + /* Skip a leading color mode specifier. */ + if (strncmp (env_colors, "off", 3) == 0 + || strncmp (env_colors, "color", 5) == 0 + || strncmp (env_colors, "extended", 8) == 0) + { + while (*env_colors != ':' && *env_colors != '\0') + ++env_colors; + } + + /* Skip any leading colon. */ + if (env_colors[0] == ':') + env_colors++; + + ptr = env_colors; + while (*ptr != '\0') + { + style_entry = objdump_find_disasm_styles_entry (ptr); + if (style_entry != NULL) + { + ptr += 3; + if (*ptr == '\0' || *ptr == ':') + *style_entry = NULL; + else + { + const char *esc_str = ptr; + + for (; *ptr != '\0' && *ptr != ':'; ++ptr) + { + if (!ISDIGIT (*ptr) && *ptr != ';') + esc_str = NULL; + } + *style_entry = esc_str; + } + } + + if (*ptr == ':') + { + *ptr = '\0'; + ptr++; + } + } } } - else if (disassembler_color != off) - bfd_fatal (_("disassembly color not correctly selected")); +} + +/* Return the escape code sequence for STYLE, or NULL if no escape code + should be emitted for this style. */ + +static const char * +objdump_color_for_disassembler_style (enum disassembler_style style) +{ + unsigned int style_idx; + static bool color_init = false; + + if (!color_init) + { + objdump_fill_styles_array (); + color_init = true; + } + + /* If this is the start of a comment, or we previously saw the start of a + comment, then force the style to comment style. */ + if (style == dis_style_comment_start) + disassembler_in_comment = true; + if (disassembler_in_comment) + style = dis_style_comment_start; + + /* Select and return the appropriate style from the styles array. */ + style_idx = (unsigned int) style; + if (style_idx > (sizeof (disasm_styles) / sizeof (disasm_styles[0]))) + return NULL; + return disasm_styles[style_idx]; - return color; } /* Like objdump_sprintf, but add in escape sequences to highlight the @@ -2268,18 +2375,16 @@ objdump_styled_sprintf (SFILE *f, enum disassembler_style style, { size_t n; va_list args; - int color = objdump_color_for_disassembler_style (style); + const char *color_esc_seq = objdump_color_for_disassembler_style (style); - if (color >= 0) + if (color_esc_seq != NULL) { while (1) { size_t space = f->alloc - f->pos; - if (disassembler_color == on) - n = snprintf (f->buffer + f->pos, space, "\033[%dm", color); - else - n = snprintf (f->buffer + f->pos, space, "\033[38;5;%dm", color); + n = snprintf (f->buffer + f->pos, space, "\033[%sm", + color_esc_seq); if (space > n) break; @@ -2305,7 +2410,7 @@ objdump_styled_sprintf (SFILE *f, enum disassembler_style style, } f->pos += n; - if (color >= 0) + if (color_esc_seq != NULL) { while (1) { -- 2.25.4