Fwd: [libc] dlclose gives "invalid shared object handle" without pthread combination.

From: venki kaps <venkiece2005_at_gmail.com>
Date: Mon, 29 Jun 2009 13:03:17 +0530
Hi,

Ref:
http://www.mail-archive.com/svn-src-all_at_freebsd.org/msg10960.html

Log:
  Allow order of initialization of loaded shared objects to be
  altered through their .init code. This might happen if init
  vector calls dlopen on its own and that dlopen causes some not
  yet initialized object to be initialized earlier as part of that
  dlopened DAG.

  Do not reset module reference counts to zero on final fini vector
  run when process is exiting. Just add an additional parameter to
  force fini vector invocation regardless of current reference count
  value if object was not destructed yet. This allows dlclose called
  from fini vector to proceed normally instead of failing with handle
  validation error.

Query:
-------
I have one question regarding " Do not reset module reference counts
to zero on final fini vector
  run when process is exiting".

Observation:
---------------
The above issue normally happened when object is destructed and gives handle
 validation error.

I have expected this is related to dl_refcount issue when process is exiting.

Am just giving some more explanation regarding this issue:

When i tested in the my Linux environment it shows the
dl_reference count is 1 when dlopen and 0 when dlclose.
In this test when the main dlclose invokes, the reference count is decremented
to zero But still other dependent objects are present and for these objects
dl_reference count is required with one(1) to close the handle successfully.

As per dl* scenario, the
dl_reference count has to be incremented by one(1) for the main
object(main executable)
as well as other ELF dependencies object.

Now, I have invoked dl_reference count is incremented by one(1) for main object
handle in _rtld_map_object function which is called by _rtld().

rtld Changes:
---------------
_rtld():
/* Load the main program. */
Location: src/libexec/ld.elf_so/rtld.c:

  _rtld_objmain = _rtld_map_object(obj_name, fd, NULL);
 _rtld_map_object():

/ *
  * Map a shared object into memory.  The argument is a file descriptor,
  * which must be open on the object and positioned at its beginning.
  * The return value is a pointer to a newly-allocated Obj_Entry structure
  * for the shared object.  Returns NULL on failure.
  */

 --- a/src/libexec/ld.elf_so/map_object.c
+++ b/src/libexec/ld.elf_so/map_object.c

_at__at_ -181,6 +181,10 _at__at_ _rtld_map_object(const char *path, int f
        phdr = (Elf_Phdr *) ((caddr_t)ehdr + ehdr->e_phoff);
        phlimit = phdr + ehdr->e_phnum;
        nsegs = 0;

+
+         /*
+          * And it was opened directly If trying to open
+          * the link map for the main executable. So the dl_recount
+          * must be the main dlopen one.
+          */
+          ++obj->dl_refcount;
+
            while (phdr < phlimit) {
                switch (phdr->p_type) {
                case PT_INTERP:


After the above changes, [libc] dlclose does not give
"invalid shared object handle" with/without pthread combination
Since the dl_reference count is 2 instead of 1 for main object handle
and 1 instead of 0 for other dependent objects.

Could you give opinion about the above issue?


Thanks & Regards,
Venkappa

---------- Forwarded message ----------
From: venki kaps <venkiece2005_at_gmail.com>
Date: Fri, Jun 19, 2009 at 10:18 AM
Subject: [libc] dlclose gives "invalid shared object handle" without
pthread combination.
To: gnats-bugs_at_netbsd.org


Hi,

I am using the NetBSD implementation of rtld(src/libexec/ld.elf_so/)
for ARM/MIPS and  have been porting NetBSD source in the Linux
environment with our own
pthread library.

system environment:
Compiler: arm-linux-gcc-4.3.3
OS: Linux
Kernel: 2.6.29

I have C++ static constructor/destructor issue with my rtld.

Problem Report:
"ld.elf_so does not execute .init/.fini functions in order" and [libc]
dlclose gives
"invalid shared object handle" when called through the fini function of another
module.

The similar NetBSD/freeBSD issues are found from the following References:
[1] http://gnats.netbsd.org/37347
[2] http://updraft3.jp.freebsd.org/cgi/query-pr.cgi?pr=kern/42956

The above issues are already commited in NetBSD-5-0-RELEASE.

I have ported NetBSD-5-0-RELEASE rtld and tested Ref[1] provided
static constructor/destructor test and did not find any issues
with shared pthread combination but noticed [libc] dlclose gives
"invalid shared object handle" without pthread combination.

The static constructor/destructor test results:

It should be :
--------------

$ ./foobar
foo_ctor
bar_ctor
tar_ctor
main_ctor
dep1_ctor
dep2_ctor
dll_ctor
dll_dtor
dep2_dtor
dep1_dtor
main_dtor
tar_dtor
bar_dtor
foo_dtor

While currently I get:
----------------------

with pthreads:

$ ./foobar
foo_ctor
bar_ctor
tar_ctor
main_ctor
dep1_ctor
dep2_ctor
dll_ctor
dll_dtor
dep2_dtor
dep1_dtor
main_dtor
tar_dtor
bar_dtor
foo_dtor

without pthreads:

$ ./foobar
foo_ctor
bar_ctor
tar_ctor
main_ctor
dep1_ctor
dep2_ctor
dll_ctor
dll_dtor
dep2_dtor
dep1_dtor
main_dtor
tar_dtor
bar_dtor
foo_dtor
Invalid shared object handle 0xbdbed400

This gives a "invalid shared object handle" message
because the refcount field (obj->dl_refcount) for the handle is zero.

it never even calls dlerr() in dlcose
but __dlclose(void *handle) source sequence,

int
dlclose(void *handle)
{
      Obj_Entry *root = _rtld_dlcheck(handle);

      if (root == NULL)
              return -1;

      _rtld_debug.r_state = RT_DELETE;
      _rtld_debug_state();

      --root->dl_refcount;
      _rtld_unload_object(root, true);

      _rtld_debug.r_state = RT_CONSISTENT;
      _rtld_debug_state();

      return 0;
}

static Obj_Entry *
_rtld_dlcheck(void *handle)
{
      Obj_Entry *obj;

      for (obj = _rtld_objlist; obj != NULL; obj = obj->next)
              if (obj == (Obj_Entry *) handle)
                      break;
      xprintf("obj->dl_refcount is %d\n",obj->dl_refcount);
      if (obj == NULL || obj->dl_refcount == 0) {
              xwarnx("Invalid shared object handle %p", handle);
              return NULL;
      }
      return obj;
}

I have printed  xprintf("obj->dl_refcount is %d\n",obj->dl_refcount);
 obj->dl_refcount is getting zero(0).
So due to "obj->dl_refcount == 0"
the error "invalid shared object handle" is showing.

I have little bit confused about dlclose destructor
with/without pthreads.

I have some queries:
1) Is it required any changes apart from the NetBSD-5-0-RELEASE/{Ref[1],[2]}?
2) Are any changes required in thread-stub?
3) i do not know why this error is coming even though all the
  constructor/destructor sequences are completed.
4) is it rtld_exit/fini/static C++ destructor/dlcose sequence problem?
 (OR)
 is it crtstuff/exit/atexit/cxa_finalize/cxa_atexit sequence problem?

Could anyone provide any inputs to the my issue?

Thanks in advance.

Thanks & Regards,
Venkappa
Received on Mon Jun 29 2009 - 05:33:18 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:50 UTC