aboutsummaryrefslogtreecommitdiff
path: root/modutils/insmod.c
diff options
context:
space:
mode:
Diffstat (limited to 'modutils/insmod.c')
-rw-r--r--modutils/insmod.c175
1 files changed, 142 insertions, 33 deletions
diff --git a/modutils/insmod.c b/modutils/insmod.c
index 2fa48083b..f53fdadeb 100644
--- a/modutils/insmod.c
+++ b/modutils/insmod.c
@@ -3,12 +3,14 @@
3 * Mini insmod implementation for busybox 3 * Mini insmod implementation for busybox
4 * 4 *
5 * This version of insmod supports x86, ARM, SH3/4, powerpc, m68k, 5 * This version of insmod supports x86, ARM, SH3/4, powerpc, m68k,
6 * and MIPS. 6 * MIPS, and v850e.
7 * 7 *
8 * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen 8 * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen
9 * Copyright (C) 1999,2000,2001 by Erik Andersen <andersee@debian.org> 9 * Copyright (C) 1999,2000,2001,2002 by Erik Andersen <andersee@debian.org>
10 * and Ron Alder <alder@lineo.com> 10 * and Ron Alder <alder@lineo.com>
11 * 11 *
12 * Modified by Miles Bader <miles@gnu.org> to support the NEC V850E.
13 *
12 * Modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4 14 * Modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4
13 * and (theoretically) SH3. I have only tested SH4 in little endian mode. 15 * and (theoretically) SH3. I have only tested SH4 in little endian mode.
14 * 16 *
@@ -104,6 +106,11 @@
104// neither used 106// neither used
105#endif 107#endif
106 108
109#if defined (__v850e__)
110#define CONFIG_USE_PLT_ENTRIES
111#define CONFIG_PLT_ENTRY_SIZE 8
112#endif
113
107//---------------------------------------------------------------------------- 114//----------------------------------------------------------------------------
108//--------modutils module.h, lines 45-242 115//--------modutils module.h, lines 45-242
109//---------------------------------------------------------------------------- 116//----------------------------------------------------------------------------
@@ -133,7 +140,7 @@
133#ifndef MODUTILS_MODULE_H 140#ifndef MODUTILS_MODULE_H
134static const int MODUTILS_MODULE_H = 1; 141static const int MODUTILS_MODULE_H = 1;
135 142
136#ident "$Id: insmod.c,v 1.78 2001/12/29 04:15:13 andersen Exp $" 143#ident "$Id: insmod.c,v 1.79 2002/04/01 09:34:25 miles Exp $"
137 144
138/* This file contains the structures used by the 2.0 and 2.1 kernels. 145/* This file contains the structures used by the 2.0 and 2.1 kernels.
139 We do not use the kernel headers directly because we do not wish 146 We do not use the kernel headers directly because we do not wish
@@ -350,7 +357,7 @@ int delete_module(const char *);
350#ifndef MODUTILS_OBJ_H 357#ifndef MODUTILS_OBJ_H
351static const int MODUTILS_OBJ_H = 1; 358static const int MODUTILS_OBJ_H = 1;
352 359
353#ident "$Id: insmod.c,v 1.78 2001/12/29 04:15:13 andersen Exp $" 360#ident "$Id: insmod.c,v 1.79 2002/04/01 09:34:25 miles Exp $"
354 361
355/* The relocatable object is manipulated using elfin types. */ 362/* The relocatable object is manipulated using elfin types. */
356 363
@@ -449,6 +456,19 @@ static const int MODUTILS_OBJ_H = 1;
449#define SHT_RELM SHT_RELA 456#define SHT_RELM SHT_RELA
450#define Elf32_RelM Elf32_Rela 457#define Elf32_RelM Elf32_Rela
451 458
459#elif defined (__v850e__)
460
461#ifndef EM_CYGNUS_V850 /* grumble */
462#define EM_CYGNUS_V850 0x9080
463#endif
464
465#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
466#define SHT_RELM SHT_RELA
467#define Elf32_RelM Elf32_Rela
468#define ELFDATAM ELFDATA2LSB
469
470#define SYMBOL_PREFIX "_"
471
452#else 472#else
453#error Sorry, but insmod.c does not yet support this architecture... 473#error Sorry, but insmod.c does not yet support this architecture...
454#endif 474#endif
@@ -626,6 +646,12 @@ static int arch_init_module (struct obj_file *f, struct new_module *);
626 646
627 647
628 648
649/* SPFX is always a string, so it can be concatenated to string constants. */
650#ifdef SYMBOL_PREFIX
651#define SPFX SYMBOL_PREFIX
652#else
653#define SPFX ""
654#endif
629 655
630 656
631#define _PATH_MODULES "/lib/modules" 657#define _PATH_MODULES "/lib/modules"
@@ -828,9 +854,22 @@ arch_apply_relocation(struct obj_file *f,
828 case R_PPC_NONE: 854 case R_PPC_NONE:
829#elif defined(__mips__) 855#elif defined(__mips__)
830 case R_MIPS_NONE: 856 case R_MIPS_NONE:
857#elif defined (__v850e__)
858 case R_V850_NONE:
831#endif 859#endif
832 break; 860 break;
833 861
862#if defined (__v850e__)
863 case R_V850_32:
864 /* We write two shorts instead of a long because even
865 32-bit insns only need half-word alignment, but
866 32-bit data needs to be long-word aligned. */
867 v += ((unsigned short *)loc)[0];
868 v += ((unsigned short *)loc)[1] << 16;
869 ((unsigned short *)loc)[0] = v & 0xffff;
870 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
871 break;
872#else /* !__v850e__ */
834#if defined(__sh__) 873#if defined(__sh__)
835 case R_SH_DIR32: 874 case R_SH_DIR32:
836#elif defined(__arm__) 875#elif defined(__arm__)
@@ -846,6 +885,8 @@ arch_apply_relocation(struct obj_file *f,
846#endif 885#endif
847 *loc += v; 886 *loc += v;
848 break; 887 break;
888#endif /* __v850e__ */
889
849#if defined(__mc68000__) 890#if defined(__mc68000__)
850 case R_68K_8: 891 case R_68K_8:
851 if (v > 0xff) 892 if (v > 0xff)
@@ -1001,6 +1042,9 @@ arch_apply_relocation(struct obj_file *f,
1001#if defined(__powerpc__) 1042#if defined(__powerpc__)
1002 case R_PPC_REL24: 1043 case R_PPC_REL24:
1003#endif 1044#endif
1045#if defined (__v850e__)
1046 case R_V850_22_PCREL:
1047#endif
1004 /* find the plt entry and initialize it if necessary */ 1048 /* find the plt entry and initialize it if necessary */
1005 assert(isym != NULL); 1049 assert(isym != NULL);
1006 1050
@@ -1021,18 +1065,33 @@ arch_apply_relocation(struct obj_file *f,
1021 ip[2] = 0x7d6903a6; /* mtctr r11 */ 1065 ip[2] = 0x7d6903a6; /* mtctr r11 */
1022 ip[3] = 0x4e800420; /* bctr */ 1066 ip[3] = 0x4e800420; /* bctr */
1023#endif 1067#endif
1068#if defined (__v850e__)
1069 /* We have to trash a register, so we assume that any control
1070 transfer more than 21-bits away must be a function call
1071 (so we can use a call-clobbered register). */
1072 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1073 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
1074#endif
1024 pe->inited = 1; 1075 pe->inited = 1;
1025 } 1076 }
1026 1077
1027 /* relative distance to target */ 1078 /* relative distance to target */
1028 v -= dot; 1079 v -= dot;
1029 /* if the target is too far away.... */ 1080 /* if the target is too far away.... */
1030 if ((int)v < -0x02000000 || (int)v >= 0x02000000) { 1081#if defined (__arm__) || defined (__powerpc__)
1031 /* go via the plt */ 1082 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
1032 v = plt + pe->offset - dot; 1083#elif defined (__v850e__)
1033 } 1084 if ((Elf32_Sword)v > 0x1fffff || (Elf32_Sword)v < (Elf32_Sword)-0x200000)
1085#endif
1086 /* go via the plt */
1087 v = plt + pe->offset - dot;
1088
1089#if defined (__v850e__)
1090 if (v & 1)
1091#else
1034 if (v & 3) 1092 if (v & 3)
1035 ret = obj_reloc_dangerous; 1093#endif
1094 ret = obj_reloc_dangerous;
1036 1095
1037 /* merge the offset into the instruction. */ 1096 /* merge the offset into the instruction. */
1038#if defined(__arm__) 1097#if defined(__arm__)
@@ -1044,6 +1103,17 @@ arch_apply_relocation(struct obj_file *f,
1044#if defined(__powerpc__) 1103#if defined(__powerpc__)
1045 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc); 1104 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
1046#endif 1105#endif
1106#if defined (__v850e__)
1107 /* We write two shorts instead of a long because even 32-bit insns
1108 only need half-word alignment, but the 32-bit data write needs
1109 to be long-word aligned. */
1110 ((unsigned short *)loc)[0] =
1111 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1112 | ((v >> 16) & 0x3f); /* offs high part */
1113 ((unsigned short *)loc)[1] =
1114 (v & 0xffff); /* offs low part */
1115#endif
1116
1047 break; 1117 break;
1048#endif /* CONFIG_USE_PLT_ENTRIES */ 1118#endif /* CONFIG_USE_PLT_ENTRIES */
1049 1119
@@ -1203,6 +1273,12 @@ static int arch_create_got(struct obj_file *f)
1203 break; 1273 break;
1204#endif 1274#endif
1205 1275
1276#if defined (__v850e__)
1277 case R_V850_22_PCREL:
1278 pltneeded = 1;
1279 break;
1280#endif
1281
1206#if defined(__arm__) 1282#if defined(__arm__)
1207 case R_ARM_PC24: 1283 case R_ARM_PC24:
1208 case R_ARM_PLT32: 1284 case R_ARM_PLT32:
@@ -1250,8 +1326,8 @@ static int arch_create_got(struct obj_file *f)
1250 pltneeded = 0; 1326 pltneeded = 0;
1251 } 1327 }
1252#endif 1328#endif
1253 }
1254 } 1329 }
1330 }
1255 1331
1256#if defined(CONFIG_USE_GOT_ENTRIES) 1332#if defined(CONFIG_USE_GOT_ENTRIES)
1257 if (got_offset) { 1333 if (got_offset) {
@@ -1610,19 +1686,45 @@ add_symbols_from(
1610 struct new_module_symbol *s; 1686 struct new_module_symbol *s;
1611 size_t i; 1687 size_t i;
1612 int used = 0; 1688 int used = 0;
1689#ifdef SYMBOL_PREFIX
1690 char *name_buf = 0;
1691 size_t name_alloced_size = 0;
1692#endif
1613 1693
1614 for (i = 0, s = syms; i < nsyms; ++i, ++s) { 1694 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
1615 1695 /* Only add symbols that are already marked external.
1616 /* Only add symbols that are already marked external. If we 1696 If we override locals we may cause problems for
1617 override locals we may cause problems for argument initialization. 1697 argument initialization. We will also create a false
1618 We will also create a false dependency on the module. */ 1698 dependency on the module. */
1619 struct obj_symbol *sym; 1699 struct obj_symbol *sym;
1620 1700 char *name = (char *)s->name;
1621 sym = obj_find_symbol(f, (char *) s->name); 1701
1622 if (sym && !ELFW(ST_BIND) (sym->info) == STB_LOCAL) { 1702#ifdef SYMBOL_PREFIX
1623 sym = obj_add_symbol(f, (char *) s->name, -1, 1703 /* Prepend SYMBOL_PREFIX to the symbol's name (the
1624 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE), 1704 kernel exports `C names', but module object files
1625 idx, s->value, 0); 1705 reference `linker names'). */
1706 size_t extra = sizeof SYMBOL_PREFIX;
1707 size_t name_size = strlen (name) + extra;
1708 if (name_size > name_alloced_size) {
1709 name_alloced_size = name_size * 2;
1710 name_buf = alloca (name_alloced_size);
1711 }
1712 strcpy (name_buf, SYMBOL_PREFIX);
1713 strcpy (name_buf + extra - 1, name);
1714 name = name_buf;
1715#endif /* SYMBOL_PREFIX */
1716
1717 sym = obj_find_symbol(f, name);
1718 if (sym && !(ELFW(ST_BIND) (sym->info) == STB_LOCAL)) {
1719#ifdef SYMBOL_PREFIX
1720 /* Put NAME_BUF into more permanent storage. */
1721 name = xmalloc (name_size);
1722 strcpy (name, name_buf);
1723#endif
1724 sym = obj_add_symbol(f, name, -1,
1725 ELFW(ST_INFO) (STB_GLOBAL,
1726 STT_NOTYPE),
1727 idx, s->value, 0);
1626 /* Did our symbol just get installed? If so, mark the 1728 /* Did our symbol just get installed? If so, mark the
1627 module as "used". */ 1729 module as "used". */
1628 if (sym->secidx == idx) 1730 if (sym->secidx == idx)
@@ -2012,9 +2114,9 @@ old_init_module(const char *m_name, struct obj_file *f,
2012 /* Fill in routines. */ 2114 /* Fill in routines. */
2013 2115
2014 routines.init = 2116 routines.init =
2015 obj_symbol_final_value(f, obj_find_symbol(f, "init_module")); 2117 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
2016 routines.cleanup = 2118 routines.cleanup =
2017 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module")); 2119 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
2018 2120
2019 /* Whew! All of the initialization is complete. Collect the final 2121 /* Whew! All of the initialization is complete. Collect the final
2020 module image and give it to the kernel. */ 2122 module image and give it to the kernel. */
@@ -2053,7 +2155,7 @@ static int
2053new_process_module_arguments(struct obj_file *f, int argc, char **argv) 2155new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2054{ 2156{
2055 while (argc > 0) { 2157 while (argc > 0) {
2056 char *p, *q, *key; 2158 char *p, *q, *key, *sym_name;
2057 struct obj_symbol *sym; 2159 struct obj_symbol *sym;
2058 char *contents, *loc; 2160 char *contents, *loc;
2059 int min, max, n; 2161 int min, max, n;
@@ -2076,7 +2178,14 @@ new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2076 return 0; 2178 return 0;
2077 } 2179 }
2078 2180
2079 sym = obj_find_symbol(f, key); 2181#ifdef SYMBOL_PREFIX
2182 sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
2183 strcpy (sym_name, SYMBOL_PREFIX);
2184 strcat (sym_name, key);
2185#else
2186 sym_name = key;
2187#endif
2188 sym = obj_find_symbol(f, sym_name);
2080 2189
2081 /* Also check that the parameter was not resolved from the kernel. */ 2190 /* Also check that the parameter was not resolved from the kernel. */
2082 if (sym == NULL || sym->secidx > SHN_HIRESERVE) { 2191 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
@@ -2440,9 +2549,9 @@ static int new_create_this_module(struct obj_file *f, const char *m_name)
2440 sizeof(struct new_module)); 2549 sizeof(struct new_module));
2441 memset(sec->contents, 0, sizeof(struct new_module)); 2550 memset(sec->contents, 0, sizeof(struct new_module));
2442 2551
2443 obj_add_symbol(f, "__this_module", -1, 2552 obj_add_symbol(f, SPFX "__this_module", -1,
2444 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0, 2553 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2445 sizeof(struct new_module)); 2554 sizeof(struct new_module));
2446 2555
2447 obj_string_patch(f, sec->idx, offsetof(struct new_module, name), 2556 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
2448 m_name); 2557 m_name);
@@ -2468,7 +2577,7 @@ static int new_create_module_ksymtab(struct obj_file *f)
2468 if (!sec) 2577 if (!sec)
2469 return 0; 2578 return 0;
2470 2579
2471 tm = obj_find_symbol(f, "__this_module"); 2580 tm = obj_find_symbol(f, SPFX "__this_module");
2472 dep = (struct new_module_ref *) sec->contents; 2581 dep = (struct new_module_ref *) sec->contents;
2473 for (i = 0; i < n_ext_modules; ++i) 2582 for (i = 0; i < n_ext_modules; ++i)
2474 if (ext_modules[i].used) { 2583 if (ext_modules[i].used) {
@@ -2554,9 +2663,9 @@ new_init_module(const char *m_name, struct obj_file *f,
2554 } 2663 }
2555 2664
2556 module->init = 2665 module->init =
2557 obj_symbol_final_value(f, obj_find_symbol(f, "init_module")); 2666 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
2558 module->cleanup = 2667 module->cleanup =
2559 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module")); 2668 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
2560 2669
2561 sec = obj_find_section(f, "__ex_table"); 2670 sec = obj_find_section(f, "__ex_table");
2562 if (sec) { 2671 if (sec) {
@@ -3201,9 +3310,9 @@ static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
3201static void hide_special_symbols(struct obj_file *f) 3310static void hide_special_symbols(struct obj_file *f)
3202{ 3311{
3203 static const char *const specials[] = { 3312 static const char *const specials[] = {
3204 "cleanup_module", 3313 SPFX "cleanup_module",
3205 "init_module", 3314 SPFX "init_module",
3206 "kernel_version", 3315 SPFX "kernel_version",
3207 NULL 3316 NULL
3208 }; 3317 };
3209 3318