New upstream version 0.15

This commit is contained in:
zhangyuan 2023-03-23 16:03:44 +08:00
parent 8435dca20b
commit 1785552f1c
34 changed files with 2189 additions and 1099 deletions

1
.gitignore vendored
View File

@ -4,4 +4,5 @@
dwz
dwz.sum
dwz.log
native.c
testsuite/dwz.tests/execs

View File

@ -3,25 +3,60 @@ VPATH = $(srcdir)
else
srcdir=$(shell pwd)
endif
CFLAGS = -O2 -g
DWZ_VERSION := $(shell cat $(srcdir)/VERSION)
override CFLAGS += -Wall -W -D_FILE_OFFSET_BITS=64 \
-DDWZ_VERSION='"$(DWZ_VERSION)"' $(shell cat $(srcdir)/COPYRIGHT_YEARS)
CFLAGS_VERSION = -DDWZ_VERSION='"$(DWZ_VERSION)"'
CFLAGS_COPYRIGHT = $(shell cat $(srcdir)/COPYRIGHT_YEARS)
CFLAGS_COMMON = -Wall -W -D_FILE_OFFSET_BITS=64
XXH_PROG = "\#define XXH_INLINE_ALL 1\n\#include <xxhash.h>\n"
XXH_INLINE_ALL_WORKS = $(shell printf $(XXH_PROG) \
| $(CC) -xc -c - -o /dev/null 2>/dev/null \
&& echo -n 1)
ifeq "$(XXH_INLINE_ALL_WORKS)" "1"
CFLAGS_COMMON += -DXXH_INLINE_ALL=1
endif
override CFLAGS += $(CFLAGS_COMMON) $(CFLAGS_VERSION) $(CFLAGS_COPYRIGHT)
prefix = /usr
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 pool.o sha1.o dwarfnames.o
LIBS=-lelf
ifneq "$(XXH_INLINE_ALL_WORKS)" "1"
LIBS += -lxxhash
endif
dwz: $(OBJECTS)
$(CC) $(LDFLAGS) -o $@ $^ -lelf
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
args.o: native.o
args.o: CFLAGS_FOR_SOURCE = \
-DNATIVE_ENDIAN_VAL=$(NATIVE_ENDIAN_VAL) \
-DNATIVE_POINTER_SIZE=$(NATIVE_POINTER_SIZE)
NATIVE_ENDIAN=$(shell readelf -h native.o \
| grep Data \
| sed 's/.*, //;s/ endian//')
NATIVE_ENDIAN_LITTLE=$(findstring $(NATIVE_ENDIAN),$(findstring little,$(NATIVE_ENDIAN)))
NATIVE_ENDIAN_BIG=$(findstring $(NATIVE_ENDIAN),$(findstring big,$(NATIVE_ENDIAN)))
NATIVE_ENDIAN_VAL=$(if $(NATIVE_ENDIAN_LITTLE),ELFDATA2LSB,$(if $(NATIVE_ENDIAN_BIG),ELFDATA2MSB,ELFDATANONE))
NATIVE_POINTER_SIZE=$(shell readelf -wi native.o \
| grep "Pointer Size:" \
| sed 's/.*: *//')
%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< $(CFLAGS_FOR_SOURCE)
install: dwz
install -D dwz $(DESTDIR)$(bindir)/dwz
install -D -m 644 $(srcdir)/dwz.1 $(DESTDIR)$(mandir)/man1/dwz.1
clean:
rm -f $(OBJECTS) *~ core* dwz $(TEST_EXECS) $(DWZ_TEST_SOURCES) \
dwz.log dwz.sum
rm -f $(OBJECTS) *~ core* dwz $(TEST_EXECS) $(DWZ_TEST_OBJECTS) \
dwz.log dwz.sum native.c native.o
rm -Rf testsuite-bin tmp.*
native.c:
echo "int main (void) { return 0; }" > $@
native.o: native.c
$(CC) -o $@ $< -c -g
PWD:=$(shell pwd -P)
@ -33,7 +68,7 @@ TEST_EXECS_x86_64 = py-section-script dw2-skip-prologue \
TEST_EXECS = hello dwz-for-test min two-typedef start hello-gold-gdb-index \
start-gold hello-gnu-pubnames $(TEST_EXECS_DWARF_ASM) \
$(TEST_EXECS_$(UNAME)) odr-struct odr-class odr-union odr-struct-ns \
odr-class-ns odr-union-ns odr-loc def-decl
odr-class-ns odr-union-ns odr-loc def-decl cycle
UNAME:=$(shell uname -p)
@ -50,15 +85,21 @@ dw2-skip-prologue:
py-section-script:
$(CC) $(TEST_SRC)/py-section-script.s -o $@ -g || touch $@
DWZ_TEST_SOURCES := $(patsubst %.o,%-for-test.c,$(OBJECTS))
%-for-test.c: %.c
sed 's/__GNUC__/NOT_DEFINED/' $< > $@
dwz-for-test: $(DWZ_TEST_SOURCES)
$(CC) $(DWZ_TEST_SOURCES) -O2 -g -lelf -o $@ -Wall -W -DDEVEL \
-D_FILE_OFFSET_BITS=64 -DDWZ_VERSION='"for-test"' -I$(srcdir) \
$(shell cat $(srcdir)/COPYRIGHT_YEARS)
DWZ_TEST_OBJECTS := $(patsubst %.o,%-for-test.o,$(OBJECTS))
dwz-for-test: $(DWZ_TEST_OBJECTS)
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
rm -f $(DWZ_TEST_OBJECTS)
args-for-test.o: CFLAGS_FOR_SOURCE = \
-DNATIVE_ENDIAN_VAL=$(NATIVE_ENDIAN_VAL) \
-DNATIVE_POINTER_SIZE=$(NATIVE_POINTER_SIZE)
$(DWZ_TEST_OBJECTS): %-for-test.o : %.c
$(CC) $< -o $@ -c \
-DUSE_GNUC=0 -DDEVEL \
-O2 -g \
$(CFLAGS_COMMON) \
-DDWZ_VERSION='"for-test"' \
$(CFLAGS_COPYRIGHT) \
$(CFLAGS_FOR_SOURCE)
min:
$(CC) $(TEST_SRC)/min.c $(TEST_SRC)/min-2.c -o $@ -g
@ -96,11 +137,11 @@ $(TEMP_ASM_FILES): %-dw.S: $(TEST_SRC)/../lib/%.exp
export DEJAGNU=$(DEJAGNU); \
runtest --tool=dwz -srcdir $(srcdir)/testsuite/ lib/$*.exp
$(filter-out no-multifile-prop, $(TEST_EXECS_DWARF_ASM)): %: %-dw.S
$(filter-out no-multifile-prop unavailable-dwarf-piece, $(TEST_EXECS_DWARF_ASM)): %: %-dw.S
$(CC) $(TEST_SRC)/main.c $< -o $@
# Fails to compile on riscv64: Error: non-constant .uleb128 is not supported.
no-multifile-prop: %: %-dw.S
no-multifile-prop unavailable-dwarf-piece: %: %-dw.S
$(CC) $(TEST_SRC)/main.c $< -o $@ || true
odr-struct:
@ -136,14 +177,25 @@ def-decl:
$(CXX) $(TEST_SRC)/decl.cc $(TEST_SRC)/def.cc $(TEST_SRC)/def2.cc \
-I$(TEST_SRC) -o $@ -g
cycle:
$(CC) $(TEST_SRC)/cycle.c -o $@ -g
# On some systems we need to set and export DEJAGNU to suppress
# WARNING: Couldn't find the global config file.
DEJAGNU ?= /dev/null
check: dwz $(TEST_EXECS)
VALGRIND_OPTIONS = -q --error-exitcode=99
check check-valgrind: dwz $(TEST_EXECS)
mkdir -p testsuite-bin
cd testsuite-bin; ln -sf $(PWD)/dwz .
cd testsuite-bin; \
if [ "$@" = "check" ]; then \
ln -sf $(PWD)/dwz .; \
else \
echo "valgrind $(VALGRIND_OPTIONS) $(PWD)/dwz \"\$$@\"" > dwz; \
chmod +x dwz; \
fi
export DEJAGNU=$(DEJAGNU); \
export PATH=$(PWD)/testsuite-bin:$$PATH; export LC_ALL=C; \
runtest --tool=dwz -srcdir $(srcdir)/testsuite $(RUNTESTFLAGS)
rm -Rf testsuite-bin $(TEST_EXECS) $(DWZ_TEST_SOURCES)
rm -Rf testsuite-bin $(TEST_EXECS) $(DWZ_TEST_OBJECTS)

28
README.release-checklist Normal file
View File

@ -0,0 +1,28 @@
- Verify that copyright notices in source files are up-to-date.
- Update COPYRIGHT_YEARS using contrib/release/gen-copyright-years.sh.
Commit modifications if there are any.
- Run contrib/release/do-release.sh.
Use:
- --minor to do a minor update: $maj.$min -> $maj.$(($min + 1))
- --major to do a major update: $maj.$min -> $(($maj + 1)).0
This:
- adds a commit that updates the VERSION file,
- creates a signed annotated release tag for that commit, and
- pushes both the commit and the tag to the remote repository.
- Run contrib/release/upload-release.sh.
This creates and uploads two release tarballs.
- Write draft release announcement.
F.i. using template of
https://sourceware.org/ml/gdb-announce/2019/msg00001.html.
- Sent out draft release announcement to maintainers for review and
further contributions.
- Sent out release announcement. Sent to:
- Maintainers
- dwz@sourceware.org
- dwarf-discuss@lists.dwarfstd.org
- gcc@gcc.gnu.org
- gdb@sourceware.org
- lldb-dev@lists.llvm.org
- Update web page ( https://sourceware.org/dwz/ ):
- Add news item with hlink to release annoucement.
- Add entry in release list.

View File

@ -1 +1 @@
0.14
0.15

743
args.c Normal file
View File

@ -0,0 +1,743 @@
/* 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;
}
}

97
args.h Normal file
View File

@ -0,0 +1,97 @@
/* 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;
extern int max_forks;
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 int multifile_force_ptr_size;
extern int multifile_force_endian;
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);

View File

@ -3,7 +3,7 @@
f="$1"
size=$(readelf -WS "$f" \
| egrep "[ \t]\.debug_info" \
| grep -E "[ \t]\.debug_info" \
| sed 's/.*\.debug_info//' \
| awk '{print $4}')
size=$((16#$size))

View File

@ -52,10 +52,16 @@ echo Bumped version: major: $major, minor: $minor
version=$major.$minor
set +x
echo $version > VERSION
git add VERSION
git commit -m "Bump version to $version"
git tag dwz-$version
git push origin master:master
git tag -s -m "dwz $version release" dwz-$version
git push origin dwz-$version

View File

@ -128,6 +128,8 @@ main ()
tmp=$(mktemp)
for f in *.c *.h *.def; do
if test "$f" = "native.c"; then continue; fi
if ! grep -q "Copyright (C)" $f; then
echo "error: found file without copyright marker: $f"
exit 1

View File

@ -4,7 +4,7 @@ set -e
pwd=$(pwd -P)
version="$1"
version=$(cat VERSION)
tag=dwz-$version
rootdir=dwz

14
dwz.1
View File

@ -77,6 +77,16 @@ the executable or shared library to the file named in the argument
of the \fB-m\fR option. Either \fB-M\fR or \fB-r\fR
option can be specified, but not both.
.TP
.B \-p N \-\-multifile-pointer-size <N|auto|native>
Specify the pointer size of the multifile, in bytes. If auto, use the
pointer size of the files, provided they match. If native, use native pointer
size, as specified in the help message.
.TP
.B \-p <l|b|auto> \-\-multifile-endian <l|b|auto|native>
Specify the endianity of the multifile. If auto, use the endianity of
the files, provided they match. If native, use native endianity, as specified
in the help message.
.TP
.B \-q \-\-quiet
Silence up some of the most common messages.
.TP
@ -111,6 +121,10 @@ Emit standard DWARF 5 Supplementary Object Files with \fI.debug_sup\fR and
corresponding forms, instead of the GNU extension \fI.gnu_debugaltlink\fR
and corresponding forms.
.TP
.B \-j <N> \-\-jobs <N>
Process \fIN\fR files in parallel. The default is processors / 2. Disabled
when multifile is used.
.TP
.B \-\-odr / \-\-no-odr
.B Experimental.
Enable/disable One-Definition-Rule optimization for C++ compilation units.

1764
dwz.c

File diff suppressed because it is too large Load Diff

139
hashtab.c
View File

@ -626,142 +626,3 @@ htab_restore (htab, name, restorefn)
fclose (f);
}
#endif
/* DERIVED FROM:
--------------------------------------------------------------------
lookup2.c, by Bob Jenkins, December 1996, Public Domain.
hash(), hash2(), hash3, and mix() are externally useful functions.
Routines to test the hash are included if SELF_TEST is defined.
You can use this free for any purpose. It has no warranty.
--------------------------------------------------------------------
*/
/*
--------------------------------------------------------------------
mix -- mix 3 32-bit values reversibly.
For every delta with one or two bit set, and the deltas of all three
high bits or all three low bits, whether the original value of a,b,c
is almost all zero or is uniformly distributed,
* If mix() is run forward or backward, at least 32 bits in a,b,c
have at least 1/4 probability of changing.
* If mix() is run forward, every bit of c will change between 1/3 and
2/3 of the time. (Well, 22/100 and 78/100 for some 2-bit deltas.)
mix() was built out of 36 single-cycle latency instructions in a
structure that could supported 2x parallelism, like so:
a -= b;
a -= c; x = (c>>13);
b -= c; a ^= x;
b -= a; x = (a<<8);
c -= a; b ^= x;
c -= b; x = (b>>13);
...
Unfortunately, superscalar Pentiums and Sparcs can't take advantage
of that parallelism. They've also turned some of those single-cycle
latency instructions into multi-cycle latency instructions. Still,
this is the fastest good hash I could find. There were about 2^^68
to choose from. I only looked at a billion or so.
--------------------------------------------------------------------
*/
/* same, but slower, works on systems that might have 8 byte hashval_t's */
#define mix(a,b,c) \
{ \
a -= b; a -= c; a ^= (c>>13); \
b -= c; b -= a; b ^= (a<< 8); \
c -= a; c -= b; c ^= ((b&0xffffffff)>>13); \
a -= b; a -= c; a ^= ((c&0xffffffff)>>12); \
b -= c; b -= a; b = (b ^ (a<<16)) & 0xffffffff; \
c -= a; c -= b; c = (c ^ (b>> 5)) & 0xffffffff; \
a -= b; a -= c; a = (a ^ (c>> 3)) & 0xffffffff; \
b -= c; b -= a; b = (b ^ (a<<10)) & 0xffffffff; \
c -= a; c -= b; c = (c ^ (b>>15)) & 0xffffffff; \
}
/*
--------------------------------------------------------------------
hash() -- hash a variable-length key into a 32-bit value
k : the key (the unaligned variable-length array of bytes)
len : the length of the key, counting by bytes
level : can be any 4-byte value
Returns a 32-bit value. Every bit of the key affects every bit of
the return value. Every 1-bit and 2-bit delta achieves avalanche.
About 36+6len instructions.
The best hash table sizes are powers of 2. There is no need to do
mod a prime (mod is sooo slow!). If you need less than 32 bits,
use a bitmask. For example, if you need only 10 bits, do
h = (h & hashmask(10));
In which case, the hash table should have hashsize(10) elements.
If you are hashing n strings (ub1 **)k, do it like this:
for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
By Bob Jenkins, 1996. bob_jenkins@burtleburtle.net. You may use this
code any way you wish, private, educational, or commercial. It's free.
See http://burtleburtle.net/bob/hash/evahash.html
Use for hash table lookup, or anything where one collision in 2^32 is
acceptable. Do NOT use for cryptographic purposes.
--------------------------------------------------------------------
*/
hashval_t
iterative_hash (const void *k_in /* the key */,
register size_t length /* the length of the key */,
register hashval_t initval /* the previous hash, or
an arbitrary value */)
{
register const unsigned char *k = (const unsigned char *)k_in;
register hashval_t a,b,c,len;
/* Set up the internal state */
len = length;
a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
c = initval; /* the previous hash value */
/*---------------------------------------- handle most of the key */
#ifndef WORDS_BIGENDIAN
/* On a little-endian machine, if the data is 4-byte aligned we can hash
by word for better speed. This gives nondeterministic results on
big-endian machines. */
if (sizeof (hashval_t) == 4 && (((size_t)k)&3) == 0)
while (len >= 12) /* aligned */
{
a += *(hashval_t *)(k+0);
b += *(hashval_t *)(k+4);
c += *(hashval_t *)(k+8);
mix(a,b,c);
k += 12; len -= 12;
}
else /* unaligned */
#endif
while (len >= 12)
{
a += (k[0] +((hashval_t)k[1]<<8) +((hashval_t)k[2]<<16) +((hashval_t)k[3]<<24));
b += (k[4] +((hashval_t)k[5]<<8) +((hashval_t)k[6]<<16) +((hashval_t)k[7]<<24));
c += (k[8] +((hashval_t)k[9]<<8) +((hashval_t)k[10]<<16)+((hashval_t)k[11]<<24));
mix(a,b,c);
k += 12; len -= 12;
}
/*------------------------------------- handle the last 11 bytes */
c += length;
switch(len) /* all the case statements fall through */
{
case 11: c+=((hashval_t)k[10]<<24); /* fall through */
case 10: c+=((hashval_t)k[9]<<16); /* fall through */
case 9 : c+=((hashval_t)k[8]<<8); /* fall through */
/* the first byte of c is reserved for the length */
case 8 : b+=((hashval_t)k[7]<<24); /* fall through */
case 7 : b+=((hashval_t)k[6]<<16); /* fall through */
case 6 : b+=((hashval_t)k[5]<<8); /* fall through */
case 5 : b+=k[4]; /* fall through */
case 4 : a+=((hashval_t)k[3]<<24); /* fall through */
case 3 : a+=((hashval_t)k[2]<<16); /* fall through */
case 2 : a+=((hashval_t)k[1]<<8); /* fall through */
case 1 : a+=k[0];
/* case 0: nothing left to add */
}
mix(a,b,c);
/*-------------------------------------------- report the result */
return c;
}

View File

@ -153,11 +153,6 @@ extern void htab_restore (htab_t, const char *, htab_restorefn);
#endif
/* An iterative hash function for arbitrary data. */
extern hashval_t iterative_hash (const void *, size_t, hashval_t);
/* Shorthand for hashing something with an intrinsic size. */
#define iterative_hash_object(OB,INIT) iterative_hash (&OB, sizeof (OB), INIT)
#ifdef __cplusplus
}
#endif /* __cplusplus */

103
pool.c Normal file
View File

@ -0,0 +1,103 @@
/* 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. */
/* Big pool allocator. obstack isn't efficient, because it aligns everything
too much, and allocates too small chunks. All these objects are only freed
together. */
#include <stddef.h>
#include <stdlib.h>
#include <inttypes.h>
#include "pool.h"
/* Pointer to the start of the current pool chunk, current first free byte
in the chunk and byte after the end of the current pool chunk. */
static unsigned char *pool, *pool_next, *pool_limit;
extern void dwz_oom (void);
/* Allocate SIZE bytes with ALIGN bytes alignment from the pool. */
void *
pool_alloc_1 (unsigned int align, unsigned int size)
{
void *ret;
if (pool == NULL
|| (size_t) (pool_limit - pool_next) < (size_t) align + size)
{
size_t new_size = (size_t) align + size;
unsigned char *new_pool;
new_size += sizeof (void *);
if (new_size < 16384 * 1024 - 64)
new_size = 16384 * 1024 - 64;
new_pool = (unsigned char *) malloc (new_size);
if (new_pool == NULL)
dwz_oom ();
*(unsigned char **) new_pool = pool;
pool_next = new_pool + sizeof (unsigned char *);
pool_limit = new_pool + new_size;
pool = new_pool;
}
pool_next = (unsigned char *) (((uintptr_t) pool_next + align - 1)
& ~(uintptr_t) (align - 1));
ret = pool_next;
pool_next += size;
return ret;
}
/* Finalize a pool and return it. */
unsigned char *
finalize_pool (void)
{
unsigned char *ret = pool;
pool = NULL;
pool_next = NULL;
pool_limit = NULL;
return ret;
}
/* Free pool P. */
static void
pool_destroy_1 (unsigned char *p)
{
while (p)
{
void *elem = (void *) p;
p = *(unsigned char **) p;
free (elem);
}
}
/* Free pool P, or the current pool if NULL. */
void
pool_destroy (unsigned char *p)
{
if (p != NULL)
{
pool_destroy_1 (p);
return;
}
pool_destroy_1 (pool);
pool = NULL;
pool_next = NULL;
pool_limit = NULL;
}

26
pool.h Normal file
View File

@ -0,0 +1,26 @@
/* 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. */
extern void *pool_alloc_1 (unsigned int, unsigned int);
extern unsigned char *finalize_pool (void);
extern void pool_destroy (unsigned char *);
#define pool_alloc(name, size) \
(struct name *) pool_alloc_1 (ALIGNOF_STRUCT (name), size)

View File

@ -0,0 +1,13 @@
struct s;
struct s {
struct s *p;
};
struct s var;
int
main (void)
{
return 0;
}

View File

@ -0,0 +1,36 @@
readelf_flags=""
if readelf -h 2>&1 | grep -q "\-wN"; then
readelf_flags=-wN
fi
cp $execs/cycle 1
# Using mode 3 in checksum_die_ref.
$execs/dwz-for-test 1 -o 1.z --devel-dump-dies 2> DUMP.1
rm -f 1.z
# Skipping mode 3 in checksum_die_ref.
$execs/dwz-for-test 1 -o 1.z --devel-dump-dies --devel-no-checksum-cycle-opt 2> DUMP.2
rm -f 1.z
# Verify that mode 3 and mode 4 have different checksums.
grep " s structure_type" DUMP.1 > LINE.1
grep " s structure_type" DUMP.2 > LINE.2
! diff -q LINE.1 LINE.2
rm -f DUMP.1 DUMP.2 LINE.1 LINE.2
# Verify that dwz actually works with --devel-no-checksum-cycle-opt.
cp 1 2
$execs/dwz-for-test -m 3 1 2 --devel-no-checksum-cycle-opt --devel-ignore-size
cnt=$(readelf -wi 3 | grep -c "DW_AT_name.*: s$")
[ $cnt -eq 1 ]
# Even with -wN readelf 2.38-15.fc37 follows and prints the contents
# of the alt file. So make sure it cannot do that by removing it.
rm 3
cnt=$(readelf -wi $readelf_flags 1 | grep -c "DW_AT_name.*: s$" || true)
[ $cnt -eq 0 ]
rm -f 1 2 3

View File

@ -6,7 +6,7 @@ cnt=$(readelf -wi 1 \
[ $cnt -eq 2 ]
$execs/dwz-for-test 1 2>/dev/null
$execs/dwz-for-test 1 2>/dev/null
cnt=$(readelf -wi 1 \
| grep 'DW_AT_name.*: aaa' \
@ -16,7 +16,7 @@ cnt=$(readelf -wi 1 \
cp $execs/two-typedef 1
$execs/dwz-for-test --devel-ignore-locus --devel-ignore-size 1
$execs/dwz-for-test --devel-ignore-locus --devel-ignore-size 1
cnt=$(readelf -wi 1 \
| grep 'DW_AT_name.*: aaa' \

View File

@ -6,7 +6,7 @@ cnt=$(readelf -wi 1 \
[ $cnt -eq 0 ]
$execs/dwz-for-test 1 2>/dev/null
$execs/dwz-for-test 1 2>/dev/null
cnt=$(readelf -wi 1 \
| grep '(DW_TAG_partial_unit' \
@ -18,7 +18,7 @@ fi
cp $execs/min 1
$execs/dwz-for-test --devel-ignore-size 1
$execs/dwz-for-test --devel-ignore-size 1
cnt=$(readelf -wi 1 \
| grep '(DW_TAG_partial_unit' \

View File

@ -1,5 +1,5 @@
cp $execs/hello 1
$execs/dwz-for-test --devel-trace 1 2>/dev/null
$execs/dwz-for-test --devel-trace 1 2>/dev/null
rm -f 1

View File

@ -400,3 +400,4 @@ loclist:
.byte 1
.Lline1_end:
.section .note.GNU-stack,"",@progbits

View File

@ -1,6 +1,8 @@
cp $execs/hello 1
gdb-add-index 1
# Redirect gdb-add-index stderr to stdout.
# https://sourceware.org/bugzilla/show_bug.cgi?id=29316
gdb-add-index 1 2>&1
readelf -S 1 | grep -q '\.gdb_index'

View File

@ -154,3 +154,4 @@
.byte 0x0 /* Terminator */
.byte 0x0 /* Terminator */
.byte 0x0 /* Terminator */
.section .note.GNU-stack,"",@progbits

12
testsuite/dwz.tests/odr-struct-multifile.sh Normal file → Executable file
View File

@ -2,6 +2,11 @@ if ! $execs/dwz-for-test --odr -v 2>/dev/null; then
exit 77
fi
readelf_flags=""
if readelf -h 2>&1 | grep -q "\-wN"; then
readelf_flags=-wN
fi
cp $execs/odr-struct 1
cp 1 2
@ -39,14 +44,17 @@ for name in member_one member_two member_three member_four; do
[ $cnt -eq 1 ]
done
# Even with -wN readelf 2.38-15.fc37 follows and prints the contents
# of the alt file. So make sure it cannot do that by removing it.
rm 3
for name in aaa bbb ccc; do
cnt=$(readelf -wi 1 | grep -c "DW_AT_name.*:.*$name" || true)
cnt=$(readelf -wi $readelf_flags 1 | grep -c "DW_AT_name.*:.*$name" || true)
[ $cnt -eq 0 ]
done
for name in member_one member_two member_three member_four; do
cnt=$(readelf -wi 1 | grep -c "DW_AT_name.*:.*$name" || true)
cnt=$(readelf -wi $readelf_flags 1 | grep -c "DW_AT_name.*:.*$name" || true)
[ $cnt -eq 0 ]
done

View File

@ -21,7 +21,10 @@ for name in member_one member_two member_three member_four; do
esac
done
decl_cnt=$(readelf -wi 1 | grep -c "DW_AT_declaration" || true)
# Check that bbb and ccc are present as DW_AT_declaration
readelf -wi 1 | grep -3 DW_AT_declaration > decls
grep bbb decls >/dev/null
grep ccc decls >/dev/null
$execs/dwz-for-test --odr 1
@ -38,8 +41,9 @@ for name in member_one member_two member_three member_four; do
done
# We expect two decls to be removed, for bbb and ccc.
expected_decl_cnt=$(($decl_cnt - 2))
decl_cnt=$(readelf -wi 1 | grep -c "DW_AT_declaration" || true)
[ $expected_decl_cnt -eq $decl_cnt ]
readelf -wi 1 | grep -3 DW_AT_declaration > decls || true
rm -f 1
if grep bbb decls >/dev/null ; then exit 1; fi
if grep ccc decls >/dev/null ; then exit 2; fi
rm -f 1 decls

View File

@ -21,7 +21,10 @@ for name in member_one member_two member_three member_four; do
esac
done
decl_cnt=$(readelf -wi 1 | grep -c "DW_AT_declaration" || true)
# Check that bbb and ccc are present as DW_AT_declaration
readelf -wi 1 | grep -3 DW_AT_declaration > decls
grep bbb decls >/dev/null
grep ccc decls >/dev/null
$execs/dwz-for-test --odr 1
@ -38,8 +41,9 @@ for name in member_one member_two member_three member_four; do
done
# We expect two decls to be removed, for bbb and ccc.
expected_decl_cnt=$(($decl_cnt - 2))
decl_cnt=$(readelf -wi 1 | grep -c "DW_AT_declaration" || true)
[ $expected_decl_cnt -eq $decl_cnt ]
readelf -wi 1 | grep -3 DW_AT_declaration > decls || true
rm -f 1
if grep bbb decls >/dev/null ; then exit 1; fi
if grep ccc decls >/dev/null ; then exit 2; fi
rm -f 1 decls

View File

@ -4,6 +4,4 @@ cp $exec 1
dwz 1
smaller-than.sh 1 $exec
rm -f 1

View File

@ -24,7 +24,10 @@ if [ $(grep -qv "DWARF compression not beneficial" dwz.err \
exit 1
fi
[ $status -eq 0 ]
if [ $status -ne 0 ]; then
cat dwz.err
exit 1
fi
smaller-than.sh 1 1.saved

View File

@ -5,9 +5,10 @@ $execs/dwz-for-test \
-l0 \
--devel-trace \
1 2 \
-j 1 \
2> dwz.err
if egrep -q "Compressing (1|2)$" dwz.err; then
if grep -Eq "Compressing (1|2)$" dwz.err; then
exit 1
fi

View File

@ -512,3 +512,4 @@
.byte 0x0 /* Terminator */
.byte 0x0 /* Terminator */
.byte 0x0 /* Terminator */
.section .note.GNU-stack,"",@progbits

View File

@ -1666,6 +1666,8 @@ namespace eval Dwarf {
_write_deferred_output
_section .note.GNU-stack "" progbits
catch {close $_output_file}
set _output_file {}
}

View File

@ -1,10 +1,45 @@
#!/bin/sh
#!/bin/bash
f1=$1
f2=$2
s1=$(ls -l $f1 | awk '{print $5}')
s2=$(ls -l $f2 | awk '{print $5}')
section_size ()
{
local f="$1"
local section="$2"
local s
s=$(readelf -S -W $f \
| grep "\.debug_$section" \
| sed 's/.*\.debug_//' \
| awk '{print $5}')
if [ "$s" = "" ]; then
echo 0
return
fi
# Convert hex to decimal.
s=$(printf "%d" $((16#$s)))
echo $s
}
size ()
{
local f="$1"
local total=0
local section
for section in info abbrev str macro types; do
total=$(($total + $(section_size $f $section)))
done
echo $total
}
s1=$(size $f1)
s2=$(size $f2)
if [ $s1 -ge $s2 ]; then
exit 1

63
util.h Normal file
View File

@ -0,0 +1,63 @@
/* 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. */
/* Utility macros. */
#define IMPLIES(A, B) (!((A) && !(B)))
#define MAX(A, B) ((A) > (B) ? (A) : (B))
#define MIN(A, B) ((A) < (B) ? (A) : (B))
#define XSTR(s) STR(s)
#define STR(s) #s
#ifndef USE_GNUC
#ifdef __GNUC__
#define USE_GNUC 1
#else
#define USE_GNUC 0
#endif
#endif
#if USE_GNUC && __GNUC__ >= 3
# define likely(x) __builtin_expect (!!(x), 1)
# define unlikely(x) __builtin_expect (!!(x), 0)
#else
# define likely(x) (x)
# define unlikely(x) (x)
#endif
#if USE_GNUC
# define FORCE_INLINE __attribute__((always_inline))
# define UNUSED __attribute__((unused))
# define USED __attribute__((used))
#else
# define FORCE_INLINE
# define UNUSED
# define USED
#endif
#if USE_GNUC
# define ALIGN_STRUCT(name)
# define ALIGNOF_STRUCT(name) __alignof__ (struct name)
#else
# define ALIGN_STRUCT(name) struct align_##name { char c; struct name s; };
# define ALIGNOF_STRUCT(name) offsetof (struct align_##name, s)
#endif