[uClibc-cvs] svn commit: trunk/uClibc/ldso/ldso/sh64

lethal at uclibc.org lethal at uclibc.org
Thu Mar 31 19:30:39 UTC 2005


Author: lethal
Date: 2005-03-31 12:30:38 -0700 (Thu, 31 Mar 2005)
New Revision: 10066

Log:
sh64 ldso updates and fixes.

Update the sh64 ldso backend to work with Jocke's ldso changes.
We also handle a few more relative relocations, and fix a few spots where
the LSB was being set incorrectly for SHmedia branches.



Modified:
   trunk/uClibc/ldso/ldso/sh64/dl-startup.h
   trunk/uClibc/ldso/ldso/sh64/dl-syscalls.h
   trunk/uClibc/ldso/ldso/sh64/dl-sysdep.h
   trunk/uClibc/ldso/ldso/sh64/elfinterp.c


Changeset:
Modified: trunk/uClibc/ldso/ldso/sh64/dl-startup.h
===================================================================
--- trunk/uClibc/ldso/ldso/sh64/dl-startup.h	2005-03-31 19:18:54 UTC (rev 10065)
+++ trunk/uClibc/ldso/ldso/sh64/dl-startup.h	2005-03-31 19:30:38 UTC (rev 10066)
@@ -5,30 +5,37 @@
 
 asm("" \
 "	.section .text..SHmedia32,\"ax\"\n"				\
-"	.globl _dl_boot\n"						\
-"	.type _dl_boot, @function\n"					\
+"	.globl _start\n"						\
+"	.type _start, @function\n"					\
 "	.align 5\n"							\
-"_dl_boot:\n"								\
+"_start:\n"								\
 "	! Set r12 to point to GOT\n"					\
-"	movi	(((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ3-.)) >> 16) & 65535), r12\n"	\
-"	shori	((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ3-.)) & 65535), r12\n"		\
+"	movi	(((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ3-.)) >> 16) & 0xffff), r12\n"	\
+"	shori	((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ3-.)) & 0xffff), r12\n"		\
 ".LZZZ3:\n"								\
 "	ptrel/u	r12, tr0\n"						\
 "	gettr	tr0, r12	! GOT address\n"			\
 "	add	r18, r63, r11	! save return address - needed?\n"	\
 "	add	r15, r63, r2	! arg = stack pointer\n"		\
-"	pt	_dl_boot2, tr0	! should work even if PIC\n"		\
-"	blink	tr0, r18	! call _dl_boot2 - user EP is in r2\n"	\
+"	pt	_dl_start, tr0	! should work even if PIC\n"		\
+"	blink	tr0, r18	! call _dl_start - user EP is in r2\n"	\
+"	add	r2, r63, r28\n"						\
+"	movi	(((_dl_fini at GOT) >> 16) & 0xffff), r1\n"		\
+"	shori	((_dl_fini at GOT) & 0xffff), r1\n"			\
+"	ldx.l	r1, r12, r2\n"						\
+"	add	r11, r63, r18\n"					\
+"	ptabs/l r28, tr0\n"						\
+"	blink	tr0, r63\n"						\
+"	.size	_start,.-_start\n"
+"	.previous\n"
 );
 
-#define DL_BOOT(X)   static void __attribute_used__ _dl_boot2 (X)
-
 /*
  * 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)
+#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *)ARGS)+1)
 
 /*
  * Here is a macro to perform a relocation.  This is only used when
@@ -38,43 +45,11 @@
  * load address.
  */
 
-/*
- * We need to do this stupidity here as the preprocessor will choke when
- * SYMTAB is NULL if we do this in PERFORM_BOOTSTRAP_RELOC().
- */
-
 #include <elf.h>
 
-static inline int __extract_lsb_from_symtab(Elf32_Sym *symtab)
-{
-	static int lsb = 0;
-
-	/* Check for SHmedia/SHcompact */
-	if (symtab)
-		lsb = symtab->st_other & 4;
-
-	return lsb;
-}
-
-/*
- * While on the subject of stupidity, there appear to be some conflicts with
- * regards to several relocation types as far as binutils is concerned
- * (Barcelona and Madrid both appear to use an out of date elf.h, whereas
- * native Catalonia has all of the necessary definitions. As a workaround,
- * we'll just define them here for sanity..
- */
-#ifndef R_SH_RELATIVE_LOW16
-#  define R_SH_RELATIVE_LOW16		197
-#  define R_SH_RELATIVE_MEDLOW16	198
-#  define R_SH_IMM_LOW16		246
-#  define R_SH_IMM_LOW16_PCREL		247
-#  define R_SH_IMM_MEDLOW16		248
-#  define R_SH_IMM_MEDLOW16_PCREL	249
-#endif
-
 #define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB)		\
 	const unsigned int r_type = ELF32_R_TYPE((RELP)->r_info);	\
-	int lsb = __extract_lsb_from_symtab(SYMTAB);			\
+	int lsb = !!((SYMTAB)->st_other & STO_SH5_ISA32);		\
 									\
 	switch (r_type)	{						\
 	case R_SH_REL32:						\
@@ -157,4 +132,3 @@
 
 #define START()   return _dl_elf_main;
 
-

Modified: trunk/uClibc/ldso/ldso/sh64/dl-syscalls.h
===================================================================
--- trunk/uClibc/ldso/ldso/sh64/dl-syscalls.h	2005-03-31 19:18:54 UTC (rev 10065)
+++ trunk/uClibc/ldso/ldso/sh64/dl-syscalls.h	2005-03-31 19:30:38 UTC (rev 10066)
@@ -4,3 +4,21 @@
 #define __set_errno(X) {(_dl_errno) = (X);}
 #include "sys/syscall.h"
 
+#undef __syscall_return
+#define __syscall_return(type, res)					\
+do {									\
+	/*								\
+	 * Note: when returning from kernel the return value is in r9	\
+	 *								\
+	 * This prevents conflicts between return value and arg1	\
+	 * when dispatching signal handler, in other words makes	\
+	 * life easier in the system call epilogue (see entry.S)	\
+	 */								\
+	register unsigned long __sr2 __asm__ ("r2") = res;		\
+	if ((unsigned long)(res) >= (unsigned long)(-125)) {		\
+		_dl_errno = -(res);					\
+		__sr2 = -1;						\
+	}								\
+	return (type)(__sr2);						\
+} while (0)
+

Modified: trunk/uClibc/ldso/ldso/sh64/dl-sysdep.h
===================================================================
--- trunk/uClibc/ldso/ldso/sh64/dl-sysdep.h	2005-03-31 19:18:54 UTC (rev 10065)
+++ trunk/uClibc/ldso/ldso/sh64/dl-sysdep.h	2005-03-31 19:30:38 UTC (rev 10066)
@@ -44,74 +44,127 @@
 /* Return the link-time address of _DYNAMIC.  Conveniently, this is the
    first element of the GOT.  This must be inlined in a function which
    uses global data.  */
-static inline Elf32_Addr __attribute__ ((unused))
-elf_machine_dynamic (void)
+static inline Elf32_Addr elf_machine_dynamic(void)
 {
 	register Elf32_Addr *got;
-	asm ("mov r12,%0" :"=r" (got));
+
+	/*
+	 * The toolchain adds 32768 to the GOT address, we compensate for
+	 * that in the movi/sub pair.
+	 *
+	 * XXX: If this is cleaned up in the toolchain, we can end up
+	 * saving 2 instructions and subsequently free up r1 from the
+	 * clobber list..
+	 */
+	__asm__ (
+		"movi\t(((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ1-.)) >> 16) & 0xffff), r2\n\t"
+		"shori\t((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ1-.)) & 0xffff), r2\n\t"
+		".LZZZ1:\tptrel/u r2, tr0\n\t"
+		"movi\t32768, r1\n\t"
+		"gettr\ttr0, r2\n\t"
+		"sub\tr2, r1, %0\n\t"
+		: "=r" (got)
+		: /* no inputs */
+		: "r1", "r2", "tr0"
+	);
+
 	return *got;
 }
 
 /* Return the run-time load address of the shared object.  */
-static inline Elf32_Addr __attribute__ ((unused))
-elf_machine_load_address (void)
+static inline Elf32_Addr elf_machine_load_address(void)
 {
 	Elf32_Addr addr;
-	asm ("mov.l 1f,r0\n\
-        mov.l 3f,r2\n\
-        add r12,r2\n\
-        mov.l @(r0,r12),r0\n\
-        bra 2f\n\
-         sub r0,r2\n\
-        .align 2\n\
-        1: .long _dl_boot at GOT\n\
-        3: .long _dl_boot at GOTOFF\n\
-        2: mov r2,%0"
-	     : "=r" (addr) : : "r0", "r1", "r2");
+
+	__asm__ (
+		"movi\t(((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ2-.)) >> 16) & 0xffff), r0\n\t"
+		"shori\t((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ2-.)) & 0xffff), r0\n\t"
+		".LZZZ2:\tptrel/u r0, tr0\n\t"
+		"movi\t(((_dl_start at GOTOFF) >> 16) & 0xffff), r2\n\t"
+		"shori\t((_dl_start at GOTOFF) & 0xffff), r2\n\t"
+		"gettr\ttr0, r0\n\t"
+		"add\tr2, r0, r2\n\t"
+		"movi\t(((_dl_start at GOT) >> 16) & 0xffff), r1\n\t"
+		"shori\t((_dl_start at GOT) & 0xffff), r1\n\t"
+		"ldx.l\tr1, r0, r1\n\t"
+		"sub\tr2, r1, %0\n\t"
+		: "=r" (addr)
+		: /* no inputs */
+		: "r0", "r1", "r2", "tr0"
+	);
+
 	return addr;
 }
 
-#define COPY_UNALIGNED_WORD(swp, twp, align) \
-  { \
-    void *__s = (swp), *__t = (twp); \
-    unsigned char *__s1 = __s, *__t1 = __t; \
-    unsigned short *__s2 = __s, *__t2 = __t; \
-    unsigned long *__s4 = __s, *__t4 = __t; \
-    switch ((align)) \
-    { \
-    case 0: \
-      *__t4 = *__s4; \
-      break; \
-    case 2: \
-      *__t2++ = *__s2++; \
-      *__t2 = *__s2; \
-      break; \
-    default: \
-      *__t1++ = *__s1++; \
-      *__t1++ = *__s1++; \
-      *__t1++ = *__s1++; \
-      *__t1 = *__s1; \
-      break; \
-    } \
-  }
+/*
+ * XXX: As we don't need to worry about r25 clobbering, we could probably
+ * get away with inlining {st,ld}{x,}.l and friends here instead and
+ * forego gcc's idea of code generation.
+ */
+#define COPY_UNALIGNED_WORD(swp, twp, align)		\
+{							\
+	void *__s = (swp), *__t = (twp);		\
+	unsigned char *__s1 = __s, *__t1 = __t;		\
+	unsigned short *__s2 = __s, *__t2 = __t;	\
+	unsigned long *__s4 = __s, *__t4 = __t;		\
+							\
+	switch ((align)) {				\
+	case 0:						\
+		*__t4 = *__s4;				\
+		break;					\
+	case 2:						\
+		*__t2++ = *__s2++;			\
+		*__t2 = *__s2;				\
+		break;					\
+	default:					\
+		*__t1++ = *__s1++;			\
+		*__t1++ = *__s1++;			\
+		*__t1++ = *__s1++;			\
+		*__t1 = *__s1;				\
+		break;					\
+	}						\
+}
 
 static inline void
-elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
-		      Elf32_Word relative_count)
+elf_machine_relative(Elf32_Addr load_off, const Elf32_Addr rel_addr,
+		     Elf32_Word relative_count)
 {
-	Elf32_Addr value;
-	Elf32_Rela * rpnt = (void *)rel_addr;
+	Elf32_Addr value, word;
+	Elf32_Rela *rpnt = (void *)rel_addr;
+	int reloc_type = ELF32_R_TYPE(rpnt->r_info);
 
 	do {
-		Elf32_Addr *const reloc_addr = (void *) (load_off + rpnt->r_offset);
+		Elf32_Addr *const reloc_addr =
+			(void *)(load_off + rpnt->r_offset);
+		int align = (int)reloc_addr & 3;
 
-		if (rpnt->r_addend)
-			value = load_off + rpnt->r_addend;
-		else {
-			COPY_UNALIGNED_WORD (reloc_addr, &value, (int) reloc_addr & 3);
-			value += load_off;
+		switch (reloc_type) {
+		case R_SH_RELATIVE_LOW16:
+			COPY_UNALIGNED_WORD(reloc_addr, &word, align);
+			word &= ~0x3fffc00;
+			value = (rpnt->r_addend + load_off);
+			word |= (value & 0xffff) << 10;
+			COPY_UNALIGNED_WORD(&word, reloc_addr, align);
+			break;
+		case R_SH_RELATIVE_MEDLOW16:
+			COPY_UNALIGNED_WORD(reloc_addr, &word, align);
+			word &= ~0x3fffc00;
+			value = (rpnt->r_addend + load_off) >> 16;
+			word |= (value & 0xffff) << 10;
+			COPY_UNALIGNED_WORD(&word, reloc_addr, align);
+			break;
+		default:
+			if (rpnt->r_addend) {
+				value = load_off + rpnt->r_addend;
+			} else {
+				COPY_UNALIGNED_WORD(reloc_addr, &value, align);
+				value += load_off;
+			}
+
+			COPY_UNALIGNED_WORD(&value, reloc_addr, align);
+			break;
 		}
-		COPY_UNALIGNED_WORD (&value, reloc_addr, (int) reloc_addr & 3);
+
 		rpnt++;
 	} while (--relative_count);
 #undef COPY_UNALIGNED_WORD

Modified: trunk/uClibc/ldso/ldso/sh64/elfinterp.c
===================================================================
--- trunk/uClibc/ldso/ldso/sh64/elfinterp.c	2005-03-31 19:18:54 UTC (rev 10065)
+++ trunk/uClibc/ldso/ldso/sh64/elfinterp.c	2005-03-31 19:30:38 UTC (rev 10066)
@@ -4,7 +4,7 @@
  *
  * SuperH (sh64) ELF shared library loader suppport
  *
- * Copyright (C) 2003  Paul Mundt <lethal at linux-sh.org>
+ * Copyright (C) 2003, 2004, 2005  Paul Mundt <lethal at linux-sh.org>
  *
  * All rights reserved.
  *
@@ -34,16 +34,16 @@
 static const char *_dl_reltypes_tab[] = {
 	/* SHcompact relocs */
 	  [0] =	"R_SH_NONE",		"R_SH_DIR32",
-	  	"R_SH_REL32",		"R_SH_DIR8WPN",
+		"R_SH_REL32",		"R_SH_DIR8WPN",
 	  [4] = "R_SH_IND12W",		"R_SH_DIR8WPL",
-	  	"R_SH_DIR8WPZ",		"R_SH_DIR8BP",
+		"R_SH_DIR8WPZ",		"R_SH_DIR8BP",
 	  [8] = "R_SH_DIR8W",		"R_SH_DIR8L",
 	 [25] = "R_SH_SWITCH16",	"R_SH_SWITCH32",
-	 	"R_SH_USES",		"R_SH_COUNT",
+		"R_SH_USES",		"R_SH_COUNT",
 	 [29] = "R_SH_ALIGN",		"R_SH_CODE",
-	 	"R_SH_DATA",		"R_SH_LABEL",
+		"R_SH_DATA",		"R_SH_LABEL",
 	 [33] = "R_SH_SWITCH8",		"R_SH_GNU_VTINHERIT",
-	 	"R_SH_GNU_VTENTRY",
+		"R_SH_GNU_VTENTRY",
 	[160] = "R_SH_GOT32",		"R_SH_PLT32",
 		"R_SH_COPY",		"R_SH_GLOB_DAT",
 	[164] = "R_SH_JMP_SLOT",	"R_SH_RELATIVE",
@@ -88,7 +88,7 @@
 	tabsize = sizeof(_dl_reltypes_tab)/sizeof(_dl_reltypes_tab[0]);
 	str	= _dl_reltypes_tab[type];
 
-  	if (type >= tabsize || str == NULL)
+	if (type >= tabsize || str == NULL)
 		str =_dl_simple_ltoa(buf, (unsigned long)(type));
 
 	return str;
@@ -295,7 +295,7 @@
 	reloc_type   = ELF32_R_TYPE(rpnt->r_info);
 	symtab_index = ELF32_R_SYM(rpnt->r_info);
 	symbol_addr  = 0;
-	lsb          = symtab[symtab_index].st_other & 4;
+	lsb          = !!(symtab[symtab_index].st_other & STO_SH5_ISA32);
 	symname      = strtab + symtab[symtab_index].st_name;
 	reloc_addr   = (unsigned long *)(intptr_t)
 		(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
@@ -362,7 +362,7 @@
 	case R_SH_IMM_LOW16:
 	case R_SH_IMM_MEDLOW16:
 	    {
-	    	unsigned long word, value;
+		unsigned long word, value;
 
 		word = (unsigned long)reloc_addr & ~0x3fffc00;
 		value = (symbol_addr + rpnt->r_addend) | lsb;
@@ -378,7 +378,7 @@
 	case R_SH_IMM_LOW16_PCREL:
 	case R_SH_IMM_MEDLOW16_PCREL:
 	    {
-	    	unsigned long word, value;
+		unsigned long word, value;
 
 		word = (unsigned long)reloc_addr & ~0x3fffc00;
 		value = symbol_addr + rpnt->r_addend -
@@ -416,7 +416,7 @@
 
 	reloc_type   = ELF32_R_TYPE(rpnt->r_info);
 	symtab_index = ELF32_R_SYM(rpnt->r_info);
-	lsb          = symtab[symtab_index].st_other & 4;
+	lsb          = !!(symtab[symtab_index].st_other & STO_SH5_ISA32);
 	reloc_addr   = (unsigned long *)(intptr_t)
 		(tpnt->loadaddr + (unsigned long)rpnt->r_offset);
 




More information about the uClibc-cvs mailing list