From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by sourceware.org (Postfix) with ESMTPS id 98906385781A for ; Wed, 17 Mar 2021 10:37:58 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 98906385781A Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=tdevries@suse.de X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id ABD12AB8C; Wed, 17 Mar 2021 10:37:57 +0000 (UTC) Date: Wed, 17 Mar 2021 11:37:55 +0100 From: Tom de Vries To: dwz@sourceware.org, jakub@redhat.com, mark@klomp.org Subject: [PATCH] Factor out args.c and args.h Message-ID: <20210317103754.GA13562@delia> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.10.1 (2018-07-13) X-Spam-Status: No, score=-12.2 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: dwz@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Dwz mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 17 Mar 2021 10:38:02 -0000 Hi, Reduces dwz.c from 17079 to 16450 lines, a reduction of 629 lines or ~3.7%. Tested performance, no regression found. Any comments? Thanks, - Tom Factor out args.c and args.h 2021-03-17 Tom de Vries * Makefile (OBJECTS): Add args.o. * dwz.c (skip_producer, add_skip_producer, do_indent, wrap) (print_options_help, usage, version, parse_args): Move ... * args.c: ... here. New file. * args.h: New file. (parse_args, skip_producer): Declare. --- Makefile | 2 +- args.c | 637 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ args.h | 94 ++++++++++ dwz.c | 631 +------------------------------------------------------------- 4 files changed, 733 insertions(+), 631 deletions(-) diff --git a/Makefile b/Makefile index 2f7c76a..e09d31a 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ exec_prefix = $(prefix) bindir = $(exec_prefix)/bin datarootdir = $(prefix)/share mandir = $(datarootdir)/man -OBJECTS = dwz.o hashtab.o sha1.o dwarfnames.o +OBJECTS = args.o dwz.o hashtab.o sha1.o dwarfnames.o dwz: $(OBJECTS) $(CC) $(LDFLAGS) -o $@ $^ -lelf install: dwz diff --git a/args.c b/args.c new file mode 100644 index 0000000..cc8c717 --- /dev/null +++ b/args.c @@ -0,0 +1,637 @@ +/* Copyright (C) 2001-2021 Red Hat, Inc. + Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2019-2021 SUSE LLC. + Written by Jakub Jelinek , 2012. + + This program 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; either version 2, or (at your option) + any later version. + + This program 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 this program; see the file COPYING. If not, write to + the Free Software Foundation, 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include +#include +#include +#include +#include +#include +#include + +#include "args.h" + +#if DEVEL +int tracing; +int ignore_size; +int ignore_locus; +int dump_checksum_p; +int dump_dies_p; +int dump_dups_p; +int dump_pus_p; +int verify_dups_p; +int verify_edge_freelist; +int stats_p; +int checksum_cycle_opt = 1; +int skip_producers_p; +#endif + +int unoptimized_multifile; +int save_temps; +int verify_edges_p; +int dump_edges_p; +int partition_dups_opt; +int progress_p; +int progress_mem_p; +int import_opt_p = 1; +int force_p; + +enum deduplication_mode deduplication_mode = dm_inter_cu; + +int uni_lang_p = 0; +int gen_cu_p = 0; + +enum die_count_methods die_count_method = estimate; + +int odr = 0; +enum odr_mode odr_mode = ODR_LINK; + +/* Filename if inter-file size optimization should be performed. */ +const char *multifile; + +/* Argument of -M option, i.e. preferred name that should be stored + into the .gnu_debugaltlink or .debug_sup section. */ +const char *multifile_name; + +/* True if -r option is present, i.e. .gnu_debugaltlink or .debug_sup section + should contain a filename relative to the directory in which + the particular file is present. */ +bool multifile_relative; + +/* True if DWARF 5 .debug_sup and DW_FORM_ref_sup4 / DW_FORM_strp_sup + should be used instead of the GNU extensions .gnu_debugaltlink + and DW_FORM_GNU_ref_alt / DW_FORM_GNU_strp_alt etc. */ +bool dwarf_5; + +/* True if -q option has been passed. */ +bool quiet; + +/* Number of DIEs, above which dwz retries processing + in low_mem mode (and give up on multifile optimizing + the file in question). */ +unsigned int low_mem_die_limit = 10000000; + +/* Number of DIEs, above which dwz gives up processing + input altogether. */ +unsigned int max_die_limit = 50000000; + +/* Phase of multifile handling. */ +unsigned char multifile_mode; + +static int die_count_method_parsed; +static int deduplication_mode_parsed; +static int odr_mode_parsed; +static int skip_producer_parsed; + +/* Options for getopt_long. */ +static struct option dwz_options[] = +{ + { "help", no_argument, 0, '?' }, + { "output", required_argument, 0, 'o' }, + { "multifile", required_argument, 0, 'm' }, + { "quiet", no_argument, 0, 'q' }, + { "hardlink", no_argument, 0, 'h' }, + { "low-mem-die-limit", required_argument, 0, 'l' }, + { "max-die-limit", required_argument, 0, 'L' }, + { "multifile-name", required_argument, 0, 'M' }, + { "relative", no_argument, 0, 'r' }, + { "version", no_argument, 0, 'v' }, + { "import-optimize", + no_argument, &import_opt_p, 1 }, + { "no-import-optimize", + no_argument, &import_opt_p, 0 }, + { "dwarf-5", no_argument, 0, '5' }, +#if DEVEL + { "devel-trace", no_argument, &tracing, 1 }, + { "devel-progress", no_argument, &progress_p, 1 }, + { "devel-progress-mem",no_argument, &progress_mem_p, 1 }, + { "devel-ignore-size", no_argument, &ignore_size, 1 }, + { "devel-ignore-locus",no_argument, &ignore_locus, 1 }, + { "devel-force", no_argument, &force_p, 1 }, + { "devel-save-temps", no_argument, &save_temps, 1 }, + { "devel-dump-checksum", + no_argument, &dump_checksum_p, 1 }, + { "devel-dump-dies", no_argument, &dump_dies_p, 1 }, + { "devel-dump-dups", no_argument, &dump_dups_p, 1 }, + { "devel-dump-pus", no_argument, &dump_pus_p, 1 }, + { "devel-unoptimized-multifile", + no_argument, &unoptimized_multifile, 1 }, + { "devel-verify-edges",no_argument, &verify_edges_p, 1 }, + { "devel-verify-dups", no_argument, &verify_dups_p, 1 }, + { "devel-dump-edges", no_argument, &dump_edges_p, 1 }, + { "devel-partition-dups-opt", + no_argument, &partition_dups_opt, 1 }, + { "devel-die-count-method", + required_argument, &die_count_method_parsed, 1 }, + { "devel-stats", no_argument, &stats_p, 1 }, + { "devel-deduplication-mode", + required_argument, &deduplication_mode_parsed, 1 }, + { "devel-uni-lang", + no_argument, &uni_lang_p, 1 }, + { "devel-no-uni-lang", + no_argument, &uni_lang_p, 0 }, + { "devel-gen-cu", + no_argument, &gen_cu_p, 1 }, + { "devel-no-gen-cu", + no_argument, &gen_cu_p, 0 }, + { "devel-checksum-cycle-opt", + no_argument, &checksum_cycle_opt, 1 }, + { "devel-no-checksum-cycle-opt", + no_argument, &checksum_cycle_opt, 0 }, + { "devel-skip-producer", + required_argument, &skip_producer_parsed, 1}, +#endif + { "odr", no_argument, &odr, 1 }, + { "no-odr", no_argument, &odr, 0 }, + { "odr-mode", required_argument, &odr_mode_parsed, 1 }, + { NULL, no_argument, 0, 0 } +}; + +/* Struct describing various usage aspects of a command line option. */ +struct option_help +{ + const char *short_name; + const char *long_name; + const char *argument; + const char *default_value; + const char *msg; +}; + +/* Describe common command line options. */ +static struct option_help dwz_common_options_help[] = +{ + { "q", "quiet", NULL, NULL, + "Silence up the most common messages." }, + { "l", "low-mem-die-limit", "", "10 million DIEs", + "Handle files larger than this limit using a slower and more memory" + " usage friendly mode and don't optimize those files in multifile mode." }, + { "L", "max-die-limit", "", "50 million DIEs", + "Don't optimize files larger than this limit." }, + { NULL, "odr", NULL, NULL, + NULL }, + { NULL, "no-odr", NULL, "Disabled", + "Enable/disable one definition rule optimization." }, + { NULL, "odr-mode", "", "link", + "Set aggressiveness level of one definition rule optimization." }, + { NULL, "import-optimize", NULL, NULL, + NULL }, + { NULL, "no-import-optimize", NULL, "Enabled", + "Enable/disable optimization that reduces the number of" + " DW_TAG_imported_unit DIEs." } +}; + +/* Describe single-file command line options. */ +static struct option_help dwz_single_file_options_help[] = +{ + { "o", "output", "OUTFILE", NULL, + "Place the output in OUTFILE." } +}; + +/* Describe mult-file command line options. */ +static struct option_help dwz_multi_file_options_help[] = +{ + { "h", "hardlink", NULL, NULL, + "Handle hardlinked files as one file." }, + { "m", "multifile", "COMMONFILE", NULL, + "Enable multifile optimization, placing common DIEs in multifile" + " COMMONFILE." }, + { "M", "multifile-name", "NAME", NULL, + "Set .gnu_debugaltlink or .debug_sup in files to NAME." }, + { "r", "relative", NULL, NULL, + "Set .gnu_debugaltlink in files to relative path from file directory" + " to multifile." }, + { "5", "dwarf-5", NULL, NULL, + "Emit DWARF 5 standardized supplementary object files instead of" + " GNU extension .debug_altlink." } +}; + +/* Describe misc command line options. */ +static struct option_help dwz_misc_options_help[] = +{ + { "v", "version", NULL, NULL, + "Display dwz version information." }, + { "?", "help", NULL, NULL, + "Display this information." } +}; + +/* Print LEN spaces to STREAM. */ +static void +do_indent (FILE *stream, unsigned int len) +{ + unsigned int i; + + for (i = 0; i < len; i++) + fprintf (stream, " "); +} + +/* Print MSG to STREAM, indenting to INDENT and wrapping at LIMIT. + Assume starting position is at INDENT. */ +static void +wrap (FILE *stream, unsigned int indent, unsigned int limit, const char *msg) +{ + unsigned int len = indent; + const char *s = msg; + while (true) + { + const char *e = strchr (s, ' '); + unsigned int word_len; + if (e == NULL) + word_len = strlen (s); + else + word_len = e - s; + if (word_len == 0) + return; + + if (len + 1 /* space */ + word_len > limit) + { + fprintf (stream, "\n"); + do_indent (stream ,indent); + len = indent; + } + else if (len > indent) + { + fprintf (stream, " "); + len += 1; + } + + if (e != NULL) + { + const char *i; + for (i = s; i < e; ++i) + fprintf (stream, "%c", *i); + } + else + fprintf (stream, "%s", s); + len += word_len; + + if (e == NULL) + break; + + s = e + 1; + } +} + +/* Print OPTIONS_HELP of length H to STREAM, indenting to help message to + INDENT an wrapping at LIMIT. */ +static void +print_options_help (FILE *stream, struct option_help *options_help, unsigned int n, + unsigned int indent, unsigned int limit) +{ + unsigned len; + const char *s; + unsigned int i; + + for (i = 0; i < n; ++i) + { + len = 0; + + fprintf (stream, " "); + len += 2; + + s = options_help[i].short_name; + if (s) + { + fprintf (stream, "-%s", s); + len += 2; + } + + s = options_help[i].long_name; + if (len == 4) + { + fprintf (stream, ", "); + len += 2; + } + fprintf (stream, "--%s", s); + len += 2 + strlen (s); + + s = options_help[i].argument; + if (s) + { + fprintf (stream, " %s", s); + len += 1 + strlen (s); + } + + s = options_help[i].msg; + if (s) + { + if (len > indent) + { + fprintf (stream, "\n"); + do_indent (stream, indent); + } + else + do_indent (stream, indent - len); + len = indent; + + wrap (stream, indent, limit, s); + } + fprintf (stream, "\n"); + + s = options_help[i].default_value; + if (s) + { + do_indent (stream, indent); + fprintf (stream, "Default value: %s.\n", s); + } + } +} + +/* Print usage and exit. */ +static void +usage (const char *progname, int failing) +{ + unsigned int n; + unsigned int indent, limit; + FILE *stream = failing ? stderr : stdout; + + fprintf (stream, + ("Usage:\n" + " %s [common options] [-h] [-m COMMONFILE] [-M NAME | -r] [FILES]\n" + " %s [common options] -o OUTFILE FILE\n" + " %s [ -v | -? ]\n"), + progname, progname, progname); + + indent = 30; + limit = 80; + fprintf (stream, "Common options:\n"); + n = (sizeof (dwz_common_options_help) + / sizeof (dwz_common_options_help[0])); + print_options_help (stream, dwz_common_options_help, n, indent, limit); + + fprintf (stream, "Single-file options:\n"); + n = (sizeof (dwz_single_file_options_help) + / sizeof (dwz_single_file_options_help[0])); + print_options_help (stream, dwz_single_file_options_help, n, indent, limit); + + fprintf (stream, "Multi-file options:\n"); + n = (sizeof (dwz_multi_file_options_help) + / sizeof (dwz_multi_file_options_help[0])); + print_options_help (stream, dwz_multi_file_options_help, n, indent, limit); + + fprintf (stream, "Miscellaneous options:\n"); + n = (sizeof (dwz_misc_options_help) + / sizeof (dwz_misc_options_help[0])); + print_options_help (stream, dwz_misc_options_help, n, indent, limit); + +#if DEVEL + fprintf (stream, "Development options:\n"); + fprintf (stream, "%s", + (" --devel-trace\n" + " --devel-progress\n" + " --devel-progress-mem\n" + " --devel-stats\n" + " --devel-ignore-size\n" + " --devel-ignore-locus\n" + " --devel-force\n" + " --devel-save-temps\n" + " --devel-dump-checksum\n" + " --devel-dump-dies\n" + " --devel-dump-dups\n" + " --devel-dump-pus\n" + " --devel-unoptimized-multifile\n" + " --devel-verify-dups\n" + " --devel-verify-edges\n" + " --devel-dump-edges\n" + " --devel-partition-dups-opt\n" + " --devel-die-count-method\n" + " --devel-deduplication-mode={none,intra-cu,inter-cu}\n" + " --devel-uni-lang / --devel-no-uni-lang\n" + " --devel-gen-cu / --devel-no-gen-cu\n" + " --devel-skip-producer \n")); +#endif + + exit (failing); +} + +/* Print version and exit. */ +static void +version (void) +{ + printf ("dwz version " DWZ_VERSION "\n" + "Copyright (C) " RH_YEARS " Red Hat, Inc.\n" + "Copyright (C) " FSF_YEARS " Free Software Foundation, Inc.\n" + "Copyright (C) " SUSE_YEARS " SUSE LLC.\n" + "This program is free software; you may redistribute it under the terms of\n" + "the GNU General Public License version 3 or (at your option) any later version.\n" + "This program has absolutely no warranty.\n"); + exit (0); +} + +static const char **skip_producers; +static size_t skip_producers_size; +static size_t nr_skip_producers; + +static void +add_skip_producer (const char *producer) +{ + size_t alloc_size; + if (skip_producers == NULL) + { + skip_producers_size = 10; + alloc_size = skip_producers_size * sizeof (const char *); + skip_producers = malloc (alloc_size); + } + else if (nr_skip_producers == skip_producers_size) + { + skip_producers_size += 10; + alloc_size = skip_producers_size * sizeof (const char *); + skip_producers = realloc (skip_producers, alloc_size); + } + + skip_producers[nr_skip_producers] = producer; + nr_skip_producers++; +} + +bool +skip_producer (const char *producer) +{ + size_t i; + + if (producer == NULL) + return false; + + for (i = 0; i < nr_skip_producers; ++i) + { + const char *skip = skip_producers[i]; + if (strncmp (skip, producer, strlen (skip)) == 0) + return true; + } + + return false; +} + +/* Parse command line arguments in ARGV. */ +void +parse_args (int argc, char *argv[], bool *hardlink, const char **outfile) +{ + unsigned long l; + char *end; + + while (1) + { + int option_index = -1; + int c = getopt_long (argc, argv, "m:o:qhl:L:M:r?v5", dwz_options, + &option_index); + if (c == -1) + break; + switch (c) + { + default: + case '?': + usage (argv[0], option_index == -1); + break; + + case 0: + /* Option handled by getopt_long. */ + if (die_count_method_parsed) + { + die_count_method_parsed = 0; + if (strcmp (optarg, "none") == 0) + { + die_count_method = none; + break; + } + if (strcmp (optarg, "estimate") == 0) + { + die_count_method = estimate; + break; + } + error (1, 0, "invalid argument --devel-die-count-method %s", + optarg); + } + if (deduplication_mode_parsed) + { + deduplication_mode_parsed = 0; + if (strcmp (optarg, "none") == 0) + { + deduplication_mode = dm_none; + break; + } + if (strcmp (optarg, "intra-cu") == 0) + { + deduplication_mode = dm_intra_cu; + break; + } + if (strcmp (optarg, "inter-cu") == 0) + { + deduplication_mode = dm_inter_cu; + break; + } + error (1, 0, "invalid argument --devel-deduplication-mode %s", + optarg); + } + if (odr_mode_parsed) + { + odr_mode_parsed = 0; + if (strcmp (optarg, "basic") == 0) + { + odr_mode = ODR_BASIC; + break; + } + if (strcmp (optarg, "link") == 0) + { + odr_mode = ODR_LINK; + break; + } + error (1, 0, "invalid argument --odr-mode %s", + optarg); + } + if (skip_producer_parsed) + { + skip_producer_parsed = 0; + add_skip_producer (optarg); + +#if DEVEL + skip_producers_p = 1; +#endif + } + break; + + case 'o': + *outfile = optarg; + break; + + case 'm': + multifile = optarg; + break; + + case 'q': + quiet = true; + break; + + case 'h': + *hardlink = true; + break; + + case 'M': + multifile_name = optarg; + break; + + case 'r': + multifile_relative = true; + break; + + case 'l': + if (strcmp (optarg, "none") == 0) + { + low_mem_die_limit = -1U; + break; + } + l = strtoul (optarg, &end, 0); + if (*end != '\0' || optarg == end || (unsigned int) l != l) + error (1, 0, "invalid argument -l %s", optarg); + low_mem_die_limit = l; + break; + + case 'L': + if (strcmp (optarg, "none") == 0) + { + max_die_limit = -1U; + break; + } + l = strtoul (optarg, &end, 0); + if (*end != '\0' || optarg == end || (unsigned int) l != l) + error (1, 0, "invalid argument -L %s", optarg); + max_die_limit = l; + break; + + case '5': + dwarf_5 = true; + break; + + case 'v': + version (); + break; + } + } + + if (progress_mem_p) + progress_p = 1; + + /* Specifying a low-mem die-limit that is larger than or equal to the + max die-limit has the effect of disabling low-mem mode. Make this + explicit by setting it to the 'none' value. */ + if (low_mem_die_limit != -1U + && low_mem_die_limit >= max_die_limit) + low_mem_die_limit = -1U; + + if (multifile_relative && multifile_name) + error (1, 0, "-M and -r options can't be specified together"); +} diff --git a/args.h b/args.h new file mode 100644 index 0000000..c899003 --- /dev/null +++ b/args.h @@ -0,0 +1,94 @@ +/* Copyright (C) 2001-2021 Red Hat, Inc. + Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2019-2021 SUSE LLC. + Written by Jakub Jelinek , 2012. + + This program 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; either version 2, or (at your option) + any later version. + + This program 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 this program; see the file COPYING. If not, write to + the Free Software Foundation, 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#if DEVEL +extern int tracing; +extern int ignore_size; +extern int ignore_locus; +extern int dump_checksum_p; +extern int dump_dies_p; +extern int dump_dups_p; +extern int dump_pus_p; +extern int verify_dups_p; +extern int verify_edge_freelist; +extern int stats_p; +extern int checksum_cycle_opt; +extern int skip_producers_p; +#else +#define tracing 0 +#define ignore_size 0 +#define ignore_locus 0 +#define dump_checksum_p 0 +#define dump_dies_p 0 +#define dump_dups_p 0 +#define dump_pus_p 0 +#define verify_dups_p 0 +#define stats_p 0 +#define checksum_cycle_opt 1 +#define skip_producers_p 0 +#endif + +extern int unoptimized_multifile; +extern int save_temps; +extern int verify_edges_p; +extern int dump_edges_p; +extern int partition_dups_opt; +extern int progress_p; +extern int progress_mem_p; +extern int import_opt_p; +extern int force_p; + +enum deduplication_mode +{ + dm_none, + dm_intra_cu, + dm_inter_cu +}; +extern enum deduplication_mode deduplication_mode; + +extern int uni_lang_p; +extern int gen_cu_p; + +enum die_count_methods +{ + none, + estimate +}; +extern enum die_count_methods die_count_method; + +extern int odr; +enum odr_mode { ODR_BASIC, ODR_LINK }; +extern enum odr_mode odr_mode; + +extern const char *multifile; +extern const char *multifile_name; +extern bool multifile_relative; + +extern unsigned char multifile_mode; + +extern bool dwarf_5; + +extern bool quiet; + +extern unsigned int low_mem_die_limit; +extern unsigned int max_die_limit; + +extern void parse_args (int, char *[], bool *, const char **); +extern bool skip_producer (const char *producer); diff --git a/dwz.c b/dwz.c index 8f64a34..31a0dd3 100644 --- a/dwz.c +++ b/dwz.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -42,6 +41,7 @@ #include "dwarf2.h" #include "hashtab.h" #include "sha1.h" +#include "args.h" #ifndef SHF_COMPRESSED /* Glibc elf.h contains SHF_COMPRESSED starting v2.22. Libelf libelf.h has @@ -148,8 +148,6 @@ print_mem (long m) fprintf (stderr, "%ld (%.1f%s)\n", m, h, unit[level]); } -static int progress_mem_p; - static void report_progress (void) { @@ -235,64 +233,8 @@ static struct obstack ob2; and restored during final cleanup. */ static struct obstack alt_ob, alt_ob2; -#if DEVEL -static int tracing; -static int ignore_size; -static int ignore_locus; -static int dump_checksum_p; -static int dump_dies_p; -static int dump_dups_p; -static int dump_pus_p; -static int verify_dups_p; -static int verify_edge_freelist; -static int stats_p; -static int checksum_cycle_opt = 1; -static int skip_producers_p; -#else -#define tracing 0 -#define ignore_size 0 -#define ignore_locus 0 -#define dump_checksum_p 0 -#define dump_dies_p 0 -#define dump_dups_p 0 -#define dump_pus_p 0 -#define verify_dups_p 0 -#define stats_p 0 -#define checksum_cycle_opt 1 -#define skip_producers_p 0 -#endif -static int unoptimized_multifile; -static int save_temps = 0; -static int verify_edges_p = 0; -static int dump_edges_p = 0; -static int partition_dups_opt; -static int progress_p; -static int import_opt_p = 1; -static int force_p = 0; -enum deduplication_mode -{ - dm_none, - dm_intra_cu, - dm_inter_cu -}; -static enum deduplication_mode deduplication_mode = dm_inter_cu; -static int uni_lang_p = 0; -static int gen_cu_p = 0; -enum die_count_methods -{ - none, - estimate -}; -static enum die_count_methods die_count_method = estimate; - -static int odr = 0; -enum odr_mode { ODR_BASIC, ODR_LINK }; -static enum odr_mode odr_mode = ODR_LINK; -static int odr_mode_parsed = 0; static bool odr_active_p = false; -static int skip_producer_parsed = 0; - /* Struct to gather statistics. */ struct stats { @@ -887,18 +829,6 @@ static int multi_endian; /* Highest .gdb_index version seen. */ static unsigned int multi_gdb_index_ver; -/* Number of DIEs, above which dwz retries processing - in low_mem mode (and give up on multifile optimizing - the file in question). */ -static unsigned int low_mem_die_limit = 10000000; - -/* Number of DIEs, above which dwz gives up processing - input altogether. */ -static unsigned int max_die_limit = 50000000; - -/* Phase of multifile handling. */ -static unsigned char multifile_mode; - enum multifile_mode_kind { MULTIFILE_MODE_WR = 1, @@ -923,29 +853,9 @@ enum multifile_mode_kind /* True if running in low_mem mode. */ #define low_mem (multifile_mode & MULTIFILE_MODE_LOW_MEM) -/* Filename if inter-file size optimization should be performed. */ -static const char *multifile; - -/* Argument of -M option, i.e. preferred name that should be stored - into the .gnu_debugaltlink or .debug_sup section. */ -static const char *multifile_name; - -/* True if -r option is present, i.e. .gnu_debugaltlink or .debug_sup section - should contain a filename relative to the directory in which - the particular file is present. */ -static bool multifile_relative; - /* SHA1 checksum (build-id) of the common file. */ static unsigned char multifile_sha1[0x14]; -/* True if DWARF 5 .debug_sup and DW_FORM_ref_sup4 / DW_FORM_strp_sup - should be used instead of the GNU extensions .gnu_debugaltlink - and DW_FORM_GNU_ref_alt / DW_FORM_GNU_strp_alt etc. */ -static bool dwarf_5; - -/* True if -q option has been passed. */ -static bool quiet; - /* A single attribute in abbreviations. */ struct abbrev_attr { @@ -6652,49 +6562,6 @@ read_lang (unsigned char *ptr, enum dwarf_form form, return ptr; } -static const char **skip_producers; -static size_t skip_producers_size; -static size_t nr_skip_producers; - -static void -add_skip_producer (const char *producer) -{ - size_t alloc_size; - if (skip_producers == NULL) - { - skip_producers_size = 10; - alloc_size = skip_producers_size * sizeof (const char *); - skip_producers = malloc (alloc_size); - } - else if (nr_skip_producers == skip_producers_size) - { - skip_producers_size += 10; - alloc_size = skip_producers_size * sizeof (const char *); - skip_producers = realloc (skip_producers, alloc_size); - } - - skip_producers[nr_skip_producers] = producer; - nr_skip_producers++; -} - -static bool -skip_producer (const char *producer) -{ - size_t i; - - if (producer == NULL) - return false; - - for (i = 0; i < nr_skip_producers; ++i) - { - const char *skip = skip_producers[i]; - if (strncmp (skip, producer, strlen (skip)) == 0) - return true; - } - - return false; -} - /* First phase of the DWARF compression. Parse .debug_info section (for kind == DEBUG_INFO) or .debug_types section (for kind == DEBUG_TYPES) for each CU in it construct internal representation for the CU @@ -16389,502 +16256,6 @@ make_temp_file (const char *name) return fd; } -static int die_count_method_parsed; -static int deduplication_mode_parsed; - -/* Options for getopt_long. */ -static struct option dwz_options[] = -{ - { "help", no_argument, 0, '?' }, - { "output", required_argument, 0, 'o' }, - { "multifile", required_argument, 0, 'm' }, - { "quiet", no_argument, 0, 'q' }, - { "hardlink", no_argument, 0, 'h' }, - { "low-mem-die-limit", required_argument, 0, 'l' }, - { "max-die-limit", required_argument, 0, 'L' }, - { "multifile-name", required_argument, 0, 'M' }, - { "relative", no_argument, 0, 'r' }, - { "version", no_argument, 0, 'v' }, - { "import-optimize", - no_argument, &import_opt_p, 1 }, - { "no-import-optimize", - no_argument, &import_opt_p, 0 }, - { "dwarf-5", no_argument, 0, '5' }, -#if DEVEL - { "devel-trace", no_argument, &tracing, 1 }, - { "devel-progress", no_argument, &progress_p, 1 }, - { "devel-progress-mem",no_argument, &progress_mem_p, 1 }, - { "devel-ignore-size", no_argument, &ignore_size, 1 }, - { "devel-ignore-locus",no_argument, &ignore_locus, 1 }, - { "devel-force", no_argument, &force_p, 1 }, - { "devel-save-temps", no_argument, &save_temps, 1 }, - { "devel-dump-checksum", - no_argument, &dump_checksum_p, 1 }, - { "devel-dump-dies", no_argument, &dump_dies_p, 1 }, - { "devel-dump-dups", no_argument, &dump_dups_p, 1 }, - { "devel-dump-pus", no_argument, &dump_pus_p, 1 }, - { "devel-unoptimized-multifile", - no_argument, &unoptimized_multifile, 1 }, - { "devel-verify-edges",no_argument, &verify_edges_p, 1 }, - { "devel-verify-dups", no_argument, &verify_dups_p, 1 }, - { "devel-dump-edges", no_argument, &dump_edges_p, 1 }, - { "devel-partition-dups-opt", - no_argument, &partition_dups_opt, 1 }, - { "devel-die-count-method", - required_argument, &die_count_method_parsed, 1 }, - { "devel-stats", no_argument, &stats_p, 1 }, - { "devel-deduplication-mode", - required_argument, &deduplication_mode_parsed, 1 }, - { "devel-uni-lang", - no_argument, &uni_lang_p, 1 }, - { "devel-no-uni-lang", - no_argument, &uni_lang_p, 0 }, - { "devel-gen-cu", - no_argument, &gen_cu_p, 1 }, - { "devel-no-gen-cu", - no_argument, &gen_cu_p, 0 }, - { "devel-checksum-cycle-opt", - no_argument, &checksum_cycle_opt, 1 }, - { "devel-no-checksum-cycle-opt", - no_argument, &checksum_cycle_opt, 0 }, - { "devel-skip-producer", - required_argument, &skip_producer_parsed, 1}, -#endif - { "odr", no_argument, &odr, 1 }, - { "no-odr", no_argument, &odr, 0 }, - { "odr-mode", required_argument, &odr_mode_parsed, 1 }, - { NULL, no_argument, 0, 0 } -}; - -/* Struct describing various usage aspects of a command line option. */ -struct option_help -{ - const char *short_name; - const char *long_name; - const char *argument; - const char *default_value; - const char *msg; -}; - -/* Describe common command line options. */ -static struct option_help dwz_common_options_help[] = -{ - { "q", "quiet", NULL, NULL, - "Silence up the most common messages." }, - { "l", "low-mem-die-limit", "", "10 million DIEs", - "Handle files larger than this limit using a slower and more memory" - " usage friendly mode and don't optimize those files in multifile mode." }, - { "L", "max-die-limit", "", "50 million DIEs", - "Don't optimize files larger than this limit." }, - { NULL, "odr", NULL, NULL, - NULL }, - { NULL, "no-odr", NULL, "Disabled", - "Enable/disable one definition rule optimization." }, - { NULL, "odr-mode", "", "link", - "Set aggressiveness level of one definition rule optimization." }, - { NULL, "import-optimize", NULL, NULL, - NULL }, - { NULL, "no-import-optimize", NULL, "Enabled", - "Enable/disable optimization that reduces the number of" - " DW_TAG_imported_unit DIEs." } -}; - -/* Describe single-file command line options. */ -static struct option_help dwz_single_file_options_help[] = -{ - { "o", "output", "OUTFILE", NULL, - "Place the output in OUTFILE." } -}; - -/* Describe mult-file command line options. */ -static struct option_help dwz_multi_file_options_help[] = -{ - { "h", "hardlink", NULL, NULL, - "Handle hardlinked files as one file." }, - { "m", "multifile", "COMMONFILE", NULL, - "Enable multifile optimization, placing common DIEs in multifile" - " COMMONFILE." }, - { "M", "multifile-name", "NAME", NULL, - "Set .gnu_debugaltlink or .debug_sup in files to NAME." }, - { "r", "relative", NULL, NULL, - "Set .gnu_debugaltlink in files to relative path from file directory" - " to multifile." }, - { "5", "dwarf-5", NULL, NULL, - "Emit DWARF 5 standardized supplementary object files instead of" - " GNU extension .debug_altlink." } -}; - -/* Describe misc command line options. */ -static struct option_help dwz_misc_options_help[] = -{ - { "v", "version", NULL, NULL, - "Display dwz version information." }, - { "?", "help", NULL, NULL, - "Display this information." } -}; - -/* Print LEN spaces to STREAM. */ -static void -do_indent (FILE *stream, unsigned int len) -{ - unsigned int i; - - for (i = 0; i < len; i++) - fprintf (stream, " "); -} - -/* Print MSG to STREAM, indenting to INDENT and wrapping at LIMIT. - Assume starting position is at INDENT. */ -static void -wrap (FILE *stream, unsigned int indent, unsigned int limit, const char *msg) -{ - unsigned int len = indent; - const char *s = msg; - while (true) - { - const char *e = strchr (s, ' '); - unsigned int word_len; - if (e == NULL) - word_len = strlen (s); - else - word_len = e - s; - if (word_len == 0) - return; - - if (len + 1 /* space */ + word_len > limit) - { - fprintf (stream, "\n"); - do_indent (stream ,indent); - len = indent; - } - else if (len > indent) - { - fprintf (stream, " "); - len += 1; - } - - if (e != NULL) - { - const char *i; - for (i = s; i < e; ++i) - fprintf (stream, "%c", *i); - } - else - fprintf (stream, "%s", s); - len += word_len; - - if (e == NULL) - break; - - s = e + 1; - } -} - -/* Print OPTIONS_HELP of length H to STREAM, indenting to help message to - INDENT an wrapping at LIMIT. */ -static void -print_options_help (FILE *stream, struct option_help *options_help, unsigned int n, - unsigned int indent, unsigned int limit) -{ - unsigned len; - const char *s; - unsigned int i; - - for (i = 0; i < n; ++i) - { - len = 0; - - fprintf (stream, " "); - len += 2; - - s = options_help[i].short_name; - if (s) - { - fprintf (stream, "-%s", s); - len += 2; - } - - s = options_help[i].long_name; - if (len == 4) - { - fprintf (stream, ", "); - len += 2; - } - fprintf (stream, "--%s", s); - len += 2 + strlen (s); - - s = options_help[i].argument; - if (s) - { - fprintf (stream, " %s", s); - len += 1 + strlen (s); - } - - s = options_help[i].msg; - if (s) - { - if (len > indent) - { - fprintf (stream, "\n"); - do_indent (stream, indent); - } - else - do_indent (stream, indent - len); - len = indent; - - wrap (stream, indent, limit, s); - } - fprintf (stream, "\n"); - - s = options_help[i].default_value; - if (s) - { - do_indent (stream, indent); - fprintf (stream, "Default value: %s.\n", s); - } - } -} - -/* Print usage and exit. */ -static void -usage (const char *progname, int failing) -{ - unsigned int n; - unsigned int indent, limit; - FILE *stream = failing ? stderr : stdout; - - fprintf (stream, - ("Usage:\n" - " %s [common options] [-h] [-m COMMONFILE] [-M NAME | -r] [FILES]\n" - " %s [common options] -o OUTFILE FILE\n" - " %s [ -v | -? ]\n"), - progname, progname, progname); - - indent = 30; - limit = 80; - fprintf (stream, "Common options:\n"); - n = (sizeof (dwz_common_options_help) - / sizeof (dwz_common_options_help[0])); - print_options_help (stream, dwz_common_options_help, n, indent, limit); - - fprintf (stream, "Single-file options:\n"); - n = (sizeof (dwz_single_file_options_help) - / sizeof (dwz_single_file_options_help[0])); - print_options_help (stream, dwz_single_file_options_help, n, indent, limit); - - fprintf (stream, "Multi-file options:\n"); - n = (sizeof (dwz_multi_file_options_help) - / sizeof (dwz_multi_file_options_help[0])); - print_options_help (stream, dwz_multi_file_options_help, n, indent, limit); - - fprintf (stream, "Miscellaneous options:\n"); - n = (sizeof (dwz_misc_options_help) - / sizeof (dwz_misc_options_help[0])); - print_options_help (stream, dwz_misc_options_help, n, indent, limit); - -#if DEVEL - fprintf (stream, "Development options:\n"); - fprintf (stream, "%s", - (" --devel-trace\n" - " --devel-progress\n" - " --devel-progress-mem\n" - " --devel-stats\n" - " --devel-ignore-size\n" - " --devel-ignore-locus\n" - " --devel-force\n" - " --devel-save-temps\n" - " --devel-dump-checksum\n" - " --devel-dump-dies\n" - " --devel-dump-dups\n" - " --devel-dump-pus\n" - " --devel-unoptimized-multifile\n" - " --devel-verify-dups\n" - " --devel-verify-edges\n" - " --devel-dump-edges\n" - " --devel-partition-dups-opt\n" - " --devel-die-count-method\n" - " --devel-deduplication-mode={none,intra-cu,inter-cu}\n" - " --devel-uni-lang / --devel-no-uni-lang\n" - " --devel-gen-cu / --devel-no-gen-cu\n" - " --devel-skip-producer \n")); -#endif - - exit (failing); -} - -/* Print version and exit. */ -static void -version (void) -{ - printf ("dwz version " DWZ_VERSION "\n" - "Copyright (C) " RH_YEARS " Red Hat, Inc.\n" - "Copyright (C) " FSF_YEARS " Free Software Foundation, Inc.\n" - "Copyright (C) " SUSE_YEARS " SUSE LLC.\n" - "This program is free software; you may redistribute it under the terms of\n" - "the GNU General Public License version 3 or (at your option) any later version.\n" - "This program has absolutely no warranty.\n"); - exit (0); -} - -/* Parse command line arguments in ARGV. */ -static void -parse_args (int argc, char *argv[], bool *hardlink, const char **outfile) -{ - unsigned long l; - char *end; - - while (1) - { - int option_index = -1; - int c = getopt_long (argc, argv, "m:o:qhl:L:M:r?v5", dwz_options, - &option_index); - if (c == -1) - break; - switch (c) - { - default: - case '?': - usage (argv[0], option_index == -1); - break; - - case 0: - /* Option handled by getopt_long. */ - if (die_count_method_parsed) - { - die_count_method_parsed = 0; - if (strcmp (optarg, "none") == 0) - { - die_count_method = none; - break; - } - if (strcmp (optarg, "estimate") == 0) - { - die_count_method = estimate; - break; - } - error (1, 0, "invalid argument --devel-die-count-method %s", - optarg); - } - if (deduplication_mode_parsed) - { - deduplication_mode_parsed = 0; - if (strcmp (optarg, "none") == 0) - { - deduplication_mode = dm_none; - break; - } - if (strcmp (optarg, "intra-cu") == 0) - { - deduplication_mode = dm_intra_cu; - break; - } - if (strcmp (optarg, "inter-cu") == 0) - { - deduplication_mode = dm_inter_cu; - break; - } - error (1, 0, "invalid argument --devel-deduplication-mode %s", - optarg); - } - if (odr_mode_parsed) - { - odr_mode_parsed = 0; - if (strcmp (optarg, "basic") == 0) - { - odr_mode = ODR_BASIC; - break; - } - if (strcmp (optarg, "link") == 0) - { - odr_mode = ODR_LINK; - break; - } - error (1, 0, "invalid argument --odr-mode %s", - optarg); - } - if (skip_producer_parsed) - { - skip_producer_parsed = 0; - add_skip_producer (optarg); - -#if DEVEL - skip_producers_p = 1; -#endif - } - break; - - case 'o': - *outfile = optarg; - break; - - case 'm': - multifile = optarg; - break; - - case 'q': - quiet = true; - break; - - case 'h': - *hardlink = true; - break; - - case 'M': - multifile_name = optarg; - break; - - case 'r': - multifile_relative = true; - break; - - case 'l': - if (strcmp (optarg, "none") == 0) - { - low_mem_die_limit = -1U; - break; - } - l = strtoul (optarg, &end, 0); - if (*end != '\0' || optarg == end || (unsigned int) l != l) - error (1, 0, "invalid argument -l %s", optarg); - low_mem_die_limit = l; - break; - - case 'L': - if (strcmp (optarg, "none") == 0) - { - max_die_limit = -1U; - break; - } - l = strtoul (optarg, &end, 0); - if (*end != '\0' || optarg == end || (unsigned int) l != l) - error (1, 0, "invalid argument -L %s", optarg); - max_die_limit = l; - break; - - case '5': - dwarf_5 = true; - break; - - case 'v': - version (); - break; - } - } - - if (progress_mem_p) - progress_p = 1; - - /* Specifying a low-mem die-limit that is larger than or equal to the - max die-limit has the effect of disabling low-mem mode. Make this - explicit by setting it to the 'none' value. */ - if (low_mem_die_limit != -1U - && low_mem_die_limit >= max_die_limit) - low_mem_die_limit = -1U; - - if (multifile_relative && multifile_name) - error (1, 0, "-M and -r options can't be specified together"); -} - /* Dwarf-compress FILE. If OUTFILE, write to result to OUTFILE, otherwise modify FILE. */ static int