public inbox for gnu-gabi@sourceware.org
 help / color / mirror / Atom feed
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

  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).