[prev in list] [next in list] [prev in thread] [next in thread] 

List:       busybox
Subject:    [BusyBox] patch to add v850 support to busybox insmod
From:       Miles Bader <miles () lsi ! nec ! co ! jp>
Date:       2002-03-25 23:07:03
[Download RAW message or body]

Hi,

This patch adds support for the v850e processor to busybox's insmod
program.  The patch is against busybox 0.60.0 from uClinux-dist-20020214.

Could you apply it?

Thanks,

-Miles

Patch:


["busybox-insmod-v850.patch" (text/x-patch)]

diff -ruP -X../diff.xcl ../orig/uClinux-dist/user/busybox/insmod.c user/busybox/insmod.c
--- ../orig/uClinux-dist/user/busybox/insmod.c	Thu Feb 14 11:42:15 2002
+++ user/busybox/insmod.c	Tue Mar 26 14:58:37 2002
@@ -6,7 +6,7 @@
  * and MIPS.
  *
  *
- * Copyright (C) 1999,2000,2001 by Lineo, inc.
+ * Copyright (C) 1999,2000,2001, 2002 by Lineo, inc.
  * Written by Erik Andersen <andersen@lineo.com>
  * and Ron Alder <alder@lineo.com>
  *
@@ -106,6 +106,11 @@
 // neither used
 #endif
 
+#if defined (__v850e__)
+#define BB_USE_PLT_ENTRIES
+#define BB_PLT_ENTRY_SIZE 8
+#endif
+
 #ifndef FILENAME_MAX
 #include <limits.h>
 #define FILENAME_MAX NAME_MAX
@@ -451,6 +456,19 @@
 #define SHT_RELM			SHT_RELA
 #define Elf32_RelM			Elf32_Rela
 
+#elif defined (__v850e__)
+
+#ifndef EM_CYGNUS_V850	/* grumble */
+#define EM_CYGNUS_V850 		0x9080
+#endif
+
+#define MATCH_MACHINE(x)	((x) == EM_V850 || (x) == EM_CYGNUS_V850)
+#define SHT_RELM		SHT_RELA
+#define Elf32_RelM		Elf32_Rela
+#define ELFDATAM		ELFDATA2LSB
+
+#define SYMBOL_PREFIX	"_"
+
 #else
 #error Sorry, but insmod.c does not yet support this architecture...
 #endif
@@ -628,6 +646,12 @@
 
 
 
+/* SPFX is always a string, so it can be concatenated to string constants.  */
+#ifdef SYMBOL_PREFIX
+#define SPFX	SYMBOL_PREFIX
+#else
+#define SPFX 	""
+#endif
 
 
 #define _PATH_MODULES	"/lib/modules"
@@ -832,9 +856,22 @@
 	case R_PPC_NONE:
 #elif defined(__mips__)
 	case R_MIPS_NONE:
+#elif defined (__v850e__)
+	case R_V850_NONE:
 #endif
 		break;
 
+#if defined (__v850e__)
+	case R_V850_32:
+		/* We write two shorts instead of a long because even
+		   32-bit insns only need half-word alignment, but
+		   32-bit data needs to be long-word aligned.  */
+		v += ((unsigned short *)loc)[0];
+		v += ((unsigned short *)loc)[1] << 16;
+		((unsigned short *)loc)[0] = v & 0xffff;
+		((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
+		break;
+#else /* !__v850e__ */
 #if defined(__sh__)
 	case R_SH_DIR32:
 #elif defined(__arm__)
@@ -850,6 +887,8 @@
 #endif
 		*loc += v;
 		break;
+#endif /* __v850e__ */
+
 #if defined(__mc68000__)
     case R_68K_8:
 		if (v > 0xff)
@@ -1005,6 +1044,9 @@
 #if defined(__powerpc__)
 	case R_PPC_REL24:
 #endif
+#if defined (__v850e__)
+	case R_V850_22_PCREL:
+#endif
       /* find the plt entry and initialize it if necessary */
       assert(isym != NULL);
 
@@ -1025,18 +1067,33 @@
 	  ip[2] = 0x7d6903a6;			      /* mtctr r11 */
 	  ip[3] = 0x4e800420;			      /* bctr */
 #endif
+#if defined (__v850e__)
+		/* We have to trash a register, so we assume that any control
+		   transfer more than 21-bits away must be a function call
+		   (so we can use a call-clobbered register).  */
+		ip[0] = 0x0621 + ((v & 0xffff) << 16);   /* mov sym, r1 ... */
+		ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
+#endif
 	  	pe->inited = 1;
 	  }
 
       /* relative distance to target */
       v -= dot;
       /* if the target is too far away.... */
-      if ((int)v < -0x02000000 || (int)v >= 0x02000000) {
-	    /* go via the plt */
-	    v = plt + pe->offset - dot;
-	  }
+#if defined (__arm__) || defined (__powerpc__)
+      if ((int)v < -0x02000000 || (int)v >= 0x02000000)
+#elif defined (__v850e__)
+      if ((Elf32_Sword)v > 0x1fffff || (Elf32_Sword)v < (Elf32_Sword)-0x200000)
+#endif
+	      /* go via the plt */
+	      v = plt + pe->offset - dot;
+
+#if defined (__v850e__)
+      if (v & 1)
+#else
       if (v & 3)
-	    ret = obj_reloc_dangerous;
+#endif
+	      ret = obj_reloc_dangerous;
 
       /* merge the offset into the instruction. */
 #if defined(__arm__)
@@ -1048,6 +1105,17 @@
 #if defined(__powerpc__)
       *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
 #endif
+#if defined (__v850e__)
+      /* We write two shorts instead of a long because even 32-bit insns
+	 only need half-word alignment, but the 32-bit data write needs
+	 to be long-word aligned.  */
+      ((unsigned short *)loc)[0] =
+	      (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
+	      | ((v >> 16) & 0x3f);             /* offs high part */
+      ((unsigned short *)loc)[1] =
+	      (v & 0xffff);                    /* offs low part */
+#endif
+
       break;
 #endif /* BB_USE_PLT_ENTRIES */
 
@@ -1207,6 +1275,12 @@
 				break;
 #endif
 
+#if defined (__v850e__)
+			case R_V850_22_PCREL:
+				pltneeded = 1;
+				break;
+#endif
+
 #if defined(__arm__)
 			case R_ARM_PC24:
 			case R_ARM_PLT32:
@@ -1254,8 +1328,8 @@
 				pltneeded = 0;
 			}
 #endif
-			}
 		}
+	}
 
 #if defined(BB_USE_GOT_ENTRIES)
 	if (got_offset) {
@@ -1631,19 +1705,45 @@
 	struct new_module_symbol *s;
 	size_t i;
 	int used = 0;
+#ifdef SYMBOL_PREFIX
+	char *name_buf = 0;
+	size_t name_alloced_size = 0;
+#endif
 
 	for (i = 0, s = syms; i < nsyms; ++i, ++s) {
-
-		/* Only add symbols that are already marked external.  If we
-		   override locals we may cause problems for argument initialization.
-		   We will also create a false dependency on the module.  */
+		/* Only add symbols that are already marked external.
+		   If we override locals we may cause problems for
+		   argument initialization.  We will also create a false
+		   dependency on the module.  */
 		struct obj_symbol *sym;
+		char *name = (char *)s->name;
 
-		sym = obj_find_symbol(f, (char *) s->name);
-		if (sym && !ELFW(ST_BIND) (sym->info) == STB_LOCAL) {
-			sym = obj_add_symbol(f, (char *) s->name, -1,
-								 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
-								 idx, s->value, 0);
+#ifdef SYMBOL_PREFIX
+		/* Prepend SYMBOL_PREFIX to the symbol's name (the
+		   kernel exports `C names', but module object files
+		   reference `linker names').  */
+		size_t extra = sizeof SYMBOL_PREFIX;
+		size_t name_size = strlen (name) + extra;
+		if (name_size > name_alloced_size) {
+			name_alloced_size = name_size * 2;
+			name_buf = alloca (name_alloced_size);
+		}
+		strcpy (name_buf, SYMBOL_PREFIX);
+		strcpy (name_buf + extra - 1, name);
+		name = name_buf;
+#endif /* SYMBOL_PREFIX */
+
+		sym = obj_find_symbol(f, name);
+		if (sym && !(ELFW(ST_BIND) (sym->info) == STB_LOCAL)) {
+#ifdef SYMBOL_PREFIX
+			/* Put NAME_BUF into more permanent storage.  */
+			name = xmalloc (name_size);
+			strcpy (name, name_buf);
+#endif
+			sym = obj_add_symbol(f, name, -1,
+					     ELFW(ST_INFO) (STB_GLOBAL,
+							    STT_NOTYPE),
+					     idx, s->value, 0);
 			/* Did our symbol just get installed?  If so, mark the
 			   module as "used".  */
 			if (sym->secidx == idx)
@@ -2033,9 +2133,9 @@
 	/* Fill in routines.  */
 
 	routines.init =
-		obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
+		obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
 	routines.cleanup =
-		obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
+		obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
 
 	/* Whew!  All of the initialization is complete.  Collect the final
 	   module image and give it to the kernel.  */
@@ -2461,9 +2561,9 @@
 										   sizeof(struct new_module));
 	memset(sec->contents, 0, sizeof(struct new_module));
 
-	obj_add_symbol(f, "__this_module", -1,
-				   ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
-				   sizeof(struct new_module));
+	obj_add_symbol(f, SPFX "__this_module", -1,
+		       ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
+		       sizeof(struct new_module));
 
 	obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
 					 m_name);
@@ -2489,7 +2589,7 @@
 		if (!sec)
 			return 0;
 
-		tm = obj_find_symbol(f, "__this_module");
+		tm = obj_find_symbol(f, SPFX "__this_module");
 		dep = (struct new_module_ref *) sec->contents;
 		for (i = 0; i < n_ext_modules; ++i)
 			if (ext_modules[i].used) {
@@ -2575,9 +2675,9 @@
 	}
 
 	module->init =
-		obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
+		obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
 	module->cleanup =
-		obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
+		obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
 
 	sec = obj_find_section(f, "__ex_table");
 	if (sec) {
@@ -3223,9 +3323,9 @@
 static void hide_special_symbols(struct obj_file *f)
 {
 	static const char *const specials[] = {
-		"cleanup_module",
-		"init_module",
-		"kernel_version",
+		SPFX "cleanup_module",
+		SPFX "init_module",
+		SPFX "kernel_version",
 		NULL
 	};
 

-- 
I'm beginning to think that life is just one long Yoko Ono album; no rhyme
or reason, just a lot of incoherent shrieks and then it's over.  --Ian Wolff


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic