Как я могу сделать псевдоним на внешней определенной функции в C?

Во время компиляции этого кода C

extern void Default_Handler(void);
void NMI_Handler(void) __attribute__ ((weak, alias ("Default_Handler")));

Я получил это

error: 'NMI_Handler' aliased to undefined symbol 'Default_Handler'

Как я могу сделать псевдоним на внешней определенной функции?

Составитель:

gcc version 7.2.1 20170904 (release) [ARM/embedded-7-branch revision 255204] (GNU Tools for Arm Embedded Processors 7-2017-q4-major)

4 ответа

Чтобы создать псевдоним внешней функции, вы можете использовать objcopy. Вот пример:

Скажем, у меня есть определение функции и я присвоил ему псевдоним, как в следующей программе (называемой myimp.c):

// myimp.c
int
myadd(int x, int y)
{
    return x+y;
}

int
coolguy (int x, int y) __attribute__((alias("myadd")));

Если мы скомпилируем это (но не будем связывать), мы получим объектный файл и сможем проверить его символы:

# compile
$ cc -c myimp.c
# look at the symbols
$ nm myimp.o
0000000000000000 T coolguy
0000000000000000 T myadd

Итак, мы видим, что __attribute__((alias("myadd")) просто добавляет символ coolguy с тем же значением 0000000000000000, что и myadd. Если вы посмотрите вman страница для нм, будет сказано, что T означает, что это глобальный символ в .textраздел. Это имеет смысл, потому что функция неstatic и содержит инструкции (в отличие от данных).

Итак, если у нас есть объектный файл, но нет источника, и мы хотим добавить псевдоним функции, мы можем сделать это, используя objcopy --add-symbol.

Скажем, у нас есть объектный файл, полученный в результате компиляции этого исходного кода:

// myimp2.c
int
myadd(int x, int y)
{
    return x+y;
}

Компилируя, как указано выше, мы получим myimp2.o, чьи инструменты таблицы символов такие:

# look at the symbols
$ nm myimp2.o
0000000000000000 T myadd

Итак, мы хотим добавить coolguy символ, который мы делаем следующим образом

# objcopy --add-symbol coolguy=.text:0000000000000000,global myimp2.o myimp2_augmented.o

Посмотрите документацию на --add-symbol в objcopy manстраница. В основном.text указывает раздел, после двоеточия значение, а затем global Я обнаружил, передав плохой тип и objcopy не удалось и сообщил мне список допустимых типов, из которых я выбрал global.

Попробуйте бежать nm на myimp2_augmented.o, вы увидите, что мы добавили символ.

Теперь у вас должна быть возможность установить связь с myimp2_augmented.o вместо того myimp.o и ваша программа может вызывать coolguy без ошибок связывания.

Как предлагается здесь, добавьте в командный файл компоновщика следующее:

PROVIDE(NMI_Handler = Default_Handler);

(И удалите объявление слабого псевдонима из кода C.)

Здесь NMI_Handler имеет слабый атрибут определения, что означает, что если NMI_Handler не определен, то определение Default_Handler будет использоваться для NMI_Handler. как правило, для прерываний, таких как NMI_Handler или Default_Handler, доступно строгое определение. Вам может понадобиться добавить этот файл в свою компиляцию для удаления ошибки. Если вы хотите обрабатывать NMI_Handler по-своему, тогда вы можете определить его где-нибудь, и это определение будет включено вместо слабого.

Для сотрудников очень популярны атрибуты weak и alias для реализации механизма переопределения для собственного проекта C, особенно в случае проектов прошивки.

И декларацию, и определение можно отметить __attribute__((weak)) и его правила приоритета связывания связаны с тем, существует ли какое-либо объявление в файле заголовка.

Было бы неплохо просто закодировать и скомпилировать его. Затем посмотрите, что произойдет при создании ссылки, поищите ее определение. Я обычно проверяю символы по -Wl,-trace,-trace-symbol=ANY_FUNCTION_NAME_YOU_WANT и nm OBJECT_FILE_NAME.

Обычно я просто создаю определение функции слабого атрибута и позволяю другим объектам переопределять его. Пример показан ниже:

In C file:

      //non-exported weak attribute definition
__attribute__((weak)) void startup_handler_dummy(void) {
        printf("[%s][%s]Entry (NO OVERRIDE HANLDER COMES HERE)\n", __FILE__, __func__);
}

//weak and alias attribute declaration
void startup_handler_dummy_impl(void) __attribute__((weak, alias("startup_handler_dummy")));

//exported weak attribute definition
__attribute__((weak)) void startup_handler(void) {
    startup_handler_dummy_impl();
}

In header file:

      #ifndef _BOARD_H_
#define _BOARD_H_
#define STARTUP_HANDLER startup_handler //to export symbol
#endif

Надеюсь, мой код поможет :)

А более подробную информацию и скриншоты программы вы можете увидеть на MyGitHub.

Другие вопросы по тегам