This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: problem with dlsym to fetch address of some functions


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]