]> sourceware.org Git - dwz.git/log
dwz.git
2 months agotestsuite: fix finding gdb without `which` master
Sam James [Sat, 27 Jul 2024 14:07:56 +0000 (15:07 +0100)]
testsuite: fix finding gdb without `which`

which isn't considered portable. Some Linux distributions like Debian and
Gentoo are seeking to remove it from their base set of packages [0].

Use POSIX's `command -v` instead.

[0] https://lwn.net/Articles/874049/

19 months agomake dejagnu test names environment-insensitive
Frank Ch. Eigler [Wed, 1 Mar 2023 15:51:58 +0000 (16:51 +0100)]
make dejagnu test names environment-insensitive

Previous versions of dwz-tests.exp emit the full path names to the
per-test .sh scripts into the .sum/.log files.  This version replaces
those patn names with just the $basename, which is enough to identify
the tests uniquely, and allows proper regression/comparison analysis.

https://sourceware.org/bugzilla/show_bug.cgi?id=30182

19 months agomake dejagnu logs more elaborate
Frank Ch. Eigler [Sat, 18 Feb 2023 11:36:15 +0000 (12:36 +0100)]
make dejagnu logs more elaborate

dwz-tests.exp produces totally barebones dwz.log files, basically
duplicating the .sum file.  If there are any errors, there's
basically no info to go on.

The patch runs the .sh subtests in -x trace mode, and logs
stdout/stderr to the .log file, so e.g. bunsen can safe-keep it.
Otherwise I believe no-op.

23 months agoBump version to 0.15 dwz-0.15
Mark Wielaard [Fri, 4 Nov 2022 00:16:29 +0000 (01:16 +0100)]
Bump version to 0.15

23 months agoAdd .note.GNU-stack in dwarf.exp generated files
Mark Wielaard [Thu, 3 Nov 2022 22:33:05 +0000 (23:33 +0100)]
Add .note.GNU-stack in dwarf.exp generated files

23 months agoCheck -DXXH_INLINE_ALL works, otherwise link against libxxhash
Mark Wielaard [Thu, 3 Nov 2022 22:08:50 +0000 (23:08 +0100)]
Check -DXXH_INLINE_ALL works, otherwise link against libxxhash

Because we don't have a real configure script this does a Makefile
shell trick trying to compile with XXH_INLINE_ALL defined when
including xxhash.h. If that fails (like on oldstable debian) it
doesn't add -DXXH_INLINE_ALL=1 to CFLAGS and does add -lxxhash
to LIBS.

23 months agogen-copyright-years.sh skip native.c
Mark Wielaard [Wed, 13 Jul 2022 10:11:44 +0000 (12:11 +0200)]
gen-copyright-years.sh skip native.c

And generate the native.c file so we don't need to keep it in git.

23 months agodo-release.sh: Create signed annotated tags
Mark Wielaard [Wed, 13 Jul 2022 10:33:26 +0000 (12:33 +0200)]
do-release.sh: Create signed annotated tags

2 years agoFix executable stack warning from linker
Martin Liška [Wed, 7 Sep 2022 19:57:26 +0000 (21:57 +0200)]
Fix executable stack warning from linker

Fixes:
missing .note.GNU-stack section implies executable stack

2 years agoUse grep -E instead of egrep.
Martin Liška [Wed, 7 Sep 2022 19:55:03 +0000 (21:55 +0200)]
Use grep -E instead of egrep.

egrep is obsoleted starting with GNU Grep 3.8.

2 years agoUse xxHash hashing algorithm.
Martin Liska [Wed, 22 Dec 2021 13:45:40 +0000 (14:45 +0100)]
Use xxHash hashing algorithm.

The algorithm provides the following speed-up with -O2:

- 1/5: sysdig (60M)
dwz_O2                : 9.7
dwz_O2_xxhash         : 8.5 (87.7%)
- 2/5: rtags (58M)
dwz_O2                : 17.6
dwz_O2_xxhash         : 15.8 (89.5%)
- 3/5: libetonyek (91M)
dwz_O2                : 10.8
dwz_O2_xxhash         : 9.4 (86.7%)
- 4/5: krita (685M)
dwz_O2                : 96.0
dwz_O2_xxhash         : 85.6 (89.1%)
- 5/5: gcc (1.2G)
dwz_O2                : 58.6
dwz_O2_xxhash         : 54.1 (92.4%)

2 years agoRedirect stder in gdb-add-index.sh test
Mark Wielaard [Fri, 1 Jul 2022 23:11:00 +0000 (01:11 +0200)]
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.

2 years agoAlways assign svalue when checking and reporting negative values
Mark Wielaard [Thu, 30 Jun 2022 12:17:32 +0000 (14:17 +0200)]
Always assign svalue when checking and reporting negative values

GCC12 warns:

In file included from /usr/include/error.h:59,
                 from dwz.c:23:
In function ‘error’,
    inlined from ‘checksum_die’ at dwz.c:3364:7:
/usr/include/bits/error.h:42:5: warning: ‘svalue’ may be used
   uninitialized [-Wmaybe-uninitialized]
   42 |  __error_alias (__status, __errnum, __format, __va_arg_pack ());
      |  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dwz.c: In function ‘checksum_die’:
dwz.c:3354:25: note: ‘svalue’ was declared here
 3354 |                 int64_t svalue = read_sleb128 (ptr);
      |                         ^~~~~~

It is correct. We jump to the common error reporting label negative
where we expect svalue to be set so we can print it in the error
message. But it isn't in all places. Fix this by explicitly assigning
svalue first in all places we goto negative on failure.

* dwz.c (checksum_die): Always assign svalue when
checking and reporting on unexpected negative values.

2 years agotestsuite: remove leading spaces
Martin Liska [Fri, 1 Jul 2022 07:53:04 +0000 (09:53 +0200)]
testsuite: remove leading spaces

2 years agotestsuite: verify directly merged DW_AT_declarations
Martin Liska [Thu, 30 Jun 2022 14:21:58 +0000 (16:21 +0200)]
testsuite: verify directly merged DW_AT_declarations

Do not rely on number of DW_AT_declaration and check symbols
instead.

2 years agoRemove double semicolon
Mark Wielaard [Thu, 30 Jun 2022 15:59:03 +0000 (17:59 +0200)]
Remove double semicolon

* dwz.c (read_debug_line): Remove double ;;

2 years agoPrint abbrev or DIE offset for Unknown DWARF error message.
Mark Wielaard [Sun, 21 Feb 2021 15:55:17 +0000 (16:55 +0100)]
Print abbrev or DIE offset for Unknown DWARF error message.

* dwz.c (read_abbrev): Add .debug_abbrev offset to error message.
(read_exprloc): Print DIE offset that referenced the unknown
operand in error message.
(read_expr_low_mem_phase1): Likewise.
(read_debug_info): Add die_offset to error messages for unknown
forms, attributes extending beyond end of CU or unknown block
form attributes.

https://sourceware.org/bugzilla/show_bug.cgi?id=27363

2 years agoWorkaround binutils readelf following and printing alt file.
Mark Wielaard [Thu, 30 Jun 2022 12:03:31 +0000 (14:03 +0200)]
Workaround binutils readelf following and printing alt file.

Even with -wN readelf 2.38-15.fc37 follows and prints the
contents of the alt file. Workaround that by removing the
alt file in tests when we are done with it. This should be
fine even when binutils readelf gets fixed to not do that
with -wN (but maybe this is by design?) This fixes the
testsuite on rawhide.

* testsuite/dwz.tests/cycle.sh: Remove 3 (alt) file
when done testing.
* testsuite/dwz.tests/odr-struct-multifile.sh:
Likewise.

2 years agoMark and init shstrtab[_len] and const in optimize_multifile
Mark Wielaard [Thu, 30 Jun 2022 11:28:26 +0000 (13:28 +0200)]
Mark and init shstrtab[_len] and const in optimize_multifile

Old gcc (4.8.5) warn that shstrtab and shstrtab_len can be clobbered
by the longjump. Work around that by marking shstrtab_gnu and
shstrtab_dwarf5 as static and shstrtab and shstrtab_len as const.
Init shstrtab and shstrtab_len at declaration.

* dwz.c (optimize_multifile): Make shstrtab_[gnu|dwarf5],
shstrtab[_len] static. shstrtab[_len] init and make const.

2 years agoFix handling readelf following links by default
Lv Ying via Dwz [Wed, 12 Jan 2022 21:29:44 +0000 (05:29 +0800)]
Fix handling readelf following links by default

The two testcases still failed when using newer readelf
(binutils commit c46b706620e):
testsuite/dwz.tests/odr-struct-multifile.sh
testsuite/dwz.tests/cycle.sh

fix the new -Wn readelf flag test

Signed-off-by: Lv Ying <lvying6@huawei.com>
3 years agoIntroduce struct pipe
Tom de Vries [Tue, 13 Apr 2021 12:29:38 +0000 (14:29 +0200)]
Introduce struct pipe

Introduce struct pipe that names the read and write fd of a pipe.

2021-04-13  Tom de Vries  <tdevries@suse.de>

* dwz.c (struct pipe): New type.
(pipes): Change variable type to struct type *.
(get_token, pass_token, dwz_files_1): Update.

3 years agoAdd -p native and -e native
Tom de Vries [Mon, 12 Apr 2021 19:50:23 +0000 (21:50 +0200)]
Add -p native and -e native

Add option parameter native to options -p and -e.

We determine native as the result of readelf output on an object generated
by using CC without CFLAGS, such that if we build dwz with -m32 on
x86_64 like so:
...
$ make CFLAGS="-m32 -O2 -g" LDFLAGS=-m32
...
and we have:
...
$ file ./dwz
dwz: ELF 32-bit LSB executable, Intel 80386 <SNIP>
...
we still have:
...
$ ./dwz -?
  ...
  -p, --multifile-pointer-size <SIZE|auto|native>
                              Set pointer size of multifile, in number of bytes.
                              Native pointer size is 8.
                              Default value: auto.
...

2021-04-12  Tom de Vries  <tdevries@suse.de>

* Makefile (args.o): Add dependency on native.o.
(CFLAGS_FOR_SOURCE, NATIVE_ENDIAN, NATIVE_ENDIAN_LITTLE)
(NATIVE_ENDIAN_BIG, NATIVE_ENDIAN_VAL): New var.
(%.o: %.c): Add pattern rule.
(clean): Update.
(native.o): Add pattern rule.
* util.h (XSTR, STR): New macro.
* args.c (NATIVE_ENDIAN): New macro.
(dwz_multi_file_options_help, usage): Mention -p native and -e native.
(parse_args): Handle -p native and -e native.
* dwz.1 (-p, -e): Mention native.
* native.c: New file.

3 years agoFactor out pool.{c,h}
Tom de Vries [Mon, 12 Apr 2021 08:10:13 +0000 (10:10 +0200)]
Factor out pool.{c,h}

Factor out pool function into files pool.c and pool.h.

2021-04-12  Tom de Vries  <tdevries@suse.de>

* Makefile (OBJECTS): Add pool.o.
* dwz.c (dwz_oom): Remove static.
(cleanup): Update call to pool_destroy.
(read_multifile): Call finalize_pool.
(dwz_files_1): Call pool_destroy.
(pool_alloc_1, pool_destroy): Move ...
* pool.c: ... here.  New file.
(pool_destroy): Add pool parameter.
* dwz.c (pool_alloc): Move ...
* pool.h: ... here.  New file.

3 years agoAdd util.h
Tom de Vries [Fri, 9 Apr 2021 15:06:24 +0000 (17:06 +0200)]
Add util.h

Factor out utility macros into new file util.h.

2021-04-09  Tom de Vries  <tdevries@suse.de>

* args.c (IMPLIES): Remove.
* dwz.c (pool_alloc): Use ALIGNOF_STRUCT.
(USE_GNUC, likely, unlikely, FORCE_INLINE, UNUSED, USED, IMPLIES):
(MAX, MIN, ALIGN_STRUCT): Move ...
* util.h: ... here.  New file. Add ALIGNOF_STRUCT.

3 years agoEliminate sed usage in building dwz-for-test
Tom de Vries [Fri, 9 Apr 2021 15:06:24 +0000 (17:06 +0200)]
Eliminate sed usage in building dwz-for-test

We started out building dwz-for-test using -U__GNUC__.  That resulted
in problems with system headers on fedora, so instead a solution using
sed was implemented.  This works well and ensures that all __GNUC__ uses
are addressed, but it makes refactoring more complicated.

Instead, use the slightly more error-prone but less cumbersome method
of replacing uses of __GNUC__ with uses of a new variable USE_GNUC,
and define USE_GNUC=0 for dwz-for-test.

2021-04-09  Tom de Vries  <tdevries@suse.de>

* Makefile: Compile dwz-for-test using -DUSE_GNUC=0.
* dwz.c (USE_GNUC): Weakly define if __GNUC__ is defined, and
use instead of __GNUC__.

3 years agoFactor out common flags between dwz and dwz-for-test
Tom de Vries [Fri, 9 Apr 2021 15:06:24 +0000 (17:06 +0200)]
Factor out common flags between dwz and dwz-for-test

Add new CFLAGS_* and LIBS variables to factor out commonality between
dwz and dwz-for-test compilations.

2021-04-09  Tom de Vries  <tdevries@suse.de>

* Makefile (CFLAGS_VERSION, CFLAGS_COPYRIGHT, CFLAGS_COMMON, LIBS):
New variables.
(CFLAGS, dwz, dwz-for-test): Use new vars.

3 years agoEnsure help message lines end with dot
Tom de Vries [Fri, 9 Apr 2021 12:00:16 +0000 (14:00 +0200)]
Ensure help message lines end with dot

I noticed a missing dot in the help message, after "parallel":
...
./dwz -?
  ...
  -j, --jobs <n>              Process <n> files in parallel
                              Default value: number of processors / 2.
...

Add an assert that catches this, and add the missing dot.

2021-04-09  Tom de Vries  <tdevries@suse.de>

* args.c (IMPLIES): New macro, copied from dwz.c.
(dwz_multi_file_options_help): Add missing dot.
(print_options_help): Assert that help messages end with dot.

3 years ago[testsuite] Fix handling of missing section in smaller-than.sh
Tom de Vries [Wed, 7 Apr 2021 04:16:01 +0000 (06:16 +0200)]
[testsuite] Fix handling of missing section in smaller-than.sh

On openSUSE Tumbleweed I run into:
...
Running testsuite/dwz.tests/dwz-tests.exp ...
testsuite/scripts/smaller-than.sh: line 18: 16#: \
  invalid integer constant (error token is "16#")
 ...
FAIL: testsuite/dwz.tests/dwz.sh
...

The relevant line in smaller-than.sh is:
...
     s=$(printf "%d" $((16#$s)))
...

This seems to be due bash (version 5.1.4), which gives:
...
$ echo $((16#))
bash: 16#: invalid integer constant (error token is "16#")
...
while bash on Leap 15.2 (version 4.4.23) gives:
...
$ echo $((16#))
0
...

Fix this by explicitly handling s == "" in proc section_size.

2021-04-07  Tom de Vries  <tdevries@suse.de>

PR dwz/27694
* testsuite/scripts/smaller-than.sh (section_size): Handle s == "".

3 years agoEnable parallel multifile with -e -p
Tom de Vries [Wed, 31 Mar 2021 07:09:58 +0000 (09:09 +0200)]
Enable parallel multifile with -e -p

Currently, parallel dwz is disabled when multifile is used:
...
$ dwz -m 5 3 1 2 4 -j 4
...

Enable this when the multifile parameter characteristics are specified using
-p and -e:
...
$ dwz -m 5 3 1 2 4 -j 4 -p 8 -e l
...
This works around the child processes having to communicate back to the parent
the found pointer size and endiannes, and doing the -j auto and -e auto
consistency checking.

The problem of the different child processes writing to the same temporary
multifile is solved by writing in file order to the temporary multifile.

In principle, the problem could be solved by writing into per-file temporary
multifiles and concatenating them afterwards.  However, the temporary
multifile contains DW_FORM_ref_addr references, and after concatenation
those references in the temporary multifile require relocation (i.e., add the
offset of the start of the file contribution).  This requires a lot of
changes in various parts of the code, so for now we choose instead this
cleaner solution.

The enforcing of writing in file order is done by passing a token to each
child process using pipes.

Experiment:
...
$ for j in 1 2; do \
    cp debug/cc1 1; cp 1 2; cp 2 3; cp 3 4; \
    echo "j: $j"; \
    ../measure/time.sh ./dwz -lnone -m 5 1 2 3 4 -j $j -p 8 -e l; \
  done
j: 1
maxmem: 1297260
real: 48.35
user: 46.93
system: 1.37
j: 2
maxmem: 1296584
real: 31.85
user: 50.46
system: 1.64
...

2021-03-30  Tom de Vries  <tdevries@suse.de>

PR dwz/25951
* dwz.c (write_multifile_1): Factor out of ...
(write_multifile): ... here.  Call get_token.
(get_token, pass_token): New function.
(wait_children_exit): Call pass_token.
(dwz_files_1): Allow parallel multifile with -j -e.  Call pass_token.

3 years agoUse vars to name parallel parts in dwz_files_1
Tom de Vries [Tue, 30 Mar 2021 07:42:44 +0000 (09:42 +0200)]
Use vars to name parallel parts in dwz_files_1

Use variables initial_parallel_p and finalize_multifile_parallel_p to name
parallel parts in dwz_files_1.

2021-03-29  Tom de Vries  <tdevries@suse.de>

* dwz.c (dwz_files_1): Add variables initial_parallel_p and
finalize_multifile_parallel_p.

3 years agoApply multifile_force_{ptr_size,endian} ASAP
Tom de Vries [Mon, 29 Mar 2021 08:14:05 +0000 (10:14 +0200)]
Apply multifile_force_{ptr_size,endian} ASAP

Rather than waiting for multi_ptr_size/multi_endian to be set in
write_multifile, apply multifile_force_{ptr_size,endian} ASAP, in
dwz_files_1.  This is a preparation for running write_multifile
in parallel.

2021-03-29  Tom de Vries  <tdevries@suse.de>

* dwz.c (dwz_files_1): Apply multifile_force_ptr_size and
multifile_force_endian.

3 years agoHandle skip_multifile in encode/decode_child_exit_status
Tom de Vries [Mon, 29 Mar 2021 07:45:44 +0000 (09:45 +0200)]
Handle skip_multifile in encode/decode_child_exit_status

Handle skip_multifile in encode_child_exit_status and
decode_child_exit_status.  This is a preparation for running write_multifile
in parallel.

2021-03-29  Tom de Vries  <tdevries@suse.de>

* dwz.c (encode_child_exit_status, decode_child_exit_status): Handle
skip_multifile.

3 years agoAdd ret to struct file_result
Tom de Vries [Mon, 29 Mar 2021 06:24:33 +0000 (08:24 +0200)]
Add ret to struct file_result

Further simplify the serial/parallel code in dwz_files_1 by factoring out the
return status handling.  Add a ret field to struct file_result to store the
per-file return status.

2021-03-29  Tom de Vries  <tdevries@suse.de>

* dwz.c (struct file_result): Add ret field.
(wait_child_exit): Return void.  Set ret.
(wait_children_exit): Return void.  Update call to wait_child_exit.
(dwz_files_1): Move return status handling out of serial/parallel code.

3 years agoFix incorrect res arg for wait_child_exit
Tom de Vries [Mon, 29 Mar 2021 06:24:33 +0000 (08:24 +0200)]
Fix incorrect res arg for wait_child_exit

In dwz_files_1 we have:
...
         file = files[i];
         struct file_result *res = &resa[i];

         if (nr_forks == max_forks)
           {
             int thisret = wait_child_exit (-1, pids, i, res);
...

The -1 pid argument to wait_child_exit means that any child status will be
returned, while the res argument passes the result array element for
the file we want to start processing, which is incorrect.

Fix this by passing the result array instead, and letting wait_child_exit
figure out which element to use.

2021-03-29  Tom de Vries  <tdevries@suse.de>

* dwz.c (wait_child_exit): Find appropriate element in result array.
(dwz_files_1): Use resa when using pid -1.

3 years agoCalculate workset before serial/parallel code in dwz_files_1
Tom de Vries [Sat, 27 Mar 2021 19:13:35 +0000 (20:13 +0100)]
Calculate workset before serial/parallel code in dwz_files_1

The function dwz_files_1 has code that can execute either serially or in
parallel.  Evidently, there's code duplication between the serial and
parallel code, which creates the burden of keeping this in sync.  The
burden can be kept minimal by keeping the duplicate code minimal.

Part of the duplicate code is the selection which files to handle.

Move this selection out of the serial/parallel code, and use it to compute
an array workset, which is then used in both the serial and parallel code.

2021-03-27  Tom de Vries  <tdevries@suse.de>

* dwz.c (dwz_files_1): Calculate workset before serial/parallel code.

3 years agoMinimize struct file_result
Tom de Vries [Sat, 27 Mar 2021 19:13:35 +0000 (20:13 +0100)]
Minimize struct file_result

Struct file_result contains fields dev, ino and nlink, which are only used
during hard link detection.

Move these from struct file_result to a new struct hl_stat.

2021-03-27  Tom de Vries  <tdevries@suse.de>

* dwz.c (struct file_result): Move fields dev, ino and nlink ...
(struct hl_stat): ... here.  New struct.
(detect_hardlinks): Use struct hl_stat.

3 years agoDo finalize-multifile in parallel
Tom de Vries [Sat, 27 Mar 2021 12:53:58 +0000 (13:53 +0100)]
Do finalize-multifile in parallel

Run the finalize-multifile phase in parallel.

Using an experiment, we can see the effect:
...
$ for j in $(seq 1 2); do \
    rm -f 1 2 3; \
    cp debug/cc1 1; cp 1 2; \
    echo "j: $j"; \
    ../measure/time.sh ./dwz -lnone -m 3 1 2 -j$j; \
  done
j: 1
maxmem: 1295068
real: 26.38
user: 25.38
system: 0.77
j: 2
maxmem: 1297724
real: 23.55
user: 25.81
system: 0.88
...

2021-03-27  Tom de Vries  <tdevries@suse.de>

* dwz.c (dwz_files_1): Run finalize-multifile phase in parallel, if
max_forks > 0.

3 years agoUse goto in dwz_files_1
Tom de Vries [Sat, 27 Mar 2021 12:53:58 +0000 (13:53 +0100)]
Use goto in dwz_files_1

Use goto in dwz_files_1 to remove indentation, replacing:
...
  if (...)
    ret = 1;
  else
    {
      /* Lots of code.  */
    }
  /* Cleanup.  */
...
with:
...
  if (...)
    {
      ret = 1;
      goto cleanup;
    }

  /* Lots of code.  */

cleanup:
  /* Cleanup.  */
...

2021-03-27  Tom de Vries  <tdevries@suse.de>

* dwz.c (dwz_files_1): Reduce indentation.

3 years agoFactor out wait_children_exit
Tom de Vries [Sat, 27 Mar 2021 12:53:58 +0000 (13:53 +0100)]
Factor out wait_children_exit

Factor new function wait_children_exit out of dwz_files_1.

2021-03-27  Tom de Vries  <tdevries@suse.de>

* dwz.c (wait_children_exit): New function, factored out of ...
(dwz_files_1): ... here.

3 years agoInitialize pids in dwz_files_1
Tom de Vries [Sat, 27 Mar 2021 12:53:58 +0000 (13:53 +0100)]
Initialize pids in dwz_files_1

The loop dealing with waiting on the remaining children contains:
...
         if (res->res == -2)
           /* Skip hard links.  */
           continue;
...

The reason we need this is because the pids array isn't initialized in this
case, so the following code:
...
          if (pids[i] == 0)
            continue;
...
would otherwise read an uninitialized variable.

Fix this by:
- initializing the pids array, and
- removing the res->res == -2 code.

2021-03-27  Tom de Vries  <tdevries@suse.de>

* dwz.c (dwz_files_1): Initialize pids.  Simplify loop waiting on
remaining children.

3 years agoFactor out wait_child_exit
Tom de Vries [Sat, 27 Mar 2021 12:53:58 +0000 (13:53 +0100)]
Factor out wait_child_exit

Factor out new function wait_child_exit out of dwz_files_1.

2021-03-27  Tom de Vries  <tdevries@suse.de>

* dwz.c (wait_child_exit): New function, factored out of ...
(dwz_files_1): ... here.

3 years agoAdd low_mem_p to struct file_result
Tom de Vries [Fri, 26 Mar 2021 15:56:31 +0000 (16:56 +0100)]
Add low_mem_p to struct file_result

Keep track of whether files were run in low-mem mode, by adding a new field
low_mem_p to struct file_result.

2021-03-26  Tom de Vries  <tdevries@suse.de>

* dwz.c (struct file_result): Add low_mem_p.
(dwz_with_low_mem): Drop low_mem_p parameter.
(init_file_result): Init low_mem_p.
(dwz_one_file): Update call to dwz_with_low_mem.
(encode_child_exit_status, decode_child_exit_status):
Drop low_mem_p parameter.
(dwz_files_1): Update call to dwz_with_low_mem.

3 years agoRun two-files-low-mem-die-limit-0.sh with -j1
Tom de Vries [Fri, 26 Mar 2021 13:28:19 +0000 (14:28 +0100)]
Run two-files-low-mem-die-limit-0.sh with -j1

On the buildbot we have for dwz-debian-arm64:
...
child process exited abnormally
FAIL: build/testsuite/dwz.tests/two-files-low-mem-die-limit-0.sh
...

AFAIU, the problem is that the test-case is grepping like this:
...
egrep -q "Compressing (1|2)$" dwz.err
...
expecting the grep to fail on these messages:
...
Compressing 1 in low-mem mode
Compressing 2 in low-mem mode
...

But with -j 2 we can have the following interleaving of the messages:
...
Compressing 1 in low-mem modeCompressing 2
 in low-mem mode
...
which makes the grep succeed.

Fix this by running the test with -j1.

2021-03-26  Tom de Vries  <tdevries@suse.de>

* testsuite/dwz.tests/two-files-low-mem-die-limit-0.sh: Run dwz
with -j1.

3 years agoFactor out {encode,decode}_child_exit_status
Tom de Vries [Fri, 26 Mar 2021 13:01:03 +0000 (14:01 +0100)]
Factor out {encode,decode}_child_exit_status

Factor out new function encode_child_exit_status and encode_child_exit_status
out of dwz_files_1.

2021-03-26  Tom de Vries  <tdevries@suse.de>

* dwz.c (encode_child_exit_status, decode_child_exit_status): New
function, factored out of ...
(dwz_files_1): ... here.

3 years agoAdd -p auto and -e auto
Tom de Vries [Fri, 26 Mar 2021 11:04:47 +0000 (12:04 +0100)]
Add -p auto and -e auto

Add new option argument auto for both -p and -e, to describe
the current behaviour more explicitly.

2021-03-26  Tom de Vries  <tdevries@suse.de>

* args.c (usage, parse_args): Add auto option argument to -p and -e.
* dwz.1 (-p, -e): Add auto option argument.

3 years agoProcess files in parallel
Tom de Vries [Fri, 26 Mar 2021 10:45:17 +0000 (11:45 +0100)]
Process files in parallel

Add an option -j <n> / --jobs <n> that allows multiple files to be processed
in parallel.  Note that this does not yet parallelize when multifile is used.

Consider the experiment do.sh:
...
ns=$(seq 1 10)

for n in $ns; do
    cp debug/cc1 $n
done

time.sh ./dwz $@ -lnone $ns
...

On a 4 smt-thread, dual core system we get:
...
$ for n in $(seq 1 4); do echo "N: $n"; ./do.sh -j $n; done
N: 1
maxmem: 1261744
real: 56.53
user: 53.24
system: 3.17
N: 2
maxmem: 1260216
real: 31.74
user: 58.84
system: 4.39
N: 3
maxmem: 1261868
real: 28.26
user: 75.65
system: 5.00
N: 4
maxmem: 1262036
real: 26.80
user: 87.31
system: 5.69
...

The sweet spot of real time reduction vs. extra user/system time seems to be
around 2, so we set the default -j to processors / 2.

2021-03-23  Tom de Vries  <tdevries@suse.de>

PR dwz/25951
* args.c (max_forks): New var.
(dwz_options, dwz_multi_file_options_help, usage): Add entries for
-j <n>.
(parse_args): Handle -j <n>.  Assign default value for max_forks.
* args.h (max_forks): Declare.
* dwz.1: Add entries for -j <n> / --jobs <n> entry.
* dwz.c (dwz_files_1): Handle max_forks.

3 years agoAdd --multifile-pointer-size <n> and --multifile-endian <l|L|b|B>
Tom de Vries [Fri, 26 Mar 2021 09:11:54 +0000 (10:11 +0100)]
Add --multifile-pointer-size <n> and --multifile-endian <l|L|b|B>

Consider binaries:
- hello.64 generated using -m64, with pointer size 8,
- hello.32 generated using -m32, with pointer size 4.

When trying to generate a multifile using files with different
pointer sizes, we get:
...
$ cp ../hello.64 1; cp 1 2; \
    cp ../hello.32 3; cp 3 4; \
    dwz -m 5 1 2 3 4; echo $?
dwz: Multi-file optimization not allowed for different pointer sizes \
  or endianity
0
...
and the multi-file optimization has not been applied for any file:
...
$ for f in 1 2 3 4; do \
    echo -n "$f: "; \
    readelf -S -W $f \
        | grep -c gnu_debugaltlink; \
    done
1: 0
2: 0
3: 0
4: 0
...

Add an option --multifile-pointer-size <n> / -p <n> that sets the pointer size
of the multifile, such that we have instead with say -p 8:
...
$ cp ../hello.64 1; cp 1 2; \
    cp ../hello.32 3; cp 3 4; \
    ./dwz -m 5 -p 8 1 2 3 4; echo $?
./dwz: File 3 skipped for multi-file optimization, different pointer size
./dwz: File 4 skipped for multi-file optimization, different pointer size
0
...
and:
...
$ for f in 1 2 3 4; do \
    echo -n "$f: "; \
    readelf -S -W $f \
        | grep -c gnu_debugaltlink; \
    done
1: 1
2: 1
3: 0
4: 0
...

Likewise, add --multifile-endian <l|L|b|B> / -e <l|L|b|B>.

2021-03-25  Tom de Vries  <tdevries@suse.de>

* args.c (multifile_force_ptr_size, multifile_force_endian): New
variable.
(dwz_options, dwz_multi_file_options_help): Add
--multifile-pointer-size and --multifile-endian entries.
(parse_args): Handle 'p' and 'e' options.
* args.h (multifile_force_ptr_size, multifile_force_endian): Declare.
* dwz.c (struct file_result): Move up.  Add skip_multifile field.
(write_multifile): Add res parameter.  Handle multifile_force_ptr_size
and multifile_force_endian.
(dwz): Update call to write_multifile.
(init_file_result): Init skip_multifile field.
(dwz_files_1): Handle res->skip_multifile.
* dwz.1: Add --multifile-pointer-size and --multifile-endian entries.

3 years agoAdd -5 to usage header
Tom de Vries [Fri, 26 Mar 2021 09:11:54 +0000 (10:11 +0100)]
Add -5 to usage header

3 years agoDon't use argv[0] in usage
Tom de Vries [Fri, 26 Mar 2021 09:11:54 +0000 (10:11 +0100)]
Don't use argv[0] in usage

Using argv[0] in the usage string makes it harder to layout the usage message:
...
$ ./build/dwz -?
Usage:
  ./build/dwz [common options] [-h] [-m COMMONFILE] [-M NAME | -r] [FILES]
  ./build/dwz [common options] -o OUTFILE FILE
  ./build/dwz [ -v | -? ]
...

Instead, just use "dwz".

2021-03-26  Tom de Vries  <tdevries@suse.de>

* args.c (usage): Drop progname argument.
(parse_args): Update call to usage.

3 years agoAdd check-valgrind
Tom de Vries [Fri, 26 Mar 2021 07:02:40 +0000 (08:02 +0100)]
Add check-valgrind

Add a make target check-valgrind, that applies valgrind to dwz when used in
the testsuite.

2021-03-25  Tom de Vries  <tdevries@suse.de>

* Makefile (check-valgrind): New target.

3 years agoFix uninitialized var in dwz_one_file
Tom de Vries [Thu, 25 Mar 2021 13:52:04 +0000 (14:52 +0100)]
Fix uninitialized var in dwz_one_file

The commit dbfecee "Move hardlink handling out of dwz function" added
initialization of res->res in dwz_files_1, but failed to do the same
in dwz_one_file.

Add the missing initialization by factoring out the initialization code from
dwz_files_1, and using it in dwz_one_file.

2021-03-25  Tom de Vries  <tdevries@suse.de>

* dwz.c (init_file_result): Factor out of ...
(dwz_files_1): ... here.
(dwz_one_file): Use init_file_result.

3 years agoMove hardlink handling out of dwz function
Tom de Vries [Thu, 25 Mar 2021 08:38:27 +0000 (09:38 +0100)]
Move hardlink handling out of dwz function

Currently hardlink handling is done in the dwz function, on per-file basis,
with the analysis having a scope of previously processed files.

Move hardlink handling out of dwz into dedicated functions detect_hardlinks
and update_hardlinks, both called from dwz_files_1.

The detect_hardlinks is called before any file is processed, the
update_hardlinks is called after all files are processed.

This allows parallelization of the processing of the files.

2021-03-23  Tom de Vries  <tdevries@suse.de>

* dwz.c (struct file_result): Add comment about res == -3 as
uninitialized.  Add hardlink_to field.
(detect_hardlinks, update_hardlinks): New function, factored out of ...
(dwz): ... here.  Drop resa and files parameters.
(dwz_with_low_mem): Drop resa and files parameters.
(dwz_one_file): Update call to dwz_with_low_mem.
(dwz_files_1): Update call to dwz_with_low_mem.  Add calls to
detect_hardlinks and update_hardlinks.

3 years agoFix memory leak in build_abbrevs
Tom de Vries [Wed, 24 Mar 2021 17:05:20 +0000 (18:05 +0100)]
Fix memory leak in build_abbrevs

I noticed that build_abbrevs leaks h in case the "return 1" path is taken:
...
  htab_t h = htab_try_create (50, abbrev_hash, abbrev_eq2, NULL);

  if (h == NULL)
    dwz_oom ();

  if (build_abbrevs_for_die (h, cu, cu->cu_die, NULL, NULL, t, ndies, vec,
     false))
    return 1;
...

Fix this by calling htab_delete before returning 1.

2021-03-24  Tom de Vries  <tdevries@suse.de>

* dwz.c (build_abbrevs): Clean up in case of return 1.

3 years agoFix memory leak in write_multifile
Tom de Vries [Wed, 24 Mar 2021 17:05:20 +0000 (18:05 +0100)]
Fix memory leak in write_multifile

When building dwz with -fsanitize=address, we run into some memory leaks:
...
$ cp hello 1; ./dwz 1; cp 1 2; ./dwz -m 3 1 2
./dwz: 1: DWARF compression not beneficial - old size 3372 new size 3372
./dwz: 2: DWARF compression not beneficial - old size 3372 new size 3372

=================================================================
==8024==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 432 byte(s) in 6 object(s) allocated from:
    #0 0x7f7ab92cc6d8 in __interceptor_calloc \
         (/usr/lib64/libasan.so.4+0xdc6d8)
    #1 0x475dc1 in htab_try_create hashtab.c:164
    #2 0x44c610 in build_abbrevs dwz.c:11230
    #3 0x44ee00 in compute_abbrevs dwz.c:11510
    #4 0x46f07c in dwz dwz.c:15396
    #5 0x474e0d in dwz_files_1 dwz.c:16327
    #6 0x475699 in dwz_files dwz.c:16417
    #7 0x4759fc in main dwz.c:16458
    #8 0x7f7ab8c41349 in __libc_start_main (/lib64/libc.so.6+0x24349)

Indirect leak of 2928 byte(s) in 6 object(s) allocated from:
    #0 0x7f7ab92cc6d8 in __interceptor_calloc \
         (/usr/lib64/libasan.so.4+0xdc6d8)
    #1 0x475de7 in htab_try_create hashtab.c:168
    #2 0x44c610 in build_abbrevs dwz.c:11230
    #3 0x44ee00 in compute_abbrevs dwz.c:11510
    #4 0x46f07c in dwz dwz.c:15396
    #5 0x474e0d in dwz_files_1 dwz.c:16327
    #6 0x475699 in dwz_files dwz.c:16417
    #7 0x4759fc in main dwz.c:16458
    #8 0x7f7ab8c41349 in __libc_start_main (/lib64/libc.so.6+0x24349)

SUMMARY: AddressSanitizer: 3360 byte(s) leaked in 12 allocation(s).
...

A more concrete way to show some of the leaks is by using this patch on
build_abbrevs:
...
+  assert (cu->cu_new_abbrev == NULL);
   cu->cu_new_abbrev = h;
   return 0;
 }
...
which triggers here:
...
 #4  0x00000000004211b1 in build_abbrevs (cu=0x7ffff65f0e38, t=0x64e640,
     ndies=0x7fffffffd81c, vec=0x649280 <ob2>) at dwz.c:11239
 #5  0x0000000000421db2 in compute_abbrevs (dso=0x0) at dwz.c:11511
 #6  0x000000000042fa2c in write_multifile (dso=0x64c210)
     at dwz.c:15104
...

We could just do a htab_delete in build_abbrevs, which takes care of all the
leaks detected by the assert.

But write_multifile drops CUs from the cu list if
cu->cu_die->die_no_multifile == 1, and if a dropped CU has cu->cu_new_abbrev
!= NULL then cu_new_abbrev is still leaked.

Fix this by calling htab_delete in the loop that drops the CUs.

2021-03-24  Tom de Vries  <tdevries@suse.de>

PR dwz/27643
* dwz.c (write_multifile): Clean up cu->cu_new_abbrev to fix memory
leak.

3 years agoFix low-mem memory leak
Tom de Vries [Wed, 24 Mar 2021 17:05:20 +0000 (18:05 +0100)]
Fix low-mem memory leak

When building dwz with -fsanitize=address, and running dwz in low-mem mode, we
run into a number of memory leaks:
...
$ dwz hello -o hello.z -l0

=================================================================
==22607==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 432 byte(s) in 6 object(s) allocated from:
    #0 0x7f560af846d8 in __interceptor_calloc (/usr/lib64/libasan.so.4+0xdc6d8)
    #1 0x475db1 in htab_try_create hashtab.c:164
    #2 0x406ed6 in read_abbrev dwz.c:1296
    #3 0x42bca9 in read_debug_info dwz.c:6818
    #4 0x4608cb in read_dwarf dwz.c:13706
    #5 0x46ef9a in dwz dwz.c:15383
    #6 0x474a27 in dwz_one_file dwz.c:16279
    #7 0x475951 in main dwz.c:16450
    #8 0x7f560a8f9349 in __libc_start_main (/lib64/libc.so.6+0x24349)

Direct leak of 72 byte(s) in 1 object(s) allocated from:
    #0 0x7f560af846d8 in __interceptor_calloc (/usr/lib64/libasan.so.4+0xdc6d8)
    #1 0x475db1 in htab_try_create hashtab.c:164
    #2 0x42a8fd in read_debug_info dwz.c:6634
    #3 0x4608cb in read_dwarf dwz.c:13706
    #4 0x46ef9a in dwz dwz.c:15383
    #5 0x474a27 in dwz_one_file dwz.c:16279
    #6 0x475951 in main dwz.c:16450
    #7 0x7f560a8f9349 in __libc_start_main (/lib64/libc.so.6+0x24349)

Indirect leak of 4072 byte(s) in 1 object(s) allocated from:
    #0 0x7f560af846d8 in __interceptor_calloc (/usr/lib64/libasan.so.4+0xdc6d8)
    #1 0x475dd7 in htab_try_create hashtab.c:168
    #2 0x42a8fd in read_debug_info dwz.c:6634
    #3 0x4608cb in read_dwarf dwz.c:13706
    #4 0x46ef9a in dwz dwz.c:15383
    #5 0x474a27 in dwz_one_file dwz.c:16279
    #6 0x475951 in main dwz.c:16450
    #7 0x7f560a8f9349 in __libc_start_main (/lib64/libc.so.6+0x24349)

Indirect leak of 2928 byte(s) in 6 object(s) allocated from:
    #0 0x7f560af846d8 in __interceptor_calloc (/usr/lib64/libasan.so.4+0xdc6d8)
    #1 0x475dd7 in htab_try_create hashtab.c:168
    #2 0x406ed6 in read_abbrev dwz.c:1296
    #3 0x42bca9 in read_debug_info dwz.c:6818
    #4 0x4608cb in read_dwarf dwz.c:13706
    #5 0x46ef9a in dwz dwz.c:15383
    #6 0x474a27 in dwz_one_file dwz.c:16279
    #7 0x475951 in main dwz.c:16450
    #8 0x7f560a8f9349 in __libc_start_main (/lib64/libc.so.6+0x24349)

SUMMARY: AddressSanitizer: 7504 byte(s) leaked in 14 allocation(s).
...

The leaks are related to the meta_abbrev_htab, which is allocated in
the initial read_debug_info call for .debug_info, and then allocated once more
in a second call to read_debug_info for .debug_types.

The second allocation overwrites the first one, and consequently the first one
is leaked.

Fix this by only allocating meta_abbrev_htab if not already allocated.

2021-03-23  Tom de Vries  <tdevries@suse.de>

PR dwz/27633
* dwz.c (read_debug_info): Don't allocate meta_abbrev_htab if already
allocated.

3 years ago[testsuite] Show error output in twice-multifile.sh
Tom de Vries [Wed, 24 Mar 2021 09:10:07 +0000 (10:10 +0100)]
[testsuite] Show error output in twice-multifile.sh

When building dwz with -fsanitize=address, we get:
...
$ make check RUNTESTFLAGS=dwz-tests.exp=twice-multifile.sh
Running src/testsuite/dwz.tests/dwz-tests.exp ...
child process exited abnormally
FAIL: src/testsuite/dwz.tests/twice-multifile.sh
...

The test-case fails because "dwz -m 3 1 2" returns 1, but we don't see
why because the error output is redirected to dwz.err.

Fix this by dumping dwz.err if "dwz -m 3 1 2" status is not zero.

2021-03-24  Tom de Vries  <tdevries@suse.de>

* testsuite/dwz.tests/twice-multifile.sh: Dump dwz.err if dwz status
        is not 0.

3 years agoFactor out dwz_with_low_mem
Tom de Vries [Tue, 23 Mar 2021 13:40:36 +0000 (14:40 +0100)]
Factor out dwz_with_low_mem

Factor out new function dwz_with_low_mem out of dwz_one_file/dwz_files_1.

2021-03-23  Tom de Vries  <tdevries@suse.de>

* dwz.c (dwz_with_low_mem): New function, factored out of ...
(dwz_one_file): ... here, and ...
(dwz_files_1): here.

3 years agoFactor out dwz_files_1
Tom de Vries [Tue, 23 Mar 2021 10:25:01 +0000 (11:25 +0100)]
Factor out dwz_files_1

In dwz_files, a variable resa is malloced at the start, and freed at the end.
This prevents (early) returns, which makes the code more complicated than
necessary.  Also, the function already contains an early return, which means
it leaks resa.

Fix this by factoring out dwz_files_1 out of dwz_files, where dwz_files is a
wrapper tasked with alloc/free of variable resa.

2021-03-23  Tom de Vries  <tdevries@suse.de>

* dwz.c (dwz_files_1): New function, factored out of ...
(dwz_files): ... here.

3 years ago[testsuite] Remove smaller-than.sh test in pr24747.sh
Tom de Vries [Mon, 22 Mar 2021 05:13:41 +0000 (06:13 +0100)]
[testsuite] Remove smaller-than.sh test in pr24747.sh

As reported in PR27603, when using clang-11 we run into:
...
Running testsuite/dwz.tests/dwz-tests.exp ...
+ exec=start-gold
+ cp start-gold 1
+ dwz 1
+ smaller-than.sh 1 start-gold
FAIL: testsuite/dwz.tests/pr24747.sh
...

The FAIL as such has been fixed by commit b3c99ab "Make smaller-than.sh match
dwz heuristic", but the only reason that dwz manages to optimize something is
because the dwarf producer is lazy and doesn't generate minimal encodings.

We cannot assume that the dwarf producer is lazy, so remove the
smaller-than.sh test.

2021-03-22  Tom de Vries  <tdevries@suse.de>

PR dwz/27603
* testsuite/dwz.tests/pr24747.sh: Remove smaller-than.sh test.

3 years agoMake smaller-than.sh match dwz heuristic
Tom de Vries [Mon, 22 Mar 2021 04:49:54 +0000 (05:49 +0100)]
Make smaller-than.sh match dwz heuristic

As reported in PR27603, when using clang-11 we run into:
...
Running testsuite/dwz.tests/dwz-tests.exp ...
+ exec=start-gold
+ cp start-gold 1
+ dwz 1
+ smaller-than.sh 1 start-gold
FAIL: testsuite/dwz.tests/pr24747.sh
...

The files are the same size:
...
$ ls -l start-gold tmp.pr24747.sh/1
-rwxr-xr-x 1 vries users 2024 Mar 18 11:58 start-gold
-rwxr-xr-x 1 vries users 2024 Mar 18 11:58 tmp.pr24747.sh/1
...
but not the same:
...
$ diff -q start-gold tmp.pr24747.sh/1
Files start-gold and tmp.pr24747.sh/1 differ
...

The .debug_info size is smaller, by 6 bytes:
...
 [Nr] Name         Type      Address  Off    Size   ES Flg Lk Inf Al
-[ 6] .debug_info  PROGBITS  00000000 0001cd 000040 00      0   0  1
+[ 6] .debug_info  PROGBITS  00000000 0001cd 00003a 00      0   0  1
...

The size reduction in the .debug_info section happens not to result in a
smaller file because subsequent sections .note.gnu.gold-version and .symtab
have a bigger-than-one align.

We could try to fix this by adapting the heuristic to not compress if the
eventual file size is equal.

Instead, fix this by making the smaller-than.sh test match the heuristic,
which only looks at the size of some .debug sections.

2021-03-22  Tom de Vries  <tdevries@suse.de>

* testsuite/scripts/smaller-than.sh: Calculate size as sum of
.debug sections.

3 years ago[testsuite] Handle readelf following links by default
Tom de Vries [Sat, 20 Mar 2021 08:37:31 +0000 (09:37 +0100)]
[testsuite] Handle readelf following links by default

Since binutils commit c46b706620e "Change the readelf and objdump programs so
that they will automatically follow links to separate debug info files" there
are a few FAILs in the dwz testsuite.

This is just due to changing the default behaviour for readelf.

Fix this by testing whether the new -Wn readelf flag is supported,
and if so, adding it to the readelf call.

2021-03-20  Tom de Vries  <tdevries@suse.de>

PR dwz/27592
* testsuite/dwz.tests/odr-struct-multifile.sh: Call readelf with -wN
if supported.
* testsuite/dwz.tests/cycle.sh: Same.

3 years agoChange files var in main to char **
Tom de Vries [Fri, 19 Mar 2021 16:40:17 +0000 (17:40 +0100)]
Change files var in main to char **

The cast on &argv[optind] to const char **:
...
main (int argc, char *argv[])
{
  ...
  const char **files;
  ...
  files = (const char **)&argv[optind];
...
violates the aliasing rules.

The array element argv[i] aliases with the array element files[i],
but the types of the elements (char * vs. const char *) are not compatible types.

Since we access the elements using both types (const char * in dwz_files/dwz,
char * in getopt_long), there's a violation.

Fix this by changing the type of files to char **.

2021-03-18  Tom de Vries  <tdevries@suse.de>

* dwz.c (dwz): Make files param a char **.
(dwz_files): Make files param char *[].
(main): Make files var a char **.

3 years agoFactor out args.c and args.h
Tom de Vries [Thu, 18 Mar 2021 08:48:42 +0000 (09:48 +0100)]
Factor out args.c and args.h

Reduces dwz.c from 17079 to 16450 lines, a reduction of 629 lines or ~3.7%.

Tested performance, no regression found.

2021-03-17  Tom de Vries  <tdevries@suse.de>

* Makefile (OBJECTS): Add args.o.
* dwz.c (skip_producer, add_skip_producer, do_indent, wrap)
(print_options_help, usage, version, parse_args): Move ...
* args.c: ... here.  New file.
* args.h: New file.
(parse_args, skip_producer): Declare.

3 years ago[testsuite] Fix pr27463.sh on riscv64
Tom de Vries [Wed, 17 Mar 2021 16:33:17 +0000 (17:33 +0100)]
[testsuite] Fix pr27463.sh on riscv64

On riscv64, I run into:
...
cc main.c unavailable-dwarf-piece-dw.S -o unavailable-dwarf-piece
unavailable-dwarf-piece-dw.S: Assembler messages:
unavailable-dwarf-piece-dw.S:24: Error: non-constant .uleb128 is not supported
  ...
make: *** [Makefile:100: unavailable-dwarf-piece] Error 1
...

Fix this similar to commit 53c0488 "[testsuite] Fix pr25109.sh on riscv64".

2021-03-17  Tom de Vries  <tdevries@suse.de>

* Makefile (no-multifile-prop): Allow target rule to fail.

3 years agoMake main more readable
Tom de Vries [Wed, 17 Mar 2021 13:14:00 +0000 (14:14 +0100)]
Make main more readable

Use variables nr_files and files in main instead of optind, where possible.

2021-03-17  Tom de Vries  <tdevries@suse.de>

* dwz.c (main): Use nr_files and files instead of optind.

3 years agoAdd --devel-skip-producer
Tom de Vries [Wed, 17 Mar 2021 08:38:41 +0000 (09:38 +0100)]
Add --devel-skip-producer

In PR27588 a test-case was reported where dwz did not optimize due
to illegal DWARF produced by nasm:
...
$ dwz libxul.so -o libxul.so.z
dwz: libxul.so: loclistptr attribute, yet no .debug_loc section
...

Add an option --devel-skip-producer <producer> such that we can filter out
CUs coming from a particular producer, such that we have instead:
...
$ readelf -wi libxul.so | grep DW_AT_producer \
    | sed 's/.*: //' | sort | uniq -c
    176 clang LLVM (rustc version 1.50.0)
      2 GNU AS 2.36.1
      2 GNU C11 11.0.1 20210315 (experimental) <SNIP>
     16 NASM 2.15.05
     76 yasm 1.3.0
$ dwz libxul.so -o libxul.so.z --devel-skip-producer NASM
$ readelf -wi libxul.so.z | grep DW_AT_producer \
    | sed 's/.*: //' | sort | uniq -c
    176 clang LLVM (rustc version 1.50.0)
      2 GNU AS 2.36.1
      2 GNU C11 11.0.1 20210315 (experimental) <SNIP>
     76 yasm 1.3.0
...

2021-03-16  Tom de Vries  <tdevries@suse.de>

* dwz.c (add_skip_producer, skip_producer): New function.
(read_debug_info): Skip CUs fi DW_AT_producer in skip_producers list.
(dwz_options, usage): Add --devel-skip-producer entries.
(parse_args): Handle skip_producer_parsed.

3 years agoPrint cu_offset for --devel-dump-pus
Tom de Vries [Tue, 16 Mar 2021 16:03:54 +0000 (17:03 +0100)]
Print cu_offset for --devel-dump-pus

While working on PR27578 I used --devel-dump-edges to identify a problem:
...
idx: 48
cu: 0xbc
incoming: 200
incoming: 201
incoming: 201
incoming: 203
incoming: 204
incoming: 208
...
but I had difficulty relating back the PU with idx 48 to a PU as printed by
--devel-dump-pus.

By adding the printing of the cu_offset for --devel-dump-pus, we have:
...
-Partial unit (phase two):
+Partial unit (phase two) @ 0xbc:
  611f5 O 2de8b1f3(deb4b00f2de8b1f3 Visual structure_type
...
and it's clear what PU is meant.

2021-03-16  Tom de Vries  <tdevries@suse.de>

* dwz.c (partition_dups_1): Print cu_offset for --devel-dump-pus.

3 years agoHandle reordered dup chains in create_import_tree
Tom de Vries [Tue, 16 Mar 2021 15:45:11 +0000 (16:45 +0100)]
Handle reordered dup chains in create_import_tree

With the test-case from PR27578, we run into:
...
$ dwz libvclplug_genlo.so.debug -o libvclplug_genlo.so.debug.z \
    -lnone --odr --devel-progress
create_import_tree phase 2
dwz: dwz.c:8833: remove_import_edges: Assertion `i == cucount' failed.
Aborted (core dumped)
...

Using --devel-verify-edges, we can trigger an assert earlier:
...
create_import_tree phase 1
dwz: dwz.c:8923: verify_edges_1: \
  Assertion `count == 0 || e1->icu->idx > last_idx' failed.
Aborted (core dumped)
...
where e1->icu->idx == 201 and last_idx == 201.

The problem is (as we can see using --devel-dump-edges) that there's a
duplicate edge from CU 201 to PU 48:
...
idx: 48
cu: 0xbc
incoming: 200
incoming: 201
incoming: 201
incoming: 203
incoming: 204
incoming: 208
...

This can be traced back to this duplicate chain:
...
duplicate chain:
 7fe2 O 2de8b1f3(fc1aa0402de8b1f3 Visual structure_type DECL
 19d67 O 2de8b1f3(fc1aa0402de8b1f3 Visual structure_type DECL
 2a7aa O 2de8b1f3(fc1aa0402de8b1f3 Visual structure_type DECL
 41434 O 2de8b1f3(fc1aa0402de8b1f3 Visual structure_type DECL
Compilation Unit @ offset 0x5bf84:
 5fd9d O 2de8b1f3(fc1aa0402de8b1f3 Visual structure_type DECL
 611f5 O 2de8b1f3(deb4b00f2de8b1f3 Visual structure_type DEF
...

Since it starts with a DECL, it will be reordered such that the DEF is at
the start.  However, that breaks the code in create_import_tree that checks
for duplicate chain members from the same CU, which assumes that those are
adjacent.

Fix this in create_import_tree.

2021-03-16  Tom de Vries  <tdevries@suse.de>

PR dwz/27578
* dwz.c (create_import_tree): Handle reorder duplicate chain.

3 years agoFix another reference from PU to CU for odr
Tom de Vries [Tue, 16 Mar 2021 15:45:11 +0000 (16:45 +0100)]
Fix another reference from PU to CU for odr

When using the test-case from PR27578 with --no-import-optimize, we run into:
...
$ dwz libvclplug_genlo.so.debug -o libvclplug_genlo.so.debug.z \
    -lnone --odr --no-import-optimize
dwz: dwz.c:12700: write_die: \
  Assertion `IMPLIES (cu->cu_kind == CU_PU, \
                      die_cu (refd)->cu_kind == CU_PU)' failed.
Aborted (core dumped)
...

The assert is triggered when trying to write out the reference to the DIE at
2f5e for DW_AT_type:
...
 <1><2e8c>: Abbrev Number: 76 (DW_TAG_structure_type)
    <2e8d>   DW_AT_name        : (indirect string, offset: 0x5f592): SalXLib
    <2e91>   DW_AT_byte_size   : 320
 ...
 <2><2ed9>: Abbrev Number: 22 (DW_TAG_member)
    <2eda>   DW_AT_name        : (indirect string, offset: 0x56c9b): aReadFDS_
    <2ede>   DW_AT_decl_file   : 33
    <2edf>   DW_AT_decl_line   : 173
    <2ee0>   DW_AT_decl_column : 21
    <2ee1>   DW_AT_type        : <0x2f5e>
    <2ee5>   DW_AT_data_member_location: 48
    <2ee6>   DW_AT_accessibility: 2     (protected)
...

The corresponding duplicate chain (with some annotations manually added) is:
...
duplicate chain:
Compilation Unit @ offset 0x44:
 2d01 O 9f6a4268(29178f4e9f6a4268 SalXLib structure_type DECL
 2e8c O 9f6a4268(87d059e89f6a4268 SalXLib structure_type DEF
 40a6 O 9f6a4268(87d059e89f6a4268 SalXLib structure_type DEF
Compilation Unit @ offset 0xfaf6:
 419be O 9f6a4268(29178f4e9f6a4268 SalXLib structure_type DECL
 50e56 O 9f6a4268(29178f4e9f6a4268 SalXLib structure_type DECL
 6063a O 9f6a4268(29178f4e9f6a4268 SalXLib structure_type DECL
Compilation Unit @ offset 0x1bb0f:
...

The duplicate chain is created by split_dups, which merged all the DECLs with
one duplicate chain containing only DEFs.

When doing the test for merged_singleton on this duplicate chain, it returns
NULL, because there are two DEFs.  However, the DEFs are from the same CU, and
the type for aReadFDS_ is 0x2f5e for both DEFs.  Consequently, there is no
duplicate chain for 0x2f5e, and we need to force a singleton duplicate chain.

Fix this by making merged_singleton return the first DEF.

2021-03-16  Tom de Vries  <tdevries@suse.de>

PR dwz/27578
* dwz.c (merged_singleton): Handle DEFs in the same CU.

3 years agoFix ubsan triggered in gdb-add-index.sh
Tom de Vries [Mon, 15 Mar 2021 10:55:19 +0000 (11:55 +0100)]
Fix ubsan triggered in gdb-add-index.sh

When compiling with CFLAGS="-O0 -ggdb3 -fsanitize=undefined"
LDFLAGS="-fsanitize=undefined' and running the testsuite, we run into:
...
dwz.c:573:64: runtime error: left shift of 144 by 24 places cannot be \
  represented in type 'int'
FAIL: src/testsuite/dwz.tests/gdb-add-index.sh
...

The problem is here in buf_read_ule32:
...
static inline uint32_t
buf_read_ule32 (unsigned char *data)
{
  return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
...

The data[3] is an unsigned char, which is promoted to int when used as shift
operand, which causes the shift to be a signed one, which can result in
undefined behaviour when shifting into the sign bit.

Fix this by casting to unsigned int.  Likewise in buf_read_ube32.

2021-03-15  Tom de Vries  <tdevries@suse.de>

* dwz.c (buf_read_ule32, buf_read_ube32): Avoid undefined signed
left-shift behaviour.

3 years agoFix UBSAN reported for Libreoffice so files
Martin Liska [Mon, 15 Mar 2021 10:17:12 +0000 (11:17 +0100)]
Fix UBSAN reported for Libreoffice so files

Use 1U in left shifts in bitvector_set_bit and bitvector_bit_p to avoid
undefined signed left-shift behaviour.

Fixes:

dwz.c:9041:28: runtime error: left shift of 1 by 31 places cannot be \
  represented in type 'int'
     #0 0x405ad3 in bitvector_bit_p dwz.c:9041
     #1 0x405ad3 in create_import_tree dwz.c:9528
     #2 0x405ad3 in dwz dwz.c:15445
     #3 0x407517 in dwz_files dwz.c:16871
     #4 0x407517 in main dwz.c:16985
     #5 0x7ffff6a8eb24 in __libc_start_main ../csu/libc-start.c:332
     #6 0x4086dd in _start (dwz+0x4086dd)

dwz.c:9032:21: runtime error: left shift of 1 by 31 places cannot be \
  represented in type 'int'
     #0 0x405a83 in bitvector_set_bit dwz.c:9032
     #1 0x405a83 in create_import_tree dwz.c:9530
     #2 0x405a83 in dwz dwz.c:15445
     #3 0x407517 in dwz_files dwz.c:16871
     #4 0x407517 in main dwz.c:16985
     #5 0x7ffff6a8eb24 in __libc_start_main ../csu/libc-start.c:332
     #6 0x4086dd in _start (dwz+0x4086dd)

2021-03-15  Martin Liska  <mliska@suse.cz>

* dwz.c (bitvector_set_bit, bitvector_bit_p): Use 1U in
left shift to avoid undefined signed left-shift behaviour.

3 years agoRemove USED and UNUSED annotations
Tom de Vries [Mon, 15 Mar 2021 09:37:18 +0000 (10:37 +0100)]
Remove USED and UNUSED annotations

Remove the USED and UNUSED annotations, where they are no longer required.

2021-03-15  Tom de Vries  <tdevries@suse.de>

* dwz.c (estimate_nr_dies, emulate_htab, die_odr_state): Remove
UNUSED.
(dump_die): Remove USED.

3 years agoMake some variables and functions static
Tom de Vries [Mon, 15 Mar 2021 09:37:18 +0000 (10:37 +0100)]
Make some variables and functions static

There is a number of variables and functions in dwz.c that is external but
could be static.  Make these static.

2021-03-15  Tom de Vries  <tdevries@suse.de>

* dwz.c (odr, odr_mode, odr_mode_parsed, odr_active_p, stats)
(dump_die, verify_edges, die_count_method_parsed)
(deduplication_mode_parsed): Make static.

3 years agoBreak up main
Tom de Vries [Wed, 10 Mar 2021 05:24:40 +0000 (06:24 +0100)]
Break up main

Factor functions parse_args, dwz_one_file and dwz_files out of main.

2021-03-09  Tom de Vries  <tdevries@suse.de>

* dwz.c (dwz): Make files parameter a const char**.
(parse_args, dwz_one_file, dwz_files): New function, factored
out of ...
(main): ... here.

3 years agoRelease process improvements
Tom de Vries [Wed, 10 Mar 2021 05:24:40 +0000 (06:24 +0100)]
Release process improvements

While doing the 0.14 release I ran into a few minor issues when running the
scripts in contrib/release:
- The script contrib/release/upload-release.sh requires a version argument,
  but the version can just be read from the VERSION file.
- The contrib/release/do-release.sh does not do the git push.  I used
  my usual push script which also does a git rebase --ignore-date, which meant
  the commit got updated and the tag no longer referred to the commit.

Also, I realized it could be useful to have a release checklist to go through.

So:
- Use $(cat VERSION) in contrib/release/upload-release.sh to get version
- Add git push commands to contrib/release/do-release.sh
- Add README.release-checklist

2021-03-08  Tom de Vries  <tdevries@suse.de>

* README.release-checklist: New file.
* contrib/release/do-release.sh: Add git push commands.
* contrib/release/upload-release.sh: Use $(cat VERSION) to get version.

3 years agoAdd --devel-progress-mem
Tom de Vries [Mon, 8 Mar 2021 13:20:31 +0000 (14:20 +0100)]
Add --devel-progress-mem

Add an option --devel-progress-mem that adds memory usage printing to
--devel-progress:
...
$ dwz cc1 -lnone -o cc1.z --devel-progress-mem
read_debug_info .debug_info
user: 4.70
sys : 0.18
VM Peak: 1178532 (1.1G)
VM Current: 1174432 (1.1G)
RSS Peak: 1091784 (1.0G)
RSS Current: 1087992 (1.0G)
partition_dups
user: 0.11
sys : 0.00
VM Peak: 1178532 (1.1G)
VM Current: 1174860 (1.1G)
RSS Peak: 1091784 (1.0G)
RSS Current: 1088372 (1.0G)
..

2021-03-04  Tom de Vries  <tdevries@suse.de>

* dwz.c (print_mem): New function.
(report_progress): Print memory usage statistics if progress_mem_p.
(dwz_options, usage): Add --devel-progress-mem entries.
(main): Set progress_p if progress_mem_p.

3 years agoAdd --devel-no-checksum-cycle-opt
Tom de Vries [Mon, 8 Mar 2021 13:20:31 +0000 (14:20 +0100)]
Add --devel-no-checksum-cycle-opt

In checksum_ref_die, we need to determine a per-toplevel-die checksum based on
the inter-toplevel-die references.  It has four modes:
- mode 1, a trivial one in which we walk towards toplevel-dies.
- mode 2, in which we optimistically assume that there are no cycles.
  If that is the case, we're done.  Otherwise, we use either mode 3 or mode 4.
- mode 3, dealing with cycles in a faster way
- mode 4, dealing with cycles

I did some testing using the testsuite and external testsuite and found that
mode 4 was not triggered once.  I'm not quite sure how to construct a
test-case for that either.

Add an option --devel-no-checksum-cycle-opt that can be used to enforce using
mode 3 instead of mode 4, and add a test-case that uses it.

2021-02-23  Tom de Vries  <tdevries@suse.de>

PR dwz/27429
* Makefile (TEST_EXECS): Add cycle.
(cycle): New target.
* dwz.c (checksum_cycle_opt): New var.
(checksum_ref_die): Handle checksum_cycle_opt.
(dwz_options, usage): Add --devel-checksum-cycle-opt entries.
* testsuite/dwz.tests/cycle.c: New test.
* testsuite/dwz.tests/cycle.sh: New test.

3 years agoBump version to 0.14 dwz-0.14
Tom de Vries [Mon, 8 Mar 2021 07:49:46 +0000 (08:49 +0100)]
Bump version to 0.14

3 years ago[testsuite] Fix odr-loc.sh with -gdwarf-5
Tom de Vries [Fri, 5 Mar 2021 09:41:00 +0000 (10:41 +0100)]
[testsuite] Fix odr-loc.sh with -gdwarf-5

When running the test-suite like this:
...
$ make clean; make; make check CC="gcc -gdwarf-5" CXX="g++ -gdwarf-5"
...
we run into:
...
FAIL: src/testsuite/dwz.tests/odr-loc.sh
...

The test-case calls dwz twice, once without and once with
--devel-ignore-locus.

The first call is there to verify that all DIEs that can be deduplicated
without --devel-ignore-locus are indeed deduplicated, but not more.

The FAIL happens because some DIEs are not deduplicated.  This is a regression
since commit 61c8d81 "Fix DW_AT_decl_file for odr".  This makes sense: the
commit changed partitioning, and now the size heuristics are preventing some
deduplication.

Fix this by ignoring the size heuristics in the first dwz call using
--devel-ignore-size.

2021-03-05  Tom de Vries  <tdevries@suse.de>

* testsuite/dwz.tests/odr-loc.sh: Call dwz first time using
--devel-ignore-size.

3 years agoFix .debug_line reference above end of section
Tom de Vries [Fri, 5 Mar 2021 06:20:07 +0000 (07:20 +0100)]
Fix .debug_line reference above end of section

Consider the file test-import-repeatedly from PR26738, combined with a trivial
a.out:
...
$ cp test-import-repeatedly 1
$ gcc -m32 -g ~/hello.c
$ cp a.out 2
...

When doing multifile optimization, we run into:
...
$ dwz -m 3 2 1
dwz: 3: .debug_line reference above end of section
...

Using --devel-save-temps and src/contrib/gen-dwz-debug-all.sh we get the
unoptimized multifile, and find there a CU:
...
  Compilation Unit @ offset 0x371:
   Length:        0x6d (32-bit)
   Version:       4
   Abbrev Offset: 0x14d
   Pointer Size:  4
 <0><37c>: Abbrev Number: 1 (DW_TAG_compile_unit)
    <37d>   DW_AT_stmt_list   : 0xda
    <381>   DW_AT_language    : 0       (Unknown: 0)
    <382>   DW_AT_comp_dir    : ./build-3.8
...
which refers to a .debug_line offset 0xda, but the debug_line section only
contains an entry at offset 0x0.

This can be explained as follows.  The DIEs written into the CU do not
contain a single DW_AT_decl_file.  Consequently, htab_line will be NULL once
we get here in write_multifile:
...
             || (line_htab != NULL && write_multifile_line ()))
...
and no .debug_line contribution will be added.  However, the CU DIE
referencing the .debug_line contribution is written regardless.

We could fix this by not writing the DW_AT_stmt_list for the CU DIE in this
case, but that would require changing the order in which abbreviations are
computed.

Instead, fix this conservatively, by removing "line_htab != NULL &&", such we
get a minimal .debug_line contribution.

2021-03-02  Tom de Vries  <tdevries@suse.de>

PR dwz/26738
* dwz.c (write_multifile): Also call write_multifile_line when
line_htab == NULL.

3 years agoClean up temporary file in hardlink mode
Tom de Vries [Thu, 4 Mar 2021 08:02:30 +0000 (09:02 +0100)]
Clean up temporary file in hardlink mode

Consider an executable file with hardlinks a.out and b.out.

When running dwz once:
...
$ dwz -h a.out b.out
...
a.out and b.out are updated, and remain hardlinks to the same file.

But when running dwz once more, a.out and b.out remain unchanged, and a
temporary file b.out.#dwz#.XXXXXX is left.

This is caused by the fact that the code in function dwz that is intended to
handle unchanged hardlinks is never triggered.  It is guarded by a
"resa[n].res == 1" condition, but res->res is set to 0 at the end of function
dwz, irrespective of whether the file changed or not.

Fix this by only setting res->res to 0 if the file changed.

This makes test-case twice-multifile.sh fail.  The test-case first
dwz-compresses files 1 and 2 in single-file mode.  Then it attempts a
dwz -m 3 1 2.

This results in a res.res value of 1 (processed, unchanged) for both files.

This causes the files not to be counted as a success in main, and multifile
mode optimization is skipped.

Fix this by handling res.res == 1 in main.

2021-03-02  Tom de Vries  <tdevries@suse.de>

PR dwz/24275
* dwz.c (dwz): Only set res->res to 0 if the file changed.
(main): Handle res.res == 1.
* testsuite/dwz.tests/twice-hardlink.sh: Remove PR24275 workaround.

3 years agoRemove dead code in function dwz
Tom de Vries [Thu, 4 Mar 2021 08:02:30 +0000 (09:02 +0100)]
Remove dead code in function dwz

Function dwz contains this code:
...
  free (dso);
  if (ret == 0 && !low_mem)
    res->res = 0;
...

The value of low_mem will always be false here.  At that point, cleanup has
been called, which resets multifile_mode back to 0.

Fix this by removing the "&& !low_mem".

2021-03-02  Tom de Vries  <tdevries@suse.de>

* dwz.c (dwz): Remove dead code.

3 years agoFix assert after goto failure
Tom de Vries [Tue, 2 Mar 2021 07:26:52 +0000 (08:26 +0100)]
Fix assert after goto failure

Consider the following code in function dwz:
...
      else if (write_aranges (dso))
       {
 cleanup ();
       failure:
 ret = 1;
       }
       ...
      char *p1 = realpath (file, NULL);
      char *p2 = realpath (multifile, NULL);
      ...
      if (p1 == NULL || p2 == NULL)
{
  ...
  error (0, 0, "Could not compute relative multifile "
       "pathname from %s to %s",
 file, multifile);
  goto failure;
...

I've managed to triggered this error in the following way.

First we do this setup:
...
$ mkdir tmpdir
$ ln -s tmpdir tmpdir-slink
$ cp hello 1
$ cp 1 2
...

Then we want to run dwz with a common file in tmpdir using the symlink
tmpdir-slink:
...
$ dwz -m ./tmpdir-slink/3 -r 1 2
...
but, stop just before calling realpath and remove the symlink to make the p2
realpath call return NULL.

We can do that using gdb:
...
$ gdb -batch \
  -ex "b 15451" \
  -ex run \
  -ex "shell rm -f tmpdir-slink" \
  -ex cont \
  --args ./dwz -m ./tmpdir-slink/3 -r 1 2
Breakpoint 1 at 0x382d1: file dwz.c, line 15451.

Breakpoint 1, dwz (file=0x7fffffffe285 "1", outfile=0x0, res=0x5555557a5260,
                   resa=0x0, files=0x7fffffffdeb8) at dwz.c:15451
15451   if (!multifile_relative)
dwz: Could not compute relative multifile pathname from 1 to ./tmpdir-slink/3
dwz: dwz.c:2170: off_htab_add_die: Assertion `*slot == NULL' failed.

Program received signal SIGABRT, Aborted.
0x00007ffff75fffb7 in raise () from /lib/x86_64-linux-gnu/libc.so.6
...
but we hit an assertion.

This is because cleanup is not called.

Fix this by moving the failure label up one line.

2021-03-02  Tom de Vries  <tdevries@suse.de>

* dwz.c (dwz): Move failure label to before cleanup.

3 years agoDocument experimental status of odr
Tom de Vries [Sat, 27 Feb 2021 10:34:55 +0000 (11:34 +0100)]
Document experimental status of odr

Add documentation of the experimental status of the odr optimization in dwz.1.

2021-02-25  Tom de Vries  <tdevries@suse.de>

PR dwz/27401
* dwz.1: Document experimental status of odr.

3 years agoAdd assert checking that CU is not referenced from PU
Tom de Vries [Sat, 27 Feb 2021 10:34:55 +0000 (11:34 +0100)]
Add assert checking that CU is not referenced from PU

One of the invariants of dwz is that references from a newly created PU can
only reference other PUs.

Add an assert that checks this.

2021-02-25  Tom de Vries  <tdevries@suse.de>

* dwz.c (write_die): Add assert.

3 years agoFix reference of PU to CU for odr
Tom de Vries [Sat, 27 Feb 2021 10:34:55 +0000 (11:34 +0100)]
Fix reference of PU to CU for odr

When compiling dwz with the assert listed in the commit message for
"Call reorder_dups ASAP", and using test-case cc1.dwz-processed like so, we
run into:
...
$ dwz cc1.dwz-processed -o 1 -lnone --odr
dwz: dwz.c:12567: write_die: Assertion \
  `IMPLIES (cu->cu_kind == CU_PU, die_cu (refd)->cu_kind == CU_PU)' failed.
Aborted (core dumped)
...

The assert is related to this duplicate chain:
...
 28dd83f O b500801d 621b6872  pointer_type \
   (type: 28dd72f die_struct structure_type)
 2903769 O b500801d 621b6872  pointer_type \
   (type: 28dd72f die_struct structure_type)
...
which contains two DIEs that are both in the same CU:
...
 <0><28d281f>: Abbrev Number: 200 (DW_TAG_compile_unit)
 ...
 <1><28dd72f>: Abbrev Number: 35 (DW_TAG_structure_type)
    <28dd730>   DW_AT_name        : (indirect string, offset: 0x1b2ca6): die_struct
    <28dd734>   DW_AT_byte_size   : 80
    <28dd735>   DW_AT_decl_file   : 87
    <28dd736>   DW_AT_decl_line   : 3069
    <28dd738>   DW_AT_decl_column : 63
    <28dd739>   DW_AT_sibling     : <0x28dd83b>
 <1><28dd83f>: Abbrev Number: 9 (DW_TAG_pointer_type)
    <28dd840>   DW_AT_byte_size   : 8
    <28dd841>   DW_AT_type        : <0x28dd72f>
 ...
 <1><2903769>: Abbrev Number: 9 (DW_TAG_pointer_type)
    <290376a>   DW_AT_byte_size   : 8
    <290376b>   DW_AT_type        : <0x28dd72f>
 ...
 <0><2911617>: Abbrev Number: 177 (DW_TAG_compile_unit)
...

The dup chain is forced to a partial unit, but the die_struct DIE is not,
because it's not part of a duplicate chain, and it's not marked as a
singleton.  Fix this by marking the die_struct DIE as singleton.

2021-02-25  Tom de Vries  <tdevries@suse.de>

PR dwz/27464
* dwz.c (partition_dups): Call mark_singletons if
cnt_ref_cus (die) == 1.

3 years agoCall reorder_dups ASAP
Tom de Vries [Sat, 27 Feb 2021 10:34:55 +0000 (11:34 +0100)]
Call reorder_dups ASAP

Currently, we call reorder_dups just before partial unit creation, and only for
DIEs that will be copied.

This approach causes a problem with reachable DIE propagation (which is done
in partition_dups after phase 1): when a dup-chain that needs to be reordered
(starts with ODR_DECL but also contains ODR_DEF) is marked as reachable during
this propagation, propagation will stop at the ODR_DECL, while it should
continue at the first ODR_DEF instead.

Fix this by calling reorder_dups ASAP, just after computing the partitions.

The problem can be detected using this assert:
...
@@ -12563,6 +12563,8 @@ write_die
      {
        dw_cu_ref refdcu = die_cu (refd);
        value = refd->u.p2.die_new_offset;
+       assert (IMPLIES (cu->cu_kind == CU_PU,
+        die_cu (refd)->cu_kind == CU_PU));
        assert (value && refdcu->cu_kind != CU_ALT);
        if (t->attr[j].form == DW_FORM_ref_addr)
  {
...

2020-01-25  Tom de Vries  <tdevries@suse.de>

PR dwz/25424
* dwz.c (partition_dups_1): Move calling of reorder_dups ...
(partition_dups): ... here.

3 years agoPrecompute partitions
Tom de Vries [Sat, 27 Feb 2021 10:34:55 +0000 (11:34 +0100)]
Precompute partitions

Currently, we calculate the duplicate chain partitions in partition_dups_1.
This is done twice, once for phase 1 and once for phase 2.

Instead, calculate the partitions once in partition_dups, and use those for
both calls to partition_dups_1.

Performance tested on cc1.  This causes a small performance regresssion:
...
user:
series:  5140 5100 5120 5130 5150 5160 5160 5180 5170 5130 \
         5180 5160 5090 5230 5140 5140 5210 5100 5170 5130
mean:  5149.50 (100%)
stddev:  35.46
series:  5120 5190 5230 5190 5200 5160 5170 5210 5270 5180 \
         5270 5240 5200 5200 5200 5170 5150 5220 5180 5140
mean:  5194.50 (100.87%)
stddev:  39.13
...

There's no significant increase of memory usage:
...
mem:
series:  1260512 1260456 1260492 1260368 1260608 1260268 1260656 1260488 \
         1260420 1260332 1260464 1260488 1260536 1260340 1260352 1260492 \
         1260268 1260276 1260316 1260316
mean:  1260422.40 (100%)
stddev:  113.73
series:  1260456 1260296 1260244 1260360 1260584 1260344 1260548 1260388 \
         1260424 1260304 1260252 1260560 1260664 1260476 1260480 1260416 \
         1260580 1260504 1260604 1260324
mean:  1260440.40 (100.00%)
...

We accept the small performance penalty because this patch is a prerequisite
for the PR25424 bug fix.

2021-02-25  Tom de Vries  <tdevries@suse.de>

* dwz.c (calculate_partitions): New function, factored out of ...
(partition_dups_1): ... here.  Drop vec_size parameter.  Add
nr_partitions and partitions parameter.  Iterate over partitions array.
(partition_dups): Call calculate_partitions.  Update calls to
partition_dups_1.

3 years agoPR27463 Accept DW_FORM_sdata for DW_AT_decl/call_file
Mark Wielaard [Fri, 26 Feb 2021 14:38:58 +0000 (15:38 +0100)]
PR27463 Accept DW_FORM_sdata for DW_AT_decl/call_file

Using DW_FORM_sdata for DW_AT_decl/call_file is somewhat inefficient
since file index numbers are always positive values. But it is a valid
form to encode a constant value. Accept DW_FORM_sdata as long as it
encodes a positive value. Extend the positive value check to
DW_FORM_implicit_const.

* dwz.c (checksum_die): Accept DW_FORM_sdata for
        DW_AT_decl/call_file as long as the value is positive. Also
        check DW_FORM_implicit_const value is positive for these
        attributes.
(die_eq_1): Handle DW_FORM_sdata for DW_AT_decl/call_file.
(build_abbrevs_for_die): Likewise.
(write_die): Likewise.
* testsuite/dwz.tests/pr27463.sh: New test.
* testsuite/lib/unavailable-dwarf-piece.exp: New testfile
from gdb.
* testsuite/dwz.tests/dwz-tests.exp: Add unavailable-dwarf-piece
for pr25109.sh.
* testsuite/dwz.tests/main.c (foo): New function and labels.
(bar): Likewise.
* Makefile (TEST_EXECS_DWARF_ASM): Add unavailable-dwarf-piece.

https://sourceware.org/bugzilla/show_bug.cgi?id=27463

3 years ago[testsuite] Fix pr25109.sh on riscv64
Tom de Vries [Fri, 26 Feb 2021 11:47:34 +0000 (12:47 +0100)]
[testsuite] Fix pr25109.sh on riscv64

On riscv64, I run into:
...
cc main.c no-multifile-prop-dw.S -o no-multifile-prop
no-multifile-prop-dw.S: Assembler messages:
no-multifile-prop-dw.S:25: Error: non-constant .uleb128 is not supported
make: *** [Makefile:99: no-multifile-prop] Error 1
...

Fix this by allowing to fail to build the test-case, and marking it as
unsupported.

2021-02-26  Tom de Vries  <tdevries@suse.de>

* Makefile (no-multifile-prop): Add target rule.
* testsuite/dwz.tests/dwz-tests.exp: Require no-multifile-prop for
pr25109.sh.

3 years agoUpdate SUSE Copyright years
Tom de Vries [Fri, 26 Feb 2021 08:42:25 +0000 (09:42 +0100)]
Update SUSE Copyright years

Update the SUSE copyright range for changes made in 2020 and 2021.

2021-02-26  Tom de Vries  <tdevries@suse.de>

* dwz.c: Extend SUSE Copyright range to 2021.
* COPYRIGHT_YEARS: Regenerate.

3 years agoFactor out same_ref_cus_p and cnt_ref_cus
Tom de Vries [Thu, 25 Feb 2021 09:40:38 +0000 (10:40 +0100)]
Factor out same_ref_cus_p and cnt_ref_cus

Factor out new functions same_ref_cus_p and cnt_ref_cus out of
partition_dups_1.

Performance tested with cc1, no regression found.

2021-02-25  Tom de Vries  <tdevries@suse.de>

* dwz.c (same_ref_cus_p, cnt_ref_cus): New function, factored out
of ...
(partition_dups_1): ... here.

3 years agoFix DW_AT_decl_file for odr
Tom de Vries [Thu, 25 Feb 2021 08:04:33 +0000 (09:04 +0100)]
Fix DW_AT_decl_file for odr

Consider odr-struct.  It has two structs aaa (from different CUs), each with
members of type bbb and ccc, but in one case bbb is a decl, in the other case
ccc is a decl.

When doing odr, we end up with one struct aaa, and no decls:
...
$ dwz --odr odr-struct
$ readelf -wi odr-struct \
    | egrep -A2 "DW_TAG_structure" \
    | egrep "DW_TAG|DW_AT_name|DW_AT_decl"
 <1><19>: Abbrev Number: 25 (DW_TAG_structure_type)
    <1a>   DW_AT_name        : ccc
 <1><2f>: Abbrev Number: 25 (DW_TAG_structure_type)
    <30>   DW_AT_name        : aaa
 <1><4b>: Abbrev Number: 25 (DW_TAG_structure_type)
    <4c>   DW_AT_name        : bbb
...

Now consider using the same file for multifile optimization, combined with
odr:
...
$ cp odr-struct 1; cp 1 2; dwz -m 3 1 2 --odr
...
The desired outcome is that the structs aaa are unified (same as above) in
both 1 and 2, and then moved to multifile 3.

The multifile looks good:
...
$ readelf -wi 3 \
    | egrep -A2 "DW_TAG_structure" \
    | egrep "DW_TAG|DW_AT_name|DW_AT_decl"
 <1><14>: Abbrev Number: 15 (DW_TAG_structure_type)
    <15>   DW_AT_name        : ccc
 <1><2a>: Abbrev Number: 15 (DW_TAG_structure_type)
    <2b>   DW_AT_name        : aaa
 <1><46>: Abbrev Number: 15 (DW_TAG_structure_type)
    <47>   DW_AT_name        : bbb
...
but some struct types are left in 1:
...
$ readelf -wi 1 \
    | egrep -A2 "DW_TAG_structure" \
    | egrep "DW_TAG|DW_AT_name|DW_AT_decl"
 <1><1e>: Abbrev Number: 12 (DW_TAG_structure_type)
    <1f>   DW_AT_name        : aaa
 <1><3d>: Abbrev Number: 12 (DW_TAG_structure_type)
    <3e>   DW_AT_name        : bbb
...

The problem is that the DW_AT_decl_file is different for struct bbb in 1 and
3, and that causes the struct types to linger in 1.

The problem can already be shown without multifile mode using:
....
$ dwz odr-struct --odr
$ llvm-dwarfdump odr-struct \
    | grep -A3 struct \
    | egrep -v "^--|DW_AT_byte_size" \
    | sed 's%/.*/%%'
0x00000019:   DW_TAG_structure_type
                DW_AT_name      ("ccc")
                DW_AT_decl_file ("odr.cc")
0x0000002f:   DW_TAG_structure_type
                DW_AT_name      ("aaa")
                DW_AT_decl_file ("odr.h")
0x0000004b:   DW_TAG_structure_type
                DW_AT_name      ("bbb")
                DW_AT_decl_file ("odr.cc")
...
The DW_AT_decl_file for struct bbb should be odr-2.cc.

The problem is caused by by odr: odr allows defs and decls to be part of the
same duplicate chain, which breaks the invariant that DIEs in the duplicate
chain are isomorph.  During write_die, the first DIE in the chain is written
out as the representative copy, which means having a decl as the first in the
chain is counterproductive.  We have reorder_dups to fix this problem, which
detects if a duplicate chain starts with a decl and then moves the first def
before it.  However, this breaks another variant: that for each partition, all
representative DIEs are from the same CU.  Consequently, the file table of the
partition may not match with the DW_AT_decl_file number.

In other words, the reordered duplicate chain is in the wrong partition.

Fix this by:
- ignoring ODR_DECL DIEs at the start of a duplicate chain when partitioning
- moving the reorder_dups call to the start of partial unit creating, such
  that we get the correct refcu.

This also breaks the invariant checked in create_import_tree that
partition_dups doesn't generate two seperate partial units with the same set
of referrer CUs, so we allow this for odr.

2021-02-19  Tom de Vries  <tdevries@suse.de>

PR dwz/27438
* dwz.c (partition_cmp): Ignore ODR_DECL dies at the
start of a duplicate chain.
(partition_dups_1): Same.  Move call to reorder_dups earlier.
(create_import_tree): Allow partial units with same set of referrers
for odr.
* testsuite/dwz.tests/odr-struct-multifile.sh: New test.

3 years agoClean up die_odr_state interface
Tom de Vries [Tue, 23 Feb 2021 11:07:51 +0000 (12:07 +0100)]
Clean up die_odr_state interface

The die_odr_state function returns the odr state for a die, and if it hasn't
been calculated, it calculates it first using a call to set_die_odr_state:
...
static unsigned int UNUSED
die_odr_state (dw_cu_ref cu, dw_die_ref die)
{
  if (die->die_odr_state != ODR_UNKNOWN)
    return die->die_odr_state;

  set_die_odr_state (cu, die);
  return die->die_odr_state;
}
...

The call to set_die_odr_state needs a cu argument, and consequently
die_odr_state also has one.  That means a call to die_odr_state needs a proper
CU argument if set_die_odr_state gets called, and for optimality a NULL CU
otherwise.

As it happens, there's only one place where the proper CU argument is
required, and it's easy to accidentally do:
...
  die_odr_state (die_cu (die), die)
...
where a NULL CU would suffice.

Fix this by explicitly calling set_die_odr_state and dropping the cu parameter
from die_odr_state.

2021-02-23  Tom de Vries  <tdevries@suse.de>

* dwz.c (set_die_odr_state): Assert die->die_odr_state == ODR_UNKNOWN.
(die_odr_state): Drop cu parameter.  Assert
die->die_odr_state != ODR_UNKNOWN.
(checksum_die): Call set_die_odr_state.  Update call to die_odr_state.
(read_debug_info, split_dups, reorder_dups, merged_singleton)
(partition_dups): Update call to die_odr_state.

3 years agoDon't print die_hash2 for ODR_UNKNOWN in dump_die_with_indent
Tom de Vries [Tue, 23 Feb 2021 09:24:21 +0000 (10:24 +0100)]
Don't print die_hash2 for ODR_UNKNOWN in dump_die_with_indent

With the following debugging session where we dwz exec hello using odr:
...
$ gdb -q --args dwz hello -o hello.z --odr
Reading symbols from dwz...
(gdb) b checksum_die
Breakpoint 1 at 0x409778: file dwz.c, line 3348.
(gdb) r
Starting program: dwz hello -o hello.z --odr

Breakpoint 1, checksum_die (...) at dwz.c:3348
3348      switch (die->die_ck_state)
(gdb) call dump_die (die)
 b X 0(0) 0 ../sysdeps/x86_64/start.S compile_unit
(gdb) p die->die_odr_state
$1 = ODR_UNKNOWN
...
we see that we're printing the die_hash2 for a die with die_odr_state ==
ODR_UNKNOWN, while this is only supposed to trigger for ODR_DECL and ODR_DEF.

Fix this in dump_die_with_indent, by not printing die_hash2 when die_odr_state ==
ODR_UNKNOWN.

2021-02-23  Tom de Vries  <tdevries@suse.de>

* dwz.c (dump_die_with_indent): Don't print die_hash2 when
die_odr_state == ODR_UNKNOWN.

3 years agoDon't call die_odr_state with unnecessarily defined cu arg
Tom de Vries [Mon, 22 Feb 2021 15:38:26 +0000 (16:38 +0100)]
Don't call die_odr_state with unnecessarily defined cu arg

When compiling dwz with this patch:
...
 die_odr_state (dw_cu_ref cu, dw_die_ref die)
 {
   if (die->die_odr_state != ODR_UNKNOWN)
-    return die->die_odr_state;
+    {
+      assert (cu == NULL);
+      return die->die_odr_state;
+    }
...
and running f.i. odr-struct.sh, we run into the abort.

The recent commit 3312feb "Fix CK_BAD propagation for --odr" introduced this
code:
...
                 if (die_odr_state (die_cu (die), die) != ODR_NONE)
                   die->u.p1.die_ref_hash = die->u.p1.die_hash;
...
and there's no need to pass a CU argument, which makes the abort trigger.

Fix this by passing a NULL CU instead.

2021-02-22  Tom de Vries  <tdevries@suse.de>

* dwz.c (read_debug_info): Pass NULL CU to die_odr_state call.

3 years agoFix CK_BAD propagation for --odr
Tom de Vries [Mon, 22 Feb 2021 07:44:16 +0000 (08:44 +0100)]
Fix CK_BAD propagation for --odr

With the reproducer from PR26252 we get:
...
$ dwz 2 -o 2.z --odr -lnone
dwz: dwz.c:7396: partition_found_dups: \
  Assertion `die->die_ck_state == CK_KNOWN' failed.
Aborted (core dumped)
...

The problem is caused by the odr code in checksum_ref_die, which skips
checksum calculation for the children of odr types, with as unintended
side-effect that it break the CK_BAD propagation to toplevel DIEs.

Fix this by making the skipping of the checksum calculation less intrusive.
Specially:
- undo all modifications related to odr in checksum_ref_die
- After calling checksum_ref_die in read_debug_info:
  - override die_ref_hash for odr DIEs, and
  - recalculate die_ref_hash for all other DIEs.

We still have the same amount of compression with cc1, that is: without odr
we have 42.30% reduction:
...
$ dwz cc1 -o cc1.z -lnone --no-odr
$ diff.sh cc1 cc1.z
.debug_info      red: 44.84%    111527248  61527733
.debug_abbrev    red: 40.28%    1722726  1028968
.debug_str       red: 0%        6609355  6609355
total            red: 42.30%    119859329 69166056
...
and with odr but without the bug fix we have 54.55%:
...
$ dwz cc1 -o cc1.z -lnone --odr
$ diff.sh cc1 cc1.z
.debug_info      red: 57.46%    111527248  47449258
.debug_abbrev    red: 75.08%    1722726  429434
.debug_str       red: 0%        6609355  6609355
total            red: 54.55%    119859329 54488047
...
and with odr and the bug fix still 54.55%:
...
$ dwz cc1 -o cc1.z -lnone --odr
$ diff.sh cc1 cc1.z
.debug_info      red: 57.46%    111527248  47446501
.debug_abbrev    red: 75.51%    1722726  422027
.debug_str       red: 0%        6609355  6609355
total            red: 54.55%    119859329 54477883
...

2021-02-18  Tom de Vries  <tdevries@suse.de>

PR dwz/26252
* dwz.c (checksum_ref_die): Undo modifications related to odr.
(read_debug_info): After calling checksum_ref_die, override
die_ref_hash for odr DIEs, and recalculate die_ref_hash for all
other DIEs.

3 years agoAdd .gitignore
Tom Tromey [Sun, 21 Feb 2021 02:13:39 +0000 (19:13 -0700)]
Add .gitignore

This adds a basic .gitignore.

3 years agoPrint --version and --help to stdout
Tom Tromey [Sun, 21 Feb 2021 02:12:54 +0000 (19:12 -0700)]
Print --version and --help to stdout

Normall --version and --help output go to stdout and cause a program
to exit with status 0.  The rationale for the exit status is that the
user asked for this behavior, and the program successfully complied.
Printing --help output to stdout is nicer for piping into a pager.

This patch changes dwz to follow this approach.

I kept the program invocation name in the Usage line.  Different
programs seem to handle this differently.

3 years agoman page: Clarify DWARF 5 support after addition of --dwarf-5 option
Jakub Jelinek [Sat, 20 Feb 2021 10:22:46 +0000 (11:22 +0100)]
man page: Clarify DWARF 5 support after addition of --dwarf-5 option

* dwz.1: Clarify DWARF 5 support after addition of --dwarf-5
option.

This page took 0.279699 seconds and 5 git commands to generate.