[PATCH] Factor out args.c and args.h
Tom de Vries
tdevries@suse.de
Wed Mar 17 10:37:55 GMT 2021
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 <tdevries@suse.de>
* 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 <jakub@redhat.com>, 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 <getopt.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <error.h>
+
+#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", "<COUNT|none>", "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", "<COUNT|none>", "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", "<basic|link>", "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 <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 <jakub@redhat.com>, 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 <errno.h>
#include <error.h>
#include <fcntl.h>
-#include <getopt.h>
#include <setjmp.h>
#include <string.h>
#include <stdbool.h>
@@ -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", "<COUNT|none>", "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", "<COUNT|none>", "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", "<basic|link>", "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 <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
More information about the Dwz
mailing list