Я пытаюсь записать некоторые маленькие тесты для довольно небольшой части довольно крупного проекта. Попытка связать этого зверя, к сожалению, довольно невозможна, не соединяя весь проект, который я не хочу делать (это - довольно сложная система для нахождения всех зависимостей и материала, и я предпочитаю не влезать в него).
Теперь, я знаю наверняка, что функции, что функции, на которые ссылаются, не будут вызваны во время моего теста, справедливое, оказывается, часть функций, которые совместно используют файл с материалом, который я действительно тестирую.
Там какой-либо путь состоит в том, чтобы просто связать эти некорректные ссылки с, скажем, прерваться, или что-то? Или существует ли инструмент, который создает соответствующий тупиковый объектный файл, где все вызовы приводят к аварийному прекращению работы, учитывая набор объектных файлов, которые я имею?
Я использую gcc (g ++) для компиляции/соединения, версии 3.4.4. Платформа является Unix (solaris/sparc, если это важно).
Вы можете просто сказать компоновщику игнорировать неразрешенные символы. Я не смог найти опцию, которая связывала бы их с 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's 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 системе попытки вызова неразрешённой функции приводят к "Ошибке сегментации".
.Попытка скомпилировать следующую программу
#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!
Скажем, какая-нибудь неразрешённая функция is, вызываемая вашим жгутом тестирования (смоделируйте это, не комментируя вызов foo
), она скомпилирует и свяжет, но при выполнении программы вы получите segfault. Убедитесь, что ulimit -c unlimited
, так что вы получите core
.
] Попробуйте GCC [] псевдоним [
] атрибут: [
/* 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")));
...
] Я могу придумать один из способов - сначала скомпилировать файлы .o для вашей библиотеки.
Затем используйте инструмент вроде nm
(общий в системах * nix), чтобы получить все символы в nm
, все «внешние» (также известные как те, которые не встречаются в этот .o) имеют тип U (он может отличаться для версий nm
, отличных от GNU, см. вашу документацию).
Если ваша библиотека представляет собой один исходный файл, то это просто, почти все символы типа U будут либо функцией, найденной в другой библиотеке, либо будут не разрешены во время компоновки. Это немного сложнее, если ваша библиотека будет состоять из нескольких исходных файлов, поскольку у вас будут зависимости между исходными файлами.
Итак, теперь у вас есть средство для создания потенциального списка неразрешенных внешних элементов, затем вы можете создать «test_stub.c», в котором есть символы-заглушки для каждого из них, которые вы можете заполнить примерно таким:
void some_func() { abort(); }
где some_func
является неразрешенным внешним. Скомпилируйте и свяжите это с вашей библиотекой, и все вызовы должны привести к прерыванию.