Projects
openEuler:Mainline
dwz
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 2
View file
_service:tar_scm:dwz.spec
Changed
@@ -1,13 +1,12 @@ Name: dwz -Version: 0.14 -Release: 3 +Version: 0.15 +Release: 1 Summary: A DWARF optimization and duplicate removal tool License: GPLv2+ and GPLv3+ URL: https://sourceware.org/dwz/ Source0:https://sourceware.org/ftp/dwz/releases/%{name}-%{version}.tar.xz BuildRequires:gcc gcc-c++ gdb elfutils-libelf-devel dejagnu - -Patch1: testsuite-Handle-readelf-following-links-by-default.patch +BuildRequires:xxhash-devel %description The package contains a program that attempts to optimize DWARF debugging @@ -53,6 +52,15 @@ %{_mandir}/man1/dwz* %changelog +* Thu Jan 19 2023 renhongxun <renhongxun@h-partner.com> - 0.15-1 +- upgrade version to 0.15 + +* Tue Jan 10 2023 dongyuzhen <dongyuzhen@h-partners.com> - 0.14-5 +- fix the testcase fail + +* Tue Oct 25 2022 yanglongkang <yanglongkang@h-partners.com> - 0.14-4 +- rebuild for next release + * Tue Jan 25 2022 renhongxun <renhongxun@h-partner.com> - 0.14-3 - fix testsuite with community patch
View file
_service:tar_scm:backport-Redirect-stder-in-gdb-add-index.sh-test.patch
Added
@@ -0,0 +1,31 @@ +From d03a041790e1d0ecb900ec1de57580bca9519daa Mon Sep 17 00:00:00 2001 +From: Mark Wielaard <mark@klomp.org> +Date: Sat, 2 Jul 2022 01:11:00 +0200 +Subject: PATCH Redirect stder in gdb-add-index.sh test + +gdb-add-index might produce an error message on stderr when trying to +disable debuginfod support. Any message to stderr makes the testcase +fail. This looks like a gdb bug: +https://sourceware.org/bugzilla/show_bug.cgi?id=29316 +But it is easy to workaround by redirecting stderr to stdout. +--- + testsuite/dwz.tests/gdb-add-index.sh | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/testsuite/dwz.tests/gdb-add-index.sh b/testsuite/dwz.tests/gdb-add-index.sh +index 5a91b23..3095efb 100644 +--- a/testsuite/dwz.tests/gdb-add-index.sh ++++ b/testsuite/dwz.tests/gdb-add-index.sh +@@ -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' + +-- +2.31.1 +
View file
_service
Changed
@@ -2,7 +2,7 @@ <service name="tar_scm"> <param name="scm">git</param> <param name="url">git@gitee.com:src-openeuler/dwz.git</param> - <param name="revision">d5dee00a14707d25d7b3ec3051c2bf4fd8849553</param> + <param name="revision">master</param> <param name="exclude">*</param> <param name="extract">*</param> </service>
View file
_service:tar_scm:dwz-0.14.tar.xz/.gitignore -> _service:tar_scm:dwz-0.15.tar.xz/.gitignore
Changed
@@ -4,4 +4,5 @@ dwz dwz.sum dwz.log +native.c testsuite/dwz.tests/execs
View file
_service:tar_scm:dwz-0.14.tar.xz/Makefile -> _service:tar_scm:dwz-0.15.tar.xz/Makefile
Changed
@@ -3,25 +3,60 @@ 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 = 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 @@ 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 @@ 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 @@ $(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)
View file
_service:tar_scm:dwz-0.15.tar.xz/README.release-checklist
Added
@@ -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
_service:tar_scm:dwz-0.14.tar.xz/VERSION -> _service:tar_scm:dwz-0.15.tar.xz/VERSION
Changed
@@ -1,1 +1,1 @@ -0.14 +0.15
View file
_service:tar_scm:dwz-0.15.tar.xz/args.c
Added
@@ -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_helpi.short_name; + if (s) + { + fprintf (stream, "-%s", s); + len += 2; + } + + s = options_helpi.long_name; + if (len == 4) + { + fprintf (stream, ", "); + len += 2; + } + fprintf (stream, "--%s", s); + len += 2 + strlen (s); + + s = options_helpi.argument; + if (s) + { + fprintf (stream, " %s", s); + len += 1 + strlen (s); + } + + s = options_helpi.msg; + if (s) + { + assert (IMPLIES (strlen (s) > 0, sstrlen (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_helpi.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_linesi); + + indent = 30; + limit = 80; + fprintf (stream, "Common options:\n"); + n = (sizeof (dwz_common_options_help) + / sizeof (dwz_common_options_help0)); + 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_help0)); + 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_help0)); + 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_help0)); + 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_producersnr_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_producersi; + 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 (optarg0) + { + 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; + } +}
View file
_service:tar_scm:dwz-0.15.tar.xz/args.h
Added
@@ -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
_service:tar_scm:dwz-0.14.tar.xz/contrib/bytes-per-die.sh -> _service:tar_scm:dwz-0.15.tar.xz/contrib/bytes-per-die.sh
Changed
@@ -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
_service:tar_scm:dwz-0.14.tar.xz/contrib/release/do-release.sh -> _service:tar_scm:dwz-0.15.tar.xz/contrib/release/do-release.sh
Changed
@@ -52,10 +52,16 @@ 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
_service:tar_scm:dwz-0.14.tar.xz/contrib/release/gen-copyright-years.sh -> _service:tar_scm:dwz-0.15.tar.xz/contrib/release/gen-copyright-years.sh
Changed
@@ -128,6 +128,8 @@ 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
_service:tar_scm:dwz-0.14.tar.xz/contrib/release/upload-release.sh -> _service:tar_scm:dwz-0.15.tar.xz/contrib/release/upload-release.sh
Changed
@@ -4,7 +4,7 @@ pwd=$(pwd -P) -version="$1" +version=$(cat VERSION) tag=dwz-$version rootdir=dwz
View file
_service:tar_scm:dwz-0.14.tar.xz/dwz.1 -> _service:tar_scm:dwz-0.15.tar.xz/dwz.1
Changed
@@ -77,6 +77,16 @@ 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 @@ 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.
View file
_service:tar_scm:dwz-0.14.tar.xz/dwz.c -> _service:tar_scm:dwz-0.15.tar.xz/dwz.c
Changed
@@ -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> @@ -35,13 +34,19 @@ #include <sys/stat.h> #include <sys/types.h> #include <sys/times.h> +#include <sys/wait.h> #include <obstack.h> #include <gelf.h> +#include <xxhash.h> + #include "dwarf2.h" #include "hashtab.h" #include "sha1.h" +#include "args.h" +#include "util.h" +#include "pool.h" #ifndef SHF_COMPRESSED /* Glibc elf.h contains SHF_COMPRESSED starting v2.22. Libelf libelf.h has @@ -109,29 +114,41 @@ # define NT_GNU_BUILD_ID 3 #endif -#if defined __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 +/* xxHash state object. Init in main. */ +static XXH64_state_t *state; -#if defined __GNUC__ -# define FORCE_INLINE __attribute__((always_inline)) -# define UNUSED __attribute__((unused)) -# define USED __attribute__((used)) -#else -# define FORCE_INLINE -# define UNUSED -# define USED -#endif +/* Clear xxHash state to zero. */ +#define hash_init_state() XXH64_reset(state, 0) + +/* Update hash STATE with VALUE. */ +#define hash_update_state_object(value) XXH64_update(state, &value, sizeof value) -/* Utility macro. */ -#define IMPLIES(A, B) (!((A) && !(B))) -#define MAX(A, B) ((A) > (B) ? (A) : (B)) -#define MIN(A, B) ((A) < (B) ? (A) : (B)) +/* Update hash STATE with OBJECT that has a provided SIZE. */ +#define hash_update_state(object, size) XXH64_update(state, object, size) +/* Get digest once we are done with a state. */ +#define hash_digest() XXH64_digest(state) + +/* Shorthand for hashing something with an intrinsic size. */ +#define hash(IN,LEN) XXH64(IN, LEN, 0) +#define iterative_hash(IN,LEN,INIT) XXH64(IN, LEN, INIT) +#define iterative_hash_object(OB,INIT) iterative_hash (&OB, sizeof (OB), INIT) + +/* Print memory amount M (in kb) in both exact and human readable, like so: + 1382508 (1.3G). */ +static void +print_mem (long m) +{ + float h = m; + int level = 0; + const char *unit = { "K", "M", "G"}; + while (h > 1024 && level <= 2) + { + h = h / 1024; + level++; + } + fprintf (stderr, "%ld (%.1f%s)\n", m, h, unitlevel); +} static void report_progress (void) @@ -157,6 +174,40 @@ clock_t sys = current.tms_stime - prev.tms_stime; fprintf (stderr, "user: %.2f\n", (float)user / (float)ticks_per_second); fprintf (stderr, "sys : %.2f\n", (float)sys / (float)ticks_per_second); + + if (progress_mem_p) + { + FILE *s = fopen ("/proc/self/status", "r"); + char *p; + bool print_next = false; + for (p = NULL; fscanf (s, "%ms", &p) && p != NULL; free (p)) + { + if (print_next) + { + long mem = strtol (p, NULL, 10); + print_mem (mem); + print_next = false; + continue; + } + + if (!(p0 == 'V' && p1 == 'm')) + continue; + + if (strcmp (&p2, "Peak:") == 0) + fprintf (stderr, "VM Peak: "); + else if (strcmp (&p2, "Size:") == 0) + fprintf (stderr, "VM Current: "); + else if (strcmp (&p2, "HWM:") == 0) + fprintf (stderr, "RSS Peak: "); + else if (strcmp (&p2, "RSS:") == 0) + fprintf (stderr, "RSS Current: "); + else + continue; + + print_next = true; + } + fclose (s); + } } #define obstack_chunk_alloc malloc @@ -168,7 +219,7 @@ /* Handle OOM situation. If handling more than one file, we might just fail to handle some large file due to OOM, but could very well handle other smaller files after it. */ -static void +void dwz_oom (void) { longjmp (oom_buf, 1); @@ -184,57 +235,7 @@ 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; -#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 -#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; - -int odr = 0; -enum odr_mode { ODR_BASIC, ODR_LINK }; -enum odr_mode odr_mode = ODR_LINK; -int odr_mode_parsed = 0; -bool odr_active_p = false; +static bool odr_active_p = false; /* Struct to gather statistics. */ struct stats @@ -253,7 +254,7 @@ unsigned int pu_ph2_cnt; unsigned int pu_toplevel_die_cnt; }; -struct stats *stats; +static struct stats *stats; /* Initialize stats struct. */ static void @@ -517,13 +518,15 @@ static inline uint32_t buf_read_ule32 (unsigned char *data) { - return data0 | (data1 << 8) | (data2 << 16) | (data3 << 24); + return (data0 | (data1 << 8) | (data2 << 16) + | ((unsigned int)data3 << 24)); } static inline uint32_t buf_read_ube32 (unsigned char *data) { - return data3 | (data2 << 8) | (data1 << 16) | (data0 << 24); + return (data3 | (data2 << 8) | (data1 << 16) + | ((unsigned int)data0 << 24)); } static inline uint64_t @@ -828,18 +831,6 @@ /* 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, @@ -864,29 +855,9 @@ /* 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_sha10x14; -/* 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 { @@ -1151,79 +1122,17 @@ #define die_safe_nextdup(die) \ ((die)->die_toplevel ? (die)->die_nextdup : (dw_die_ref) NULL) -#ifdef __GNUC__ -# define ALIGN_STRUCT(name) -#else -# define ALIGN_STRUCT(name) struct align_##name { char c; struct name s; }; -#endif ALIGN_STRUCT (abbrev_tag) ALIGN_STRUCT (dw_file) ALIGN_STRUCT (dw_cu) ALIGN_STRUCT (dw_die) -/* 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. */ - -/* 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; /* After read_multifile, pool variable is moved over to this variable as the pool from read_multifile needs to be around for subsequent dwz calls. Freed only during the final cleanup at the very end. */ static unsigned char *alt_pool; -/* Allocate SIZE bytes with ALIGN bytes alignment from the pool. */ -static 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; -} - -/* Free the whole pool. */ -static void -pool_destroy (void) -{ - pool_next = NULL; - pool_limit = NULL; - while (pool) - { - void *p = (void *) pool; - pool = *(unsigned char **) pool; - free (p); - } -} - -#ifdef __GNUC__ -# define pool_alloc(name, size) \ - (struct name *) pool_alloc_1 (__alignof__ (struct name), size) -#else -# define pool_alloc(name, size) \ - (struct name *) pool_alloc_1 (offsetof (struct align_##name, s), size) -#endif - static struct abbrev_tag * pool_clone_abbrev (struct abbrev_tag *t) { @@ -1300,16 +1209,18 @@ { unsigned int i; - t->hash = iterative_hash_object (t->tag, 0); - t->hash = iterative_hash_object (t->nattr, t->hash); - t->hash = iterative_hash_object (t->children, t->hash); + hash_init_state (); + hash_update_state_object (t->tag); + hash_update_state_object (t->nattr); + hash_update_state_object (t->children); for (i = 0; i < t->nattr; i++) { - t->hash = iterative_hash_object (t->attri.attr, t->hash); - t->hash = iterative_hash_object (t->attri.form, t->hash); + hash_update_state_object (t->attri.attr); + hash_update_state_object (t->attri.form); if (t->attri.form == DW_FORM_implicit_const) - t->hash = iterative_hash_object (t->valuesi, t->hash); + hash_update_state_object (t->valuesi); } + t->hash = hash_digest (); } /* Maximum number of attributes in a DIE. */ @@ -1351,8 +1262,9 @@ || form == DW_FORM_data16 || form == DW_FORM_line_strp))) { - error (0, 0, "%s: Unknown DWARF %s", - dso->filename, get_DW_FORM_str (form)); + error (0, 0, "%s: Unknown DWARF %s at .debug_abbrev %zd", + dso->filename, get_DW_FORM_str (form), + p - debug_sectionsDEBUG_ABBREV.data); htab_delete (h); return NULL; } @@ -1882,7 +1794,7 @@ { case DW_FORM_string: f = (char *) ptr; - end = strchr ((char *)ptr, 0) + 1;; + end = strchr ((char *)ptr, 0) + 1; break; case DW_FORM_strp: { @@ -1992,7 +1904,7 @@ /* Estimate the amount of DIEs in the .debug_info section, based on the size of that section. */ -static unsigned int UNUSED +static unsigned int estimate_nr_dies (void) { unsigned int average_die_size = 11; @@ -2000,7 +1912,7 @@ return nr_dies; } -static size_t UNUSED +static size_t emulate_htab (size_t initial, size_t final_nr_elements) { size_t size = initial; @@ -2574,8 +2486,10 @@ *need_adjust = true; break; default: - error (0, 0, "%s: Unknown DWARF %s", - dso->filename, get_DW_OP_str (op)); + error (0, 0, "%s: Unknown DWARF %s " + "referenced from DIE at %x", + dso->filename, get_DW_OP_str (op), + die->die_offset); return 1; } } @@ -2776,8 +2690,10 @@ skip_leb128 (ptr); break; default: - error (0, 0, "%s: Unknown DWARF %s", - dso->filename, get_DW_OP_str (op)); + error (0, 0, "%s: Unknown DWARF %s " + "referenced from DIE at %x", + dso->filename, get_DW_OP_str (op), + die->die_offset); return 1; } } @@ -3310,7 +3226,7 @@ } /* Return the initialized die_odr_state field for DIE with CU. */ -static unsigned int UNUSED +static unsigned int die_odr_state (dw_die_ref die) { assert (die->die_odr_state != ODR_UNKNOWN); @@ -3391,6 +3307,7 @@ size_t len = 0; unsigned char *old_ptr; bool handled = false; + int64_t svalue; uint64_t value; while (form == DW_FORM_indirect) @@ -3464,7 +3381,7 @@ value = read_uleb128 (ptr); handled = true; break; case DW_FORM_sdata: { - int64_t svalue = read_sleb128 (ptr); + svalue = read_sleb128 (ptr); if (svalue >= 0) { value = svalue; @@ -3482,9 +3399,10 @@ } case DW_FORM_implicit_const: { - if (t->valuesi >= 0) + svalue = t->valuesi; + if (svalue >= 0) { - value = t->valuesi; + value = svalue; handled = true; break; } @@ -3515,22 +3433,17 @@ struct dw_file *cu_file = &cu->cu_filesvalue - 1; size_t file_len = strlen (cu_file->file); s = t->attri.attr; - die->u.p1.die_hash - = iterative_hash_object (s, die->u.p1.die_hash); - die->u.p1.die_hash - = iterative_hash_object (cu_file->time, - die->u.p1.die_hash); - die->u.p1.die_hash - = iterative_hash_object (cu_file->size, - die->u.p1.die_hash); - die->u.p1.die_hash - = iterative_hash (cu_file->file, file_len + 1, - die->u.p1.die_hash); + hash_init_state (); + hash_update_state_object (die->u.p1.die_hash); + hash_update_state_object (s); + hash_update_state_object (cu_file->time); + hash_update_state_object (cu_file->size); + hash_update_state (cu_file->file, file_len + 1); if (cu_file->dir) - die->u.p1.die_hash - = iterative_hash (cu_file->dir, - strlen (cu_file->dir) + 1, - die->u.p1.die_hash); + { + hash_update_state (cu_file->dir, + strlen (cu_file->dir) + 1); + } /* Ignore DW_AT_comp_dir for DW_AT_*_file <built-in> etc. if immediately followed by DW_AT_*_line 0. */ else if (cu_file->file_angle_brackets_encapsulated_no_slash @@ -3540,7 +3453,13 @@ ? DW_AT_decl_line : DW_AT_call_line) && t->attri + 1.form == DW_FORM_data1 && *new_ptr == 0) - break; + { + die->u.p1.die_hash = hash_digest (); + break; + } + + die->u.p1.die_hash = hash_digest (); + if (cu->cu_comp_dir && (cu_file->dir ? cu_file->dir0 : cu_file->file0) != '/') @@ -3570,7 +3489,7 @@ value = read_uleb128 (ptr); handled = true; break; case DW_FORM_sdata: { - int64_t svalue = read_sleb128 (ptr); + svalue = read_sleb128 (ptr); if (svalue >= 0) { value = svalue; @@ -3581,9 +3500,10 @@ goto negative; } case DW_FORM_implicit_const: - if (t->valuesi >= 0) + svalue = t->valuesi; + if (svalue >= 0) { - value = t->valuesi; + value = svalue; handled = true; break; } @@ -4380,7 +4300,7 @@ } } } - if (minidx != -1U) + if (checksum_cycle_opt && minidx != -1U) { idx = 0; checksum_ref_die (die_cu (arrminidx), arrminidx, @@ -5544,7 +5464,7 @@ } /* Dump DIE to stderr. */ -void USED +static void dump_die (dw_die_ref die) { dump_die_with_indent (0, die); @@ -5654,7 +5574,7 @@ static hashval_t strp_hash3 (const void *p) { - return iterative_hash (p, strlen (p), 0); + return hash (p, strlen (p)); } /* Corresponding equality function in strp_htab. */ @@ -5684,7 +5604,7 @@ p = debug_sectionsDEBUG_STR.data + off; len = strlen ((char *) p); - hash = iterative_hash (p, len, 0); + hash = hash (p, len); if (alt_strp_htab) { if (htab_find_with_hash (alt_strp_htab, p, hash)) @@ -5766,7 +5686,7 @@ p = debug_sectionsDEBUG_STR.data + off; len = strlen ((char *) p); - hash = iterative_hash (p, len, 0); + hash = hash (p, len); if (alt_strp_htab) { unsigned char *q = (unsigned char *) @@ -5807,7 +5727,7 @@ { p = debug_sectionsDEBUG_STR.data + off; len = strlen ((char *) p); - hash = iterative_hash (p, len, 0); + hash = hash (p, len); if (htab_find_with_hash (alt_strp_htab, p, hash)) return dwarf_5 ? DW_FORM_strp_sup : DW_FORM_GNU_strp_alt; } @@ -5817,7 +5737,7 @@ return DW_FORM_strp; p = debug_sectionsDEBUG_STR.data + off; q = (unsigned char *) strchr ((char *) p, '\0'); - hash = iterative_hash (p, q - p, 0); + hash = hash (p, q - p); se.off = off; se.new_off = hash & ~1U; struct strp_entry *s = (struct strp_entry *) @@ -5973,7 +5893,7 @@ memcpy (p, debug_sectionsDEBUG_STR.data + arri->off, len); slot = htab_find_slot_with_hash (strp_htab, p, - iterative_hash (p, len - 1, 0), + hash (p, len - 1), INSERT); if (slot == NULL) dwz_oom (); @@ -5989,7 +5909,7 @@ if (tail_offset_list != NULL) tail_offset_listk++ = arrj->new_off; slot = htab_find_slot_with_hash (strp_htab, q, - iterative_hash (q, l - 1, 0), + hash (q, l - 1), INSERT); if (slot == NULL) dwz_oom (); @@ -6659,7 +6579,8 @@ if (dup_htab == NULL) dwz_oom (); } - if (unlikely (op_multifile || rd_multifile || fi_multifile || low_mem)) + if (unlikely (meta_abbrev_htab == NULL + && (op_multifile || rd_multifile || fi_multifile || low_mem))) { meta_abbrev_htab = htab_try_create (500, meta_abbrev_hash, meta_abbrev_eq, @@ -7179,15 +7100,16 @@ case DW_FORM_block: abort (); default: - error (0, 0, "%s: Unknown DWARF %s", - dso->filename, get_DW_FORM_str (form)); + error (0, 0, "%s: Unknown DWARF %s at DIE %x", + dso->filename, get_DW_FORM_str (form), die_offset); goto fail; } if (ptr > endcu) { - error (0, 0, "%s: Attributes extend beyond end of CU", - dso->filename); + error (0, 0, "%s: Attributes extend beyond end of CU " + "for DIE %x", + dso->filename, die_offset); goto fail; } @@ -7195,8 +7117,9 @@ { if (len >= (size_t) (endcu - ptr)) { - error (0, 0, "%s: Attributes extend beyond end of CU", - dso->filename); + error (0, 0, "%s: Attributes extend beyond end of CU " + "for DIE %x", + dso->filename, die_offset); goto fail; } @@ -7210,8 +7133,9 @@ > DW_AT_GNU_call_site_target_clobbered)) { error (0, 0, "%s: Unknown DWARF %s with " - "block DW_FORM", - dso->filename, get_DW_AT_str (t->attri.attr)); + "block DW_FORM for DIE %x", + dso->filename, get_DW_AT_str (t->attri.attr), + die_offset); goto fail; } @@ -7265,6 +7189,12 @@ } cu->cu_comp_dir = get_AT_string (cu->cu_die, DW_AT_comp_dir); + if (skip_producers_p + && skip_producer (get_AT_string (cu->cu_die, DW_AT_producer))) + { + cu->cu_die->die_remove = 1; + continue; + } enum dwarf_form form; debug_line_off = get_AT_int (cu->cu_die, DW_AT_stmt_list, &present, &form); @@ -8195,12 +8125,13 @@ else stats->pu_ph2_cnt++; } - if (dump_pus_p) - fprintf (stderr, "Partial unit (%s):\n", - second_phase ? "phase two" : "phase one"); partial_cu->cu_kind = CU_PU; partial_cu->cu_offset = *last_partial_cu == NULL ? 0 : (*last_partial_cu)->cu_offset + 1; + if (dump_pus_p) + fprintf (stderr, "Partial unit (%s) @ 0x%x:\n", + second_phase ? "phase two" : "phase one", + partial_cu->cu_offset); partial_cu->cu_version = refcu->cu_version; if (uni_lang_p) partial_cu->lang = refcu->lang; @@ -8378,7 +8309,12 @@ { case ODR_DEF: if (res) - return NULL; + { + if (die_cu (res) == die_cu (d)) + continue; + else + return NULL; + } else res = d; break; @@ -8904,7 +8840,7 @@ /* Helper function for debugging create_import_tree. Call verify_edges_1 on all CUs and PUs. */ -void +static void verify_edges (struct import_cu **ipus, unsigned int npus, unsigned int ncus, unsigned int phase) { @@ -8976,7 +8912,7 @@ { unsigned div = idx / (sizeof (BITVECTOR_TYPE) * 8); unsigned mod = idx % (sizeof (BITVECTOR_TYPE) * 8); - vectordiv |= (1 << mod); + vectordiv |= (1U << mod); } /* Test bit IDX in bitvector VECTOR. */ @@ -8985,7 +8921,7 @@ { unsigned div = idx / (sizeof (BITVECTOR_TYPE) * 8); unsigned mod = idx % (sizeof (BITVECTOR_TYPE) * 8); - return (vectordiv & (1 << mod)) != 0; + return (vectordiv & (1U << mod)) != 0; } /* Clear at least bits A, B in VECTOR, possibly more. */ @@ -9075,11 +9011,18 @@ ipu->cu = pu; pu->u1.cu_icu = ipu; assert (rdie->die_toplevel); + dw_die_ref firstdie = NULL; + dw_cu_ref firstdiecu = NULL; for (die = rdie->die_nextdup, prev_cu = NULL; die; die = die->die_nextdup) { dw_cu_ref diecu = die_cu (die); - if (diecu == prev_cu) + if (firstdie == NULL) + { + firstdie = die; + firstdiecu = die_cu (firstdie); + } + if (diecu == prev_cu || (die != firstdie && diecu == firstdiecu)) continue; ipu->incoming_count++; size += 1 + (diecu->cu_version == 2 ? ptr_size : 4); @@ -9089,11 +9032,18 @@ obstack_alloc (&ob2, ipu->incoming_count * sizeof (*ipu->incoming)); + firstdie = NULL; + firstdiecu = NULL; for (die = rdie->die_nextdup, i = 0, prev_cu = NULL; die; die = die->die_nextdup) { dw_cu_ref diecu = die_cu (die); - if (diecu == prev_cu) + if (firstdie == NULL) + { + firstdie = die; + firstdiecu = die_cu (firstdie); + } + if (diecu == prev_cu || (die != firstdie && diecu == firstdiecu)) continue; icu = diecu->u1.cu_icu; if (icu == NULL) @@ -9935,17 +9885,16 @@ { void **slot; struct line_entry le; - hashval_t h; - if (id == 0) return 0; assert (id <= cu->cu_nfiles); le.file = &cu->cu_filesid - 1; - h = iterative_hash_object (le.file->time, 0); - h = iterative_hash_object (le.file->size, h); - h = iterative_hash (le.file->file, strlen (le.file->file) + 1, h); + hash_init_state (); + hash_update_state_object (le.file->time); + hash_update_state_object (le.file->size); + hash_update_state (le.file->file, strlen (le.file->file) + 1); if (le.file->dir) - h = iterative_hash (le.file->dir, strlen (le.file->dir) + 1, h); + hash_update_state (le.file->dir, strlen (le.file->dir) + 1); if (line_htab == NULL) { line_htab = htab_try_create (50, line_hash, line_eq, NULL); @@ -9953,15 +9902,15 @@ dwz_oom (); max_line_id = 1; } - le.hash = h; - slot = htab_find_slot_with_hash (line_htab, &le, h, INSERT); + le.hash = hash_digest (); + slot = htab_find_slot_with_hash (line_htab, &le, le.hash, INSERT); if (slot == NULL) dwz_oom (); if (*slot == NULL) { struct line_entry *l = pool_alloc (line_entry, sizeof (*l)); l->file = le.file; - l->hash = h; + l->hash = le.hash; l->new_id = max_line_id++; *slot = (void *) l; return l->new_id; @@ -10433,7 +10382,7 @@ /* This should only happen if there were multiple same transparent units within a single object file. */ && htab_find_with_hash (strp_htab, p, - iterative_hash (p, len, 0)) == NULL) + hash (p, len)) == NULL) can_share = false; s = ptr; break; @@ -11238,7 +11187,10 @@ if (build_abbrevs_for_die (h, cu, cu->cu_die, NULL, NULL, t, ndies, vec, false)) - return 1; + { + htab_delete (h); + return 1; + } cu->cu_new_abbrev = h; return 0; @@ -14443,7 +14395,7 @@ memset (&ob, '\0', sizeof (ob2)); die_nontoplevel_freelist = NULL; die_collapsed_child_freelist = NULL; - pool_destroy (); + pool_destroy (NULL); first_cu = NULL; last_cu = NULL; ptr_size = 0; @@ -15040,10 +14992,26 @@ } #endif +/* Helper structure for file state. */ +struct file_result +{ + /* -3: Uninitialized. + -2: Already processed under different name. + -1: Ignore. + 0: Processed, changed. + 1: Processed, unchanged. */ + int res; + int ret; + size_t hardlink_to; + unsigned int die_count; + bool skip_multifile; + bool low_mem_p; +}; + /* Collect potentially shareable DIEs, strings and .debug_macro opcode sequences into temporary .debug_* files. */ static int -write_multifile (DSO *dso) +write_multifile_1 (DSO *dso, struct file_result *res) { dw_cu_ref cu; bool any_cus = false; @@ -15059,18 +15027,50 @@ if (multi_ehdr.e_ident0 == '\0') multi_ehdr = dso->ehdr; - if ((multi_ptr_size && ptr_size != multi_ptr_size) - || (multi_endian - && multi_endian != (do_read_32 == buf_read_ule32 - ? ELFDATA2LSB : ELFDATA2MSB))) + if (multifile_force_ptr_size && ptr_size != multifile_force_ptr_size) + { + error (0, 0, "File %s skipped for multi-file optimization, different" + " pointer size", dso->filename); + res->skip_multifile = true; + return 1; + } + else if (multi_ptr_size == 0) + multi_ptr_size = ptr_size; + else if (ptr_size != multi_ptr_size) + { + error (0, 0, "Multi-file optimization not allowed for different" + " pointer sizes"); + multifile = NULL; + return 1; + } + else + { + /* Same ptr_size. */ + } + + int endianity = (do_read_32 == buf_read_ule32 + ? ELFDATA2LSB + : ELFDATA2MSB); + if (multifile_force_endian && endianity != multifile_force_endian) + { + error (0, 0, "File %s skipped for multi-file optimization, different" + " endianity", dso->filename); + res->skip_multifile = true; + return 1; + } + else if (multi_endian == 0) + multi_endian = endianity; + else if (multi_endian != endianity) { error (0, 0, "Multi-file optimization not allowed for different" - " pointer sizes or endianity"); + " endianity"); multifile = NULL; return 1; } - multi_ptr_size = ptr_size; - multi_endian = do_read_32 == buf_read_ule32 ? ELFDATA2LSB : ELFDATA2MSB; + else + { + /* Same endianity. */ + } #if DEVEL clear_p2_field (); @@ -15096,10 +15096,15 @@ dw_cu_ref *cup; for (cup = &first_cu; *cup && (*cup)->cu_kind != CU_TYPES; ) - if ((*cup)->cu_die->die_no_multifile == 0) - cup = &(*cup)->cu_next; - else - *cup = (*cup)->cu_next; + { + if ((*cup)->cu_new_abbrev) + htab_delete ((*cup)->cu_new_abbrev); + + if ((*cup)->cu_die->die_no_multifile == 0) + cup = &(*cup)->cu_next; + else + *cup = (*cup)->cu_next; + } *cup = NULL; multifile_mode = MULTIFILE_MODE_WR; if (tracing) @@ -15177,6 +15182,64 @@ return ret; } +struct pipe +{ + int readfd; + int writefd; +}; + +static bool write_multifile_parallel_p; +static int child_id; +static struct pipe *pipes; + +/* Get token. */ +static void +get_token (void) +{ + int n = child_id; + int readfd = pipesn.readfd; + int writefd = pipesn.writefd; + close (writefd); + char buf; + read (readfd, &buf, 1); + close (readfd); +} + +/* Pass token to child N. */ +static void +pass_token (int n) +{ + int readfd = pipesn.readfd; + int writefd = pipesn.writefd; + close (readfd); + char buf = '\0'; + write (writefd, &buf, 1); + close (writefd); +} + +/* Wrapper around write_multifile_1 that ensures write_multifile_1 is called + in file order. */ +static int +write_multifile (DSO *dso, struct file_result *res) +{ + int ret; + + if (write_multifile_parallel_p) + { + get_token (); + + multi_info_off = lseek (multi_info_fd, 0L, SEEK_END); + multi_abbrev_off = lseek (multi_abbrev_fd, 0L, SEEK_END); + multi_line_off = lseek (multi_line_fd, 0L, SEEK_END); + multi_str_off = lseek (multi_str_fd, 0L, SEEK_END); + multi_macro_off = lseek (multi_macro_fd, 0L, SEEK_END); + } + + ret = write_multifile_1 (dso, res); + + return ret; +} + /* During fi_multifile phase, see what DIEs in a partial unit contain no children worth keeping where all real DIEs have dups in the shared .debug_info section and what remains is @@ -15252,33 +15315,21 @@ return 0; } -/* Helper structure for hardlink discovery. */ -struct file_result -{ - /* -2: Already processed under different name. - -1: Ignore. - 0: Processed, changed. - 1: Processed, unchanged. */ - int res; - dev_t dev; - ino_t ino; - nlink_t nlink; - unsigned int die_count; -}; - /* Handle compression of a single file FILE. If OUTFILE is non-NULL, the result will be stored into that file, otherwise the result will be written into a temporary file that is renamed over FILE. */ static int -dwz (const char *file, const char *outfile, struct file_result *res, - struct file_result *resa, char **files) +dwz (const char *file, const char *outfile, struct file_result *res) { DSO *dso; int ret = 0, fd; unsigned int i; struct stat st; + if (res->res == -1) + return 1; + res->res = -1; fd = open (file, O_RDONLY); if (fd < 0) @@ -15294,64 +15345,6 @@ } res->res = 1; - res->dev = st.st_dev; - res->ino = st.st_ino; - res->nlink = st.st_nlink; - /* Hardlink handling if requested. */ - if (resa != NULL) - { - size_t n; - for (n = 0; &resan != res; n++) - if (resan.res >= 0 - && resan.nlink > 1 - && resan.dev == st.st_dev - && resan.ino == st.st_ino) - break; - if (&resan != res) - { - /* If a hardlink to this has been processed before - and we didn't change it, just assume the same - state. */ - if (resan.res == 1) - { - if (tracing) - fprintf (stderr, "Skipping hardlink %s to unchanged file\n", - file); - close (fd); - res->res = -2; - return 0; - } - /* If it changed, try to hardlink it again. */ - if (resan.res == 0) - { - size_t len = strlen (file); - char *filename = alloca (len + sizeof (".#dwz#.XXXXXX")); - int fd2; - if (tracing) - fprintf (stderr, "Updating hardlink %s to changed file\n", - file); - memcpy (filename, file, len); - memcpy (filename + len, ".#dwz#.XXXXXX", - sizeof (".#dwz#.XXXXXX")); - fd2 = mkstemp (filename); - if (fd2 >= 0) - { - close (fd2); - unlink (filename); - if (link (filesn, filename) == 0) - { - if (rename (filename, file) == 0) - { - close (fd); - res->res = -2; - return 0; - } - unlink (filename); - } - } - } - } - } if (tracing) { @@ -15430,7 +15423,7 @@ + debug_sectionsDEBUG_TYPES.new_size)); if (multifile && !fi_multifile && !low_mem) - write_multifile (dso); + write_multifile (dso, res); cleanup (); if (outfile != NULL) @@ -15569,7 +15562,7 @@ debug_sectionsDEBUG_GNU_PUBTYPES.new_size = 0; if (multifile && !fi_multifile && !low_mem) - write_multifile (dso); + write_multifile (dso, res); bool save_to_temp = save_temps && multifile && multifile_mode == 0; cleanup (); @@ -15631,15 +15624,17 @@ Elf_Scn *scn; Elf_Data *data; char *e_ident; - const char shstrtab_gnu + static const char shstrtab_gnu = "\0.shstrtab\0.note.gnu.build-id\0.gdb_index\0" ".debug_info\0.debug_abbrev\0.debug_line\0.debug_str\0.debug_macro"; - const char shstrtab_dwarf5 + static const char shstrtab_dwarf5 = "\0.shstrtab\0.gdb_index\0" ".debug_info\0.debug_abbrev\0.debug_line\0.debug_str\0.debug_macro\0" ".debug_sup"; - const char *shstrtab; - size_t shstrtab_len; + const char *const shstrtab = dwarf_5 ? shstrtab_dwarf5 : shstrtab_gnu; + const size_t shstrtab_len = (dwarf_5 + ? sizeof shstrtab_dwarf5 + : sizeof shstrtab_gnu); const char *p; unsigned char note0x24, *np, *supp; struct sha1_ctx ctx; @@ -15665,16 +15660,6 @@ fprintf (stderr, "optimize_multifile\n"); } - if (dwarf_5) - { - shstrtab = shstrtab_dwarf5; - shstrtab_len = sizeof shstrtab_dwarf5; - } - else - { - shstrtab = shstrtab_gnu; - shstrtab_len = sizeof shstrtab_gnu; - } debug_sectionsDEBUG_INFO.size = multi_info_off; debug_sectionsDEBUG_INFO.data = (multi_info_off @@ -15798,7 +15783,7 @@ hashval_t hash; q = (unsigned char *) strchr ((char *) p, '\0'); - hash = iterative_hash (p, q - p, 0); + hash = hash (p, q - p); se.off = p - debug_sectionsDEBUG_STR.data; se.new_off = hash & ~1U; slot = htab_find_slot_with_hash (strp_htab, &se, se.new_off, INSERT); @@ -16118,8 +16103,7 @@ { q = (unsigned char *) strchr ((char *) p, '\0') + 1; slot = htab_find_slot_with_hash (strp_htab, p, - iterative_hash (p, q - p - 1, - 0), INSERT); + hash (p, q - p - 1), INSERT); if (slot == NULL) dwz_oom (); assert (*slot == NULL); @@ -16132,8 +16116,7 @@ p = debug_sectionsDEBUG_STR.data + *pi; q = (unsigned char *) strchr ((char *) p, '\0'); slot = htab_find_slot_with_hash (strp_htab, p, - iterative_hash (p, q - p, - 0), INSERT); + hash (p, q - p), INSERT); if (slot == NULL) dwz_oom (); assert (*slot == NULL); @@ -16157,10 +16140,7 @@ alt_macro_htab = macro_htab; macro_htab = NULL; alt_first_cu = first_cu; - alt_pool = pool; - pool = NULL; - pool_next = NULL; - pool_limit = NULL; + alt_pool = finalize_pool (); alt_ob = ob; alt_ob2 = ob2; memset (&ob, '\0', sizeof (ob)); @@ -16261,618 +16241,628 @@ return fd; } -int die_count_method_parsed; -int deduplication_mode_parsed; - -/* Options for getopt_long. */ -static struct option dwz_options = +/* As dwz, but retry with MULTIFILE_MODE_LOW_MEM if the low_mem_die_limit + is hit. */ +static int +dwz_with_low_mem (const char *file, const char *outfile, + struct file_result *res) { - { "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-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 }, -#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 } -}; + int ret; -/* 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; -}; + res->low_mem_p = false; -/* 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." } -}; + ret = (low_mem_die_limit == 0 + ? 2 + : dwz (file, outfile, res)); -/* 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 (ret == 2) + { + multifile_mode = MULTIFILE_MODE_LOW_MEM; + res->low_mem_p = true; -/* 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." } -}; + ret = dwz (file, outfile, res); + } -/* 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." } -}; + return ret; +} -/* Print LEN spaces to STREAM. */ +/* Initialize struct file_result RES. */ static void -do_indent (FILE *stream, unsigned int len) +init_file_result (struct file_result *res) { - unsigned int i; + res->die_count = 0; + res->res = -3; + res->skip_multifile = false; + res->low_mem_p = false; +} + +/* Dwarf-compress FILE. If OUTFILE, write to result to OUTFILE, otherwise + modify FILE. */ +static int +dwz_one_file (const char *file, const char *outfile) +{ + struct file_result res; + + if (stats_p) + init_stats (file); + + init_file_result (&res); - for (i = 0; i < len; i++) - fprintf (stream, " "); + return dwz_with_low_mem (file, outfile, &res); } -/* 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) +/* Helper structure for hardlink discovery. */ +struct hl_stat { - unsigned int len = indent; - const char *s = msg; - while (true) + dev_t dev; + ino_t ino; + nlink_t nlink; +}; + +/* Detect which FILES are hardlinks, and mark those in RESA. */ +static bool +detect_hardlinks (int nr_files, char *files, struct file_result *resa) +{ + bool found = false; + struct hl_stat hl_statnr_files; + int i; + + /* Try to open all files. */ + for (i = 0; i < nr_files; i++) { - 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; + struct file_result *res = &resai; + int fd; + struct stat st; - if (len + 1 /* space */ + word_len > limit) - { - fprintf (stream, "\n"); - do_indent (stream ,indent); - len = indent; - } - else if (len > indent) - { - fprintf (stream, " "); - len += 1; - } + const char *file = filesi; + res->res = -1; - if (e != NULL) + fd = open (file, O_RDONLY); + if (fd < 0) + error (0, errno, "Failed to open input file %s", file); + else if (fstat (fd, &st) < 0) + error (0, errno, "Failed to stat input file %s", file); + else { - const char *i; - for (i = s; i < e; ++i) - fprintf (stream, "%c", *i); + res->res = 1; + hl_stati.dev = st.st_dev; + hl_stati.ino = st.st_ino; + hl_stati.nlink = st.st_nlink; } - else - fprintf (stream, "%s", s); - len += word_len; - if (e == NULL) - break; + close (fd); + } - s = e + 1; + /* Detect hard links. */ + for (i = 0; i < nr_files; i++) + { + struct file_result *res = &resai; + int n; + for (n = 0; n != i; n++) + if (resan.res >= 0 + && hl_statn.nlink > 1 + && hl_statn.dev == hl_stati.dev + && hl_statn.ino == hl_stati.ino) + break; + if (n == i) + continue; + res->res = -2; + res->hardlink_to = n; + found = true; } + + return found; } -/* Print OPTIONS_HELP of length H to STREAM, indenting to help message to - INDENT an wrapping at LIMIT. */ +/* Update the FILES marked as hardlink in RESA. */ static void -print_options_help (FILE *stream, struct option_help *options_help, unsigned int n, - unsigned int indent, unsigned int limit) +update_hardlinks (int nr_files, char *files, struct file_result *resa) { - unsigned len; - const char *s; - unsigned int i; + int i; - for (i = 0; i < n; ++i) + /* Update hardlinks. */ + for (i = 0; i < nr_files; i++) { - len = 0; - - fprintf (stream, " "); - len += 2; - - s = options_helpi.short_name; - if (s) - { - fprintf (stream, "-%s", s); - len += 2; - } + struct file_result *res = &resai; + const char *file = filesi; + size_t n; + if (res->res != -2) + continue; + n = res->hardlink_to; - s = options_helpi.long_name; - if (len == 4) - { - fprintf (stream, ", "); - len += 2; + /* If a hardlink to this has been processed before + and we didn't change it, just assume the same + state. */ + if (resan.res == 1) + { + if (tracing) + fprintf (stderr, "Skipping hardlink %s to unchanged file\n", + file); + continue; } - fprintf (stream, "--%s", s); - len += 2 + strlen (s); - s = options_helpi.argument; - if (s) + /* If it changed, try to hardlink it again. */ + if (resan.res == 0) { - fprintf (stream, " %s", s); - len += 1 + strlen (s); + size_t len = strlen (file); + char *filename = alloca (len + sizeof (".#dwz#.XXXXXX")); + int fd2; + if (tracing) + fprintf (stderr, "Updating hardlink %s to changed file\n", + file); + memcpy (filename, file, len); + memcpy (filename + len, ".#dwz#.XXXXXX", + sizeof (".#dwz#.XXXXXX")); + fd2 = mkstemp (filename); + if (fd2 >= 0) + { + close (fd2); + unlink (filename); + if (link (filesn, filename) == 0) + { + if (rename (filename, file) == 0) + ; + else + unlink (filename); + } + } } + } +} - s = options_helpi.msg; - if (s) - { - if (len > indent) - { - fprintf (stream, "\n"); - do_indent (stream, indent); - } - else - do_indent (stream, indent - len); - len = indent; +/* Encode child process exit status. */ +static int +encode_child_exit_status (int thisret, struct file_result *res) +{ + assert (thisret == 0 || thisret == 1); + if (thisret == 0 && res->low_mem_p) + thisret = 2; + assert (res->res >= -3 && res->res <= 1); + return (thisret + + ((res->res + 3) << 2) + + ((res->skip_multifile ? 1 : 0) << 5)); +} - wrap (stream, indent, limit, s); - } - fprintf (stream, "\n"); +/* Decode child process exit status. */ +static int +decode_child_exit_status (int state, struct file_result *res) +{ + int ret; + if (!WIFEXITED (state)) + error (1, 0, "Child dwz process got killed"); + int status = WEXITSTATUS (state); + ret = status & 0x3; + status >>= 2; - s = options_helpi.default_value; - if (s) - { - do_indent (stream, indent); - fprintf (stream, "Default value: %s.\n", s); - } + res->low_mem_p = false; + if (ret == 2) + { + ret = 0; + res->low_mem_p = true; } + + res->res = (int)(status & 0x7) - 3; + status >>= 3; + + res->skip_multifile = (status & 0x1) ? true : false; + + return ret; } -/* Print usage and exit. */ +/* Wait on child exit with PID, update PIDS and RES. */ static void -usage (const char *progname, int failing) +wait_child_exit (pid_t pid, pid_t *pids, int nr_pids, + struct file_result *resa) { - 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_help0)); - 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_help0)); - 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_help0)); - 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_help0)); - print_options_help (stream, dwz_misc_options_help, n, indent, limit); + int state; + pid_t got_pid = waitpid (pid, &state, 0); -#if DEVEL - fprintf (stream, "Development options:\n"); - fprintf (stream, "%s", - (" --devel-trace\n" - " --devel-progress\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")); -#endif + int i; + for (i = 0; i < nr_pids; ++i) + if (pidsi == got_pid) + { + pidsi = 0; + break; + } + assert (i < nr_pids); - exit (failing); + resai.ret = decode_child_exit_status (state, &resai); } -/* Print version and exit. */ +static int *workset; +static int workset_size = 0; +int current_multifile_owner = -1; +int current_multifile_owner_file_idx = -1; + +/* Wait on exit of chilren in PIDS, update RESA. */ static void -version (void) +wait_children_exit (pid_t *pids, int nr_files, struct file_result *resa) { - 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); + int i; + for (i = 0; i < nr_files; i++) + { + struct file_result *res = &resai; + if (pidsi == 0) + continue; + wait_child_exit (pidsi, &pidsi, 1, res); + if (current_multifile_owner_file_idx == -1 + || i < current_multifile_owner_file_idx) + continue; + assert (i == current_multifile_owner_file_idx); + current_multifile_owner++; + if (current_multifile_owner == workset_size) + continue; + current_multifile_owner_file_idx + = worksetcurrent_multifile_owner; + pass_token (current_multifile_owner); + } } -int -main (int argc, char *argv) +/* Dwarf-compress FILES. If HARDLINK, detect if some files are hardlinks and + if so, dwarf-compress just one, and relink the others. */ +static int +dwz_files_1 (int nr_files, char *files, bool hardlink, + struct file_result *resa) { - const char *outfile = NULL; int ret = 0; - int i; - unsigned long l; - char *end; - struct file_result res; - bool hardlink = false; + int i, j; const char *file; + int successcount = 0; - if (elf_version (EV_CURRENT) == EV_NONE) - error (1, 0, "library out of date"); + for (i = 0; i < nr_files; ++i) + init_file_result (&resai); - while (1) + if (multifile) { - 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) + if (multifile_force_ptr_size) + multi_ptr_size = multifile_force_ptr_size; + if (multifile_force_endian) + multi_endian = multifile_force_endian; + + multi_info_fd = make_temp_file ("dwz.debug_info"); + multi_abbrev_fd = make_temp_file ("dwz.debug_abbrev"); + multi_line_fd = make_temp_file ("dwz.debug_line"); + multi_str_fd = make_temp_file ("dwz.debug_str"); + multi_macro_fd = make_temp_file ("dwz.debug_macro"); + if (multi_info_fd == -1 + || multi_abbrev_fd == -1 + || multi_line_fd == -1 + || multi_str_fd == -1 + || multi_macro_fd == -1) { - default: - case '?': - usage (argv0, option_index == -1); - break; + error (0, 0, "Could not create multifile temporary files"); + multifile = NULL; + } + } + + if (hardlink) + hardlink = detect_hardlinks (nr_files, files, resa); - case 0: - /* Option handled by getopt_long. */ - if (die_count_method_parsed) + workset = malloc (nr_files * sizeof (int)); + if (workset == NULL) + error (1, ENOMEM, "failed to allocate workset array"); + for (i = 0; i < nr_files; i++) + { + struct file_result *res = &resai; + if (res->res == -2) + /* Skip hard links. */ + continue; + worksetworkset_size = i; + workset_size++; + } + + bool initial_parallel_p = max_forks > 1; + if (initial_parallel_p && multifile) + { + if (multifile_force_ptr_size != 0 && multifile_force_endian != 0) + { + write_multifile_parallel_p = true; + pipes = malloc (workset_size * 2 * sizeof (int)); + if (pipes == NULL) + error (1, ENOMEM, "failed to allocate pipes array"); + for (i = 0; i < workset_size; i++) + { + int fds2; + if (pipe (fds) != 0) + error (1, ENOMEM, "failed to initialize pipe"); + pipesi.readfd = fds0; + pipesi.writefd = fds1; + } + } + else + initial_parallel_p = false; + } + if (initial_parallel_p) + { + pid_t pidsnr_files; + int nr_forks = 0; + for (i = 0; i < nr_files; i++) + pidsi = 0; + for (j = 0; j < workset_size; j++) + { + int i = worksetj; + + if (nr_forks == max_forks) { - die_count_method_parsed = 0; - if (strcmp (optarg, "none") == 0) - { - die_count_method = none; - break; - } - if (strcmp (optarg, "estimate") == 0) + if (multifile == NULL) + wait_child_exit (-1, pids, i, resa); + else { - die_count_method = estimate; - break; - } - error (1, 0, "invalid argument --devel-die-count-method %s", - optarg); + int k = current_multifile_owner_file_idx; + wait_child_exit (pidsk, &pidsk, 1, &resak); + current_multifile_owner++; + current_multifile_owner_file_idx + = worksetcurrent_multifile_owner; + pass_token (current_multifile_owner); + } + nr_forks--; + } + + pid_t fork_res = fork (); + assert (fork_res != -1); + if (fork_res == 0) + { + child_id = j; + file = filesi; + struct file_result *res = &resai; + int thisret = dwz_with_low_mem (file, NULL, res); + return encode_child_exit_status (thisret, res); } - if (deduplication_mode_parsed) + else { - deduplication_mode_parsed = 0; - if (strcmp (optarg, "none") == 0) + if (multifile && j == 0) { - deduplication_mode = dm_none; - break; - } - if (strcmp (optarg, "intra-cu") == 0) - { - deduplication_mode = dm_intra_cu; - break; + current_multifile_owner = j; + current_multifile_owner_file_idx + = worksetcurrent_multifile_owner; + pass_token (current_multifile_owner); } - if (strcmp (optarg, "inter-cu") == 0) - { - deduplication_mode = dm_inter_cu; - break; - } - error (1, 0, "invalid argument --devel-deduplication-mode %s", - optarg); + pidsi = fork_res; + nr_forks++; } - if (odr_mode_parsed) + } + if (nr_forks > 0) + wait_children_exit (pids, nr_files, resa); + } + else + { + for (j = 0; j < workset_size; j++) + { + int i = worksetj; + file = filesi; + struct file_result *res = &resai; + if (stats_p) + init_stats (file); + res->ret = dwz_with_low_mem (file, NULL, res); + } + } + + for (j = 0; j < workset_size; j++) + { + int i = worksetj; + struct file_result *res = &resai; + int thisret = res->ret; + if (thisret == 1) + ret = 1; + else if (!res->low_mem_p && !res->skip_multifile && res->res >= 0) + successcount++; + } + + if (hardlink) + update_hardlinks (nr_files, files, resa); + + if (multifile == NULL) + return ret; + + if (successcount < 2) + { + error (0, 0, "Too few files for multifile optimization"); + return ret; + } + + if (write_multifile_parallel_p) + { + multi_info_off = lseek (multi_info_fd, 0L, SEEK_END); + multi_abbrev_off = lseek (multi_abbrev_fd, 0L, SEEK_END); + multi_line_off = lseek (multi_line_fd, 0L, SEEK_END); + multi_str_off = lseek (multi_str_fd, 0L, SEEK_END); + multi_macro_off = lseek (multi_macro_fd, 0L, SEEK_END); + } + if (multi_info_off == 0 && multi_str_off == 0 && multi_macro_off == 0) + { + if (!quiet) + error (0, 0, "No suitable DWARF found for multifile optimization"); + return ret; + } + + if (write_multifile_parallel_p) + { + /* We reproduce here what happens when we run sequentially. This is a + kludge that probably needs to be replaced by IPC. */ + for (i = 0; i < nr_files; i++) + { + struct file_result *res = &resai; + if (!res->low_mem_p && !res->skip_multifile && res->res >= 0) { - odr_mode_parsed = 0; - if (strcmp (optarg, "basic") == 0) + int fd = open (filesi, O_RDONLY); + if (fd < 0) + return ret; + DSO *dso = fdopen_dso (fd, filesi); + if (dso == NULL) { - odr_mode = ODR_BASIC; - break; + close (fd); + return ret; } - if (strcmp (optarg, "link") == 0) - { - odr_mode = ODR_LINK; - break; - } - error (1, 0, "invalid argument --odr-mode %s", - optarg); + assert (multi_ehdr.e_ident0 == '\0'); + multi_ehdr = dso->ehdr; + break; } - break; - - case 'o': - outfile = optarg; - break; - - case 'm': - multifile = optarg; - break; + } + } - case 'q': - quiet = true; - break; + unsigned int multifile_die_count = 0; + int multi_fd = optimize_multifile (&multifile_die_count); + DSO *dso; + if (multi_fd == -1) + return 1; - case 'h': - hardlink = true; - break; + dso = read_multifile (multi_fd, multifile_die_count); + if (dso == NULL) + { + ret = 1; + goto cleanup; + } - case 'M': - multifile_name = optarg; - break; + workset_size = 0; + for (i = 0; i < nr_files; i++) + { + struct file_result *res = &resai; + /* Don't process again files that couldn't + be processed successfully. Also skip hard links. */ + if (res->res == -1 || res->res == -2 + || res->skip_multifile) + continue; + worksetworkset_size = i; + workset_size++; + } - case 'r': - multifile_relative = true; - break; + bool finalize_multifile_parallel_p = max_forks > 1; + if (finalize_multifile_parallel_p) + { + pid_t pidsnr_files; + int nr_forks = 0; + for (i = 0; i < nr_files; i++) + pidsi = 0; + for (j = 0; j < workset_size; j++) + { + int i = worksetj; - case 'l': - if (strcmp (optarg, "none") == 0) + if (nr_forks == max_forks) { - low_mem_die_limit = -1U; - break; + wait_child_exit (-1, pids, i, resa); + nr_forks--; } - 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) + pid_t fork_res = fork (); + assert (fork_res != -1); + if (fork_res == 0) { - max_die_limit = -1U; - break; + file = filesi; + struct file_result *res = &resai; + multifile_mode = MULTIFILE_MODE_FI; + int thisret = dwz (file, NULL, res); + return encode_child_exit_status (thisret, res); } - 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; + else + { + pidsi = fork_res; + nr_forks++; + } + } + if (nr_forks > 0) + wait_children_exit (pids, nr_files, resa); + } + else + { + for (j = 0; j < workset_size; j++) + { + int i = worksetj; + struct file_result *res = &resai; + dw_cu_ref cu; + file = filesi; + if (stats_p) + init_stats (file); + multifile_mode = MULTIFILE_MODE_FI; + for (cu = alt_first_cu; cu; cu = cu->cu_next) + alt_clear_dups (cu->cu_die); + res->ret = dwz (file, NULL, res); } } - /* 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; + for (j = 0; j < workset_size; j++) + { + int i = worksetj; + struct file_result *res = &resai; + int thisret = res->ret; + ret |= thisret; + } + + if (hardlink) + update_hardlinks (nr_files, files, resa); + + elf_end (dso->elf); + close (multi_fd); + free (dso); + + cleanup: + cleanup (); + + strp_htab = alt_strp_htab; + off_htab = alt_off_htab; + dup_htab = alt_dup_htab; + macro_htab = alt_macro_htab; + ob = alt_ob; + ob2 = alt_ob2; + cleanup (); + pool_destroy (alt_pool); + + return ret; +} + +/* Wrapper around dwz_files_1 that takes care of malloc and free of resa. */ +static int +dwz_files (int nr_files, char *files, bool hardlink) +{ + int ret; + struct file_result *resa + = (struct file_result *) malloc ((nr_files) * sizeof (*resa)); + if (resa == NULL) + error (1, ENOMEM, "failed to allocate result array"); + + ret = dwz_files_1 (nr_files, files, hardlink, resa); + + free (resa); + return ret; +} + +int +main (int argc, char *argv) +{ + int ret; + const char *outfile; + bool hardlink; + int nr_files; + char **files; - if (multifile_relative && multifile_name) - error (1, 0, "-M and -r options can't be specified together"); + state = XXH64_createState (); - if (optind == argc || optind + 1 == argc) + if (elf_version (EV_CURRENT) == EV_NONE) + error (1, 0, "library out of date"); + + outfile = NULL; + hardlink = false; + parse_args (argc, argv, &hardlink, &outfile); + nr_files = argc - optind; + files = &argvoptind; + + if (nr_files <= 1) { - file = optind == argc ? "a.out" : argvoptind; + const char *file = nr_files == 0 ? "a.out" : files0; + if (multifile != NULL) { error (0, 0, "Too few files for multifile optimization"); multifile = NULL; } - if (stats_p) - init_stats (file); - res.die_count = 0; - ret = (low_mem_die_limit == 0 - ? 2 - : dwz (file, outfile, &res, NULL, NULL)); - if (ret == 2) - { - multifile_mode = MULTIFILE_MODE_LOW_MEM; - ret = dwz (file, outfile, &res, NULL, NULL); - } + + ret = dwz_one_file (file, outfile); } else { - int nr_files = argc - optind; - struct file_result *resa - = (struct file_result *) malloc ((nr_files) * sizeof (*resa)); - bool hardlinks = false; - int successcount = 0; - - for (i = 0; i < nr_files; ++i) - resai.die_count = 0; - if (resa == NULL) - error (1, ENOMEM, "failed to allocate result array"); if (outfile != NULL) error (1, 0, "-o option not allowed for multiple files"); - if (multifile) - { - multi_info_fd = make_temp_file ("dwz.debug_info"); - multi_abbrev_fd = make_temp_file ("dwz.debug_abbrev"); - multi_line_fd = make_temp_file ("dwz.debug_line"); - multi_str_fd = make_temp_file ("dwz.debug_str"); - multi_macro_fd = make_temp_file ("dwz.debug_macro"); - if (multi_info_fd == -1 - || multi_abbrev_fd == -1 - || multi_line_fd == -1 - || multi_str_fd == -1 - || multi_macro_fd == -1) - { - error (0, 0, "Could not create multifile temporary files"); - multifile = NULL; - } - } - for (i = optind; i < argc; i++) - { - int thisret; - file = argvi; - if (stats_p) - init_stats (file); - thisret = (low_mem_die_limit == 0 - ? 2 - : dwz (file, NULL, &resai - optind, - hardlinks ? resa : NULL, &argvoptind)); - if (thisret == 2) - { - multifile_mode = MULTIFILE_MODE_LOW_MEM; - thisret = dwz (file, NULL, &resai - optind, - hardlinks ? resa : NULL, &argvoptind); - } - else if (thisret == 1) - ret = 1; - else if (resai - optind.res >= 0) - successcount++; - if (hardlink - && resai - optind.res >= 0 - && resai - optind.nlink > 1) - hardlinks = true; - } - if (multifile && successcount < 2) - { - error (0, 0, "Too few files for multifile optimization"); - multifile = NULL; - } - if (multifile - && multi_info_off == 0 && multi_str_off == 0 && multi_macro_off == 0) - { - if (!quiet) - error (0, 0, "No suitable DWARF found for multifile optimization"); - multifile = NULL; - } - if (multifile) - { - unsigned int multifile_die_count = 0; - int multi_fd = optimize_multifile (&multifile_die_count); - DSO *dso; - if (multi_fd == -1) - return 1; - dso = read_multifile (multi_fd, multifile_die_count); - if (dso == NULL) - ret = 1; - else - { - for (i = optind; i < argc; i++) - { - dw_cu_ref cu; - file = argvi; - if (stats_p) - init_stats (file); - multifile_mode = MULTIFILE_MODE_FI; - /* Don't process again files that couldn't - be processed successfully. */ - if (resai - optind.res == -1) - continue; - for (cu = alt_first_cu; cu; cu = cu->cu_next) - alt_clear_dups (cu->cu_die); - ret |= dwz (file, NULL, &resai - optind, - hardlinks ? resa : NULL, &argvoptind); - } - elf_end (dso->elf); - close (multi_fd); - free (dso); - } - cleanup (); - strp_htab = alt_strp_htab; - off_htab = alt_off_htab; - dup_htab = alt_dup_htab; - macro_htab = alt_macro_htab; - pool = alt_pool; - ob = alt_ob; - ob2 = alt_ob2; - cleanup (); - } - free (resa); + + ret = dwz_files (nr_files, files, hardlink); } if (stats_p)
View file
_service:tar_scm:dwz-0.14.tar.xz/hashtab.c -> _service:tar_scm:dwz-0.15.tar.xz/hashtab.c
Changed
@@ -626,142 +626,3 @@ 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( ki, leni, 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 += (k0 +((hashval_t)k1<<8) +((hashval_t)k2<<16) +((hashval_t)k3<<24)); - b += (k4 +((hashval_t)k5<<8) +((hashval_t)k6<<16) +((hashval_t)k7<<24)); - c += (k8 +((hashval_t)k9<<8) +((hashval_t)k10<<16)+((hashval_t)k11<<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)k10<<24); /* fall through */ - case 10: c+=((hashval_t)k9<<16); /* fall through */ - case 9 : c+=((hashval_t)k8<<8); /* fall through */ - /* the first byte of c is reserved for the length */ - case 8 : b+=((hashval_t)k7<<24); /* fall through */ - case 7 : b+=((hashval_t)k6<<16); /* fall through */ - case 6 : b+=((hashval_t)k5<<8); /* fall through */ - case 5 : b+=k4; /* fall through */ - case 4 : a+=((hashval_t)k3<<24); /* fall through */ - case 3 : a+=((hashval_t)k2<<16); /* fall through */ - case 2 : a+=((hashval_t)k1<<8); /* fall through */ - case 1 : a+=k0; - /* case 0: nothing left to add */ - } - mix(a,b,c); - /*-------------------------------------------- report the result */ - return c; -}
View file
_service:tar_scm:dwz-0.14.tar.xz/hashtab.h -> _service:tar_scm:dwz-0.15.tar.xz/hashtab.h
Changed
@@ -153,11 +153,6 @@ #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 */
View file
_service:tar_scm:dwz-0.15.tar.xz/pool.c
Added
@@ -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; +}
View file
_service:tar_scm:dwz-0.15.tar.xz/pool.h
Added
@@ -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
_service:tar_scm:dwz-0.15.tar.xz/testsuite/dwz.tests/cycle.c
Added
@@ -0,0 +1,13 @@ +struct s; + +struct s { + struct s *p; +}; + +struct s var; + +int +main (void) +{ + return 0; +}
View file
_service:tar_scm:dwz-0.15.tar.xz/testsuite/dwz.tests/cycle.sh
Added
@@ -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
_service:tar_scm:dwz-0.14.tar.xz/testsuite/dwz.tests/devel-ignore-locus.sh -> _service:tar_scm:dwz-0.15.tar.xz/testsuite/dwz.tests/devel-ignore-locus.sh
Changed
@@ -6,7 +6,7 @@ $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 @@ 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
_service:tar_scm:dwz-0.14.tar.xz/testsuite/dwz.tests/devel-ignore-size.sh -> _service:tar_scm:dwz-0.15.tar.xz/testsuite/dwz.tests/devel-ignore-size.sh
Changed
@@ -6,7 +6,7 @@ $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 @@ 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
_service:tar_scm:dwz-0.14.tar.xz/testsuite/dwz.tests/devel-trace.sh -> _service:tar_scm:dwz-0.15.tar.xz/testsuite/dwz.tests/devel-trace.sh
Changed
@@ -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
_service:tar_scm:dwz-0.14.tar.xz/testsuite/dwz.tests/dw2-skip-prologue.S -> _service:tar_scm:dwz-0.15.tar.xz/testsuite/dwz.tests/dw2-skip-prologue.S
Changed
@@ -400,3 +400,4 @@ .byte 1 .Lline1_end: + .section .note.GNU-stack,"",@progbits
View file
_service:tar_scm:dwz-0.14.tar.xz/testsuite/dwz.tests/gdb-add-index.sh -> _service:tar_scm:dwz-0.15.tar.xz/testsuite/dwz.tests/gdb-add-index.sh
Changed
@@ -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
_service:tar_scm:dwz-0.14.tar.xz/testsuite/dwz.tests/implptr-64bit-d2o4a8r8t0.S -> _service:tar_scm:dwz-0.15.tar.xz/testsuite/dwz.tests/implptr-64bit-d2o4a8r8t0.S
Changed
@@ -154,3 +154,4 @@ .byte 0x0 /* Terminator */ .byte 0x0 /* Terminator */ .byte 0x0 /* Terminator */ + .section .note.GNU-stack,"",@progbits
View file
_service:tar_scm:dwz-0.14.tar.xz/testsuite/dwz.tests/odr-struct-multifile.sh -> _service:tar_scm:dwz-0.15.tar.xz/testsuite/dwz.tests/odr-struct-multifile.sh
Changed
@@ -2,6 +2,11 @@ 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 @@ $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
_service:tar_scm:dwz-0.14.tar.xz/testsuite/dwz.tests/odr-struct-ns.sh -> _service:tar_scm:dwz-0.15.tar.xz/testsuite/dwz.tests/odr-struct-ns.sh
Changed
@@ -21,7 +21,10 @@ 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 @@ 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
_service:tar_scm:dwz-0.14.tar.xz/testsuite/dwz.tests/odr-struct.sh -> _service:tar_scm:dwz-0.15.tar.xz/testsuite/dwz.tests/odr-struct.sh
Changed
@@ -21,7 +21,10 @@ 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 @@ 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
_service:tar_scm:dwz-0.14.tar.xz/testsuite/dwz.tests/pr24747.sh -> _service:tar_scm:dwz-0.15.tar.xz/testsuite/dwz.tests/pr24747.sh
Changed
@@ -4,6 +4,4 @@ dwz 1 -smaller-than.sh 1 $exec - rm -f 1
View file
_service:tar_scm:dwz-0.14.tar.xz/testsuite/dwz.tests/twice-multifile.sh -> _service:tar_scm:dwz-0.15.tar.xz/testsuite/dwz.tests/twice-multifile.sh
Changed
@@ -24,7 +24,10 @@ 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
_service:tar_scm:dwz-0.14.tar.xz/testsuite/dwz.tests/two-files-low-mem-die-limit-0.sh -> _service:tar_scm:dwz-0.15.tar.xz/testsuite/dwz.tests/two-files-low-mem-die-limit-0.sh
Changed
@@ -5,9 +5,10 @@ -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
_service:tar_scm:dwz-0.14.tar.xz/testsuite/dwz.tests/varval.S -> _service:tar_scm:dwz-0.15.tar.xz/testsuite/dwz.tests/varval.S
Changed
@@ -512,3 +512,4 @@ .byte 0x0 /* Terminator */ .byte 0x0 /* Terminator */ .byte 0x0 /* Terminator */ + .section .note.GNU-stack,"",@progbits
View file
_service:tar_scm:dwz-0.14.tar.xz/testsuite/lib/dwarf.exp -> _service:tar_scm:dwz-0.15.tar.xz/testsuite/lib/dwarf.exp
Changed
@@ -1666,6 +1666,8 @@ _write_deferred_output + _section .note.GNU-stack "" progbits + catch {close $_output_file} set _output_file {} }
View file
_service:tar_scm:dwz-0.14.tar.xz/testsuite/scripts/smaller-than.sh -> _service:tar_scm:dwz-0.15.tar.xz/testsuite/scripts/smaller-than.sh
Changed
@@ -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
View file
_service:tar_scm:dwz-0.15.tar.xz/util.h
Added
@@ -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
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2