Need to get at address of loaded shared object

Is there a way to get at the address of a loaded shared library within an
application? I want to parse the ELF file to determine dynamic symbols I
want to load up via dlsym(), but I’m trying to avoid reading the file in
twice.

Regards,

Richard

From outside or inside the application?

Can you describe a bit more about what you want to achieve?

Richard Doucet wrote:

Is there a way to get at the address of a loaded shared library within an
application? I want to parse the ELF file to determine dynamic symbols I
want to load up via dlsym(), but I’m trying to avoid reading the file in
twice.

Regards,

Richard


cburgess@qnx.com

From inside the application. I’m trying to find all of the functions who’s
name matches a particular pattern after C++ name mangling. Once I have
these methods name, I can get there address via dlsym(), then then exectute
them once.

I use to parse the Elf file via objdump, but this utility would not be
available on the final target machine, as they are not development boxes…


“Colin Burgess” <cburgess@qnx.com> wrote in message
news:dc7spf$jn5$2@inn.qnx.com

From outside or inside the application?

Can you describe a bit more about what you want to achieve?

Richard Doucet wrote:
Is there a way to get at the address of a loaded shared library within an
application? I want to parse the ELF file to determine dynamic symbols I
want to load up via dlsym(), but I’m trying to avoid reading the file in
twice.

Regards,

Richard


cburgess@qnx.com

Is there a way to get at this address???

“Richard Doucet” <doucetr@DONTaeclSPAM.caME> wrote in message
news:dc7uao$267$1@inn.qnx.com

From inside the application. I’m trying to find all of the functions
who’s name matches a particular pattern after C++ name mangling. Once I
have these methods name, I can get there address via dlsym(), then then
exectute them once.

I use to parse the Elf file via objdump, but this utility would not be
available on the final target machine, as they are not development
boxes…


“Colin Burgess” <> cburgess@qnx.com> > wrote in message
news:dc7spf$jn5$> 2@inn.qnx.com> …
From outside or inside the application?

Can you describe a bit more about what you want to achieve?

Richard Doucet wrote:
Is there a way to get at the address of a loaded shared library within
an application? I want to parse the ELF file to determine dynamic
symbols I want to load up via dlsym(), but I’m trying to avoid reading
the file in twice.

Regards,

Richard


cburgess@qnx.com

Sorry, I’m travelling and haven’t checked this group for a while.
You can directly access the ELF header and from there find the symbols.
You may have problems though since stripping an executable (or putting in an image filesystem)
will strip out the symbol table, leaving on the dynamic symbol table (ie those symbols
required for symbolic linking).

I’m not sure on the C++ mangling functions though. I think with 3.x there is a demangler
somewhere in libsupc++.a?

Richard Doucet wrote:

Is there a way to get at this address???

“Richard Doucet” <> doucetr@DONTaeclSPAM.caME> > wrote in message
news:dc7uao$267$> 1@inn.qnx.com> …

From inside the application. I’m trying to find all of the functions
who’s name matches a particular pattern after C++ name mangling. Once I
have these methods name, I can get there address via dlsym(), then then
exectute them once.

I use to parse the Elf file via objdump, but this utility would not be
available on the final target machine, as they are not development
boxes…


“Colin Burgess” <> cburgess@qnx.com> > wrote in message
news:dc7spf$jn5$> 2@inn.qnx.com> …

From outside or inside the application?

Can you describe a bit more about what you want to achieve?

Richard Doucet wrote:

Is there a way to get at the address of a loaded shared library within
an application? I want to parse the ELF file to determine dynamic
symbols I want to load up via dlsym(), but I’m trying to avoid reading
the file in twice.

Regards,

Richard


cburgess@qnx.com

\


cburgess@qnx.com

Richard Doucet wrote:

Is there a way to get at this address???

Attached is a demo app of ripping out base addresses of MAP_ELF sections.

FYI - you can’t/shouldn’t use dlsym() directly to rip out function
pointers due to different types (function pointers are not object pointers).


Cheers,
Adam

QNX Software Systems
[ amallory@qnx.com ]

With a PC, I always felt limited by the software available.
On Unix, I am limited only by my knowledge.
–Peter J. Schoenster <pschon@baste.magibox.net>

“Colin Burgess” <cburgess@qnx.com> wrote in message
news:dcfeo1$j31$1@inn.qnx.com

Sorry, I’m travelling and haven’t checked this group for a while.
You can directly access the ELF header and from there find the symbols.
You may have problems though since stripping an executable (or putting in
an image filesystem)
will strip out the symbol table, leaving on the dynamic symbol table (ie
those symbols
required for symbolic linking).

That’s OK, as I’m looking for the dynamic symbol table anyways.

I’m not sure on the C++ mangling functions though. I think with 3.x
there is a demangler
somewhere in libsupc++.a?

There is a cxa_demangle module within that library, although I don’t really
need to demangle the name.

Thanks, code work great, although I would have tought that there would have
been an easier way.

What do you mean about not being able to rip out the function pointer via
dlsym()? According to the docs, it seems legit…

“Adam Mallory” <amallory@qnx.com> wrote in message
news:dcllqb$4ak$1@inn.qnx.com

Richard Doucet wrote:
Is there a way to get at this address???

Attached is a demo app of ripping out base addresses of MAP_ELF sections.

FYI - you can’t/shouldn’t use dlsym() directly to rip out function
pointers due to different types (function pointers are not object
pointers).


Cheers,
Adam

QNX Software Systems
[ > amallory@qnx.com > ]

With a PC, I always felt limited by the software available.
On Unix, I am limited only by my knowledge.
–Peter J. Schoenster <> pschon@baste.magibox.net




#include <stdio.h
#include <stdlib.h
#include <unistd.h
#include <errno.h
#include <fcntl.h
#include <sys/mman.h
#include <sys/procfs.h
#include <sys/procmgr.h
#include <sys/neutrino.h

struct dinfo_s {
procfs_debuginfo info;
char pathbuffer[PATH_MAX];
};


int main(int argc, char* argv[]) {
char buf[128];
int fd;
struct dinfo_s dinfo;
procfs_mapinfo *m,*p;
int nmaps = 1;
int n = 0;

sprintf(buf, “/proc/%d/as”, getpid());
fd = open(buf, O_RDONLY);
if (fd == -1) {
perror(“open”);
exit(1);
}

if(devctl(fd, DCMD_PROC_PAGEDATA, NULL, 0, &nmaps) != EOK) {
perror(“devctl pd”);
exit(1);
}
if((m = malloc(sizeof(*m)*nmaps)) == NULL) {
perror(“malloc”);
exit(1);
}
if(devctl(fd, DCMD_PROC_PAGEDATA, m, sizeof(*m)*nmaps, &nmaps) != EOK) {
perror(“devctl pd big”);
exit(1);
}

for (n=0 ; n < nmaps ; n++) {
p = m+n;
if (p->flags & MAP_ELF) {
dinfo.info.vaddr = p->vaddr;
if(devctl(fd, DCMD_PROC_MAPDEBUG, &dinfo, sizeof dinfo, NULL) != EOK) {
perror(“devctl”);
exit(1);
}
printf(“vaddr %08x, size %x flags %08x name %s ba %08x\n”,
(unsigned)p->vaddr, (unsigned)p->size, p->flags,
dinfo.info.path, dinfo.info.vaddr);
}
}

return 0;
}

Richard Doucet wrote:

Thanks, code work great, although I would have tought that there would have
been an easier way.

What do you mean about not being able to rip out the function pointer via
dlsym()? According to the docs, it seems legit…

The issue is that dlsym() returns a void*. According to ANSI C:


(6.2.5)

26 A pointer to void shall have the same representation and alignment
requirements as a pointer to a character type. Similarly, pointers to
qualified or unqualified versions of compatible types shall have the
same representation and alignment requirements. All pointers to
structure types shall have the same representation and alignment
requirements as each other. All pointers to union types shall have the
same representation and alignment requirements as each other. Pointers
to other types need not have the same representation or alignment
requirements.

So it would seem that void* is not a type which guarantees that a
function pointer object type will have the same representation (ie. they
are not interchangeable). You could return a pointer to a structure
containing those function pointers of course.

Our documentation looks to be based off of the UNIX’98 standard (which
shows a very similar example). I’m also pretty sure there is much code
in the world which banks on this type of behaviour as well (like the
assumption there is 8 bits to an unsigned char). At best it’s unclear
to me that dlsym() can portably and safely be used to directly extract
function pointers, at worst it doesn’t work.


Cheers,
Adam

QNX Software Systems
[ amallory@qnx.com ]

With a PC, I always felt limited by the software available.
On Unix, I am limited only by my knowledge.
–Peter J. Schoenster <pschon@baste.magibox.net>

Adam Mallory wrote:

Richard Doucet wrote:

Thanks, code work great, although I would have tought that there would
have been an easier way.

What do you mean about not being able to rip out the function pointer
via dlsym()? According to the docs, it seems legit…


The issue is that dlsym() returns a void*. According to ANSI C:


(6.2.5)

So it would seem that void* is not a type which guarantees that a
function pointer object type will have the same representation (ie. they
are not interchangeable). You could return a pointer to a structure
containing those function pointers of course

This is not really about representation, it’s about conversions. ANSI C
doesn’t guarantee that pointers to other data types (except character
types) have the same representation as void* either, but since it
defines the semantics of conversions between void* and other data
pointers, you’re fine there. For instance, even on systems where void
pointers have a different size than int pointers, C guarantees that you
can convert a valid int pointer to void* and back and the result will
point to the same object as the original pointer did. This ensures that
void pointers can be used to store pointers to any kind of objects.

But not functions. C does not say what happens when you convert between
a function pointer and a data pointer (including void*). This allows
implementing C on machines where function pointers have more bits than
can fit into any data pointers, or the other way around. As far as ANSI
C is concerned, there’s nothing wrong with an implementation where
converting between void* and a function pointer produces a completely
bogus value, or always produces a null pointer, or even crashes.

But, of course, dlsym() is not an ANSI C function. It’s a POSIX
function. If POSIX promises that you can meaningfully convert the void
pointer returned by dlsym() to a function pointer, then it is the
implementor’s job to give you a compiler that allows fulfilling that
promise, even if ANSI C doesn’t require it. POSIX doesn’t like this
restriction because it wants to think of itself as an OS and library
standard rather than a language standard, but it’s a fact of life.

Our documentation looks to be based off of the UNIX’98 standard (which
shows a very similar example). I’m also pretty sure there is much code
in the world which banks on this type of behaviour as well (like the
assumption there is 8 bits to an unsigned char). At best it’s unclear
to me that dlsym() can portably and safely be used to directly extract
function pointers, at worst it doesn’t work.

It’s safe, at least for now. This is what POSIX says about it in the
Rationale section of dlsym()
(http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html):

The ISO C standard does not require that pointers to functions
can be cast back and forth to pointers to data. Indeed, the
ISO C standard does not require that an object of type void *
can hold a pointer to a function. Implementations supporting
the XSI extension, however, do require that an object of type
void * can hold a pointer to a function. The result of
converting a pointer to a function into a pointer to another
data type (except void *) is still undefined, however. Note
that compilers conforming to the ISO C standard are required to
generate a warning if a conversion from a void * pointer to a
function pointer is attempted as in:

fptr = (int (*)(int))dlsym(handle, “my_function”);

Due to the problem noted here, a future version may either add
a new function to return function pointers, or the current
interface may be deprecated in favor of two new functions: one
that returns data pointers and the other that returns function
pointers.

BTW This problem is a relatively new discovery to the POSIX and Unix
folks – that explains why the author of the above didn’t get it quite
right (ISO C does not require any warnings). I imagine that after they
notice that mmap(PROT_EXEC) has a similar issue, they will eventually
learn how to live with the fact that POSIX can’t be easily implemented
on wierd machines that have big function pointers and small data
pointers, just like they have accepted the fact that it can’t be
implemented on wierd machines where unsigned char is not exactly 8 bits
wide.