9 Haziran 2017 Cuma

dlsym metodu

Giriş
dlsym ile bir metodu ismen bulmak mümkün. Çağrının döndürdüğü sonuç bir function pointer'a atanarak metod çağrısı yapılor. Yani çağrılmak istenen metodun imzasını bilmek gerekir.

C++ Uygulaması
Eğer C++ uygulaması ise isimler mangled olacağı için nm ile ismi bulmak gerekir. Şöyle yaparız.
void* ptr = dlsym(handle, "mangled_name_you_got_from_nm");
Şöyle yaparız.
auto ptr = reinterpret_cast<int(*)(int)>(dlsym(handle, "mangled_name"));
C Uygulaması 
Örnek
Elimizdeki C .so dosyasında var isimli değişken olsun. libhello.c
int var;
int func() {
    return 7;
}
libhello.h
extern int var;
int func();
Şöyle yaparız.
#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>
#include <dlfcn.h>
#include "libhello.h"

int main() {
  void* h = dlopen("libhello.so", RTLD_NOW);
  uintptr_t&var  =  (uintptr_t)dlsym(h, "var" );
  uintptr_t&func =  (uintptr_t)dlsym(h, "func");
}
Örnek
Şöyle yaparız. Çağrı sonucu f function pointer'ına atanıyor.
#define _GNU_SOURCE     /* for RTLD_NEXT */
#include <dlfcn.h>
/* ... */
void f (*exit_addr)(int) = dlsym(RTLD_NEXT, "exit");

Hata Kontrolü
Örnek
dlerror() ile yapılabilir. Şöyle yaparız.
typedef int (*add_func_ptr)(int);

void *handle;

char *error;

handle = dlopen("./add.so", RTLD_LAZY);
if (!handle)
{
  fputs(dlerror(), stderr);
  exit(1);
}

add_func_ptr addfun;
addfun = (add_func_ptr)dlsym(handle, "add");
if ((error = dlerror()) != NULL)
{
  fputs(error, stderr);
  exit(1);
}

printf("%d\n", (*addfun)(2));
dlclose(handle);

RTLD_NEXT ve RDLD_MAIN_ONLY ne anlama gelir
dlsym metodları ararken zaten yüklü bir metodu bul veya tüm .so kütüphanelerini ara seçeneği ile kullanılabilir.
RTLD_MAIN_ONLY
Örnek'te ana uygulama içindeki main_greeting() metodu zaten yüklü. dlsym RTLD_MAIN_ONLY seçeneği ile kullanılarak .so dosyalarını aramadan main_greeting() metodunu veriyor.
#include <dlfcn.h>
#include <stdio.h>

void main_greeting(void)
{
    printf("%s\n", "hello world");
}

void lib_func(void)
{
    void (*greeting)(void) = dlsym(RTLD_MAIN_ONLY, "main_greeting");

    greeting ? greeting() : printf("%s\n", dlerror());
}

int main(void)
{
    lib_func();

    return 0;
}

RTLD_NEXT
Örnek'te cos metodu ismi ile bulunuyor ve bir function pointer'a atanıyor.
#include <stdlib.h>
    #include <stdio.h>
    #include <dlfcn.h>

    int main(int argc, char **argv) {
        void *handle;
        double (*cosine)(double);
        char *error;

        handle = dlopen ("/lib/libm.so.6", RTLD_LAZY);
        if (!handle) {
            fputs (dlerror(), stderr);
            exit(1);
        }

        cosine = dlsym(handle, "cos");
        if ((error = dlerror()) != NULL)  {
            fputs(error, stderr);
            exit(1);
        }

        printf ("%f\n", (*cosine)(2.0));
        dlclose(handle);
    }

Hiç yorum yok:

Yorum Gönder