problem with dlsym to fetch address of some functions
Peter Rosin
peda@lysator.liu.se
Wed Sep 24 07:41:00 GMT 2014
On 2014-09-23 21:52, Paulo César Pereira de Andrade wrote:
> 2014-09-23 16:40 GMT-03:00 Marco Atzeri <marco.atzeri@gmail.com>:
>> On 23/09/2014 20:43, Paulo César Pereira de Andrade wrote:
>>>
>>> Hi,
>>>
>>> Forgive me if this is expected. I am probably abusing dlsym
>>> behavior on other systems.
>>
>>
>> It will be much more clear if you
>
> Sorry for not clear initial problem description.
>
>> 1) produce a simple small complete test case,
>
> $ cat x.c
> extern int sprintf(char*,char*, ...);
> extern int puts(char*);
> extern void *dlsym(void*, char*);
> char buff[128];
> int main(void) {
> int (*fn)(char*,char*,...);
> sprintf(buff, "%.1f", 1.0);
> puts(buff);
> fn = dlsym((void*)0, "sprintf");
> (*fn)(buff, "%.1f", 1.0);
> puts(buff);
> return 0;
> }
>
> $ gcc -O0 -g3 x.c
>
>> 2) explain the outcome you obtain (or not)
>
> $ ./a.exe
> 1.0
> f
The problem is that sprintf is a popular function available in
many dlls. Especially so on Cygwin which is a layer upon layer
thingy. When you are not specifying what dll dlsym should look
in, dlsym just picks the first sprintf it finds.
Consider this program:
#include <stdio.h>
#include <dlfcn.h>
char buff[128];
int main(void) {
int (*fn)(char*,char*,...);
void *cygwin1 = dlopen("cygwin1.dll", RTLD_GLOBAL);
void *ntdll = dlopen("ntdll.dll", RTLD_GLOBAL);
void *msvcrt = dlopen("msvcrt.dll", RTLD_GLOBAL);
printf("cygwin1 %p\n", cygwin1);
printf("ntdll %p\n", ntdll);
printf("msvcrt %p\n", msvcrt);
fn = dlsym(RTLD_DEFAULT, "sprintf");
printf("\n\"default\" sprintf %p\n", fn);
(*fn)(buff, "%.1f", 1.0);
puts(buff);
fn = dlsym(cygwin1, "sprintf");
printf("\ncygwin1 sprintf %p\n", fn);
(*fn)(buff, "%.1f", 1.0);
puts(buff);
fn = dlsym(ntdll, "sprintf");
printf("\nntdll sprintf %p\n", fn);
(*fn)(buff, "%.1f", 1.0);
puts(buff);
fn = dlsym(msvcrt, "sprintf");
printf("\nmsvcrt sprintf %p\n", fn);
(*fn)(buff, "%.1f", 1.0);
puts(buff);
return 0;
}
It produces the following output for me (Cygwin/32):
cygwin1 0x61000000
ntdll 0x77970000
msvcrt 0x75c70000
"default" sprintf 0x77a45555
f
cygwin1 sprintf 0x610d7784
1.0
ntdll sprintf 0x77a45555
f
msvcrt sprintf 0x75c8d354
1.0
So, it appears that you get ntdll:sprintf, which apparently
is not a very complete version. Maybe Cygwin could do better
and look in Cygwin dlls before going on to lower level stuff?
PTC, I'm sure...
Cheers,
Peter
--
Problem reports: http://cygwin.com/problems.html
FAQ: http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
More information about the Cygwin
mailing list