Skip to content

Commit

Permalink
elf: reverse unloading of objects in needed list
Browse files Browse the repository at this point in the history
New versions of boost like 1.69.0 have more complicated
dependendencies and cause issues with some of the unit tests.

```
tst-rcu-list.so
  libboost_unit_test_framework.so.1.69.0
    libboost_timer.so.1.69.0
      libboost_chrono.so.1.69.0
        libboost_system.so.1.69.0
        libgcc_s.so.1
      libboost_system.so.1.69.0
      libgcc_s.so.1
    libboost_system.so.1.69.0
    libgcc_s.so.1
  libboost_filesystem.so.1.69.0
    libboost_system.so.1.69.0
    libgcc_s.so.1
  libgcc_s.so.1
```

More specifically unit tests like tst-rcu-list and tst-rcu-hashtable
crash when executing FINI functions while unloading boost libraries
with a stack trace like this:

```
#0  0x00000000403a3cf2 in processor::cli_hlt () at arch/x64/processor.hh:247
#1  arch::halt_no_interrupts () at arch/x64/arch.hh:48
#2  osv::halt () at arch/x64/power.cc:26
#3  0x0000000040239dae in abort (fmt=fmt@entry=0x4064155f "Aborted\n") at runtime.cc:132
#4  0x00000000402028ab in abort () at runtime.cc:98
#5  0x000000004021981e in osv::generate_signal (siginfo=..., ef=0xffff80000123c068) at libc/signal.cc:124
#6  0x0000000040463f7f in osv::handle_mmap_fault (addr=<optimized out>, sig=<optimized out>, ef=<optimized out>) at libc/signal.cc:139
#7  0x000000004033da62 in mmu::vm_fault (addr=17592187015168, addr@entry=17592187015648, ef=ef@entry=0xffff80000123c068) at core/mmu.cc:1337
#8  0x000000004039dc30 in page_fault (ef=0xffff80000123c068) at arch/x64/mmu.cc:42
#9  <signal handler called>
#10 0x00001000000ed1e0 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() ()
#11 0x000000004023a357 in __cxxabiv1::__cxa_finalize (dso=<optimized out>) at runtime.cc:183
#12 0x000010000041f5f7 in __do_global_dtors_aux ()
#13 0x00002000001008f0 in ?? ()
#14 0x0000000040352f34 in elf::object::run_fini_funcs (this=0xffffa000015d0a00) at core/elf.cc:1105
```

The order in which FINI functions are executed currently follows
the order in which its objects are unloaded. It is not exactly clear why,
but there seems to be some dependency between child
objects in the DT_NEEDED list of paricular object. For example,
if in tst-rcu-list.so the libboost_unit_test_framework.so.1.69.0
is unloaded first and libboost_filesystem.so.1.69.0 unloaded later,
the std string destructor called by libboost_filesystem.so.1.69.0 FINI
function causes page fault shown above.

The commit #4d24b90aa38d90bdcf5ebecf7a5badeca3b657eb from 6 years ago
made process of unloading of objects symmetrical to the loading one
but not quite exactly which seems to be a culprit.

This patch refines the `elf::unload_needed()` method by changing the order
in which the dependent object references are released.

First we release references held by the `_used_by_resolve_plt_got` set
mostly because they are added after DT_NEEDED is processed and `_needed` populated and
we want this to be symmetrical.

Secondly we release references from the `_needed` vector
by iterating and removing elements starting at the end. This
also makes the unloading behavior symmetrical to the order
in which the objects from DT_NEEDED were loaded in first place.

Concluding with this patch all the unit tests now
pass when linked the boost 1.69.0 from Fedora 30 host.

Signed-off-by: Waldemar Kozaczuk <[email protected]>
Message-Id: <[email protected]>
  • Loading branch information
wkozaczuk authored and nyh committed Dec 9, 2019
1 parent 70bbe0d commit 5415cf4
Showing 1 changed file with 3 additions and 1 deletion.
4 changes: 3 additions & 1 deletion core/elf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1000,8 +1000,10 @@ void object::load_needed(std::vector<std::shared_ptr<object>>& loaded_objects)

void object::unload_needed()
{
_needed.clear();
_used_by_resolve_plt_got.clear();
while (!_needed.empty()) {
_needed.pop_back();
}
}

ulong object::get_tls_size()
Expand Down

0 comments on commit 5415cf4

Please sign in to comment.