This is the mail archive of the libc-help@sourceware.org mailing list for the glibc 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: operation and limitations of dladdr()?


On Tue, Mar 29, 2016 at 4:27 PM, Britton Kerin <britton.kerin@gmail.com> wrote:
> I'm trying to learn as much as possible about dladdr() before
> unleashing a small lib that uses it on the world.  Two questions:
>
> Does the fact that dladdr() reports the symbol with the nearest
> address lower than the given
> one mean that that might be the correct function?

I don't quite follow exactly what you're trying to ask.

So let me clarify a few things.

(a) The input argument to dladdr can be any address. There is no
restriction placed on the void *.

Therefore the function operates as flexibly as possible to determine
the nearest symbol with an address lower than the address you
provided.

In theory that address should be a function pointer or official
procedure descriptor, and point at the function of interest.

If you always pass a function pointer or OPD then the result is
reliably equal to the symbol address (with some exceptions).

The exceptions which I have not verified are: What happens if you take
the address of a GNU Indirect function and pass it to dladdr? Do you
get the address of the resolver function or the resolved function?

(b) The implementation is flexible.

The implementation tries hard to return a sensible function given the
address you passed. The heuristic is to look for the next symbol with
an address lower than the given address. Might this be wrong? It may
be.

It is wrong in ways which I personally consider to be bugs, but that
have not been fixed yet because nobody has cared that much. One such
case is the case where the machine implementation returns the address
of the procedure linkage table slot as the address of the function. In
this case dladdr should actually detect it is looking at a PLT,
resolve the entry, and then return the resolved result. The present
implementation does not do this additional step and so sometimes you
might get an odd result as noted in the linux man page. This is a flaw
in the implementation, and if you can put together a test case for it
I think it should be filed as a bug. It isn't impossible to fix and is
simply a quirk of the implementations.

> In other words why this:
>
>        const char *dli_sname;  /* Name of nearest symbol with address
> lower than addr */
>        void      *dli_saddr;  /* Exact address of symbol name in dli_sname */
>
> I would have thought that the address of the function about to be
> executed would have to match the library address exactly, but maybe
> not.

It does not. You can pass any value as the void * addr to thefunction.

> What does it mean if they don't match?

It means there was no symbol information for any symbol with an
address lower than the address you passed as addr.

Imagine what happens if you call `dladdr (NULL, &mydlinfo);`, there is
no symbol at NULL (0x0) or lower.

> My current strategy is to be cowardly and not tell the user that the correct
> function has been found unless I get an exact match.

That's fine. The glibc implementation is simply more flexible than that.

Cheers,
Carlos.


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