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

Konstantin Belousov kostikbel at gmail.com
Thu Jul 17 00:45:45 UTC 2014


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.

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.

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.

> diff -r 63a383d5fd3e libexec/rtld-elf/Symbol.map
> --- libexec/rtld-elf/Symbol.map	Thu May 01 08:14:39 2014 -0600
> +++ libexec/rtld-elf/Symbol.map	Wed Jul 16 15:06:30 2014 -0600
> @@ -20,6 +20,7 @@ FBSD_1.0 {
>  
>  FBSD_1.3 {
>      fdlopen;
> +    __gnu_Unwind_Find_exidx;
>  };
>  
>  FBSDprivate_1.0 {
> diff -r 63a383d5fd3e libexec/rtld-elf/arm/Makefile.inc
> --- libexec/rtld-elf/arm/Makefile.inc	Thu May 01 08:14:39 2014 -0600
> +++ libexec/rtld-elf/arm/Makefile.inc	Wed Jul 16 15:06:30 2014 -0600
> @@ -1,1 +1,5 @@
>  # $FreeBSD: head/libexec/rtld-elf/arm/Makefile.inc 130646 2004-06-17 17:53:16Z cognet $
> +
> +SRCS+= find_exidx.c
> +CFLAGS+= -I${TOPSRCDIR}/contrib/libexecinfo
> +
> diff -r 63a383d5fd3e libexec/rtld-elf/arm/find_exidx.c
> --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
> +++ libexec/rtld-elf/arm/find_exidx.c	Wed Jul 16 15:06:30 2014 -0600
> @@ -0,0 +1,103 @@
> +/*-
> + * Copyright (c) 2014 Ian Lepore <ian at freebsd.org>
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +#include <sys/cdefs.h>
> +__FBSDID("$FreeBSD$");
> +
> +#include <sys/types.h>
> +#include <sys/elf_common.h>
> +#include <sys/link_elf.h>
> +#include <machine/elf.h>
> +#include <stddef.h>
> +#include <unwind.h>	/* This is contrib/libexecinfo/unwind.h */
> +
> +/*
> + * ARM EABI unwind helper for dynamically linked code.
> + *
> + * This code iterates all shared objects that have been loaded, looking for one
> + * whose in-memory text address range contains the given PC.  It returns the
> + * address of the exidx section in that shared object along with the number of
> + * entries in that section, or NULL if it wasn't found.  This overrides a
> + * weak-linkage default implementation in the unwinder library that only works
> + * for a static-linked application.
> + */
> +
> +struct cbdata {
> +	_Unwind_Ptr pc;
> +	_Unwind_Ptr exptr;
> +	int         excount;
> +};
> +
> +static int
> +findexcb(struct dl_phdr_info *info, size_t size, void *data)
> +{
> +	struct cbdata * cbd;
> +	const Elf_Phdr *hdr;
> +	Elf_Addr exptr, pc, vaddr;
> +	Elf_Word len;
> +	int i, exlen, found;
> +	const int FOUND_PC = 0x01;
> +	const int FOUND_EX = 0x02;
> +	const int SIZEOF_EIT_ENTRY = 8; /* Not available in a header file. */
> +
> +	cbd = data;
> +	found = 0;
> +	pc = (Elf_Addr)cbd->pc;
> +	for (i = 0, hdr = info->dlpi_phdr; i < info->dlpi_phnum; i++, hdr++) {
> +		vaddr = info->dlpi_addr + hdr->p_vaddr;
> +		len = hdr->p_memsz;
> +		if (hdr->p_type == PT_LOAD && (hdr->p_flags & PF_X) != 0 &&
> +		    pc >= vaddr && pc < vaddr + len) {
> +			found |= FOUND_PC;
> +		} else if (hdr->p_type == PT_ARM_EXIDX) {
> +			found |= FOUND_EX;
> +			exptr = vaddr;
> +			exlen = len;
> +		}
> +		if (found == (FOUND_PC | FOUND_EX)) {
> +			cbd->exptr = (_Unwind_Ptr)(exptr);
> +			cbd->excount = exlen / SIZEOF_EIT_ENTRY;
> +			return (1); /* Stop iterating. */
> +		}
> +	}
> +	return (0); /* Continue iterating with next object. */
> +
> +}
> +
> +_Unwind_Ptr
> +__gnu_Unwind_Find_exidx(_Unwind_Ptr pc, int * pcount)
> +{
> +	struct cbdata cbd;
> +
> +	cbd.pc = pc;
> +	cbd.exptr = NULL;
> +	cbd.excount = 0;
> +	dl_iterate_phdr(findexcb, &cbd);
> +	if (cbd.exptr != NULL)
> +		*pcount = cbd.excount;
> +	return (cbd.exptr);
> +}
> +
> diff -r 63a383d5fd3e sys/arm/include/elf.h
> --- a/sys/arm/include/elf.h	Thu May 01 08:14:39 2014 -0600
> +++ b/sys/arm/include/elf.h	Wed Jul 16 15:06:30 2014 -0600
> @@ -55,6 +55,9 @@ typedef struct {        /* Auxiliary vec
>  
>  #define	ELF_MACHINE_OK(x) ((x) == EM_ARM)
>  
> +/* Unwind info section type */
> +#define	PT_ARM_EXIDX (PT_LOPROC + 1)
> +
>  /*
>   * Relocation types.
>   */

> _______________________________________________
> freebsd-hackers at freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
> To unsubscribe, send any mail to "freebsd-hackers-unsubscribe at freebsd.org"

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.freebsd.org/pipermail/freebsd-hackers/attachments/20140717/c31164f3/attachment.sig>


More information about the freebsd-hackers mailing list