Question

My problem is as follows:

I have a structure containing function pointers like this:

typedef void (CALLING_COVNENTION * functionType_t) (/*...*/);

typedef struct myFuncpointerStruc_s
{
    /*...*/
    functionType_t funcIdentifier;
    /*...*/
}myFuncpointerStruc_t;

Now I want to assign a functionpointer of exactly that type to it. But sadly dlsym() is returning a void * instead of something like function_poitner_type

So my first try:

functionscope ()
{
    myFuncpointerStruc_t structIdentifier;

    structIdentifier.funcIdentifier= dlsym (hAndle, "calledName");
}

ended in the warning:

WARNING: ISO C forbids assignment between function pointer and 'void *'

Ok, that confused me... gcc was never talking that harsh to me. But OK lets get tricky I thought there will probably be any backdoor to keep it standard conform. So I tried this:

functionscope ()
{
    myFuncpointerStruc_t structIdentifier;

    *(void **) &structIdentifier.funcIdentifier = dlsym (hAndle, "calledName");
}

Hm.... obviously...

warning: dereferencing type-punned pointer will break strict aliasing rules

As I don't know what happens dlsym() internally I can't know I will break, as I get returned a real void * that aliases my function, or something quite different, can I?

So I cant know, will the use of this function pointer now break strict-aliasing rules or won't it?

But anyway: For my company it is law to use the compilerflag -fstrict-aliasing. So this is also not a possible solution for me, even if it would be conform.

So I tried it by going on.

My next idea was: what about to parse a char * version of dlsym() into memcopy?

The result:

functionscope ()
{
    myFuncpointerStruc_t structIdentifier;

    unsigned char *localTestPtr = ((unsigned char *) dlsym (hAndle, "calledName");  

    memcpy (g_interfaceSvCheck.pfnPFD_SVCHK_GET_VERSION, localTestPtr, sizeof (localTestPtr));
}

The warning I'm getting now is pretty specific again:

warning: ISO C forbids passing argument 1 of ´memcpy´ between function pointer and ´void *´

So my next idea was kind of "lets go back to the bytes" maybe there I will get a way it will be working on. (But slowly I'm running out of ideas...)

So I did:

functionscope ()
{
    size_t testIndex;
    myFuncpointerStruc_t structIdentifier;
    unsigned char *localTestPtr = ((unsigned char *) dlsym (hAndle, "calledName");

    for (testIndex = 0; testIndex < sizeof (localTestPtr); testIndex++)
    {
        ((unsigned char *)(structIdentifier.funcIdentifier))[testIndex] = ((unsigned char *)&localTestPtr)[testIndex];
    }

}

This ended in a quiet different warning:

WARNING: ISO C forbids conversion of function pointer to object pointer type

So finally my freakiest try was:

functionscope ()
{
    size_t testIndex;
    myFuncpointerStruc_t structIdentifier;
    unsigned char *localTestPtr = ((unsigned char *) dlsym (hAndle, "calledName");  
    unsigned char * FakeFunctionPointer;

    FakeFunctionPointer = 
        (((unsigned char *)structIdentifier) + offsetof (myFuncpointerStruc_t , funcIdentifier));

    for (testIndex = 0; testIndex < sizeof (localTestPtr); testIndex++)
    {
        FakeFunctionPointer[testIndex] = ((unsigned char *)&localTestPtr)[testIndex];
    }
}

And even here the problem is, that offsetoff's second parameter can't get converted to void * as it is a function pointer.

I'm stucked and don't know how to get further, could anyone help me please finding a solution?

I just have these warnings by using gcc 4.2 not with clang.

The targeted C version is -std=c99 to avoid is -std=POSIX and -std=gnu99

But this gcc warnings don't sound outdated to me. I'm working currently on FreeBSD and I have really no idea left how to solve this.

Was it helpful?

Solution

This is kind of tricky:

#define CALLING_CONVENTION 

typedef void (CALLING_CONVENTION * functionType_t) (/*...*/);
typedef struct myFuncpointerStruc_s
{
  /*...*/
  functionType_t funcIdentifier;
  /*...*/
} myFuncpointerStruc_t;

int main()
{
  myFuncpointerStruc_t structIdentifier = {0};

  {
    functionType_t * pfuncIdentifier = &structIdentifier.funcIdentifier;

    *(void **) (pfuncIdentifier) = dlsym(handle, "calledName");
  }

  ...
}

The above solution just tricks to compiler. The does not work from -O1 on anymore ... :-(


As there indeed is no solution, the only solution is to calm down the compiler. And the GNU people showed insight on this and invented: __attribute__ ((__may_alias__))

Here we can use it as follows:

#define CALLING_CONVENTION 

typedef void * __attribute__ ((__may_alias__)) pvoid_may_alias_t;

typedef void (CALLING_CONVENTION * functionType_t) (/*...*/);
typedef struct myFuncpointerStruc_s
{
  /*...*/
  functionType_t funcIdentifier;
  /*...*/
} myFuncpointerStruc_t;

int main()
{
  myFuncpointerStruc_t structIdentifier = {0};

  *(pvoid_may_alias_t *) (&structIdentifier.funcIdentifier) = dlsym(handle, "calledName");
  }

  ...
}

And btw: Where does ldsym() come from? I only know dlsym().

OTHER TIPS

Use two type-casts:

func_type *funptr;
funptr= (func_type *)(intptr_t)dlsym();

Type-casting funptr will cause troubles if size of code-pointers and data-pointers aren't equal.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top