Code Monkey home page Code Monkey logo

Comments (6)

Mr-JingShi avatar Mr-JingShi commented on August 18, 2024

Sorry,I thought I was wrong when I submit the issue, so I closed it,
but after debugging, I found that I was right, so I reopened it.

from plthook.

Mr-JingShi avatar Mr-JingShi commented on August 18, 2024

if (dlinfo(hndl, RTLD_DI_LINKMAP, &lmap) != 0) {

if (dladdr1(address, &info, (void**)&lmap, RTLD_DL_LINKMAP) == 0) {

if (dlinfo(hndl, RTLD_DI_LINKMAP, &lmap) != 0) {

We should hold the hndl (the return value of dlopen) until pltook_close.

Can you reply me?

from plthook.

kubo avatar kubo commented on August 18, 2024

lmap points to a node of a linked list maintained by the dynamic linker.
On the other hand, POSIX doesn't define actual type of a handle returned by dlopen.

I think ... lmap is equal to hndl,

It is correct on Linux. However it isn't on other platforms using ELF.
Linux glibc chooses to reuse lmap as a dlopen handle.

The following code prints same two addresses on Linux.

#include <stdio.h>
#include <string.h>
#include <link.h>
#include <dlfcn.h>

int main()
{
  struct link_map *lmap = _r_debug.r_map; // See link.h
  while (lmap != NULL) {
    if (strstr(lmap->l_name, "libc.so.6") != NULL) {
      printf("%p: link_map address of libc.so.6 searched from the global variable _r_debug\n", lmap);
    }
    lmap = lmap->l_next;
  }
  printf("%p: dlopen handle of libc.so.6\n", dlopen("libc.so.6", RTLD_LAZY));
}

so, if hndl is invalid after dlclose, lmap is invalid too.

No. lmap is valid until the dynamic library is unloaded from the process.

from plthook.

Mr-JingShi avatar Mr-JingShi commented on August 18, 2024

Thanks for talking with me

test.c

#include <stdio.h>
#include <string.h>
#include <link.h>
#include <dlfcn.h>

void test() {
  struct link_map *lmap = _r_debug.r_map; // See link.h
  while (lmap != NULL) {
    if (strstr(lmap->l_name, "libtest.so") != NULL) {
      printf("%p: link_map address of libtest.so searched from the global variable _r_debug\n", lmap);
    } else if (strstr(lmap->l_name, "libc.so.6") != NULL) {
      printf("%p: link_map address of libc.so.6 searched from the global variable _r_debug\n", lmap);
    }
    lmap = lmap->l_next;
  }
}

int main()
{
  printf("-------------------\n");
  test();
  printf("-------------------\n");

  void* handle = dlopen("libtest.so", RTLD_LAZY);
  if (handle != NULL) {
    printf("%p: dlopen handle of libtest.so\n", handle);
  }

  printf("-------------------\n");
  test();
  dlclose(handle);

  printf("-------------------\n");
  test();
  printf("-------------------\n");
  return 0;
}
gcc -o test test.c -ldl

ldd test
  linux-vdso.so.1 (0x00007ffe6d3fa000)
  libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f72cc1fa000)
  libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f72cbe09000)
  /lib64/ld-linux-x86-64.so.2 (0x00007f72cc600000)

./test
-------------------
0x7f18128ec4f0: link_map address of libc.so.6 searched from the global variable _r_debug
-------------------
0x55b015f49690: dlopen handle of libtest.so
-------------------
0x7f18128ec4f0: link_map address of libc.so.6 searched from the global variable _r_debug
0x55b015f49690: link_map address of libtest.so searched from the global variable _r_debug
-------------------
0x7f18128ec4f0: link_map address of libc.so.6 searched from the global variable _r_debug
-------------------

Sometimes dynamic libraries are used as plugins,
if dlopen is used without linking libtest.so (such as my test.c/test), it is not ok.
your's testprog is ok, because you have linked libtest.so.

from plthook.

kubo avatar kubo commented on August 18, 2024

In https://man7.org/linux/man-pages/man3/dlclose.3.html,

The function dlclose() decrements the reference count on the
dynamically loaded shared object referred to by handle.

If the object's reference count drops to zero and no symbols in
this object are required by other objects, then the object is
unloaded after first calling any destructors defined for the
object.

dlclose(hndl);

This code doesn't unload the shared library even when it is loaded by dlopen.

if dlopen is used without linking libtest.so (such as my test.c/test), it is not ok.

In this situation, the reference count of libtest.so increases to two at line 353
and decreases to one at line 374. The count doesn't drop to zero.

from plthook.

Mr-JingShi avatar Mr-JingShi commented on August 18, 2024

Thank you,I see

#include <stdio.h>
#include <string.h>
#include <link.h>
#include <dlfcn.h>

#include <plthook.h>

static double strtod_cdecl_hook_func(const char *str, char **endptr)
{
    printf("strtod_cdecl_hook_func\n");

    return 0;
}

int main()
{
  plthook_t* plthook = NULL;
  const char* filename = "libtest.so";
  plthook_open(&plthook, filename);

  unsigned int pos = 0;
  const char* name = NULL;
  void **addr = NULL;
  const char* funcname = "strtod_cdecl";
  unsigned int found = 0;
  while (plthook_enum(plthook, &pos, &name, &addr) == 0) {
    if (strcmp(funcname, name) == 0) {
        found = 1;
        break;
    }
  }
  if (0 != found)
  {
    plthook_replace(plthook, funcname, (void*)strtod_cdecl_hook_func, NULL);
  }

  plthook_close(plthook);

  // strtod_cdecl("3.7", NULL);

  return 0;
}
gcc -o test test.c ../plthook_elf.c -ldl

My previous idea was not to link libtest.so when compiling, such as above.
But i found i was wrong.
(1) I can not call strtod_cdecl whitout linking libtest.so, Unless I explicitly call the dlopen and dlsym.
(2) https://man7.org/linux/man-pages/man3/dlclose.3.html,
RTLD_NOLOAD (since glibc 2.2)
Don't load the shared object. This can be used to test if
the object is already resident (dlopen() returns NULL if
it is not, or the object's handle if it is resident).
This flag can also be used to promote the flags on a
shared object that is already loaded. For example, a
shared object that was previously loaded with RTLD_LOCAL
can be reopened with RTLD_NOLOAD | RTLD_GLOBAL.

void *hndl = dlopen(filename, RTLD_LAZY | RTLD_NOLOAD);

If I do not link libtest.so, Line 353 hndl is NULL.
(3) if i don't link libtest.so and don't call strtod_cdecl in main, strtod_cdecl doesn't appear in Dynamic Relocation Symbol Table.
It's not PLT than delayed binding.

I see, Thank you

from plthook.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.