LINUX.ORG.RU

Вопрос по линкеру


0

0

Добрый день!

Помогите, пожалуйста, решить срочную задачу связанную с линковкой под linux!

Задача: в программе используются функции стандартных библиотек, например, socket(), bind() и т.д. из libc. В отладочных целях необходимо подменить их на свои, при этом очень желательно не менять сам исходник, а сделать это на уровне линковки. Добавляю в проект свой исходник, в котором заимплементированы уже мои версии socket(), bind() и т.д. Но линковщик все равно использует функции из libc, а libc отключать нельзя т.к. из нее используется еще много чего, как быть?


Ответ на: комментарий от Zenom

У меня на linux-е опыта еще нет поэтому таких хитростей не знаю :)

Насколько я почитал про LD_PRELOAD, в моем случае нужно мои переопределенные функции поместить в .so библиотеку, а при запуске программы в LD_PRELOAD указать путь к ней, так? Тогда функции будут вызываться из нее? Тут дело осложняется тем что проект собирается с помощью autotools, и нужно чтобы билд конфигурировался через него. А тут получается что перед запуском нужно обновлять переменные окружения :( У линковщика ld нет каких-нибудь приоритетов при разрешении имен функций, т.е. чтобы первым делом имена функции он искал в одной библиотеке, потом в другой и т.д.

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

>А тут получается что перед запуском нужно обновлять переменные окружения
не нужно.
просто запускай так:
LD_PRELOAD=log_syscalls.so ./my_application

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

немного каламбурное утверждение)
в build-time тоже будет подключаться всё, что в LD_PRELOAD указано, но только в build-time требуемые функции (socket, bind, etc) не вызываются.

Автору топика настоятельно советую понять разницу между временем компиляции и временем исполнения, равно как и разницу между самими этими процессами

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

Разницу между компиляцией и выполнением программы я понимаю, надеюсь что и у вас проблем с пониманием нет.

Возможно я немного сумбурно изложил суть проблемы из-за этого начался стеб. Попробую еще раз объяснить.

Необходимо так сконфигурировать билд, чтобы при запуске собранной программы не требовалось ничего дополнительно делать (т.е. дописывать LD_PRELOAD и т.д.). Было бы так же хорошо чтобы не было дополнительной .so библиотеки с моими функциями, а чтобы эти функции статически прилинковались в проект, возможно такое сделать?

Logger
() автор топика
Ответ на: комментарий от JackYF

>Ну сделай скрипт запуска, делов-то.
Что, иначе нельзя?

anonymous
()
Ответ на: комментарий от JackYF

Дело в том что для проведения юнит тестов используется специальный фреймворк - check, он сам компилирует проект и запускает тесты, поэтому свободы действий при запуске программы у меня нет :(

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

>Дело в том что для проведения юнит тестов используется специальный фреймворк - check, он сам компилирует проект и запускает тесты, поэтому свободы действий при запуске программы у меня нет :(

Ну допиши в компиляцию проекта:

Было: /usr/bin/myprogram
Стало: /usr/lib/myprogram/start, /usr/lib/myprogram/libc_replaces.so, /usr/bin/myprogram = '#!/bin/sh LD_PRELOAD=/usr/bin/myprogram/libc_replaces.so /usr/lib/myprogram/start'.

А check пусть до посинения дёргает всю ту же /usr/bin/myprogram.

JackYF ★★★★
()

Попробуй при линковке явно указывать в списке libc, и помести его в списке после своих библиотек

runtime ★★★★
()

1. Наиболее разумный вариант заключается в использовании ключа -wrap
у ld (info ld). Он специально предназначен для подобных целей.
Например, если желательно подменить free, то используем
(пусть tmp2.c):
void __wrap_free(char *abc)
{
// что-то еще
__real_free(abc); // вызов нормального free
// что-то еще
}
При компиляции и сборке можно использовать что-то типа:
gcc -o tmp tmp.c tmp2.c -Wl,-wrap,free
В этом случае имеющиеся уже в shared-библиотеках разрешенные имена
подменяться уже не будут. __real_free будет ссылаться на родной.
2. Альтернативно можно использовать ключ -r для ld
и --redefine-sym <old>=<new> для objcopy.
Стратегия следующая:
ld -r собираем все кроме стандартных библиотек
objcopy используем чтобы заменить стандартные имена на фуфло
(дабы не конфликтовало), далее добираем остаточки gcc
Второй способ (objcopy) даже позволяет превратить однозадачную
библиотеку в n-задачную (если источников нет, а хочется).

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

io, огромное вам спасибо!!! Первый способ с -wrap это именно то что мне нужно! Сделал сейчас на коленке простой пример все работает как надо, завтра попробую в проект заимплементировать.

Второй способ не очень понял, если не трудно, расскажите поподробнее или примерчик использования небольшой.

Еще раз спасибо! :)

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

Берем предыдущий пример. Собираем все кроме tmp2 (где вместо
real_free прямо пишем free) в один общий файл:
gcc -c tmp.o tmp.c
ld -r all.o tmp.o ..... (остальные файлы проекта)

Делаем переименование и сборку.
objcopy --redefine-sym free=__wrap_free all.o all_wrap.o
gcc -o final all_wrap.o tmp2.o

Необходимо только в любо случае учитывать что внутренние вызовы
разделяемой библиотеки мы не перехватываем.
Если препрет, то надо использовать статические.

Для превращения однозадачной (например использующей общие
глобальные символы) библиотеки все аналогично, просто вылавливаем все глобальные символы и дублируем нужное число раз. Например,
из open_our_library_once делаем open_our_library_once_number7
и делаем десяток экземпляров библиотеки. Каждая нить вызывает свой
экземпляр через массив ссылок.

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

Спасибо, более-менее понятно, но в моем случае идеально подошел первый вариант :)

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

>чтобы эти функции статически прилинковались в проект
подключать статическую библиотеку)
ваш Кэп))

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