[CFR] Adding a function to rtld-elf.so, how to handle Symbol.map?

Ian Lepore ian at FreeBSD.org
Thu Jul 17 18:10:11 UTC 2014


On Thu, 2014-07-17 at 20:29 +0300, Konstantin Belousov wrote:
> On Thu, Jul 17, 2014 at 11:09:50AM -0600, Ian Lepore wrote:
> > On Thu, 2014-07-17 at 03:45 +0300, Konstantin Belousov wrote:
> > > On Wed, Jul 16, 2014 at 03:23:53PM -0600, Ian Lepore wrote:
> > > > I need to add an ARM-specific function to rtld-elf.so to help locate
> > > > exception unwind info in shared objects.  I'm confused about how to add
> > > > the function to Symbol.map... do I have to add a 1.4 section because it
> > > > was first added in FreeBSD 11, or does it go into an existing section
> > > > because it doesn't introduce changes to an existing ABI?
> > > > 
> > > > -- Ian
> > > > 
> > > There is no sense in continuing iterating if the pc value falls into the
> > > segment range, but segment does not have PF_X permission bit; there may
> > > be at most one segment mapped at the given address.  That said, the
> > > _rtld_addr_phdr() is more suitable function to use for findexcb(), since
> > > it provides you with the needed object directly, without iterating on
> > > the previously loaded objects.
> > > 
> > 
> > Oh, I didn't know about _rtld_addr_phdr(), I'll rewrite it using that to
> > do the iteration part for me.
> The _rtld_addr_phdr() does not iterate.  If it did it job by calling
> dl_iterate_phdr(3), it would be part of libc.
> 

Are we talking about the same function?  It looks to me like
_rtld_addr_phdr() calls obj_from_addr(), which iterates like:

     for (obj = obj_list;  obj != NULL;  obj = obj->next)
	[ return this object if the addr is within it ]


> > 
> > > Why do you need the __gnu_Unwind_Find_exidx() be the part of rtld ?
> > > I do not see a reason for e.g. libc/arm not be a good home for the
> > > function.  We try to not extend the ABI of rtld unless there are
> > > very strong reasons.  The function implementation does not use any
> > > internal rtld structures, only external interfaces.
> > > 
> > 
> > There is a default version of this function which works only for
> > statically linked apps in contrib/gcc/config/arm/unwind-arm.c, defined
> > with __attribute__((weak)).  For dynamically linked apps, a replacement
> > version needs to override the weak-linkage default to find the exidx
> > data in one of the loaded objects.  The scheme is similar to the stuff
> > in libc/gen/dlfcn.c.
> Our rtld does not follow ELF standard.  There is no requirement that
> weak symbol has lower resolution priority than non-weak.  Basically,
> libc dlfcn.c relies on the bug.  Eventually, this stuff should be only
> compiled for the libc.a.
> 
> > 
> > I did some looking around and Netbsd, Android, and Risc Os all
> > implemented this in their dynamic loaders, so that seemed like the way
> > to go.  Android actually puts a function with this __gnu name in its
> > libc, but all that function does is calls dl_unwind_find_exidx() which
> > is implemented in their loader.
> > 
> > I've just discovered that the arm unwind support code that will arrive
> > as part of clang 3.5 appears to assume the Android way of things unless
> > __LINUX__ is defined, so maybe it would be good to follow that model
> > ourselves and add a dl_unwind_find_exidx() stub to libc/gen/dlfcn.c and
> > name the new implementation in ld-elf to match.
> I think that Android/__LINUX__ combination does the right thing, by
> providing the symbol in libc. A libc implementation does not need any
> additional service from rtld, except already existing _rtld_addr_phdr().
> 

The implementation (whether in libc or elsewhere) needs to behave
differently depending on whether shared objects are involved or not.
The mechanism other projects are using to achieve this is weak
implementation for static linked, overridden by a dynamic implementation
in ld-elf.so.  If we don't use that mechanism, then what mechanism do we
have for using either #ifdef in the code or .ifdef in a makefile to
change the implementation based on building libc.a vs libc.so?

> Also, I recomment you to look at the libc helper __elf_phdr_match_addr
> from libc/gen/elf_utils.c, which, together with _rtld_addr_phdr(),
> seemingly implements 70% of your function.
> 

I don't see how __elf_phdr_match_addr helps at all.  It appears to just
return true/false to say whether an address falls within a shared object
or not.  _rtld_addr_phdr() will already give me the shared object that
contains the address, then I still have to iterate the entries in the
phdr to find the address and size of the exidx section.

> That said, please do not put MD function in dlfcn.c, but into a new
> file in libc/arm/gen/.
> > 
> > > What is the supposed use of the function ? Are the consumers of it
> > > only the system libraries, or is it planned that user binaries will
> > > reference the symbol directly from their symbol table ?
> > 
> > > If first, the place for the symbol is FBSDprivate_1.0 namespace.
> > > If it must be used directly by binaries for which we provide ABI
> > > stability guarantees, than FBSD_1.4 is the correct namespace to
> > > put the symbol into, regardless of the shared object which would
> > > provide it.
> > > 
> > 
> > The problem I'm working on is making C++ exceptions work on ARM.  The
> > exception handling code in the C++ runtime support libraries needs this.
> > It might also be needed by other code/tools that need to generate
> > backtraces or otherwise use the unwind info.
> > 
> > I guess I don't know how/where to draw the line between public and
> > private libraries.  If someone is using a version of gcc later than
> > 4.2.1, the libraries that are part of that toolchain are going to
> > reference this function name, that feels kind of public to me.
> 
> I.e., it is provided so that third-party runtime libraries could use
> the symbol to do the lookup of exception tables ? This indeed sounds
> as the public interface, so it should go into FBSD_1.4.

-- Ian




More information about the freebsd-hackers mailing list