svn commit: branches/uClibc-nptl/ldso/ldso/arm

kraj at uclibc.org kraj at uclibc.org
Thu Jul 10 01:19:06 UTC 2008


Author: kraj
Date: 2008-07-09 18:19:04 -0700 (Wed, 09 Jul 2008)
New Revision: 22733

Log:
Handle ARM TLS relocations

Modified:
   branches/uClibc-nptl/ldso/ldso/arm/dl-sysdep.h
   branches/uClibc-nptl/ldso/ldso/arm/elfinterp.c
   branches/uClibc-nptl/ldso/ldso/arm/resolve.S


Changeset:
Modified: branches/uClibc-nptl/ldso/ldso/arm/dl-sysdep.h
===================================================================
--- branches/uClibc-nptl/ldso/ldso/arm/dl-sysdep.h	2008-07-10 01:16:18 UTC (rev 22732)
+++ branches/uClibc-nptl/ldso/ldso/arm/dl-sysdep.h	2008-07-10 01:19:04 UTC (rev 22733)
@@ -5,6 +5,9 @@
  * Copyright (C) 2000-2004 by Erik Andersen <andersen at codepoet.org>
  */
 
+#ifndef _ARCH_DL_SYSDEP
+#define _ARCH_DL_SYSDEP
+
 /* Define this if the system uses RELOCA.  */
 #undef ELF_USES_RELOCA
 #include <elf.h>
@@ -60,12 +63,16 @@
 #define ADDR_ALIGN 0xfff
 #define OFFS_ALIGN 0x7ffff000
 
-/* 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_PLT iff TYPE describes relocation of a PLT entry or
+   TLS variable, so undefined references 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_ARM_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT)	\
+#define elf_machine_type_class(type)									\
+  ((((type) == R_ARM_JUMP_SLOT || (type) == R_ARM_TLS_DTPMOD32			\
+     || (type) == R_ARM_TLS_DTPOFF32 || (type) == R_ARM_TLS_TPOFF32)	\
+    * ELF_RTYPE_CLASS_PLT)												\
    | (((type) == R_ARM_COPY) * ELF_RTYPE_CLASS_COPY))
 
 /* Return the link-time address of _DYNAMIC.  Conveniently, this is the
@@ -140,3 +147,4 @@
 		*reloc_addr += load_off;
 	} while (--relative_count);
 }
+#endif /* !_ARCH_DL_SYSDEP */

Modified: branches/uClibc-nptl/ldso/ldso/arm/elfinterp.c
===================================================================
--- branches/uClibc-nptl/ldso/ldso/arm/elfinterp.c	2008-07-10 01:16:18 UTC (rev 22732)
+++ branches/uClibc-nptl/ldso/ldso/arm/elfinterp.c	2008-07-10 01:19:04 UTC (rev 22733)
@@ -78,7 +78,7 @@
 
 	/* Get the address of the GOT entry */
 	new_addr = _dl_find_hash(symname, tpnt->symbol_scope,
-				 tpnt, ELF_RTYPE_CLASS_PLT);
+				 tpnt, ELF_RTYPE_CLASS_PLT, NULL);
 	if (unlikely(!new_addr)) {
 		_dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
 			_dl_progname, symname);
@@ -196,28 +196,41 @@
 	int symtab_index;
 	unsigned long *reloc_addr;
 	unsigned long symbol_addr;
+	const Elf32_Sym *def = 0;
+	struct elf_resolve *def_mod = 0;
 	int goof = 0;
 
-	reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
+	reloc_addr = (unsigned long *) (tpnt->loadaddr
+                                    + (unsigned long) rpnt->r_offset);
+
 	reloc_type = ELF32_R_TYPE(rpnt->r_info);
 	symtab_index = ELF32_R_SYM(rpnt->r_info);
 	symbol_addr = 0;
 
 	if (symtab_index) {
+		def = _dl_find_hash(strtab + symtab[symtab_index].st_name,
+                                scope, tpnt,
+                                elf_machine_type_class(reloc_type),
+                                &def_mod);
 
-		symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name,
-				scope, tpnt, elf_machine_type_class(reloc_type));
-
+		if (def)
+			symbol_addr = def->st_value + def_mod->loadaddr;
 		/*
 		 * 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 (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK) {
-			_dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
-				     _dl_progname, strtab + symtab[symtab_index].st_name);
-			_dl_exit (1);
+		else if (ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK) {
+			/* This may be non-fatal if called from dlopen.  */
+			return 1;
+
 		}
+	} else {
+        /* Relocs against STN_UNDEF are usually treated as using a
+           symbol value of zero, and using the module containing the
+           reloc itself.  */
+		def = &symtab[symtab_index];
+		def_mod = tpnt;
 	}
 
 #if defined (__SUPPORT_LD_DEBUG__)
@@ -273,6 +286,20 @@
 				_dl_memcpy((void *) reloc_addr,
 					   (void *) symbol_addr, symtab[symtab_index].st_size);
 				break;
+#if USE_TLS
+			case R_ARM_TLS_DTPMOD32:
+				*reloc_addr = def_mod->l_tls_modid;
+				break;
+
+			case R_ARM_TLS_DTPOFF32:
+				*reloc_addr += def->st_value;
+				break;
+
+			case R_ARM_TLS_TPOFF32:
+				CHECK_STATIC_TLS ((struct link_map *) def_mod);
+				*reloc_addr += (def->st_value + def_mod->l_tls_offset);
+				break;
+#endif
 			default:
 				return -1; /*call _dl_exit(1) */
 		}

Modified: branches/uClibc-nptl/ldso/ldso/arm/resolve.S
===================================================================
--- branches/uClibc-nptl/ldso/ldso/arm/resolve.S	2008-07-10 01:16:18 UTC (rev 22732)
+++ branches/uClibc-nptl/ldso/ldso/arm/resolve.S	2008-07-10 01:19:04 UTC (rev 22733)
@@ -95,6 +95,10 @@
 
 #include <features.h>
 
+#define sl r10
+#define fp r11
+#define ip r12
+
  .text
  .align 4      @ 16 byte boundary and there are 32 bytes below (arm case)
  #if !defined(__thumb__) || defined(__thumb2__)




More information about the uClibc-cvs mailing list