From: Suprateeka R Hegde <hegdesmailbox@gmail.com>
To: Roland McGrath <roland@hack.frob.com>
Cc: gnu-gabi@sourceware.org
Subject: Re: Deferred Binding of Function Pointers in SHLIB
Date: Fri, 01 Jan 2016 00:00:00 -0000 [thread overview]
Message-ID: <b16b18e1-375f-8e46-d928-a5b241b74c43@gmail.com> (raw)
In-Reply-To: <20160610213649.D8A7B2C39F7@topped-with-meat.com>
Thanks for the response. You are right that my observation is incorrect.
However something else is the story here. And my requirement/proposal is
still valid. Read more inline.
On 11-Jun-2016 03:06 AM, Roland McGrath wrote:
> I think you are confused about what you're observing. Lazy binding
> happens only for PLT entries, i.e. for direct function calls. There
> is never lazy binding for data initializers like your example uses.
Yes, I got confused. Coming after a decade of work on a platform where
PIC is default, I missed adding -fpic while creating the executable. And
I thought -fpic is default. That is the difference that confused me. In
addition I was lazy enough not to debug, but to rely on messages of the
dynamic linker.
This is what happened:
In executable,
---
$ cat exe.c
#include <stdio.h>
extern void foo(void);
void (*func_p)(void) = NULL;
int main()
{
printf("printf()\n");
func_p = foo;
(*func_p)();
return 0;
}
$ cc exe.c -Wl,--unresolved-symbol=ignore-all
$ ./a.out
printf()
Segmentation fault (core dumped)
---
printf() is called and then SEGV. Observe there is no message from
dynamic linker at startup regarding UNDEF foo.
In contrast, in the shlib case,
---
$ cat main.c
extern void libmain(void);
int main() { libmain(); return 0; }
$ cat libmain.c
#include <stdio.h>
extern void foo(void);
void (*func_p)(void) = NULL;
int libmain()
{
printf("printf()\n");
func_p = foo;
(*func_p)();
return 0;
}
$ cc -fpic -shared libmain.c -Wl,--unresolved-symbol=ignore-all
$ cc main.c -L. -lmain -Wl,--unresolved-symbol=ignore-all
$ LD_LIBRARY_PATH=. ./a.out
./a.out: symbol lookup error: ./libmain.so: undefined symbol: foo
---
Observe that there is an error message from the dynamic linker at
startup even before printf is called.
This missing startup message made me think that, in case of executable,
there is lazy bind happening.
(Sorry I should have debugged it and not relied on the message)
Just because of the non-PIC mode for exe, the dynamic linker is deprived
of the capability to give out a neat error message and exit gracefully.
Had the same executable been built with -fpic, the result would have
been same -- error message from the dynamic linker:
---
$ cc exe.c -Wl,--unresolved-symbol=ignore-all
$ ./a.out
./a.out: symbol lookup error: ./a.out: undefined symbol: foo
---
However, the story does not end here. I make a minor change to exe.c:
---
$ cat exe.c
#include <stdio.h>
extern void foo(void);
void (*func_p)(void) = foo; /* func_p initialized before main */
int main()
{
printf("printf()\n");
(*func_p)();
return 0;
}
$ cat libfoo.c
#include <stdio.h>
void foo(void) { printf("In Foo\n"); }
$ cc -fpic -shared libfoo.c -o libfoo.so
$ cc exe.c -L. -lfoo
---
After the exe build, change libfoo.c and make foo() as bar(), but keep
the name of shlib same -- libfoo.so. What I did is, provide a well
defined foo() during link edit time. But remove foo() at runtime. Then I
see:
---
$ LD_LIBRARY_PATH=. ./a.out
printf()
./a.out: symbol lookup error: ./a.out: undefined symbol: foo
LD_BIND_NOW=1 LD_LIBRARY_PATH=. ./a.out
./a.out: symbol lookup error: ./a.out: undefined symbol: foo
---
Observe that without LD_BIND_NOW, lazy bind is happening. With
LD_BIND_NOW, its all at startup and hence printf() is not even called.
Now, convert this modified exe.c into a shlib as before, and again
remove foo at runtime. Then, there is no lazy bind at all. I see:
---
$ LD_LIBRARY_PATH=. ./a.out
./a.out: symbol lookup error: ./libmain.so: undefined symbol: foo
---
So, observing all these, it is all about whether foo gets a JUMP_SLOT
reloc or not. In other words, foo gets a PLT or not (?).
What I want to propose is that the behavior should be consistent across
exe and shlib. However, It is not the case as seen above. Is there any
anti option to -fno-plt of GCC6 :-)
> Your use of -Wl,--unresolved-symbols=ignore-all means that the
> non-shared case (libmain.c as executable) is simply mis-linked. (If
> you remove that switch, then the link will fail to complete and you
> can never get a binary to run.)
Not really. One can get the symbols at runtime too. Not everything need
to be resolved at link-edit time. For instance, using LD_PRELOAD,
dlopen-with-RTLD_GLOBAL, etc.
(See my thread on GNU dlopen vs POSIX/IEEE on the mailing list:
https://sourceware.org/ml/gnu-gabi/2016-q2/msg00015.html)
My real case is as follows:
I have an executable with hundreds of function pointers as an array.
Functions are called using array index which depends on the arguments
passed to the executable. This executable is short lived and in each
invocation calls only one function.
Without lazy bind, all these function pointers are being resolved at
startup. This increases startup time which becomes significant given the
fact that the executable is very short lived.
--
Supra
next prev parent reply other threads:[~2016-06-13 15:28 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-01-01 0:00 Suprateeka R Hegde
2016-01-01 0:00 ` Roland McGrath
2016-01-01 0:00 ` Suprateeka R Hegde [this message]
2016-01-01 0:00 ` Carlos O'Donell
2016-01-01 0:00 ` Suprateeka R Hegde
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b16b18e1-375f-8e46-d928-a5b241b74c43@gmail.com \
--to=hegdesmailbox@gmail.com \
--cc=gnu-gabi@sourceware.org \
--cc=roland@hack.frob.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).