On Sat, May 7, 2022 at 8:32 AM Waldek Kozaczuk <[email protected]> wrote:

> After upgrading to newest Ubuntu 2022.04 I started seeing following
> crashes of programs using libgcc_s.so:
>
> #0  _dl_find_object (pc1=0x10000003f5ca <_Unwind_Resume+58>,
> result=0x200000200180) at linux.cc:542
> #1  0x00001000000410f6 in _Unwind_Find_FDE ()
> #2  0x000010000003d833 in ?? ()
> #3  0x000010000003ead0 in ?? ()
> #4  0x000010000003f5cb in _Unwind_Resume ()
> #5  0x0000100000062daa in ?? ()
> #6  0x0000100000075b5c in
> boost::execution_monitor::vexecute(boost::function<void ()> const&) ()
> #7  0x000010000007f0a9 in boost::unit_test::framework::init(bool (*)(),
> int, char**) ()
> #8  0x000010000009254d in boost::unit_test::unit_test_main(bool (*)(),
> int, char**) ()
> #9  0x000000004039d001 in osv::application::run_main
> (this=0xffffa00000bd8c10) at core/app.cc:416
> #10 0x000000004039d20d in operator() (app=<optimized out>, __closure=0x0)
> at core/app.cc:236
> #11 _FUN () at core/app.cc:238
> #12 0x00000000403d084a in operator() (__closure=0xffffa00000d57800) at
> libc/pthread.cc:116
> #13 std::__invoke_impl<void, pthread_private::pthread::pthread(void*
> (*)(void*), void*, sigset_t, const
> pthread_private::thread_attr*)::<lambda()>&> (__f=...)
>     at /usr/include/c++/11/bits/invoke.h:61
> #14 std::__invoke_r<void, pthread_private::pthread::pthread(void*
> (*)(void*), void*, sigset_t, const
> pthread_private::thread_attr*)::<lambda()>&> (__fn=...)
>     at /usr/include/c++/11/bits/invoke.h:154
> #15 std::_Function_handler<void(), pthread_private::pthread::pthread(void*
> (*)(void*), void*, sigset_t, const
> pthread_private::thread_attr*)::<lambda()> >::_M_invoke(const
> std::_Any_data &) (__functor=...) at
> /usr/include/c++/11/bits/std_function.h:290
> #16 0x000000004036b58e in sched::thread::main (this=0xffff800000f6a040) at
> core/sched.cc:1267
> #17 sched::thread_main_c (t=0xffff800000f6a040) at
> arch/x64/arch-switch.hh:325
> #18 0x00000000402fda03 in thread_main () at arch/x64/entry.S:116
>
> After some digging I discovered this new function was added as per this
> patch to libc -
> https://www.mail-archive.com/[email protected]/msg275305.html. And
> there s this description:
>
> http://www.gnu.org/software/libc/manual/html_node/Dynamic-Linker-Introspection.html
>
> It is interesting that libgcc_s.so on pretty new Fedora 35 with newer gcc
> does not need this.
>
> I tried to stub something but this is not enough:
>
> struct dl_find_object
> {
>   __extension__ unsigned long long int dlfo_flags;
>   void *dlfo_map_start;        /* Beginning of mapping containing address.
>  */
>   void *dlfo_map_end;        /* End of mapping.  */
>   struct link_map *dlfo_link_map;
>   void *dlfo_eh_frame;        /* Exception handling data of the object.  */
>   __extension__ unsigned long long int __dflo_reserved[7];
> };
>
> #include <osv/elf.hh>
> extern "C" int
> _dl_find_object (void *pc1, dl_find_object* result)
> {
>    result->dlfo_eh_frame = 0;
>

According to
http://www.gnu.org/software/libc/manual/html_node/Dynamic-Linker-Introspection.html,
this is " If the platform uses DWARF unwinding information, this is the
in-memory address of the PT_GNU_EH_FRAME segment.".

Maybe we need to save it in object::process_headers(), or more slowly (does
speed matter?) read it from _pheaders, like:

    for (auto& p : _phdrs) {
        if (p.p_type == PT_GNU_EH_FRAME) {
           result->dlfo_eh_frame = p; // or something like this.
        }
    }


>    result->dlfo_link_map = 0; // where would this come from?
>

According to dladdr(3) this is what the "link map" needs to contain:
                  struct link_map {
                      ElfW(Addr) l_addr;  /* Difference between the
                                             address in the ELF file and
                                             the address in memory */
                      char      *l_name;  /* Absolute pathname where
                                             object was found */
                      ElfW(Dyn) *l_ld;    /* Dynamic section of the
                                             shared object */
                      struct link_map *l_next, *l_prev;
                                          /* Chain of loaded objects */

                      /* Plus additional fields private to the
                         implementation */
                  };

I'm not sure which Linux or gcc header files has this, we'll probably need
to have our own version of this.
It appears we should have a "link_map" structure as part of our "object"
which we'll fill with this information when loading the object and its
dependencies.
Doesn't sound hard.


>    auto eo = elf::get_program()->object_containing_addr(pc1);
>    result->dlfo_map_start = (void*)(eo->base());
>    result->dlfo_map_end = (void*)(eo->end());
>    return 0;
> }
>
> Any suggestions would be welcome.
>
> Regards,
> Waldek
>
> --
> You received this message because you are subscribed to the Google Groups
> "OSv Development" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/osv-dev/8a1d87f7-4d50-44d7-872a-7a94bc453397n%40googlegroups.com
> <https://groups.google.com/d/msgid/osv-dev/8a1d87f7-4d50-44d7-872a-7a94bc453397n%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/osv-dev/CANEVyjuqqguXWdBuXJP%3DrA80qpffb31YOxcrn%3DdS6eyUw58xrA%40mail.gmail.com.

Reply via email to