Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
elf: reverse unloading of objects in needed list
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