-1

I want to use a personal "pthread_self" function. I want to rewrite the "pthread_self()" and, at the final, call to the real "pthread_self". is it possible in C/C++?

Example:

#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());
}
chridam
  • 100,957
  • 23
  • 236
  • 235
  • @netcoder he used `::` so its definitely C++. – Aniket Inge Jan 28 '13 at 18:36
  • @José Ramón Arias I'm confused, if this is C++ then surely "main" should have a return type? – Phorce Jan 28 '13 at 18:36
  • @Aniket: Yeah but he used `` so it's ambiguous. – netcoder Jan 28 '13 at 18:36
  • ohkay `::` doesn't work so its C then – Aniket Inge Jan 28 '13 at 18:37
  • using **::** in Visual Studio helps with intellisense (even for C), which I'm assuming is the reason for the **::** in this case. – Inisheer Jan 28 '13 at 18:38
  • this is definitely not Visual Studio, see the `` includes? @Inisheer – Aniket Inge Jan 28 '13 at 18:39
  • 1
    People, you don't seem to get the point. He is trying to override a free function which is not possible. –  Jan 28 '13 at 18:41
  • @aleguna, I don't knwo _what_ he is doing, the language even doesn't seem clear. I only tried my part of telling him its C code :| – Aniket Inge Jan 28 '13 at 18:42
  • 1
    @alaguna, it's certainly possible. binutils ld `-wrap`, for example. – Carl Norum Jan 28 '13 at 18:43
  • 1
    possible duplicate of [Override a function call in C](http://stackoverflow.com/questions/617554/override-a-function-call-in-c) – Carl Norum Jan 28 '13 at 18:43
  • 1
    @aleguna: It is certainly possible, especially for shared libraries. – netcoder Jan 28 '13 at 18:46
  • But why rely on a preprocessor hack or a compiler specific extension when you can refactor your function name? and thus, keep it portable across other compilers and also readable? – Aniket Inge Jan 28 '13 at 18:47
  • @Aniket, because sometimes you want to have a temporary wrapper for debugging and you don't want to modify hundreds of vendor-provided source files? – Carl Norum Jan 28 '13 at 18:48
  • Sorry, I tried to make an example of a C or C++ code. The "::" only is a way of tell you that at this point I wanted to call the real function pthread_self() of the pthread library. I am compiling in linux with gcc. – José Ramón Arias Jan 29 '13 at 07:24
  • Thanks @Carl Norum for your link ([Override a function call in C](http://stackoverflow.com/questions/617554/override-a-function-call-in-c)). In this thread is very interesting the next PDF: [Intercepting Arbitrary Functions...](http://www.cs.umd.edu/Library/TRs/CS-TR-4585/CS-TR-4585.pdf) – José Ramón Arias Jan 29 '13 at 07:28
  • @JoséRamónArias: You still haven't told us what language you used. Is it C or C++? It can't be both, pick one. – netcoder Jan 29 '13 at 10:43
  • Possible duplicate of [Function interposition in Linux without dlsym](http://stackoverflow.com/questions/998464/function-interposition-in-linux-without-dlsym) –  Aug 17 '16 at 12:29

5 Answers5

0

the code seems to be C89 without a return type for main. So I suggest you remove the :: operator infront of pthread_self() in the function pthread_self(void) and recompile.

Also call your pthread_self() by some other name such as pthread_self_2(void)

Aniket Inge
  • 25,375
  • 5
  • 50
  • 78
  • Yes but that doesn't solve the problem, you'll get infinite recursion. – netcoder Jan 28 '13 at 18:39
  • @netcoder he is doing something before the recursive function - it could be an early `return`? see his comments – Aniket Inge Jan 28 '13 at 18:40
  • I assume that by `And finally call to de real pthread_self():` he means call the `libpthread`'s version, not his own. – netcoder Jan 28 '13 at 18:41
  • @Aniket No, as he said, he wants to *wrap around* the already existing function. – leemes Jan 28 '13 at 18:42
  • @Aniket, he is trying to call 'default' function provided by the posix library at the end. This is not possible –  Jan 28 '13 at 18:43
  • @aleguna, it's totally possible. See the 'possible duplicate' link I posted above. – Carl Norum Jan 28 '13 at 18:44
  • @CarlNorum Yeah, they use basically the same idea as me in my answer. – leemes Jan 28 '13 at 18:52
  • @leemes - for the accepted answer yes. I think the second one down is better, and describes the `-wrap` method. – Carl Norum Jan 28 '13 at 18:59
  • @CarlNorum Oh, that one is nice, you are right. But it seems to be compiler-specific which is stuff I try to avoid as long as it's possible. – leemes Jan 28 '13 at 19:01
0

Will it be allowed to overload pthread_self() with a dummy variable (never used)?

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__ );
}

produces

$ g++ test.cpp -lpthread

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

$ 

Two other approaches might be:

  • Write a function my_pthread_self(), use it everywhere, and have it call real pthread_self()

  • Have a macro PTHREAD_SELF which calls your wrapper which internally calls real pthread_self()

Arun
  • 19,750
  • 10
  • 51
  • 60
  • Not in C (he didn't clearly specify what he wants to use, it looks ambiguous). – leemes Jan 28 '13 at 18:43
  • Also, this implies a change of the code for *each call*, which is what he obviously tries to avoid, since otherwise he could easily write a wrapper with a different name (or I don't see the problem with such a wrapper) – leemes Jan 28 '13 at 18:50
  • Thanks. I would like a solution for C and C++. If it is not possible, then only in C++. And, as @leemes said, I don't want to change the actual sources. I'm looking for a transparent change. – José Ramón Arias Jan 29 '13 at 07:10
0

The following is a bit hacky but should work in C. Put the following in a header which you would have to include before or instead of <pthread.h> (but never after pthread.h):

pthread_t _pthread_self(void);

#define pthread_self _pthread_self

And in the corresponding .c file:

#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();
}

Now, when you write pthread_self in some other file than that .c file, it expands to your wrapper function. Within the .c file above, since this hack is not done, the call within the wrapper will call the library function.

leemes
  • 44,967
  • 21
  • 135
  • 183
0

This should give you some ideas. If you control the linking of your executable, you don't need to use LD_PRELOAD.

  • Link-only answer. Good link (+1), but could go stale any day now rendering this answer useless (-1). – DevSolar Aug 17 '16 at 07:37
  • @DevSolar: I'll gladly give you a +1 if you paraphrase the link as an answer :). I find it too daunting. –  Aug 17 '16 at 12:28
0

Thanks to all of you. Based mainly on these two links Intercepting Arbitrary Functions on... and Tutorial: Function Interposition in Linux show by @Carl Norum and @Arkadyi, I show you a possible solution:

I have two source files and a 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;
}

And the 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
  • "I show you a possible solution" -- You show uncommented code without a word about what you are doing and why it works. Your first link is also gone stale. – DevSolar Aug 17 '16 at 07:35