Переопределить вызов функции в C из той же единицы компиляции

Я пытаюсь переопределить вызов функции в C , но сталкиваюсь с проблемой, когда функция используется в той же единице компиляции. В приведенном ниже коде я пытаюсь заменить функцию get _разрешением (), но я могу добиться этого, только если это делается в test.c, а не в display.c

// display.c -------------------------------------------------------------

#include 

void get_resolution()
{
    printf("Original get_resolution\n");
}

void display()
{
    get_resolution();
}

// test.c ----------------------------------------------------------------

#include 

void __wrap_get_resolution()
{
    printf("Mock get_resolution\n");
    // __real_get_resolution(); // Should be possible to call original
}

int main()
{
    display();         // **ISSUE** Original get_resolution() is called
    get_resolution();  // __wrap_get_resolution() is called
    return 0;
}

// gcc -Wl,--wrap,get_resolution display.c test.c

. Мое требование состоит в том, что когда я вызываю display ()из main (), я хочу, чтобы __wrap _get _разрешение ()выполнялось, но я всегда вижу, что исходное разрешение получает _()вызывается. Небольшой анализ сборки dis -показывает, что функция get _разрешения называется по-другому:

На дисплее()-> Адрес получения _разрешения ()уже разрешен

00000000 <_get_resolution>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 ec 18                sub    $0x18,%esp
   6:   c7 04 24 00 00 00 00    movl   $0x0,(%esp)
   d:   e8 00 00 00 00          call   12 <_get_resolution+0x12>
  12:   c9                      leave  
  13:   c3                      ret    

00000014 <_display>:
  14:   55                      push   %ebp
  15:   89 e5                   mov    %esp,%ebp
  17:   83 ec 08                sub    $0x8,%esp
  1a:   e8 e1 ff ff ff          call   0 <_get_resolution>
  1f:   c9                      leave  
  20:   c3                      ret    
  21:   90                      nop
  22:   90                      nop
  23:   90                      nop

В основном()-> Адрес получения разрешения _еще не разрешен

00000000 <___wrap_get_resolution>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 ec 18                sub    $0x18,%esp
   6:   c7 04 24 00 00 00 00    movl   $0x0,(%esp)
   d:   e8 00 00 00 00          call   12 <___wrap_get_resolution+0x12>
  12:   c9                      leave  
  13:   c3                      ret    

00000014 <_main>:
  14:   55                      push   %ebp
  15:   89 e5                   mov    %esp,%ebp
  17:   83 e4 f0                and    $0xfffffff0,%esp
  1a:   e8 00 00 00 00          call   1f <_main+0xb>
  1f:   e8 00 00 00 00          call   24 <_main+0x10>
  24:   e8 00 00 00 00          call   29 <_main+0x15>
  29:   b8 00 00 00 00          mov    $0x0,%eax
  2e:   c9                      leave  
  2f:   c3                      ret    

Теперь вопрос в том, как запретить компилятору разрешать адрес get _разрешение (), используемый в функции display (), и вместо этого использовать таблицу перемещений, чтобы функция get _разрешение ()можно переопределить на этапе связывания?

РЕДАКТИРОВАТЬ:

  1. Судя по ответу hroptatyr, добавление void get_resolution() __attribute__((weak));решает проблему при использовании mingw -gcc, но не на моей целевой платформе QNX/ARM/gcc (4.4.2)
  2. Даже такой метод времени выполнения, как перехват функции, приемлем, если кто-то может указать на хорошую библиотеку с поддержкой цели ARM.

6
задан Community 23 May 2017 в 12:18
поделиться