mirror of https://gitee.com/openkylin/dwz.git
744 lines
19 KiB
C
744 lines
19 KiB
C
/* 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 <assert.h>
|
|
#include <getopt.h>
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <error.h>
|
|
#include <gelf.h>
|
|
#include <sys/sysinfo.h>
|
|
|
|
#include "args.h"
|
|
|
|
#include "util.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;
|
|
int max_forks = -1;
|
|
|
|
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;
|
|
|
|
/* Pointer size of multifile. */
|
|
int multifile_force_ptr_size;
|
|
/* Endianity of multifile. */
|
|
int multifile_force_endian;
|
|
|
|
/* 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 },
|
|
{ "multifile-pointer-size",
|
|
required_argument, 0, 'p' },
|
|
{ "multifile-endian",
|
|
required_argument, 0, 'e' },
|
|
{ "jobs", required_argument, 0, 'j' },
|
|
{ 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." }
|
|
};
|
|
|
|
#if NATIVE_ENDIAN_VAL == ELFDATA2MSB
|
|
#define NATIVE_ENDIAN "big"
|
|
#elif NATIVE_ENDIAN_VAL == ELFDATA2LSB
|
|
#define NATIVE_ENDIAN "little"
|
|
#else
|
|
#define NATIVE_ENDIAN "not available"
|
|
#endif
|
|
|
|
/* 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." },
|
|
{ "p", "multifile-pointer-size", "<SIZE|auto|native>", "auto",
|
|
"Set pointer size of multifile, in number of bytes."
|
|
" Native pointer size is " XSTR (NATIVE_POINTER_SIZE) "." },
|
|
{ "e", "multifile-endian", "<l|b|auto|native>", "auto",
|
|
"Set endianity of multifile."
|
|
" Native endianity is " NATIVE_ENDIAN "." },
|
|
{ "j", "jobs", "<n>", "number of processors / 2",
|
|
"Process <n> files in parallel." }
|
|
};
|
|
|
|
/* 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)
|
|
{
|
|
assert (IMPLIES (strlen (s) > 0, s[strlen (s) - 1] == '.'));
|
|
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 (int failing)
|
|
{
|
|
unsigned int n, i;
|
|
unsigned int indent, limit;
|
|
FILE *stream = failing ? stderr : stdout;
|
|
const char *header_lines[] = {
|
|
"dwz [common options] [-h] [-m COMMONFILE] [-M NAME | -r] [-5]",
|
|
" [-p <SIZE|auto|native>] [-e <l|b|auto|native>] [-j N] [FILES]",
|
|
"dwz [common options] -o OUTFILE FILE",
|
|
"dwz [ -v | -? ]"
|
|
};
|
|
unsigned int nr_header_lines
|
|
= sizeof (header_lines) / sizeof (*header_lines);
|
|
|
|
fprintf (stream, "Usage:\n");
|
|
for (i = 0; i < nr_header_lines; ++i)
|
|
fprintf (stream, " %s\n", header_lines[i]);
|
|
|
|
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?v5p:e:j:", dwz_options,
|
|
&option_index);
|
|
if (c == -1)
|
|
break;
|
|
switch (c)
|
|
{
|
|
default:
|
|
case '?':
|
|
usage (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 'p':
|
|
if (strcmp (optarg, "auto") == 0)
|
|
{
|
|
multifile_force_ptr_size = 0;
|
|
break;
|
|
}
|
|
if (strcmp (optarg, "native") == 0)
|
|
{
|
|
multifile_force_ptr_size = NATIVE_POINTER_SIZE;
|
|
break;
|
|
}
|
|
l = strtoul (optarg, &end, 0);
|
|
if (*end != '\0' || optarg == end || (unsigned int) l != l)
|
|
error (1, 0, "invalid argument -l %s", optarg);
|
|
multifile_force_ptr_size = l;
|
|
break;
|
|
|
|
case 'e':
|
|
if (strcmp (optarg, "auto") == 0)
|
|
{
|
|
multifile_force_endian = 0;
|
|
break;
|
|
}
|
|
if (strcmp (optarg, "native") == 0)
|
|
{
|
|
switch (NATIVE_ENDIAN_VAL)
|
|
{
|
|
case ELFDATA2MSB:
|
|
case ELFDATA2LSB:
|
|
multifile_force_endian = NATIVE_ENDIAN_VAL;
|
|
break;
|
|
default:
|
|
error (1, 0, "Cannot determine native endian");
|
|
}
|
|
break;
|
|
}
|
|
if (strlen (optarg) != 1)
|
|
error (1, 0, "invalid argument -l %s", optarg);
|
|
switch (optarg[0])
|
|
{
|
|
case 'l':
|
|
case 'L':
|
|
multifile_force_endian = ELFDATA2LSB;
|
|
break;
|
|
case 'b':
|
|
case 'B':
|
|
multifile_force_endian = ELFDATA2MSB;
|
|
break;
|
|
default:
|
|
error (1, 0, "invalid argument -l %s", optarg);
|
|
}
|
|
break;
|
|
|
|
case 'v':
|
|
version ();
|
|
break;
|
|
|
|
case 'j':
|
|
l = strtoul (optarg, &end, 0);
|
|
if (*end != '\0' || optarg == end || (unsigned int) l != l)
|
|
error (1, 0, "invalid argument -j %s", optarg);
|
|
max_forks = l;
|
|
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");
|
|
|
|
if (max_forks == -1)
|
|
{
|
|
long nprocs = get_nprocs ();
|
|
/* Be conservative on max forks: 4 procs may be actually be 4 SMT
|
|
threads with only 2 cores. */
|
|
max_forks = nprocs / 2;
|
|
}
|
|
}
|