Могу ли я связать неразрешенные ссылки для отмены?
Я пытаюсь написать небольшие тесты для довольно небольшой части довольно большого проекта. К сожалению, попытка связать этого зверя довольно сложно без объединения всего проекта, который я не хочу делать (это довольно сложная система для поиска всех зависимостей и т.д., И я не могу вмешиваться в нее).
Теперь я точно знаю, что функции, на которые ссылающиеся функции не будут вызываться во время моего теста, просто являются частью функций, которые делят файл с материалами, которые я тестирую.
Можно ли просто связать эти нерешенные ссылки, допустим, отменить или что-то еще? Или есть инструмент, который создает соответствующий файл-заглушку, где все вызовы приводят к отмене, учитывая набор файлов объектов, которые у меня есть?
Я использую gcc (g++) для компиляции/компоновки, версия 3.4.4. Платформа - unix (solaris/sparc, если это важно).
Ответы
Ответ 1
Вы можете просто сказать компоновщику, чтобы игнорировать неразрешенные символы. Я не мог найти вариант, который связывает их с abort
или что-то в этом роде.
Политика игнорирования неразрешенных символов в объектных файлах является наиболее естественной, я полагаю:
gcc -Wl,--unresolved-symbols=ignore-in-object-files obj.o another.o etc.o
Другие варианты включают (цитирование man ld
):
--unresolved-symbols=method
Determine how to handle unresolved symbols. There are four possi-
ble values for method:
ignore-all
Do not report any unresolved symbols.
report-all
Report all unresolved symbols. This is the default.
ignore-in-object-files
Report unresolved symbols that are contained in shared
libraries, but ignore them if they come from regular object
files.
ignore-in-shared-libs
Report unresolved symbols that come from regular object files,
but ignore them if they come from shared libraries. This can
be useful when creating a dynamic binary and it is known that
all the shared libraries that it should be referencing are
included on the linker command line.
The behaviour for shared libraries on their own can also be con-
trolled by the --[no-]allow-shlib-undefined option.
Normally the linker will generate an error message for each
reported unresolved symbol but the option --warn-unresolved-sym-
bols can change this to a warning.
В моей системе Linux попытки вызвать нерешенную функцию приводят к "Ошибка сегментации".
Ответ 2
Ну, один из способов, которым я могу думать, - сначала скомпилировать файлы .o для вашей библиотеки.
Затем используйте инструмент, например nm
(обычный в системах * nix), чтобы получить все символы, в nm
все "внешние" (такие же, которые не найдены в этом .o) имеют тип U (он может отличаться для версий, отличных от GNU nm
, см. вашу документацию).
Если ваша библиотека является всего одним исходным файлом, то она проста, почти все символы типа U будут либо функцией, найденной в другой библиотеке, либо не будут решены во время ссылки. Это немного сложнее, если ваша библиотека будет более чем одним исходным файлом, так как у вас будут зависимости между исходными файлами.
Итак, теперь у вас есть средство для создания потенциального списка нерешенных внешних, тогда вы можете создать "test_stub.c", который имеет символы заглушки для каждого из них, которые вы могли бы заполнить примерно так:
void some_func() { abort(); }
где some_func
является a, будет нерешенным внешним. Компилируйте и свяжите это со своей библиотекой, и все вызовы должны привести к прерыванию.
Ответ 3
Попытка скомпилировать следующую программу
#include <iostream>
extern int bar();
int foo()
{
return bar() + 3;
}
int main()
{
std::cout << "Hello, world!" << std::endl;
// std::cout << foo() << std::endl;
return 0;
}
приводит к
$ g++ -o main main.cc
/tmp/ccyvuYPK.o: In function `foo()':
main.cc:(.text+0x5): undefined reference to `bar()'
collect2: ld returned 1 exit status
Но мы можем сказать, что компоновщик игнорирует неразрешенные символы и запускает его просто отлично:
$ g++ -Wl,--unresolved-symbols=ignore-all -o main main.cc
$ ./main
Hello, world!
Скажите, что какая-то нерешенная функция вызывается вашей тестовой жгутой (имитируйте это, раскомментировав вызов foo
), она будет компилироваться и правильно связываться, но при выполнении программы вы получите segfault. Обязательно ulimit -c unlimited
, чтобы получить core
.
Ответ 4
Попробуйте атрибут GCC alias
:
/* cannot directly alias to yet undefined symbols,
* so need an intermediate function.
*/
static void do_abort() { abort(); }
void func0() __attribute__ ((weak, alias ("do_abort")));
void func1() __attribute__ ((weak, alias ("do_abort")));
...