Subject: toolchain/26858: id3tag in pkgsrc/audio/id3lib causes bus error on sparc
To: None <gnats-bugs@gnats.NetBSD.org>
From: None <nakayama@netbsd.org>
List: netbsd-bugs
Date: 09/06/2004 00:40:16
>Number:         26858
>Category:       toolchain
>Synopsis:       id3tag in pkgsrc/audio/id3lib causes bus error on sparc
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    toolchain-manager
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Sep 05 15:41:01 UTC 2004
>Closed-Date:
>Last-Modified:
>Originator:     Takeshi Nakayama
>Release:        NetBSD 2.0_BETA
>Organization:
>Environment:
System: NetBSD nyx 2.0_BETA NetBSD 2.0_BETA (NYX32) #119: Mon Aug 30 21:17:28 JST 2004
Architecture: sparc
Machine: sparc64

>Description:
	libid3-3.8.so.3.0 compiled by pkgsrc/audio/id3lib contains
	a relocation type R_SPARC_UA32, but 32-bit sparc's
	ld.elf_so cannot handle unaligned type. So it occurs bus
	error.

% ldd /usr/pkg/bin/id3tag
/usr/pkg/bin/id3tag:
         -lstdc++.5 => /usr/lib/libstdc++.so.5
         -lm.0 => /usr/lib/libm.so.0
         -lgcc_s.1 => /usr/lib/libgcc_s.so.1
         -lid3-3.8.3 => /usr/pkg/lib/libid3-3.8.so.3
         -lz.0 => /usr/lib/libz.so.0
         -lc.12 => /usr/lib/libsparc_v8.so.0
         -lc.12 => /usr/lib/libc.so.12

% objdump -R /usr/pkg/lib/libid3-3.8.so.3 | grep R_SPARC_UA32
0006435e R_SPARC_UA32      __gxx_personality_v0
00064e15 R_SPARC_UA32      __gxx_personality_v0
00064ea6 R_SPARC_UA32      __gxx_personality_v0
00065781 R_SPARC_UA32      __gxx_personality_v0
000657b2 R_SPARC_UA32      __gxx_personality_v0
000668dd R_SPARC_UA32      __gxx_personality_v0
0006693e R_SPARC_UA32      __gxx_personality_v0
00067935 R_SPARC_UA32      __gxx_personality_v0

>How-To-Repeat:
	Run id3tag in pkgsrc/audio/id3lib on 32-bit sparc.

>Fix:
	Following patch brought from sparc64 seems to fix this
	problem.

Index: mdreloc.c
===================================================================
RCS file: /cvsroot/src/libexec/ld.elf_so/arch/sparc/mdreloc.c,v
retrieving revision 1.33
diff -u -d -r1.33 mdreloc.c
--- mdreloc.c	24 Jul 2003 10:12:29 -0000	1.33
+++ mdreloc.c	5 Sep 2004 15:10:36 -0000
@@ -66,6 +66,7 @@
 #define _RF_P		0x20000000		/* Location relative */
 #define _RF_G		0x10000000		/* GOT offset */
 #define _RF_B		0x08000000		/* Load address relative */
+#define _RF_U		0x04000000		/* Unaligned */
 #define _RF_SZ(s)	(((s) & 0xff) << 8)	/* memory target size */
 #define _RF_RS(s)	( (s) & 0xff)		/* right shift */
 static const int reloc_target_flags[] = {
@@ -92,7 +93,7 @@
 	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* GLOB_DAT */
 				_RF_SZ(32) | _RF_RS(0),		/* JMP_SLOT */
 	      _RF_A|	_RF_B|	_RF_SZ(32) | _RF_RS(0),		/* RELATIVE */
-	_RF_S|_RF_A|		_RF_SZ(32) | _RF_RS(0),		/* UA_32 */
+	_RF_S|_RF_A|	_RF_U|	_RF_SZ(32) | _RF_RS(0),		/* UA_32 */
 
 	/*unknown*/		_RF_SZ(32) | _RF_RS(0),		/* PLT32 */
 	/*unknown*/		_RF_SZ(32) | _RF_RS(0),		/* HIPLT22 */
@@ -107,6 +108,9 @@
 	_RF_S|_RF_A|/*unknown*/	_RF_SZ(32) | _RF_RS(0),		/* HH22 */
 	_RF_S|_RF_A|/*unknown*/	_RF_SZ(32) | _RF_RS(0),		/* HM10 */
 	_RF_S|_RF_A|/*unknown*/	_RF_SZ(32) | _RF_RS(0),		/* LM22 */
+	_RF_S|_RF_A|_RF_P|/*unknown*/	_RF_SZ(32) | _RF_RS(0),	/* PC_HH22 */
+	_RF_S|_RF_A|_RF_P|/*unknown*/	_RF_SZ(32) | _RF_RS(0),	/* PC_HM10 */
+	_RF_S|_RF_A|_RF_P|/*unknown*/	_RF_SZ(32) | _RF_RS(0),	/* PC_LM22 */
 	_RF_S|_RF_A|_RF_P|/*unknown*/	_RF_SZ(32) | _RF_RS(0),	/* WDISP16 */
 	_RF_S|_RF_A|_RF_P|/*unknown*/	_RF_SZ(32) | _RF_RS(0),	/* WDISP19 */
 	/*unknown*/		_RF_SZ(32) | _RF_RS(0),		/* GLOB_JMP */
@@ -124,14 +128,16 @@
 	"GLOB_DAT", "JMP_SLOT", "RELATIVE", "UA_32", "PLT32",
 	"HIPLT22", "LOPLT10", "LOPLT10", "PCPLT22", "PCPLT32",
 	"10", "11", "64", "OLO10", "HH22",
-	"HM10", "LM22", "WDISP16", "WDISP19", "GLOB_JMP",
-	"7", "5", "6"
+	"HM10", "LM22", "PC_HH22", "PC_HM10", "PC_LM22", 
+	"WDISP16", "WDISP19", "GLOB_JMP", "7", "5", "6"
 };
 #endif
 
 #define RELOC_RESOLVE_SYMBOL(t)		((reloc_target_flags[t] & _RF_S) != 0)
 #define RELOC_PC_RELATIVE(t)		((reloc_target_flags[t] & _RF_P) != 0)
 #define RELOC_BASE_RELATIVE(t)		((reloc_target_flags[t] & _RF_B) != 0)
+#define RELOC_UNALIGNED(t)		((reloc_target_flags[t] & _RF_U) != 0)
+#define RELOC_USE_ADDEND(t)		((reloc_target_flags[t] & _RF_A) != 0)
 #define RELOC_TARGET_SIZE(t)		((reloc_target_flags[t] >> 8) & 0xff)
 #define RELOC_VALUE_RIGHTSHIFT(t)	(reloc_target_flags[t] & 0xff)
 
@@ -153,6 +159,7 @@
 	_BM(10), _BM(11), -1,		/* _10, _11, _64 */
 	_BM(10), _BM(22),		/* _OLO10, _HH22 */
 	_BM(10), _BM(22),		/* _HM10, _LM22 */
+	_BM(22), _BM(10), _BM(22),	/* _PC_HH22, _PC_HM10, _PC_LM22 */
 	_BM(16), _BM(19),		/* _WDISP16, _WDISP19 */
 	-1,				/* GLOB_JMP */
 	_BM(7), _BM(5), _BM(6)		/* _7, _5, _6 */
@@ -299,17 +306,41 @@
 		value >>= RELOC_VALUE_RIGHTSHIFT(type);
 		value &= mask;
 
-		/* We ignore alignment restrictions here */
-		*where &= ~mask;
-		*where |= value;
+		if (RELOC_UNALIGNED(type)) {
+			/* Handle unaligned relocations. */
+			Elf_Addr tmp = 0;
+			char *ptr = (char *)where;
+			int i, size = RELOC_TARGET_SIZE(type)/8;
+
+			/* Read it in one byte at a time. */
+			for (i=0; i<size; i++)
+				tmp = (tmp << 8) | ptr[i];
+
+			tmp &= ~mask;
+			tmp |= value;
+
+			/* Write it back out. */
+			for (i=0; i<size; i++)
+				ptr[i] = ((tmp >> (8*i)) & 0xff);
+#ifdef RTLD_DEBUG_RELOC
+			value = (Elf_Word)tmp;
+#endif
+
+		} else {
+			*where &= ~mask;
+			*where |= value;
+#ifdef RTLD_DEBUG_RELOC
+			value = (Elf_Word)*where;
+#endif
+		}
 #ifdef RTLD_DEBUG_RELOC
 		if (RELOC_RESOLVE_SYMBOL(type)) {
 			rdbg(("%s %s in %s --> %p in %s", reloc_names[type],
 			    obj->strtab + obj->symtab[symnum].st_name,
-			    obj->path, (void *)*where, defobj->path));
+			    obj->path, (void *)value, defobj->path));
 		} else {
 			rdbg(("%s in %s --> %p", reloc_names[type],
-			    obj->path, (void *)*where));
+			    obj->path, (void *)value));
 		}
 #endif
 	}
>Release-Note:
>Audit-Trail:
>Unformatted: