what's wrong with libc and it's time call ?

Hi all,

what’s wrong with the code below ??

I can’t see reason why this program is crashing …

Armin


#include <stdio.h>
#include <time.h>
#include <dlfcn.h>

typedef time_t (*timefunc)( time_t );
timefunc tim;

void* handle;
time_t x;

int main(void)
{
/* Open a shared library. */
handle = dlopen( “/lib/libc.so”, RTLD_NOW );

/* Find the address of the time function */
tim = (timefunc)dlsym( handle, “time” );

/* Invoke the time function */
x = (*tim)( NULL ); -->> Memory fault (core dumped)
---------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^
exit(0);
}

I would dlopen(NULL) since you’ll always have libc loaded.
I believe the time() call uses a syspage pointer that
hasn’t been initialized.

Armin Steinhoff wrote:

Hi all,

what’s wrong with the code below ??

I can’t see reason why this program is crashing …

Armin


#include <stdio.h
#include <time.h
#include <dlfcn.h

typedef time_t (*timefunc)( time_t );
timefunc tim;

void* handle;
time_t x;

int main(void)
{
/* Open a shared library. */
handle = dlopen( “/lib/libc.so”, RTLD_NOW );

/* Find the address of the time function */
tim = (timefunc)dlsym( handle, “time” );

/* Invoke the time function */
x = (*tim)( NULL ); -->> Memory fault (core dumped)
---------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^
exit(0);
}

Garry Turcotte wrote:

I would dlopen(NULL) since you’ll always have libc loaded.

I have to use routines from different shared libraries … one of them
is the libc. What means dlopen(NULL) ?

The code below is working!

#include <stdio.h>
#include <time.h>
#include <dlfcn.h>

typedef clock_t (*timefunc)( void );
timefunc tim;

void* handle;
clock_t x;

int main(void)
{
/* Open a shared library. */
handle = dlopen( “/lib/libc.so”, RTLD_NOW );

/* Find the address of a function */
tim = (timefunc)dlsym( handle, “clock” );

/* Invoke the function */
x = (*tim)();

exit(0);
}


I believe the time() call uses a syspage pointer that
hasn’t been initialized.

And who is responsible for that?


Regards

Armin


Armin Steinhoff wrote:


Hi all,

what’s wrong with the code below ??

I can’t see reason why this program is crashing …

Armin


#include <stdio.h
#include <time.h
#include <dlfcn.h

typedef time_t (*timefunc)( time_t );
timefunc tim;

void* handle;
time_t x;

int main(void)
{
/* Open a shared library. /
handle = dlopen( “/lib/libc.so”, RTLD_NOW );
/
Find the address of the time function /
tim = (timefunc)dlsym( handle, “time” );
/
Invoke the time function */
x = (*tim)( NULL ); -->> Memory fault (core dumped)
---------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^
exit(0);
}

Armin Steinhoff <a-steinhoff@web.de> wrote:

Garry Turcotte wrote:
I would dlopen(NULL) since you’ll always have libc loaded.

I have to use routines from different shared libraries … one of them
is the libc. What means dlopen(NULL) ?

The code below is working!

#include <stdio.h
#include <time.h
#include <dlfcn.h

typedef clock_t (*timefunc)( void );
timefunc tim;

void* handle;
clock_t x;

int main(void)
{
/* Open a shared library. */
handle = dlopen( “/lib/libc.so”, RTLD_NOW );

/* Find the address of a function */
tim = (timefunc)dlsym( handle, “clock” );

/* Invoke the function */
x = (*tim)();

exit(0);
}



I believe the time() call uses a syspage pointer that
hasn’t been initialized.

And who is responsible for that?



Regards

Armin

You can do it if you like:



#include <stdio.h>
#include <time.h>
#include <dlfcn.h>
#include <sys/syspage.h>

typedef time_t (*timefunc)( time_t );
timefunc tim;

void* handle;
time_t x;

int main(int argc, char **argv)
{
struct syspage_entry **syspage_ptrp;

/* Open a shared library. */
handle = dlopen( “/lib/libc.so”, RTLD_NOW);

syspage_ptrp = dlsym( handle, “_syspage_ptr” );
*syspage_ptrp = _syspage_ptr;

/* Find the address of the time function */
tim = (timefunc)dlsym( handle, “time” );

/* Invoke the time function */
x = (*tim)( NULL );
exit(0);
}

Sean,


thanks for your reply.

Is the initialization of the _syspage_ptr only neccessary if I’m using
the libc?

Why is the clock() example working?

Regards

Armin


Sean Boudreau wrote:

Armin Steinhoff <> a-steinhoff@web.de> > wrote:

Garry Turcotte wrote:

I would dlopen(NULL) since you’ll always have libc loaded.


I have to use routines from different shared libraries … one of them
is the libc. What means dlopen(NULL) ?


The code below is working!


#include <stdio.h
#include <time.h
#include <dlfcn.h


typedef clock_t (timefunc)( void );
timefunc tim;


void
handle;
clock_t x;


int main(void)
{
/* Open a shared library. */
handle = dlopen( “/lib/libc.so”, RTLD_NOW );

/* Find the address of a function */
tim = (timefunc)dlsym( handle, “clock” );

/* Invoke the function */
x = (*tim)();

exit(0);
}



I believe the time() call uses a syspage pointer that
hasn’t been initialized.


And who is responsible for that?



Regards


Armin


You can do it if you like:



#include <stdio.h
#include <time.h
#include <dlfcn.h
#include <sys/syspage.h

typedef time_t (*timefunc)( time_t );
timefunc tim;

void* handle;
time_t x;

int main(int argc, char **argv)
{
struct syspage_entry **syspage_ptrp;

/* Open a shared library. */
handle = dlopen( “/lib/libc.so”, RTLD_NOW);

syspage_ptrp = dlsym( handle, “_syspage_ptr” );
*syspage_ptrp = _syspage_ptr;

/* Find the address of the time function */
tim = (timefunc)dlsym( handle, “time” );

/* Invoke the time function */
x = (*tim)( NULL );
exit(0);
}

clock() doesn’t use the syspage.

This turns out to be because our libc initilization
is ‘special’, probably because we assume it’s always
present.

I’ve opened PR 22978 to at least start a discussion
internally as to whether the libc init should
be done via a normal elf DT_INIT section which
would be caught by dlopen().

The fix I gave below is really just a workaround
for time(). You may run into other issues with
other funcs due to the lack of full initilization.

A better solution for now is probably something
like tim = time for any symbol in libc since as
stated it’s always present on QNX.

Regards,

-seanb

Armin Steinhoff <a-steinhoff@web.de> wrote:

Sean,



thanks for your reply.

Is the initialization of the _syspage_ptr only neccessary if I’m using
the libc?

Why is the clock() example working?

Regards

Armin



Sean Boudreau wrote:
Armin Steinhoff <> a-steinhoff@web.de> > wrote:

Garry Turcotte wrote:

I would dlopen(NULL) since you’ll always have libc loaded.


I have to use routines from different shared libraries … one of them
is the libc. What means dlopen(NULL) ?


The code below is working!


#include <stdio.h
#include <time.h
#include <dlfcn.h


typedef clock_t (timefunc)( void );
timefunc tim;


void
handle;
clock_t x;


int main(void)
{
/* Open a shared library. */
handle = dlopen( “/lib/libc.so”, RTLD_NOW );

/* Find the address of a function */
tim = (timefunc)dlsym( handle, “clock” );

/* Invoke the function */
x = (*tim)();

exit(0);
}



I believe the time() call uses a syspage pointer that
hasn’t been initialized.


And who is responsible for that?



Regards


Armin


You can do it if you like:



#include <stdio.h
#include <time.h
#include <dlfcn.h
#include <sys/syspage.h

typedef time_t (*timefunc)( time_t );
timefunc tim;

void* handle;
time_t x;

int main(int argc, char **argv)
{
struct syspage_entry **syspage_ptrp;

/* Open a shared library. */
handle = dlopen( “/lib/libc.so”, RTLD_NOW);

syspage_ptrp = dlsym( handle, “_syspage_ptr” );
*syspage_ptrp = _syspage_ptr;

/* Find the address of the time function */
tim = (timefunc)dlsym( handle, “time” );

/* Invoke the time function */
x = (*tim)( NULL );
exit(0);
}

Sean Boudreau wrote:

clock() doesn’t use the syspage.

This turns out to be because our libc initilization
is ‘special’, probably because we assume it’s always
present.

I’ve opened PR 22978 to at least start a discussion
internally as to whether the libc init should
be done via a normal elf DT_INIT section which
would be caught by dlopen().

IMHO it’s a bug. If any lib requires private data initalization, it
must be done in a ctor/init, libc or not.

The fix I gave below is really just a workaround
for time(). You may run into other issues with
other funcs due to the lack of full initilization.

A better solution for now is probably something
like tim = time for any symbol in libc since as
stated it’s always present on QNX.

Either do dlopen(NULL, RTLD_NOW) to get a handle to the global space or
you could do something cheesy like:


void (*ilc)(int a, char **b, char **c, uintptr_t d, uintptr_t e);

hd = dlopen("/lib/libc.so", RTLD_NOW);

ilc = dlsym(hd, “_init_libc”);
ilc(argc, argv, NULL, NULL, NULL);


and this will call the libc initialization routine.

\

Cheers,
Adam

QNX Software Systems
[ amallory@qnx.com ]

With a PC, I always felt limited by the software available.
On Unix, I am limited only by my knowledge.
–Peter J. Schoenster <pschon@baste.magibox.net>

Adam Mallory wrote:

Sean Boudreau wrote:

clock() doesn’t use the syspage.

This turns out to be because our libc initilization
is ‘special’, probably because we assume it’s always
present.

I’ve opened PR 22978 to at least start a discussion
internally as to whether the libc init should
be done via a normal elf DT_INIT section which
would be caught by dlopen().


IMHO it’s a bug. If any lib requires private data initalization, it
must be done in a ctor/init, libc or not.

The fix I gave below is really just a workaround
for time(). You may run into other issues with
other funcs due to the lack of full initilization.

A better solution for now is probably something
like tim = time for any symbol in libc since as
stated it’s always present on QNX.


Either do dlopen(NULL, RTLD_NOW) to get a handle to the global space

OK … seems so that in that case the libc will be completely
initialized … also syspage_ptrp.

My workaround is now to do a second dlopen(NULL, mode) after a dlopen of
the libc (/lib/libc.so).

The tests shows no problems so far.

or
you could do something cheesy like:


void (*ilc)(int a, char **b, char **c, uintptr_t d, uintptr_t e);

hd = dlopen("/lib/libc.so", RTLD_NOW);

ilc = dlsym(hd, “_init_libc”);
ilc(argc, argv, NULL, NULL, NULL);

Thanks, but what are the correct values for argc, argv ?

Regards

Armin



and this will call the libc initialization routine.

“Adam Mallory” <amallory@qnx.com> wrote in message
news:cpd5qk$4h6$1@inn.qnx.com

Sean Boudreau wrote:
clock() doesn’t use the syspage.

This turns out to be because our libc initilization
is ‘special’, probably because we assume it’s always
present.

I’ve opened PR 22978 to at least start a discussion
internally as to whether the libc init should
be done via a normal elf DT_INIT section which
would be caught by dlopen().

IMHO it’s a bug. If any lib requires private data initalization, it
must be done in a ctor/init, libc or not.

Gentlemen… while you’re at it… I had a PR (which I can’t remember now)
created rather long time ago to add support for Solaris-style RTLD_NEXT
‘special value’ for the handle argument of dlsym(). It is useful for
overriding libc functions (which is probably what Armin was trying to do
anyway) by eliminating the need to do silly stuff like dlopen(libc).

Btw, if one still wants to do silly stuff like dlopen(libc), Solaris also
provides RTLD_NOLOAD mode for dlopen().

– igor

Igor Kovalenko wrote:

Igor Kovalenko wrote:

“Adam Mallory” <> amallory@qnx.com> > wrote in message
news:cpd5qk$4h6$> 1@inn.qnx.com> …

Sean Boudreau wrote:

clock() doesn’t use the syspage.

This turns out to be because our libc initilization
is ‘special’, probably because we assume it’s always
present.

I’ve opened PR 22978 to at least start a discussion
internally as to whether the libc init should
be done via a normal elf DT_INIT section which
would be caught by dlopen().


IMHO it’s a bug. If any lib requires private data initalization, it
must be done in a ctor/init, libc or not.



Gentlemen… while you’re at it… I had a PR (which I can’t remember
now)
created rather long time ago to add support for Solaris-style RTLD_NEXT
‘special value’ for the handle argument of dlsym(). It is useful for
overriding libc functions (which is probably what Armin was trying to do
anyway)

No I don’t do that … ctypes does the dlopen/dlsym calls in order to
map calls of shared libraries for the use with Python. I’m going to do
this with the shared libs of Photon (e.g.) in order to use Photon as a
GUI for Python

by eliminating the need to do silly stuff like dlopen(libc).

Btw, if one still wants to do silly stuff like dlopen(libc), Solaris also
provides RTLD_NOLOAD mode for dlopen().

dlopen(libc) is absolutely not silly stuff … it is neccessary in order
to map QNX services ‘on the fly’ for Python by pure Python code.

libc is only one of the libraries which can provide services for Python!

Have a look to the ctype project if you want to know what the issues are.

Regards

Armin

– igor

“Armin Steinhoff” <a-steinhoff@web.de> wrote in message
news:cphmh9$eoa$2@inn.qnx.com

Igor Kovalenko wrote:
[…]
Gentlemen… while you’re at it… I had a PR (which I can’t remember
now)
created rather long time ago to add support for Solaris-style RTLD_NEXT
‘special value’ for the handle argument of dlsym(). It is useful for
overriding libc functions (which is probably what Armin was trying to
do
anyway)


No I don’t do that … ctypes does the dlopen/dlsym calls in order to
map calls of shared libraries for the use with Python. I’m going to do
this with the shared libs of Photon (e.g.) in order to use Photon as a
GUI for Python

So, you’re wrapping libc functions. Which is another way to say the same
thing.

by eliminating the need to do silly stuff like dlopen(libc).

Btw, if one still wants to do silly stuff like dlopen(libc), Solaris
also
provides RTLD_NOLOAD mode for dlopen().


dlopen(libc) is absolutely not silly stuff … it is neccessary in order
to map QNX services ‘on the fly’ for Python by pure Python code.

Loading a shared library that’s already in your process memory is by
definition
a silly thing. If you need to wrap it, all you need is a handle
to the existing copy for dlsym(), which is what RTLD_NOLOAD provides. You
can get somewhat similar effect using dlopen(NULL) in QNX. One way or
another, libc is going to be a ‘special’ case since it is always present.

– igor

Igor Kovalenko wrote:

“Armin Steinhoff” <> a-steinhoff@web.de> > wrote in message
news:cphmh9$eoa$> 2@inn.qnx.com> …

Igor Kovalenko wrote:

[…]

Gentlemen… while you’re at it… I had a PR (which I can’t remember
now)
created rather long time ago to add support for Solaris-style RTLD_NEXT
‘special value’ for the handle argument of dlsym(). It is useful for
overriding libc functions (which is probably what Armin was trying to

do

anyway)


No I don’t do that … ctypes does the dlopen/dlsym calls in order to
map calls of shared libraries for the use with Python. I’m going to do
this with the shared libs of Photon (e.g.) in order to use Photon as a
GUI for Python


So, you’re wrapping libc functions. Which is another way to say the same
thing.


by eliminating the need to do silly stuff like dlopen(libc).

Btw, if one still wants to do silly stuff like dlopen(libc), Solaris

also

provides RTLD_NOLOAD mode for dlopen().


dlopen(libc) is absolutely not silly stuff … it is neccessary in order
to map QNX services ‘on the fly’ for Python by pure Python code.


Loading a shared library that’s already in your process memory is by
definition
a silly thing.

You mean by your definition! Please have in mind your view isn’t THE
common view!

If you need to wrap it, all you need is a handle
to the existing copy for dlsym(), which is what RTLD_NOLOAD provides. You
can get somewhat similar effect using dlopen(NULL) in QNX. One way or
another, libc is going to be a ‘special’ case since it is always present.

That’s only a ‘special case’ with Solaris and QNX.

It works different with Windows, OS X and other operating systems.
IMHO … dlopen shouldn’t re-load in general a shared lib if it is
already loaded, so we have not to handle it externally.

I don’t know why QSSL should re-implement the ‘special’ dlopen interface
of Solaris?


Armin

– igor

Armin Steinhoff wrote:

Igor Kovalenko wrote:

“Armin Steinhoff” <> a-steinhoff@web.de> > wrote in message
news:cphmh9$eoa$> 2@inn.qnx.com> …

Igor Kovalenko wrote:


[…]

Gentlemen… while you’re at it… I had a PR (which I can’t remember
now)
created rather long time ago to add support for Solaris-style
RTLD_NEXT
‘special value’ for the handle argument of dlsym(). It is useful for
overriding libc functions (which is probably what Armin was trying to


do

anyway)


No I don’t do that … ctypes does the dlopen/dlsym calls in order to
map calls of shared libraries for the use with Python. I’m going to do
this with the shared libs of Photon (e.g.) in order to use Photon as a
GUI for Python



So, you’re wrapping libc functions. Which is another way to say the same
thing.


by eliminating the need to do silly stuff like dlopen(libc).

Btw, if one still wants to do silly stuff like dlopen(libc), Solaris


also

provides RTLD_NOLOAD mode for dlopen().


dlopen(libc) is absolutely not silly stuff … it is neccessary in order
to map QNX services ‘on the fly’ for Python by pure Python code.



Loading a shared library that’s already in your process memory is by
definition
a silly thing.


You mean by your definition! Please have in mind your view isn’t THE
common view!

If you need to wrap it, all you need is a handle
to the existing copy for dlsym(), which is what RTLD_NOLOAD provides. You
can get somewhat similar effect using dlopen(NULL) in QNX. One way or
another, libc is going to be a ‘special’ case since it is always present.


That’s only a ‘special case’ with Solaris and QNX.

It works different with Windows, OS X and other operating systems.

BTW … re-open of a shared lib leads under Linux just to an
incrementation of the ref counter of that lib; the returned handle will
be the initial returned handle.

There is no need for a RTLD_NOLOAD :slight_smile:

IMHO … dlopen shouldn’t re-load in general a shared lib if it is
already loaded, so we have not to handle it externally.

I don’t know why QSSL should re-implement the ‘special’ dlopen interface
of Solaris?

The handling of shared libs are simply buggy in Solaris …

Armin



Armin


– igor

Adam Mallory wrote:

Sean Boudreau wrote:

clock() doesn’t use the syspage.

This turns out to be because our libc initilization
is ‘special’, probably because we assume it’s always
present.

I’ve opened PR 22978 to at least start a discussion
internally as to whether the libc init should
be done via a normal elf DT_INIT section which
would be caught by dlopen().


IMHO it’s a bug. If any lib requires private data initalization, it
must be done in a ctor/init, libc or not.

The fix I gave below is really just a workaround
for time(). You may run into other issues with
other funcs due to the lack of full initilization.

A better solution for now is probably something
like tim = time for any symbol in libc since as
stated it’s always present on QNX.


Either do dlopen(NULL, RTLD_NOW) to get a handle to the global space or
you could do something cheesy like:


void (*ilc)(int a, char **b, char **c, uintptr_t d, uintptr_t e);

hd = dlopen("/lib/libc.so", RTLD_NOW);

ilc = dlsym(hd, “_init_libc”);
ilc(argc, argv, NULL, NULL, NULL);

shared libs of Linux have the special symbols _init() and _finit().
This routines are called by dlopen/dlclose of a shared lib.
( _init/_finit are defined by the ELF ABI standard(?) …)

Does dlopen/dlclose not handle _ini()/_fini() ?
Or are these functions not defined for the shared libs of QNX6 ?

Regards

Armin


and this will call the libc initialization routine.

QNX doesn’t reload it if you open the same lib. But /lib/libc.so is not
the libc that is loaded.

It will be whatever /usr/lib/ldqnx.so.2 points to, which is normally
/proc/boot/libc.so.2

Your example works in this case.

Armin Steinhoff wrote:

Armin Steinhoff wrote:

Igor Kovalenko wrote:

“Armin Steinhoff” <> a-steinhoff@web.de> > wrote in message
news:cphmh9$eoa$> 2@inn.qnx.com> …

Igor Kovalenko wrote:



[…]

Gentlemen… while you’re at it… I had a PR (which I can’t remember
now)
created rather long time ago to add support for Solaris-style
RTLD_NEXT
‘special value’ for the handle argument of dlsym(). It is useful for
overriding libc functions (which is probably what Armin was trying to



do

anyway)


No I don’t do that … ctypes does the dlopen/dlsym calls in order to
map calls of shared libraries for the use with Python. I’m going to do
this with the shared libs of Photon (e.g.) in order to use Photon as a
GUI for Python




So, you’re wrapping libc functions. Which is another way to say the same
thing.


by eliminating the need to do silly stuff like dlopen(libc).

Btw, if one still wants to do silly stuff like dlopen(libc), Solaris



also

provides RTLD_NOLOAD mode for dlopen().


dlopen(libc) is absolutely not silly stuff … it is neccessary in
order
to map QNX services ‘on the fly’ for Python by pure Python code.




Loading a shared library that’s already in your process memory is by
definition
a silly thing.



You mean by your definition! Please have in mind your view isn’t THE
common view!

If you need to wrap it, all you need is a handle
to the existing copy for dlsym(), which is what RTLD_NOLOAD provides.
You
can get somewhat similar effect using dlopen(NULL) in QNX. One way or
another, libc is going to be a ‘special’ case since it is always
present.



That’s only a ‘special case’ with Solaris and QNX.

It works different with Windows, OS X and other operating systems.


BTW … re-open of a shared lib leads under Linux just to an
incrementation of the ref counter of that lib; the returned handle will
be the initial returned handle.

There is no need for a RTLD_NOLOAD > :slight_smile:

IMHO … dlopen shouldn’t re-load in general a shared lib if it is
already loaded, so we have not to handle it externally.

I don’t know why QSSL should re-implement the ‘special’ dlopen
interface of Solaris?


The handling of shared libs are simply buggy in Solaris …

Armin





Armin


– igor


cburgess@qnx.com

“Armin Steinhoff” <a-steinhoff@web.de> wrote in message
news:cpk0rh$6t4$1@inn.qnx.com

You mean by your definition! Please have in mind your view isn’t THE
common view!

Oh well. Let’s see what is your view then.

If you need to wrap it, all you need is a handle
to the existing copy for dlsym(), which is what RTLD_NOLOAD provides.
You
can get somewhat similar effect using dlopen(NULL) in QNX. One way or
another, libc is going to be a ‘special’ case since it is always
present.


That’s only a ‘special case’ with Solaris and QNX.

I strongly suspect that libc will be always loaded in any Unix-like OS. That
makes it special, does not it?

It works different with Windows, OS X and other operating systems.

BTW … re-open of a shared lib leads under Linux just to an
incrementation of the ref counter of that lib; the returned handle will be
the initial returned handle.

There is no need for a RTLD_NOLOAD > :slight_smile:

Ok. But that means Linux people think it would be silly idea to load a
library again, right?

IMHO … dlopen shouldn’t re-load in general a shared lib if it is
already loaded, so we have not to handle it externally.

So you think that too. Aren’t you contradicting yourself now?

I don’t know why QSSL should re-implement the ‘special’ dlopen interface
of Solaris?

The handling of shared libs are simply buggy in Solaris …

On what exactly grounds you claim that Solaris handling is ‘buggy’?

– igor

Igor Kovalenko wrote:

“Armin Steinhoff” <> a-steinhoff@web.de> > wrote in message
news:cpk0rh$6t4$> 1@inn.qnx.com> …

You mean by your definition! Please have in mind your view isn’t THE
common view!


Oh well. Let’s see what is your view then.


If you need to wrap it, all you need is a handle
to the existing copy for dlsym(), which is what RTLD_NOLOAD provides.
You
can get somewhat similar effect using dlopen(NULL) in QNX. One way or
another, libc is going to be a ‘special’ case since it is always
present.


That’s only a ‘special case’ with Solaris and QNX.


I strongly suspect that libc will be always loaded in any Unix-like OS. That
makes it special, does not it?


It works different with Windows, OS X and other operating systems.

BTW … re-open of a shared lib leads under Linux just to an
incrementation of the ref counter of that lib; the returned handle will be
the initial returned handle.

There is no need for a RTLD_NOLOAD > :slight_smile:


Ok. But that means Linux people think it would be silly idea to load a
library again, right?

That’s exactly what I said! But dlopen() is the only way to get a
handle. Rigth ??


Armin

Colin Burgess wrote:

QNX doesn’t reload it if you open the same lib. But /lib/libc.so is not
the libc that is loaded.

It will be whatever /usr/lib/ldqnx.so.2 points to, which is normally
/proc/boot/libc.so.2

OK … but libc.so.2 is the libc, correct ?

Your example works in this case.

Yes … ctypes is now working 100%. Thanks so far!

Regards

Armin