Override function call in C from the same compilation unit

I am trying to Override a function call in C , but I ran into a problem when a function is used in the same compilation unit. In the code below, I am trying to replace the get_resolution () function, but I can only achieve it if it is done in test.c, but not from display.c

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

#include <stdio.h>

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

void display()
{
    get_resolution();
}

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

#include <stdio.h>

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

My requirement is that when I call display () from main (), I want __wrap_get_resolution () to be executed, but I always see that the original get_resolution () is being called. A little analysis of dis-assembly shows that the get_resolution function is called differently:

In display () -> get_resolution () address is already resolved

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

In main () -> get_resolution addresses have not been resolved yet

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_resolution(), (), , get_resolution() ?

:

  • hroptatyr void get_resolution() __attribute__((weak)); mingw-gcc, QNX/ARM/gcc (4.4.2)
  • , hook, , - ARM.
+5
6

:

void __wrap_get_resolution()
{
    /* calling the real one here */
    get_resolution();
}

#define get_resolution   __wrap_get_resolution

int main()
{
    /* the __wrap... gets called */
    get_resolution();
    ...
}

, "" , , .

, , :

int main()
{
    void(*get_resolution)() = __wrap_get_resolution;
    get_resolution();
    ...
}

, .

Edit
, , display.c , weak , http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

ELF, a.out GNU.

/* in display.c */
void __real_get_resolution()
{
    ...
}
void get_resolution() __attribute__((weak, alias("__real_get_resolution")));

/* in test.c */
void get_resolution()
{
    /* this version will take precedence over get_resolution() in display.c */
    ...
    /* lastly call the real thing */
    __real_get_resolution();
}

, get_resolution() ( "" ), .

+5

: C

, user (unser linux) LD_PRELOAD.

.

.

0

, :

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

0

, ; GNU as ( ). , !

, get_resolution undefined display.c. 2 , get_resolution . , #ifdef .

0

, , . this .

++, , . , , ASLR linux . , , , .

0

'wrap', gcc, , . , get_resolution, , , ( ).

, , display.c( , ). get_resolution C, display.c.

0
source

All Articles