[PATCH 3/6] ldso: Add ARC support

Vineet Gupta Vineet.Gupta1 at synopsys.com
Fri Nov 15 09:37:53 UTC 2013


On 11/12/2013 07:34 PM, Bernhard Reutner-Fischer wrote:
> I take it you double-checked the table below against the defines in
> include/elf.h

Yes.

>> +static const char *_dl_reltypes_tab[] =
>> +{
> +__asm__(
> +    ".section .text                                             \n"
> +    ".balign 4                                                  \n"
> +    ".global  _start                                            \n"
> .hidden _start ?

yes both global + hidden. Otherwise ld can't seem to find it.

>> diff --git a/ldso/ldso/arc/dl-syscalls.h b/ldso/ldso/arc/dl-syscalls.h
>> new file mode 100644
>> index 000000000000..1ab7b552a217
>> --- /dev/null
>> +++ b/ldso/ldso/arc/dl-syscalls.h
>> @@ -0,0 +1,8 @@
>> +/*
>> + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
>> + *
>> + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
>> + */
>> +
>> +#include "sys/syscall.h"
>> +#include <bits/uClibc_page.h>
> Sounds like it could go with the stub only?

Done.

>> diff --git a/ldso/ldso/arc/dl-sysdep.h b/ldso/ldso/arc/dl-sysdep.h
>> new file mode 100644
>> index 000000000000..642f020f42e1
>> --- /dev/null
>> +++ b/ldso/ldso/arc/dl-sysdep.h
>> @@ -0,0 +1,156 @@
>> +/*
>> + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
>> + *
>> + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
>> + */
>> +
>> +#include "elf.h"
>> +
>> +/*
>> + * Define this if the system uses RELOCA.
>> + */
>> +#define ELF_USES_RELOCA
>> +
>> +/*
>> + * Dynamic Linking ABI for ARCompact ISA
>> + *
>> + * 		      PLT
>> + * 	--------------------------------
>> + *	|  ld r11, [pcl, off-to-GOT[1]  |  0   (20 bytes)
>> + *	|				|  4
>> + * plt0	|  ld r10, [pcl, off-to-GOT[2]	|  8
> table layout seems to be broken here
>
>> + *	|				| 12
>> + *	|  j [r10]			| 16
>> + * 	--------------------------------
>> + * 	|    Base address of GOT	| 20
>> + * 	--------------------------------
>> + *	|  ld r12, [pcl, off-to-GOT[3]  | 24   (12 bytes each)
>> + * plt1 |				|
> .. and here.

All fixed.

>
>> + * 	|  j_s.d  [r12]			| 32
>> + *	|  mov_s  r12, pcl		| 34
>> + * 	--------------------------------
>> + * 	|				| 36
>> + *      ~				~
>> + *      ~				~
>> + * 	|				|
>> + * 	--------------------------------
>> + *
>> + *	     GOT
>> + * 	--------------
>> + * 	|    [0]      |
>> + * 	--------------
>> + * 	|    [1]      |  Module info - setup by ldso
>> + * 	--------------
>> + * 	|    [2]      |  resolver entry point
>> + * 	--------------
>> + * 	|    [3]      |
>> + * 	|    ...      |  Runtime address for function symbols
>> + * 	|    [f]      |
>> + * 	--------------
>> + * 	|    [f+1]    |
>> + * 	|    ...      |  Runtime address for data symbols
>> + * 	|    [last]   |
>> + * 	--------------
>> + */
>> +
>> +/*
>> + * Initialization sequence for a GOT.
>> + * Caller elf_resolve() seeds @GOT_BASE from DT_PLTGOT - which essentially is
>> + * pointer to first PLT entry. The actual GOT base is 5th word in PLT
>> + *
>> + */
>> +#define INIT_GOT(GOT_BASE,MODULE)						\
>> +do {										\
>> +	unsigned long *__plt_base = (unsigned long *)GOT_BASE;			\
>> +	if(MODULE->libtype != program_interpreter)				\
> you sure you need the above?

Nope, Now removed.

>> +		GOT_BASE = (unsigned long *)(__plt_base[5] +			\
>> +			                     (unsigned long)MODULE->loadaddr);	\
>> +	GOT_BASE[1] = (unsigned long) MODULE;				   	\
>> +	GOT_BASE[2] = (unsigned long) _dl_linux_resolve;		   	\
>> +} while(0)
>> +
>> +/* Here we define the magic numbers that this dynamic loader should accept */
>> +#define MAGIC1 EM_ARCOMPACT
>> +#undef  MAGIC2
>> +
>> +/* Used for error messages */
>> +#define ELF_TARGET "ARC"
>> +
>> +struct elf_resolve;
>> +extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt,
>> +					 unsigned int plt_pc);
>> +
>> +extern unsigned __udivmodsi4 (unsigned, unsigned)
>> +  __attribute ((visibility("hidden")));
> yuck ;)
> And please use __foo__ throughout, for attribute, inline.

OK.

>> +
>> +#define do_rem(result, n, base)  ((result) =				\
>> +									\
>> +	__builtin_constant_p (base) ? (n) % (unsigned) (base) :		\
> I'd prefer if you marked that as (__extension__ ({

You mean

-       ({                                                              \
+       __extension__ ({                                       \

If so, done.

However I read man gcc for __extension__, but not sure how it applies here (and
only here).

>> + */
>> +static inline Elf32_Addr elf_machine_dynamic (void) attribute_unused;
>> +static inline Elf32_Addr
> Perhaps you want  __always_inline and in similar spots?

Done for all three

>> +++ b/ldso/ldso/arc/elfinterp.c
>> @@ -0,0 +1,284 @@
>> +/*
>> + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
>> + *
>> + * Lots of code copied from ../i386/elfinterp.c, so:
>> + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
>> + *               David Engel, Hongjiu Lu and Mitch D'Souza
>> + * Copyright (C) 2001-2002, Erik Andersen
>> + * All rights reserved.
>> + *
>> + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
>> + */
>> +#include "ldso.h"
>> +
>> +unsigned long
>> +_dl_linux_resolver(struct elf_resolve *tpnt, unsigned int plt_pc)
>> +{
>> +	ELF_RELOC *this_reloc, *rel_base;
>> +	char *strtab, *symname, *new_addr;
>> +	ElfW(Sym) *symtab;
>> +	int symtab_index;
>> +	unsigned int *got_addr;
>> +	unsigned long plt_base;
>> +	int plt_idx;
>> +
>> +	/* start of .rela.plt */
>> +	rel_base = (ELF_RELOC *)(tpnt->dynamic_info[DT_JMPREL]);
>> +
>> +	/* starts of .plt (addr of PLT0) */
>> +	plt_base = tpnt->dynamic_info[DT_PLTGOT];
>> +
>> +	/*
>> +	 * compute the idx of the yet-unresolved PLT entry in .plt
>> +         * Same idx will be used to find the relo entry in .rela.plt
>> +	 */
> whitespace damage above

Oops - fixed now.

>> +	plt_idx = (plt_pc - plt_base)/0xc  - 2; /* ignoring 2 dummy PLTs */
> magic 12 ?

Added/used #define ARC_PLT_SIZE  12


>> +
>> +	this_reloc = rel_base + plt_idx;
>> +
>> +	symtab_index = ELF_R_SYM(this_reloc->r_info);
>> +	symtab = (ElfW(Sym) *)(intptr_t) (tpnt->dynamic_info[DT_SYMTAB]);
>> +	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB]);
>> +	symname= strtab + symtab[symtab_index].st_name;
>> +
>> +	/* relo-offset to fixup, shd be a .got entry */
>> +	got_addr = (unsigned int *)(this_reloc->r_offset + tpnt->loadaddr);
>> +
>> +	/* Get the address of the GOT entry */
>> +	new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt,
>> +                            ELF_RTYPE_CLASS_PLT, NULL);
>> +
>> +	if (unlikely(!new_addr)) {
>> +		_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
>> +		_dl_exit(1);
>> +	}
>> +
>> +
>> +#if defined (__SUPPORT_LD_DEBUG__)
> please remove braces

All fixed.

>> +static int
>> +_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
>> +		   ELF_RELOC *rpnt);
>> +
>> +static int
>> +_dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
>> +	      ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab);
> Please restructure so you don't need these forward declarations.

Done.

>
> Also, it would be nice if you could switch to using a function pointer
> for the real handler, see all other arches.

I consciously did that micro-optimization to avoid the overhead of an indirect
function pointer for processing each symbol relo.

>> +}
>> diff --git a/ldso/ldso/arc/resolve.S b/ldso/ldso/arc/resolve.S
>> new file mode 100644
>> index 000000000000..8609b339effa
>> --- /dev/null
>> +++ b/ldso/ldso/arc/resolve.S
>> @@ -0,0 +1,59 @@
>> +/*
>> + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
>> + *
>> + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
>> + */
>> +
>> +#define __ASSEMBLY__
> please remove that define.

Done.

>> +
>> +#include <bits/asm.h>
> Can you instead of asm.h use ENTRY and PLTJMP et al from sysdep.h please?
> Everywhere.

I was afraid this will come up :-) Fixed now.
Also while at it, converted ENDFUNC -> END to make it more conventional.

Thanks for your review.

-Vineet


More information about the uClibc mailing list