Bug 27578 - --odr mode fails for a Libreoffice shared library
Summary: --odr mode fails for a Libreoffice shared library
Status: RESOLVED FIXED
Alias: None
Product: dwz
Classification: Unclassified
Component: default (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Nobody
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-03-15 07:51 UTC by Martin Liska
Modified: 2021-03-16 16:12 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
Shared library (487.86 KB, application/zstd)
2021-03-15 07:51 UTC, Martin Liska
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Liska 2021-03-15 07:51:35 UTC
Created attachment 13310 [details]
Shared library

I see the following assert:

$ ./dwz --odr libvclplug_genlo.so-7.1.1.2-0.x86_64.debug
dwz: dwz.c:8826: remove_import_edges: Assertion `i == cucount' failed.
Aborted (core dumped)
Comment 1 Tom de Vries 2021-03-15 11:02:32 UTC
With --no-import-optimize, we run instead into:
...
$ dwz ./libvclplug_genlo.so.debug -o libvclplug_genlo.so.debug.z -lnone --odr --no-import-optimize
dwz: /home/vries/dwz/dwz.git/dwz.c:12685: write_die: Assertion `IMPLIES (cu->cu_kind == CU_PU, die_cu (refd)->cu_kind == CU_PU)' failed.
Aborted
...
Comment 2 Tom de Vries 2021-03-15 12:27:22 UTC
(In reply to Tom de Vries from comment #1)
> With --no-import-optimize, we run instead into:
> ...
> $ dwz ./libvclplug_genlo.so.debug -o libvclplug_genlo.so.debug.z -lnone
> --odr --no-import-optimize
> dwz: /home/vries/dwz/dwz.git/dwz.c:12685: write_die: Assertion `IMPLIES
> (cu->cu_kind == CU_PU, die_cu (refd)->cu_kind == CU_PU)' failed.
> Aborted
> ...

Fixed by:
...
diff --git a/dwz.c b/dwz.c
index 54b4bda..fcbc3aa 100644
--- a/dwz.c
+++ b/dwz.c
@@ -8433,7 +8433,12 @@ merged_singleton (dw_die_ref die)
       {
       case ODR_DEF:
        if (res)
-         return NULL;
+         {
+           if (die_cu (res) == die_cu (d))
+             continue;
+           else
+             return NULL;
+         }
        else
          res = d;
        break;
...

But that doesn't fix the assert reported in comment 0.
Comment 3 Tom de Vries 2021-03-15 12:53:30 UTC
(In reply to Martin Liska from comment #0)
> Created attachment 13310 [details]
> Shared library
> 
> I see the following assert:
> 
> $ ./dwz --odr libvclplug_genlo.so-7.1.1.2-0.x86_64.debug
> dwz: dwz.c:8826: remove_import_edges: Assertion `i == cucount' failed.
> Aborted (core dumped)

That's triggered in phase 2.  When using --devel-verify-edges, we get an assert at the end of phase 1:
...
$ ./dwz ./libvclplug_genlo.so.debug -o libvclplug_genlo.so.debug.z -lnone --odr --devel-verify-edges 
dwz: dwz.c:8923: verify_edges_1: Assertion `count == 0 || e1->icu->idx > last_idx' failed.
Aborted (core dumped)
...
Comment 4 Tom de Vries 2021-03-15 13:14:53 UTC
OK, that's due to:
...
idx: 48
cu: 0xbc
incoming: 200
incoming: 201
incoming: 201
incoming: 203
incoming: 204
incoming: 208
...

There are two incoming edges from the same CU.  So, one CU is importing the same PU twice.  We can see this in the output if we do --no-import-optimize:
...
 <1><4742f>: Abbrev Number: 51 (DW_TAG_imported_unit)
    <47430>   DW_AT_import      : <0x7f02>      [Abbrev Number: 18 (DW_TAG_partial_unit)]
 <1><47434>: Abbrev Number: 51 (DW_TAG_imported_unit)
    <47435>   DW_AT_import      : <0x7f02>      [Abbrev Number: 18 (DW_TAG_partial_unit)]
...
Comment 5 Tom de Vries 2021-03-15 14:19:42 UTC
Tentative patch:
...
@@ -9130,11 +9135,18 @@ create_import_tree (void)
       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);
@@ -9144,11 +9156,18 @@ create_import_tree (void)
                       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)
...