LINUX.ORG.RU

как перехватить подключение библиотеки?


0

1

По мотивам предыдущего топика.

Ядролорды, посоветуйте, как можно перехватить и обработать запрос на поиск библиотеки?

Финальная цель в том, чтобы отменить стандартный механизм поиска библиотеки. Например, если a.out -> my.so -> my2.so, хочется, чтобы для каждого элемента в цепочке использовались разные правила.

В ведре не шарю, поэтому если поточнее назовете место в исходниках, которое нужно распотрошить, это отлично ^_^.

Может, уже есть готовые утилиты для этого?

tailgunner, Eddy_Em, котятки, стоит ли сгореть в аду?

★★★★☆

стоит ли сгореть в аду?

Да. Хотя то, что ты хочешь, технически возможно через подмену ld-linux.so.

tailgunner ★★★★★
()
Ответ на: комментарий от Legioner

Хотя фигню написал, это если программа сама будет грузить библиотеку, а не загрузчик.

Legioner ★★★★★
()

это же не ядро делает. Если это linux, то man ld-linux и если не получится уложиться в стандартный функционал ld.so, то вероятно придётся писать свой лоадер и подменять его для elf бинаря.

mashina ★★★★★
()
Ответ на: комментарий от mashina

и если не получится уложиться в стандартный функционал ld.so

мне нужно бинарный пакетный менеджер, в котором можно было бы указывать зависимости сразу от нескольких версий библиотеки одновременно. Т.е. нужно чтобы если a.out юзает x.so.1, my1.so юзает x.so.2, my2.so юзает x.so.3, то цепочка a.out->my1.so->my2.so должна жить и здравствовать, несмотря на то, что они юзают три несовместимые версии одного и того же. Если я поправлю ld-linux, чтобы он не просто подключал либу, а проверял имя-путь-пакет того, кто просит подключение, это возможно, это взлетит?

stevejobs ★★★★☆
() автор топика
Последнее исправление: stevejobs (всего исправлений: 1)

Зонд какой-то. Гори.

Лучше уж попробуй LD_PRELOAD какой-нибудь, раз так хочется. Ну, а если собираешься libc курочить — я не советник.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от stevejobs

Хром как-то слинкован по зависимостям не с lib.so а сразу с lib.1.so. Кури маны к линкеру, например.

anonymous
()

Я не согласен насчёт идеи гореть в аду.

Фича полезная. Должна быть реализована через подмену ld-linux.so, по идее.

Если надумаешь пилить, может я тоже помогу.

geekless ★★
()
Ответ на: комментарий от stevejobs

Т.е. нужно чтобы если a.out юзает x.so.1, my1.so юзает x.so.2, my2.so юзает x.so.3, то цепочка a.out->my1.so->my2.so

Хм, знаешь, а вот за это можно уже и гореть в аду. разные версии одной библиотеки в одном адресном пространстве — это даже не грабли, это умело поставленный капкан.

geekless ★★
()
Ответ на: комментарий от stevejobs

a.out юзает x.so.1, my1.so юзает x.so.2, my2.so юзает x.so.3, то цепочка a.out->my1.so->my2.so должна жить и здравствовать

~$ cat 1.c 2.c 3.c 4.c
int main() {
	printf( "%d\n", foo() );
	printf( "%d\n", a() );
	printf( "%d\n", b() );
}

int a() {
	return foo();
}
int b() {
	return foo();
}
int foo() {
	return D;
}

~$ gcc 4.c -shared -o foo.so.1 -DD=1 -Wl,-soname,foo.so.1 -Wl,--default-symver
~$ gcc 4.c -shared -o foo.so.2 -DD=2 -Wl,-soname,foo.so.2 -Wl,--default-symver
~$ gcc 4.c -shared -o foo.so.3 -DD=3 -Wl,-soname,foo.so.3 -Wl,--default-symver
~$ gcc 2.c -shared -fPIC -o 1.so foo.so.2
~$ gcc 3.c -shared -fPIC -o 2.so foo.so.3
~$ gcc 1.c 1.so 2.so foo.so.1 -Wl,-rpath,/home/igor
~$ ./a.out 
1
2
3

если я правильно понял задачу

wota ★★
()
Ответ на: комментарий от wota

а теперь без gcc! :) участники всё те же самые, но они уже собраны, в расчете на одну и ту же либу. Нужно им каким-то образом подсунуть несколько разных версий этой либы.

stevejobs ★★★★☆
() автор топика
Ответ на: комментарий от wota

а в чем разница? Я правда не шарю во всей этой нативщине :) Плюс оно может быть собрано как ты показал, а может ведь и dlopen. Хорошо бы, чтобы оно работало во всех случаях (или несколько способов под разные случаи), чтобы таким макаром можно было использовать готовые бинарные сборки, типа репозиториев дебиана.

stevejobs ★★★★☆
() автор топика
Ответ на: комментарий от stevejobs

а в чем разница?

http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html

Хорошо бы, чтобы оно работало во всех случаях

dlopen можно переопределить, и с ним как раз все легко, в том числе с разруливанием символов, а вот разрулить одинаковые символы без версионинга из x.so.1, x.so.2, x.so.3 задача как минимум не тривиальная, а в общем случае - скорее всего нерешабельная без своего динамического линкера

wota ★★
()
Ответ на: комментарий от stevejobs

простите за многословность, но для dlopen все просто:

./run.sh 
#!/bin/bash

cat run.sh
echo "***dlopen.c***"
cat dlopen.c
echo "***lib1.c, lib2.c***"
cat lib1.c lib2.c
echo "***main.c***"
cat main.c
echo "***test.c***"
cat test.c

gcc -fPIC -shared -Wl,-soname,dlopen.so -o dlopen.so dlopen.c

gcc -fPIC -shared -Wl,-soname,test.so -o test.so test.c
gcc -fPIC -shared -o lib1.so lib1.c
gcc -fPIC -shared -o lib2.so lib2.c
gcc main.c -o main -ldl

export LD_PRELOAD=$(pwd)/dlopen.so
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:.
echo "***./main***"
./main

***dlopen.c***
#define _GNU_SOURCE
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>

#include <execinfo.h>
#include <stdlib.h>
#include <unistd.h>

int test(void)
{
  int res=1;
  int j, nptrs;
#define SIZE 3
  void *buffer[SIZE];
  char **strings;

  nptrs = backtrace(buffer, SIZE);
  //printf("backtrace() returned %d addresses\n", nptrs);

  strings = backtrace_symbols(buffer, nptrs);
  if (strings == NULL) {
    perror("backtrace_symbols");
    exit(EXIT_FAILURE);
  }

  //for (j = 0; j < nptrs; j++)
  //  printf("%s\n", strings[j]);
  if(nptrs==3)
    res=memcmp("test.so",strings[2],7);

  free(strings);
  return res;
}

static void* (*real_dlopen)(const char *filename, int flag) = 0;
void *dlopen(const char *filename, int flag)
{
  if(!real_dlopen) real_dlopen = dlsym(RTLD_NEXT, "dlopen");
  printf("dlopen(%s,%i)\n",filename,flag);
  if(test()==0)
    return real_dlopen("lib2.so", flag);
  else
    return real_dlopen(filename, flag);
}
***lib1.c, lib2.c***
#include <stdio.h>

void fun()
{
  printf("fun from lib1.so\n");
}
#include <stdio.h>

void fun()
{
  printf("fun from lib2.so\n");
}
***main.c***
#include <dlfcn.h>
#include <stdio.h>

typedef void (*tfun)();
void test_fun()
{
  void* lib = dlopen("lib1.so", RTLD_LAZY);
  if(lib)
  {
    tfun fun = (tfun)dlsym(lib,"fun");
    if(fun) fun();
  }
}
void call_lib()
{
  void* lib = dlopen("test.so", RTLD_LAZY);
  if(lib)
  {
    tfun fun = (tfun)dlsym(lib,"fun");
    if(fun)
      fun();
  }
}
int main()
{
  test_fun();
  call_lib();

  return 0;
}
***test.c***
#include <dlfcn.h>
#include <stdio.h>

typedef void (*tfun)();
void fun()
{
  void* lib = dlopen("lib1.so", RTLD_LAZY);
  if(lib)
  {
    tfun fun = (tfun)dlsym(lib,"fun");
    if(fun) fun();
  }
}
***./main***
dlopen(lib1.so,1)
fun from lib1.so
dlopen(test.so,1)
dlopen(lib1.so,1)
fun from lib2.so

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.