Missing _dl_find_object()

133 views
Skip to first unread message

Waldek Kozaczuk

unread,
May 7, 2022, 1:32:10 AM5/7/22
to OSv Development
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/gcc-p...@gcc.gnu.org/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;
   result->dlfo_link_map = 0; // where would this come from?
   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

Waldek Kozaczuk

unread,
May 7, 2022, 12:07:51 PM5/7/22
to OSv Development
And here is how gcc changed to use _dl_find_object() - https://github.com/gcc-mirror/gcc/commit/790854ea7670f11c14d431c102a49181d2915965. It seems to be used during unwinding.

Waldek Kozaczuk

unread,
May 9, 2022, 11:06:01 AM5/9/22
to OSv Development
I think I have a good handle on what needs to be done and I have been able to successfully test it somehow.

Should be sending some patches soon.

Regards,
Waldek

Nadav Har'El

unread,
May 9, 2022, 11:08:16 AM5/9/22
to Waldek Kozaczuk, OSv Development
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 osv-dev+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/osv-dev/8a1d87f7-4d50-44d7-872a-7a94bc453397n%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages