[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: GNU dlopen(3) differs from POSIX/IEEE



(I was away from work. Apologize for the delay in response)

On 13-Jun-2016 11:21 PM, Carlos O'Donell wrote:
On 06/13/2016 10:48 AM, Suprateeka R Hegde wrote:
Without provding libfoo on the link line, I could not get a JUMP_SLOT
for foo. So I provided -lfoo for the link-edit phase and then renamed
libfoo.so to libfoo1.so and also created a dummy libfoo.so without
foo. This way, I could get a JUMP_SLOT for foo. This hack was not
necessary on other platforms as foo gets a PLT entry even without
definition. By getting a JUMP_SLOT, I could verify if LD_PRELOAD
works in this case.

Correct, you don't get a PLT entry for foo unless it's in a shared
library at link-edit time.

Could you actually provide the exact steps you used in a GNU/Linux-
--based system to produce the final executable?

My experience is that you will either see a failure at link-edit
time, failure at runtime (missing libfoo.so, undefined symbol foo),
and will never get to the point where you can run the application
and get a segfault. I'm curious to see exactly the way you constructed
the scenario.

This is just to show there are ways to bring symbols to global space at runtime. LD_PRELOAD is one way. dlopen(3) with RTLD_GLOBAL would be another way, but on GNU based system it is not as per POSIX/IEEE specs.

So I tested for at least the LD_PRELOAD way. Here are the exact steps:

---
$ cat main.c
#include <dlfcn.h>
extern void foo(void);
int main()
{
          dlopen("./libfoo1.so", RTLD_GLOBAL);
          foo();
          return 0;
}

$ cat libfoo.c
#include <stdio.h>
void foo(void) { printf("In foo\n"); }

$ cat libjunk.c
#include <stdio.h>
void junk(void) { printf("Junky\n"); }


$ cc -fpic -shared libfoo.c -o libfoo.so
$ cc main.c -ldl -L. -lfoo # Gets a JUMP_SLOT for foo
$ cp libfoo.so libfoo1.so

$ # Now change libfoo.so not to contain foo. In other words
$ # not to resolve foo from startup libfoo.so. Keep it unresolved
$ # for lazy bind to happen to a runtime-brought-in global foo.

$ cc -fpic -shared libjunk.c -o libfoo.so
$ LD_PRELOAD=./libfoo1.so ./a.out
In foo
---

As you see, program works fine and foo is lazy bound to foo from libfoo1.so, which has been brought in at runtime without being there at link-edit time. The same case would have worked even without LD_PRELOAD, and with only dlopen-RTLD_GLOBAL if the GNU dlopen(3) matched the spec defined by POSIX/IEEE.

Therefore if the application's global symbol references all must be
defined before it starts there is no possibility for dlopen with
RTLD_GLOBAL to add symbols to the global scope that can be used
to result such symbols, because they are already resolved.

No possibility with current GNU implementation. But possible with POSIX/IEEE compliant dlopen(3). The test case works fine on other POSIX compliant system.

All I am saying is, dlopen(3) with RTLD_GLOBAL also should bring in foo at runtime to be compliant with POSIX.

--
Supra