Snaipe / Mimick

A KISS, cross-platform C mocking library
MIT License
152 stars 43 forks source link

function pointer - runtime substitution with mmk_stub #21

Closed CallistorrB closed 1 year ago

CallistorrB commented 3 years ago

Hello,

I'm trying to accomplish function pointer - runtime substitution with the following code snippet found on stackoverflow but I am getting the following error when trying to run this code snippet. I only want to choose which function pointer is active at the moment, is this possible with Mimick? If not is there any way I can accomplish function pointer run time substitution (ie choosing which function will be run).

#include <stdlib.h>
#include <assert.h>
#include <mimick.h>

static int my_square(int x) { return x + 1; }

int main(void) {
    mmk_stub("square@lib:foo", my_square);

    assert(myfunction(0, 0) == 2);

    mmk_reset(square);
}
CallistorrB commented 3 years ago

Error message from compiler:

.c.obj -c ../sample/strdup/test.c
../sample/strdup/test.c:59:14: error: expected identifier or '('
    mmk_stub("square@lib:foo", my_square);
CallistorrB commented 3 years ago

This example has been compiled with MSVC. After some hacking in the samples provided by Mimick I made a example because it still does not work correctly. When running the executable I get: ASCII value = 1 instead of TEST value = 1. After debugging Mimick I found out that the following file stub.c returns -ENOENT when getting plt_get_offsets. Is there any idea why the function create_trampoline is not called?

/* stub.c */
 size_t nb_off = 0;
 plt_offset *off = plt_get_offsets(pctx, lib, name, &nb_off);
 if (!off || !nb_off)
    return -ENOENT;
/* test.c */
#include <mimick.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include "random_minute_generator.h"

void RandomMinuteGenerator_Get_FAKE(void)
{ 
    printf("TEST value = %d", 1 );
}

int main(void)
{
    mmk_stub_create("RandomMinuteGenerator_Get@lib:random_number_generator", RandomMinuteGenerator_Get_FAKE, NULL);
    mmk_reset(RandomMinuteGenerator_Get);
    return 0;
}
/* random_minute_generator.h */
#ifndef RANDOMMINUTEGENERATOR_H_
# define RANDOMMINUTEGENERATOR_H_

# ifdef _MSC_VER
#  ifdef DLL_EXPORT
#   define API __declspec(dllexport)
#  else
#   define API __declspec(dllimport)
#  endif
# else
#  define API
# endif

API void RandomMinuteGenerator_Get(void);

#endif /* !RANDOMMINUTEGENERATOR_H_ */
/* random_minute_generator.c */
#define DLL_EXPORT 1
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "random_minute_generator.h"

void RandomMinuteGenerator_Get(void)
{ 
    printf("ASCII value = %d", 1 );
}
CallistoM commented 1 year ago

For future reference for other users; stubbing a function:

    mmk_stub m = mmk_stub_create("RandomMinuteGenerator_Get@self", RandomMinuteGenerator_Get_FAKE, NULL);
    RandomMinuteGenerator_Get(); <-- call to stubbed function
    mmk_stub_destroy(m);
    RandomMinuteGenerator_Get(); <-- call to existing function