[PATCH v3 3/7] ldso: Add ARC support

Vineet Gupta Vineet.Gupta1 at synopsys.com
Fri Dec 20 14:11:06 UTC 2013


On 12/20/2013 06:59 PM, Bernhard Reutner-Fischer wrote:
> On Fri, Dec 13, 2013 at 02:49:22PM +0530, Vineet Gupta wrote:
>> Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
>> ---
>>  ldso/ldso/arc/dl-debug.h    |  68 +++++++++++
>>  ldso/ldso/arc/dl-startup.h  |  89 ++++++++++++++
>>  ldso/ldso/arc/dl-syscalls.h |   5 +
>>  ldso/ldso/arc/dl-sysdep.h   | 150 ++++++++++++++++++++++++
>>  ldso/ldso/arc/elfinterp.c   | 279 ++++++++++++++++++++++++++++++++++++++++++++
>>  ldso/ldso/arc/resolve.S     |  57 +++++++++
>>  6 files changed, 648 insertions(+)
>>  create mode 100644 ldso/ldso/arc/dl-debug.h
>>  create mode 100644 ldso/ldso/arc/dl-startup.h
>>  create mode 100644 ldso/ldso/arc/dl-syscalls.h
>>  create mode 100644 ldso/ldso/arc/dl-sysdep.h
>>  create mode 100644 ldso/ldso/arc/elfinterp.c
>>  create mode 100644 ldso/ldso/arc/resolve.S
>>
>> diff --git a/ldso/ldso/arc/dl-debug.h b/ldso/ldso/arc/dl-debug.h
>> new file mode 100644
>> index 000000000000..ff559f27fa31
>> --- /dev/null
>> +++ b/ldso/ldso/arc/dl-debug.h
>> @@ -0,0 +1,68 @@
>> +/*
>> + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
>> + *
>> + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
>> + */
>> +static const char *_dl_reltypes_tab[] =
>> +{
>> +	"R_ARC_NONE",		/* 0 */
>> +	"R_ARC_8",
>> +	"R_ARC_16",
>> +	"R_ARC_24",
>> +	"R_ARC_32",
>> +	"R_ARC_B26",		/* 5 */
>> +	"R_ARC_B22_PCREL",
>> +	"R_ARC_H30",
>> +	"R_ARC_N8",
>> +	"R_ARC_N16",
>> +	"R_ARC_N24",		/* 10 */
>> +	"R_ARC_N32",
>> +	"R_ARC_SDA",
>> +	"R_ARC_SECTOFF",
>> +	"R_ARC_S21H_PCREL",
>> +	"R_ARC_S21W_PCREL",	/* 15 */
>> +	"R_ARC_S25H_PCREL",
>> +	"R_ARC_S25W_PCREL",
>> +	"R_ARC_SDA32",
>> +	"R_ARC_SDA_LDST",
>> +	"R_ARC_SDA_LDST1",	/* 20 */
>> +	"R_ARC_SDA_LDST2",
>> +	"R_ARC_SDA16_LD",
>> +	"R_ARC_SDA16_LD1",
>> +	"R_ARC_SDA16_LD2",
>> +	"R_ARC_S13_PCREL",	/* 25 */
>> +	"R_ARC_W",
>> +	"R_ARC_32_ME",
>> +	"R_ARC_N32_ME",
>> +	"R_ARC_SECTOFF_ME",
>> +	"R_ARC_SDA32_ME",	/* 30 */
>> +	"R_ARC_W_ME",
>> +	"R_ARC_H30_ME",
>> +	"R_ARC_SECTOFF_U8",
>> +	"R_ARC_SECTOFF_S9",
>> +	"R_AC_SECTOFF_U8",	/* 35 */
>> +	"R_AC_SECTOFF_U8_1",
>> +	"R_AC_SECTOFF_U8_2",
>> +	"R_AC_SECTOFF_S9",
>> +	"R_AC_SECTOFF_S9_1",
>> +	"R_AC_SECTOFF_S9_2",	/* 40 */
>> +	"R_ARC_SECTOFF_ME_1",
>> +	"R_ARC_SECTOFF_ME_2",
>> +	"R_ARC_SECTOFF_1",
>> +	"R_ARC_SECTOFF_2",
>> +	"",			/* 45 */
>> +	"",
>> +	"",
>> +	"",
>> +	"",
>> +	"R_ARC_PC32",		/* 50 */
>> +	"R_ARC_GOTPC32",
>> +	"R_ARC_PLT32",
>> +	"R_ARC_COPY",
>> +	"R_ARC_GLOB_DAT",
>> +	"R_ARC_JMP_SLOT",	/* 55 */
>> +	"R_ARC_RELATIVE",
>> +	"R_ARC_GOTOFF",
>> +	"R_ARC_GOTPC",
>> +	"R_ARC_GOT32",
>> +};
>> diff --git a/ldso/ldso/arc/dl-startup.h b/ldso/ldso/arc/dl-startup.h
>> new file mode 100644
>> index 000000000000..4a8d5d786b63
>> --- /dev/null
>> +++ b/ldso/ldso/arc/dl-startup.h
>> @@ -0,0 +1,89 @@
>> +/*
>> + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
>> + *
>> + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
>> + */
>> +
>> +/*
>> + * vineetg: Refactoring/cleanup of loader entry point
>> + *  Removed 6 useless insns
>> + * Joern Improved it even further:
>> + *  -better insn scheduling
>> + *  -no need for conditional code for _dl_skip_args
>> + *  -use of assembler .&2 expressions vs. @gotpc refs (avoids need for GP)
>> + *
>> + * What this code does:
>> + *  -ldso starts execution here when kernel returns from execve()
>> + *  -calls into generic ldso entry point _dl_start( )
>> + *  -optionally adjusts argc for executable if exec passed as cmd
>> + *  -calls into app main with address of finaliser
>> + */
>> +__asm__(
>> +    ".section .text                                             \n"
>> +    ".align 4                                                  	\n"
>> +    ".global _start                                             \n"
>> +    ".hidden _start                                             \n"
>> +    ".type  _start, at function                                    \n"
>> +
>> +    "_start:                                                    \n"
>> +    "   ; ldso entry point, returns app entry point             \n"
>> +    "   bl.d    _dl_start                                       \n"
>> +    "   mov_s   r0, sp          ; pass ptr to aux vector tbl    \n"
>> +
>> +    "   ; If ldso ran as cmd with executable file nm as arg     \n"
>> +    "   ; as arg, skip the extra args calc by dl_start()        \n"
> 
> too many "as arg"

Fixed.

> 
>> +    "   ld_s    r1, [sp]       ; orig argc from aux-vec Tbl     \n"
>> +#ifdef STAR_9000535888_FIXED
> 
> what is that STAR_9000535888_FIXED thing, can we remove this?


That's SNPS internal bug number for a pending gas issue. This requires a
gcc/binutils fix (@pcl and related relos) which is available in the NPTL branches
of those tools - so not ready for prime time just yet. I will send out an update
at appropriate time.

> 
>> +    "   ld      r12, [pcl, _dl_skip_args-.+(.&2)]               \n"
>> +#else
>> +    "   add     r12, pcl, _dl_skip_args-.+(.&2)                 \n"
>> +    "   ld      r12, [r12]                                      \n"
>> +#endif
>> +
>> +    "   add     r2, pcl, _dl_fini-.+(.&2)   ; finalizer         \n"
>> +
>> +    "   add2    sp, sp, r12    ; discard argv entries from stack\n"
>> +    "   sub_s   r1, r1, r12    ; adjusted argc, on stack        \n"
>> +    "   st_s    r1, [sp]                                        \n"
>> +
>> +    "   j_s.d   [r0]           ; app entry point                \n"
>> +    "   mov_s   r0, r2         ; ptr to finalizer _dl_fini      \n"
>> +
>> +    ".size  _start,.-_start                                     \n"
>> +    ".previous                                                  \n"
>> +);
>> +
>> +/*
>> + * Get a pointer to the argv array.  On many platforms this can be just
>> + * the address if the first argument, on other platforms we need to
>> + * do something a little more subtle here.
>> + */
>> +#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long*) ARGS + 1)
>> +
>> +/*
>> + * Dynamic loader bootstrapping:
>> + * Since we don't modify text at runtime, these can only be data relos
>> + * (so safe to assume that they are word aligned).
>> + * And also they HAVE to be RELATIVE relos only
>> + * @RELP is the relo entry being processed
>> + * @REL is the pointer to the address we are relocating.
>> + * @SYMBOL is the symbol involved in the relocation
>> + * @LOAD is the load address.
>> + */
>> +
>> +#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB)		\
>> +do {									\
>> +	int type = ELF32_R_TYPE((RELP)->r_info);			\
>> +	if (likely(type == R_ARC_RELATIVE))				\
>> +		*REL += (unsigned long) LOAD;				\
>> +	else								\
>> +		_dl_exit(1);						\
>> +}while(0)
>> +
>> +/*
>> + * This will go away once we have DT_RELACOUNT
>> + */
>> +#define ARCH_NEEDS_BOOTSTRAP_RELOCS
>> +
>> +/* we dont need to spit out argc, argv etc for debugging */
>> +#define NO_EARLY_SEND_STDERR    1
>> diff --git a/ldso/ldso/arc/dl-syscalls.h b/ldso/ldso/arc/dl-syscalls.h
>> new file mode 100644
>> index 000000000000..a0b5afc9ec78
>> --- /dev/null
>> +++ b/ldso/ldso/arc/dl-syscalls.h
>> @@ -0,0 +1,5 @@
>> +/*
>> + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
>> + *
>> + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
>> + */
> 
> I would have added a
> /* stub for arch-specific syscall issues */
> but ok as is.
> 

Added as requested.

>> diff --git a/ldso/ldso/arc/dl-sysdep.h b/ldso/ldso/arc/dl-sysdep.h
>> new file mode 100644
>> index 000000000000..dfde3323373b
>> --- /dev/null
>> +++ b/ldso/ldso/arc/dl-sysdep.h
>> @@ -0,0 +1,150 @@
>> +/*
>> + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
>> + *
>> + * Licensed under the LGPL v2.1 or later, 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
>> + *	|				| 12
>> + *	|  j [r10]			| 16
>> + *	--------------------------------
>> + *	|    Base address of GOT	| 20
>> + *	--------------------------------
>> + *	|  ld r12, [pcl, off-to-GOT[3]  | 24   (12 bytes each)
>> + * plt1 |				|
>> + *	|  j_s.d  [r12]			| 32
> 
> plt0 and plt1 lines are still broken, please fix.

Pretty weird - I'm using TS=8 and GVIM seems to show everything correct. Actually
the plt1 is weirder - if I remove the WS after plt1, it becomes unaligned in
editor. Do I need to fixup all TABs in this table to explicit white space. Can you
please do the fixup yourself if I may so ask.

> 
>> + *	|  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;		\
>> +	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_hidden;
>> +
>> +#define do_rem(result, n, base)  ((result) =				\
>> +									\
>> +	__builtin_constant_p (base) ? (n) % (unsigned) (base) :		\
>> +	__extension__ ({						\
>> +		register unsigned r1 __asm__ ("r1") = (base);		\
>> +									\
>> +		__asm("bl.d @__udivmodsi4` mov r0,%1"			\
> 
> __asm__

Done !

> 
>> +		: "=r" (r1)						\
>> +	        : "r" (n), "r" (r1)					\
>> +	        : "r0", "r2", "r3", "r4", "lp_count", "blink", "cc");	\
>> +									\
>> +		r1;							\
>> +	})								\
>> +)
>> +
>> +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
>> +   PLT entries should not be allowed to define the value.
>> +   ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
>> +   of the main executable's symbols, as for a COPY reloc.  */
>> +#define elf_machine_type_class(type) \
>> +  ((((type) == R_ARC_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)	\
>> +   | (((type) == R_ARC_COPY) * ELF_RTYPE_CLASS_COPY))
>> +
>> +/*
>> + * Get the runtime address of GOT[0]
>> + */
>> +static __always_inline Elf32_Addr elf_machine_dynamic(void)
>> +{
>> +	Elf32_Addr dyn;
>> +
>> +	__asm__("ld %0,[pcl,_DYNAMIC at gotpc]\n\t" : "=r" (dyn));
>> +	return dyn;
>> +
>> +/*
>> + * Another way would have been to simply return GP, which due to some
>> + * PIC reference would be automatically setup by gcc in caller
>> + *	register Elf32_Addr *got __asm__ ("gp"); return *got;
>> + */
>> +}
>> +
>> +/* Return the run-time load address of the shared object.  */
>> +static __always_inline Elf32_Addr elf_machine_load_address(void)
>> +{
>> +    /* To find the loadaddr we subtract the runtime addr of any symbol
>> +     * say _dl_start from it's build-time addr.
>> +     */
>> +	Elf32_Addr addr, tmp;
>> +	__asm__ (
>> +        "ld  %1, [pcl, _dl_start at gotpc] ;build addr of _dl_start   \n"
>> +        "add %0, pcl, _dl_start-.+(.&2) ;runtime addr of _dl_start \n"
>> +        "sub %0, %0, %1                 ;delta                     \n"
>> +        : "=&r" (addr), "=r"(tmp)
>> +    );
>> +	return addr;
>> +}
>> +
>> +static __always_inline void
>> +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
>> +		      Elf32_Word relative_count)
>> +{
>> +	 Elf32_Rel * rpnt = (void *) rel_addr;
>> +	--rpnt;
>> +	do {
>> +		Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset);
>> +		*reloc_addr += load_off;
>> +	} while (--relative_count);
>> +}
>> diff --git a/ldso/ldso/arc/elfinterp.c b/ldso/ldso/arc/elfinterp.c
>> new file mode 100644
>> index 000000000000..a3d741b65c4e
>> --- /dev/null
>> +++ b/ldso/ldso/arc/elfinterp.c
>> @@ -0,0 +1,279 @@
>> +/*
>> + * 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 or later, see the file COPYING.LIB in this tarball.
>> + */
>> +#include "ldso.h"
>> +
>> +#define ARC_PLT_SIZE	12
>> +
>> +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
>> +	 */
>> +	plt_idx = (plt_pc - plt_base)/ARC_PLT_SIZE  - 2; /* ignoring 2 dummy PLTs */
>> +
>> +	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__
>> +	if (_dl_debug_bindings) {
>> +		_dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
>> +		if(_dl_debug_detail)
>> +			_dl_dprintf(_dl_debug_file, "\n\tpatched %x ==> %pc @ %pl\n",
>> +					*got_addr, new_addr, got_addr);
>> +	}
>> +
>> +	if (!_dl_debug_nofixups)
>> +		*got_addr = (unsigned int)new_addr;
>> +#else
>> +	/* Update the .got entry with the runtime address of symbol */
>> +	*got_addr = (unsigned int)new_addr;
>> +#endif
>> +
>> +	/*
>> +	 * Return the new addres, where the asm trampoline will jump to
>> +	 *  after re-setting up the orig args
>> +	 */
>> +	return (unsigned long) new_addr;
>> +}
>> +
>> +
>> +static int
>> +_dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
>> +	     ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)
>> +{
>> +	int reloc_type;
>> +	int symtab_index;
>> +	char *symname;
>> +	unsigned long *reloc_addr;
>> +	unsigned long symbol_addr;
>> +#if defined __SUPPORT_LD_DEBUG__
>> +	unsigned long old_val = 0;
>> +#endif
>> +	struct symbol_ref sym_ref;
>> +
>> +	reloc_addr   = (unsigned long *)(tpnt->loadaddr + rpnt->r_offset);
>> +	reloc_type   = ELF_R_TYPE(rpnt->r_info);
>> +	symtab_index = ELF_R_SYM(rpnt->r_info);
>> +	symbol_addr  = 0;
>> +
>> +	sym_ref.sym = &symtab[symtab_index];
>> +	sym_ref.tpnt = NULL;
>> +
>> +#if defined __SUPPORT_LD_DEBUG__
>> +	if (reloc_addr)
>> +		old_val = *reloc_addr;
>> +#endif
>> +
>> +	if (symtab_index) {
>> +		symname = strtab + symtab[symtab_index].st_name;
>> +		symbol_addr = (unsigned long) _dl_find_hash(symname, scope, tpnt,
>> +				elf_machine_type_class(reloc_type), &sym_ref);
>> +
>> +		/*
>> +		 * We want to allow undefined references to weak symbols,
>> +		 * this might have been intentional. We should not be linking
>> +		 * local symbols here, so all bases should be covered.
>> +		 */
>> +
>> +		if (unlikely(!symbol_addr
>> +		    && ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) {
>> +			/* Non-fatal if called from dlopen, hence different ret code */
>> +			return 1;
>> +		}
>> +	} else if (reloc_type == R_ARC_RELATIVE ) {
>> +		*reloc_addr += tpnt->loadaddr;
>> +		goto log_entry;
>> +	}
>> +
>> +	switch (reloc_type) {
>> +	case R_ARC_32:
>> +		*reloc_addr += symbol_addr + rpnt->r_addend;
>> +		break;
>> +	case R_ARC_PC32:
>> +		*reloc_addr += symbol_addr + rpnt->r_addend - (unsigned long) reloc_addr;
>> +		break;
>> +	case R_ARC_GLOB_DAT:
>> +	case R_ARC_JMP_SLOT:
>> +		*reloc_addr = symbol_addr;
>> +		break;
>> +	case R_ARC_COPY:
>> +		_dl_memcpy((void *) reloc_addr,(void *) symbol_addr,
>> +				symtab[symtab_index].st_size);
>> +		break;
>> +	default:
>> +		return -1;
>> +	}
>> +
>> +log_entry:
>> +#if defined __SUPPORT_LD_DEBUG__
>> +	if(_dl_debug_detail)
> 
> missing space after if
> 
>> +		_dl_dprintf(_dl_debug_file,"\tpatched: %lx ==> %lx @ %pl: addend %x ",
>> +				old_val, *reloc_addr, reloc_addr, rpnt->r_addend);
>> +#endif
>> +
>> +	return 0;
>> +}
>> +
>> +static int
>> +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,
>> +		  ELF_RELOC *rpnt)
>> +{
>> +	int reloc_type;
>> +	unsigned long *reloc_addr;
>> +#if defined __SUPPORT_LD_DEBUG__
>> +	unsigned long old_val;
>> +#endif
>> +
>> +	reloc_addr = (unsigned long *)(tpnt->loadaddr + rpnt->r_offset);
>> +	reloc_type = ELF_R_TYPE(rpnt->r_info);
>> +
>> +#if defined __SUPPORT_LD_DEBUG__
>> +	old_val = *reloc_addr;
>> +#endif
>> +
>> +	switch (reloc_type) {
>> +	case R_ARC_JMP_SLOT:
>> +		*reloc_addr += tpnt->loadaddr;
>> +		break;
>> +	default:
>> +		return -1;
>> +	}
>> +
>> +#if defined __SUPPORT_LD_DEBUG__
>> +	if(_dl_debug_reloc && _dl_debug_detail)
>> +		_dl_dprintf(_dl_debug_file, "\tpatched: %lx ==> %lx @ %pl\n",
>> +				old_val, *reloc_addr, reloc_addr);
>> +#endif
>> +
>> +	return 0;
>> +}
>> +
>> +#define ___DO_LAZY  1
>> +#define ___DO_NOW   2
>> +
>> +static int _dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
>> +		     unsigned long rel_addr, unsigned long rel_size, int type)
>> +{
>> +	unsigned int i;
>> +	char *strtab;
>> +	ElfW(Sym) *symtab;
>> +	ELF_RELOC *rpnt;
>> +	int symtab_index;
>> +	int res = 0;
>> +
>> +	/* Now parse the relocation information */
>> +	rpnt = (ELF_RELOC *)(intptr_t) (rel_addr);
>> +	rel_size = rel_size / sizeof(ELF_RELOC);
>> +
>> +	symtab = (ElfW(Sym) *)(intptr_t) (tpnt->dynamic_info[DT_SYMTAB]);
>> +	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB]);
>> +
>> +	for (i = 0; i < rel_size; i++, rpnt++) {
>> +
>> +		symtab_index = ELF_R_SYM(rpnt->r_info);
>> +
>> +		debug_sym(symtab,strtab,symtab_index);
>> +		debug_reloc(symtab,strtab,rpnt);
>> +
>> +		/* constant propagation subsumes the 'if' */
>> +		if (type == ___DO_LAZY)
>> +			res = _dl_do_lazy_reloc(tpnt, scope, rpnt);
>> +		else
>> +			res = _dl_do_reloc(tpnt, scope, rpnt, symtab, strtab);
>> +
>> +		if (res != 0)
>> +			break;
>> +	}
>> +
>> +	if (unlikely(res != 0)) {
>> +		if (res < 0) {
>> +			int reloc_type = ELF_R_TYPE(rpnt->r_info);
>> +#if defined __SUPPORT_LD_DEBUG__
>> +			_dl_dprintf(2, "can't handle reloc type %s\n ",
>> +				    _dl_reltypes(reloc_type));
>> +#else
>> +			_dl_dprintf(2, "can't handle reloc type %x\n",
>> +				    reloc_type);
>> +#endif
>> +			_dl_exit(-res);
>> +		} else {
>> +			_dl_dprintf(2, "can't resolve symbol\n");
>> +			/* Fall thru to return res */
>> +		}
>> +	}
>> +
>> +	return res;
>> +}
>> +
>> +void
>> +_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
>> +				      unsigned long rel_addr,
>> +				      unsigned long rel_size)
>> +{
>> +	/* This func is called for processing .rela.plt of loaded module(s)
>> +	 * The relo entries handled are JMP_SLOT type for fixing up .got slots
>> +	 * for external function calls.
>> +	 * This function doesn't resolve the slots: that is done lazily at
>> +	 * runtime. The build linker (at least thats what happens for ARC) had
>> +	 * pre-init the .got slots to point to PLT0. All that is done here is
>> +	 * to fix them up to point to load value of PLT0 (as opposed to the
>> +	 * build value).
>> +	 * On ARC, the loadaddr of dyn exec is zero, thus elfaddr == loadaddr
>> +	 * Thus there is no point in adding "0" to values and un-necessarily
>> +	 * stir up the caches and TLB.
>> +	 * For lsdo processing busybox binary, this skips over 380 relo entries
>> +	 */

Added fix for a small typo above "lsdo"

Patch inline below - I'll also post it to list.

--------------------------->
>From d7f194a3d2f834ac73fd9711116b266aef31cd45 Mon Sep 17 00:00:00 2001
From: Vineet Gupta <vgupta at synopsys.com>
Date: Fri, 20 Dec 2013 19:35:23 +0530
Subject: [PATCH] ldso: ARC fixlets (fallouts of Bernhard's review)

Signed-off-by: Vineet Gupta <vgupta at synopsys.com>
---
 ldso/ldso/arc/dl-startup.h  | 2 +-
 ldso/ldso/arc/dl-syscalls.h | 2 ++
 ldso/ldso/arc/dl-sysdep.h   | 2 +-
 ldso/ldso/arc/elfinterp.c   | 4 ++--
 4 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/ldso/ldso/arc/dl-startup.h b/ldso/ldso/arc/dl-startup.h
index 4a8d5d786b63..016155473423 100644
--- a/ldso/ldso/arc/dl-startup.h
+++ b/ldso/ldso/arc/dl-startup.h
@@ -31,7 +31,7 @@ __asm__(
     "   mov_s   r0, sp          ; pass ptr to aux vector tbl    \n"

     "   ; If ldso ran as cmd with executable file nm as arg     \n"
-    "   ; as arg, skip the extra args calc by dl_start()        \n"
+    "   ; skip the extra args calc by dl_start()                \n"
     "   ld_s    r1, [sp]       ; orig argc from aux-vec Tbl     \n"
 #ifdef STAR_9000535888_FIXED
     "   ld      r12, [pcl, _dl_skip_args-.+(.&2)]               \n"
diff --git a/ldso/ldso/arc/dl-syscalls.h b/ldso/ldso/arc/dl-syscalls.h
index a0b5afc9ec78..a3cbb011b555 100644
--- a/ldso/ldso/arc/dl-syscalls.h
+++ b/ldso/ldso/arc/dl-syscalls.h
@@ -3,3 +3,5 @@
  *
  * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
  */
+
+/* stub for arch-specific syscall issues */
diff --git a/ldso/ldso/arc/dl-sysdep.h b/ldso/ldso/arc/dl-sysdep.h
index dfde3323373b..6e2e47c0d29c 100644
--- a/ldso/ldso/arc/dl-sysdep.h
+++ b/ldso/ldso/arc/dl-sysdep.h
@@ -87,7 +87,7 @@ extern unsigned __udivmodsi4(unsigned, unsigned) attribute_hidden;
     __extension__ ({                        \
         register unsigned r1 __asm__ ("r1") = (base);        \
                                     \
-        __asm("bl.d @__udivmodsi4` mov r0,%1"            \
+        __asm__("bl.d @__udivmodsi4` mov r0,%1"            \
         : "=r" (r1)                        \
             : "r" (n), "r" (r1)                    \
             : "r0", "r2", "r3", "r4", "lp_count", "blink", "cc");    \
diff --git a/ldso/ldso/arc/elfinterp.c b/ldso/ldso/arc/elfinterp.c
index a3d741b65c4e..1d4481c6ff05 100644
--- a/ldso/ldso/arc/elfinterp.c
+++ b/ldso/ldso/arc/elfinterp.c
@@ -148,7 +148,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, struct r_scope_elem *scope,

 log_entry:
 #if defined __SUPPORT_LD_DEBUG__
-    if(_dl_debug_detail)
+    if (_dl_debug_detail)
         _dl_dprintf(_dl_debug_file,"\tpatched: %lx ==> %lx @ %pl: addend %x ",
                 old_val, *reloc_addr, reloc_addr, rpnt->r_addend);
 #endif
@@ -263,7 +263,7 @@ _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
      * On ARC, the loadaddr of dyn exec is zero, thus elfaddr == loadaddr
      * Thus there is no point in adding "0" to values and un-necessarily
      * stir up the caches and TLB.
-     * For lsdo processing busybox binary, this skips over 380 relo entries
+     * For ldso processing busybox binary, this skips over 380 relo entries
      */
     if (rpnt->dyn->loadaddr != 0)
         _dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, ___DO_LAZY);
-- 
1.8.1.2




More information about the uClibc mailing list