调用覆盖函数库

时间:2013-01-28 18:33:10

标签: c++ c

我想使用个人“pthread_self”功能。我想重写“pthread_self()”,并在最后,调用真正的“pthread_self”。 在C / C ++中有可能吗?

示例:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>

pthread_t pthread_self(void)
{
  // Do something else.....
  // ...
  // And finally call to de real pthread_self():
  return ::pthread_self();  // This doesn't work
}

main()
{
    printf("\nThis is my main thread: %lu\n", pthread_self());
}

5 个答案:

答案 0 :(得分:0)

代码似乎是C89而没有main的返回类型。因此,我建议您删除函数::pthread_self()前面的pthread_self(void)运算符并重新编译。

也可以通过pthread_self()

之类的其他名称来呼叫您的pthread_self_2(void)

答案 1 :(得分:0)

是否允许使用虚拟变量(从未使用过载)重载pthread_self()

pthread_t pthread_self( bool )
{
    // Do something else.....
    // ...
    // And finally call to de real pthread_self():
    printf( "%s\n", __PRETTY_FUNCTION__ );
    return ::pthread_self();  // This doesn't work
}

int main()
{
    printf( "%s\n", __PRETTY_FUNCTION__ );
    pthread_self( false );
    printf( "%s\n", __PRETTY_FUNCTION__ );
}

产生

$ g++ test.cpp -lpthread

$ ./a.out
int main()
pthread_t pthread_self(bool)
int main()

$ 

另外两种方法可能是:

  • 编写一个函数my_pthread_self(),在任何地方使用它,让它调用真实pthread_self()

  • 有一个宏PTHREAD_SELF调用您的包装器,内部调用真实的pthread_self()

答案 2 :(得分:0)

以下是有点hacky但应该在C中工作。将以下内容放在标题中,您必须在之前包含或代替<pthread.h>(但从来没有之后 pthread.h):

pthread_t _pthread_self(void);

#define pthread_self _pthread_self

并在相应的.c文件中:

#include <pthread>
#include "wrapper.h"
#undef pthread_self    // undo the hack locally

pthread_t _pthread_self(void)
{
  // Do something else.....
  // ...
  // And finally call to the real pthread_self():
  return pthread_self();
}

现在,当您在某个其他文件中编写pthread_self而不是.c文件时,它会扩展到您的包装函数。在上面的.c文件中,由于这个hack没有完成,包装器内的调用将调用库函数。

答案 3 :(得分:0)

This应该给你一些想法。如果您控制可执行文件的链接,则不需要使用LD_PRELOAD。

答案 4 :(得分:0)

感谢大家。 主要基于@Carl Norum和@Arkadyi展示的这两个链接Intercepting Arbitrary Functions on...Tutorial: Function Interposition in Linux,我向您展示了一个可能的解决方案:

我有两个源文件和一个Makefile:

<强> mipthread_self.C

#include <stdio.h>
#include <pthread.h>

#if defined (__STDC__) || defined (__cplusplus) || defined (c__plusplus)

#if defined (__cplusplus) || defined (c__plusplus)
extern "C" {
#endif

pthread_t __real_pthread_self();

pthread_t __wrap_pthread_self(void)
{
   printf("This is mipthread_self %lu\n", __real_pthread_self());
   return __real_pthread_self();
}

#if defined (__cplusplus) || defined (c__plusplus)
}
#endif

#endif

<强> TEST.C

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>


void* start_function(void* value)
{
    printf("Thread start function is running for: %u\n", (unsigned int)pthread_self());
    sleep(5);
    pthread_exit(value);
}

int main()
{
    int res;
    pthread_t thread1, thread2;
    void* threadReturnValue;

    res = pthread_create(&thread1, NULL, start_function, (void*)"thread-one");
    if (res != 0) {
        perror("Creation of thread failed");
        exit(EXIT_FAILURE);
    }
    printf("Thread1 created with id: %u\n", (unsigned int)thread1);

    res = pthread_create(&thread2, NULL, start_function, (void*)"thread-two");
    if (res != 0) {
        perror("Creation of thread failed");
        exit(EXIT_FAILURE);
    }
    printf("Thread2 created with id: %u\n", (unsigned int)thread2);

    res = pthread_join(thread1, &threadReturnValue);
    if (res != 0) {
        perror("Joining of thread failed");
        exit(EXIT_FAILURE);
    }
    printf("%s joined.\n", (char*)threadReturnValue);

    res = pthread_join(thread2, &threadReturnValue);
    if (res != 0) {
        perror("Joining of thread failed");
        exit(EXIT_FAILURE);
    }
    printf("%s joined.\n", (char*)threadReturnValue);

    return 0;
}

Makefile

BIN=test

CFLAGS=-g -m32 -fPIC -Wall $(DEFINES)
TIPO=-m32

PWD=`pwd`
DIR_OBJ=$(PWD)
DIR_BIN=$(DIR_OBJ)

INCLUDES=
LD_LIBRARIES=-L$(DIR_OBJ) -lmipthread -Xlinker --wrap -Xlinker pthread_self -lpthread -lstdc++


$(BIN): libmipthread.a
        @echo ""
        @echo "Se va a generar el binario $@"
        @echo ""
        gcc $(CFLAGS) test.C -o $(DIR_BIN)/$@ $(LD_LIBRARIES)

libmipthread.a: mipthread_self.o
        ar crv $(DIR_OBJ)/$@ $(DIR_OBJ)/$<

mipthread_self.o: mipthread_self.C
        gcc $(CFLAGS) -c ${PWD}/$< -o $(DIR_OBJ)/$@ $(INCLUDES)

clean:
        rm $(DIR_OBJ)/*.o
        rm $(DIR_OBJ)/*.a
        rm $(DIR_OBJ)/test