This patch, from Quinn Jensen <jensenq@lineo.com>, adds MIPS support

to busybox insmod.  Thanks Quinn!!!
 -Erik
This commit is contained in:
Eric Andersen 2001-02-24 20:01:53 +00:00
parent afeb96547f
commit 2bf658d5cd
2 changed files with 254 additions and 8 deletions

131
insmod.c
View File

@ -20,6 +20,12 @@
* I've only tested the code on mpc8xx platforms in big-endian mode. * I've only tested the code on mpc8xx platforms in big-endian mode.
* Did some cleanup and added BB_USE_xxx_ENTRIES... * Did some cleanup and added BB_USE_xxx_ENTRIES...
* *
* Quinn Jensen <jensenq@lineo.com> added MIPS support 23-Feb-2001.
* based on modutils-2.4.2
* MIPS specific support for Elf loading and relocation.
* Copyright 1996, 1997 Linux International.
* Contributed by Ralf Baechle <ralf@gnu.ai.mit.edu>
*
* Based almost entirely on the Linux modutils-2.3.11 implementation. * Based almost entirely on the Linux modutils-2.3.11 implementation.
* Copyright 1996, 1997 Linux International. * Copyright 1996, 1997 Linux International.
* New implementation contributed by Richard Henderson <rth@tamu.edu> * New implementation contributed by Richard Henderson <rth@tamu.edu>
@ -80,6 +86,10 @@
#define BB_GOT_ENTRY_SIZE 4 #define BB_GOT_ENTRY_SIZE 4
#endif #endif
#if defined(__mips__)
// neither used
#endif
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
//--------modutils module.h, lines 45-242 //--------modutils module.h, lines 45-242
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -109,7 +119,7 @@
#ifndef MODUTILS_MODULE_H #ifndef MODUTILS_MODULE_H
static const int MODUTILS_MODULE_H = 1; static const int MODUTILS_MODULE_H = 1;
#ident "$Id: insmod.c,v 1.49 2001/02/20 20:47:08 andersen Exp $" #ident "$Id: insmod.c,v 1.50 2001/02/24 20:01:53 andersen Exp $"
/* This file contains the structures used by the 2.0 and 2.1 kernels. /* This file contains the structures used by the 2.0 and 2.1 kernels.
We do not use the kernel headers directly because we do not wish We do not use the kernel headers directly because we do not wish
@ -315,7 +325,7 @@ int delete_module(const char *);
#ifndef MODUTILS_OBJ_H #ifndef MODUTILS_OBJ_H
static const int MODUTILS_OBJ_H = 1; static const int MODUTILS_OBJ_H = 1;
#ident "$Id: insmod.c,v 1.49 2001/02/20 20:47:08 andersen Exp $" #ident "$Id: insmod.c,v 1.50 2001/02/24 20:01:53 andersen Exp $"
/* The relocatable object is manipulated using elfin types. */ /* The relocatable object is manipulated using elfin types. */
@ -361,6 +371,18 @@ static const int MODUTILS_OBJ_H = 1;
#define Elf32_RelM Elf32_Rela #define Elf32_RelM Elf32_Rela
#define ELFDATAM ELFDATA2MSB #define ELFDATAM ELFDATA2MSB
#elif defined(__mips__)
#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
#define SHT_RELM SHT_REL
#define Elf32_RelM Elf32_Rel
#ifdef __MIPSEB__
#define ELFDATAM ELFDATA2MSB
#endif
#ifdef __MIPSEL__
#define ELFDATAM ELFDATA2LSB
#endif
#elif defined(__i386__) #elif defined(__i386__)
/* presumably we can use these for anything but the SH and ARM*/ /* presumably we can use these for anything but the SH and ARM*/
@ -594,6 +616,15 @@ struct arch_got_entry {
}; };
#endif #endif
#if defined(__mips__)
struct mips_hi16
{
struct mips_hi16 *next;
Elf32_Addr *addr;
Elf32_Addr value;
};
#endif
struct arch_file { struct arch_file {
struct obj_file root; struct obj_file root;
#if defined(BB_USE_PLT_ENTRIES) #if defined(BB_USE_PLT_ENTRIES)
@ -602,6 +633,9 @@ struct arch_file {
#if defined(BB_USE_GOT_ENTRIES) #if defined(BB_USE_GOT_ENTRIES)
struct obj_section *got; struct obj_section *got;
#endif #endif
#if defined(__mips__)
struct mips_hi16 *mips_hi16_list;
#endif
}; };
struct arch_symbol { struct arch_symbol {
@ -724,6 +758,9 @@ struct obj_file *arch_new_file(void)
#if defined(BB_USE_GOT_ENTRIES) #if defined(BB_USE_GOT_ENTRIES)
f->got = NULL; f->got = NULL;
#endif #endif
#if defined(__mips__)
f->mips_hi16_list = NULL;
#endif
return &f->root; return &f->root;
} }
@ -783,6 +820,8 @@ arch_apply_relocation(struct obj_file *f,
case R_386_NONE: case R_386_NONE:
#elif defined(__powerpc__) #elif defined(__powerpc__)
case R_PPC_NONE: case R_PPC_NONE:
#elif defined(__mips__)
case R_MIPS_NONE:
#endif #endif
break; break;
@ -794,6 +833,8 @@ arch_apply_relocation(struct obj_file *f,
case R_386_32: case R_386_32:
#elif defined(__powerpc__) #elif defined(__powerpc__)
case R_PPC_ADDR32: case R_PPC_ADDR32:
#elif defined(__mips__)
case R_MIPS_32:
#endif #endif
*loc += v; *loc += v;
break; break;
@ -812,6 +853,86 @@ arch_apply_relocation(struct obj_file *f,
break; break;
#endif #endif
#if defined(__mips__)
case R_MIPS_26:
if (v % 4)
ret = obj_reloc_dangerous;
if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
ret = obj_reloc_overflow;
*loc =
(*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
0x03ffffff);
break;
case R_MIPS_HI16:
{
struct mips_hi16 *n;
/* We cannot relocate this one now because we don't know the value
of the carry we need to add. Save the information, and let LO16
do the actual relocation. */
n = (struct mips_hi16 *) xmalloc(sizeof *n);
n->addr = loc;
n->value = v;
n->next = ifile->mips_hi16_list;
ifile->mips_hi16_list = n;
break;
}
case R_MIPS_LO16:
{
unsigned long insnlo = *loc;
Elf32_Addr val, vallo;
/* Sign extend the addend we extract from the lo insn. */
vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
if (ifile->mips_hi16_list != NULL) {
struct mips_hi16 *l;
l = ifile->mips_hi16_list;
while (l != NULL) {
struct mips_hi16 *next;
unsigned long insn;
/* The value for the HI16 had best be the same. */
assert(v == l->value);
/* Do the HI16 relocation. Note that we actually don't
need to know anything about the LO16 itself, except where
to find the low 16 bits of the addend needed by the LO16. */
insn = *l->addr;
val =
((insn & 0xffff) << 16) +
vallo;
val += v;
/* Account for the sign extension that will happen in the
low bits. */
val =
((val >> 16) +
((val & 0x8000) !=
0)) & 0xffff;
insn = (insn & ~0xffff) | val;
*l->addr = insn;
next = l->next;
free(l);
l = next;
}
ifile->mips_hi16_list = NULL;
}
/* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
val = v + vallo;
insnlo = (insnlo & ~0xffff) | (val & 0xffff);
*loc = insnlo;
break;
}
#endif
#if defined(__arm__) #if defined(__arm__)
#elif defined(__sh__) #elif defined(__sh__)
case R_SH_REL32: case R_SH_REL32:
@ -977,6 +1098,7 @@ arch_apply_relocation(struct obj_file *f,
int arch_create_got(struct obj_file *f) int arch_create_got(struct obj_file *f)
{ {
#if defined(BB_USE_GOT_ENTRIES) || defined(BB_USE_PLT_ENTRIES)
struct arch_file *ifile = (struct arch_file *) f; struct arch_file *ifile = (struct arch_file *) f;
int i; int i;
#if defined(BB_USE_GOT_ENTRIES) #if defined(BB_USE_GOT_ENTRIES)
@ -1097,6 +1219,7 @@ int arch_create_got(struct obj_file *f)
ifile->plt = obj_create_alloced_section(f, ".plt", ifile->plt = obj_create_alloced_section(f, ".plt",
BB_PLT_ENTRY_SIZE, BB_PLT_ENTRY_SIZE,
plt_offset); plt_offset);
#endif
#endif #endif
return 1; return 1;
} }
@ -2772,7 +2895,7 @@ int obj_create_image(struct obj_file *f, char *image)
for (sec = f->load_order; sec; sec = sec->load_next) { for (sec = f->load_order; sec; sec = sec->load_next) {
char *secimg; char *secimg;
if (sec->header.sh_size == 0) if (sec->contents == 0 || sec->header.sh_size == 0)
continue; continue;
secimg = image + (sec->header.sh_addr - base); secimg = image + (sec->header.sh_addr - base);
@ -2857,7 +2980,7 @@ struct obj_file *obj_load(FILE * fp)
sec->header = section_headers[i]; sec->header = section_headers[i];
sec->idx = i; sec->idx = i;
switch (sec->header.sh_type) { if(sec->header.sh_size) switch (sec->header.sh_type) {
case SHT_NULL: case SHT_NULL:
case SHT_NOTE: case SHT_NOTE:
case SHT_NOBITS: case SHT_NOBITS:

View File

@ -20,6 +20,12 @@
* I've only tested the code on mpc8xx platforms in big-endian mode. * I've only tested the code on mpc8xx platforms in big-endian mode.
* Did some cleanup and added BB_USE_xxx_ENTRIES... * Did some cleanup and added BB_USE_xxx_ENTRIES...
* *
* Quinn Jensen <jensenq@lineo.com> added MIPS support 23-Feb-2001.
* based on modutils-2.4.2
* MIPS specific support for Elf loading and relocation.
* Copyright 1996, 1997 Linux International.
* Contributed by Ralf Baechle <ralf@gnu.ai.mit.edu>
*
* Based almost entirely on the Linux modutils-2.3.11 implementation. * Based almost entirely on the Linux modutils-2.3.11 implementation.
* Copyright 1996, 1997 Linux International. * Copyright 1996, 1997 Linux International.
* New implementation contributed by Richard Henderson <rth@tamu.edu> * New implementation contributed by Richard Henderson <rth@tamu.edu>
@ -80,6 +86,10 @@
#define BB_GOT_ENTRY_SIZE 4 #define BB_GOT_ENTRY_SIZE 4
#endif #endif
#if defined(__mips__)
// neither used
#endif
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
//--------modutils module.h, lines 45-242 //--------modutils module.h, lines 45-242
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -109,7 +119,7 @@
#ifndef MODUTILS_MODULE_H #ifndef MODUTILS_MODULE_H
static const int MODUTILS_MODULE_H = 1; static const int MODUTILS_MODULE_H = 1;
#ident "$Id: insmod.c,v 1.49 2001/02/20 20:47:08 andersen Exp $" #ident "$Id: insmod.c,v 1.50 2001/02/24 20:01:53 andersen Exp $"
/* This file contains the structures used by the 2.0 and 2.1 kernels. /* This file contains the structures used by the 2.0 and 2.1 kernels.
We do not use the kernel headers directly because we do not wish We do not use the kernel headers directly because we do not wish
@ -315,7 +325,7 @@ int delete_module(const char *);
#ifndef MODUTILS_OBJ_H #ifndef MODUTILS_OBJ_H
static const int MODUTILS_OBJ_H = 1; static const int MODUTILS_OBJ_H = 1;
#ident "$Id: insmod.c,v 1.49 2001/02/20 20:47:08 andersen Exp $" #ident "$Id: insmod.c,v 1.50 2001/02/24 20:01:53 andersen Exp $"
/* The relocatable object is manipulated using elfin types. */ /* The relocatable object is manipulated using elfin types. */
@ -361,6 +371,18 @@ static const int MODUTILS_OBJ_H = 1;
#define Elf32_RelM Elf32_Rela #define Elf32_RelM Elf32_Rela
#define ELFDATAM ELFDATA2MSB #define ELFDATAM ELFDATA2MSB
#elif defined(__mips__)
#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
#define SHT_RELM SHT_REL
#define Elf32_RelM Elf32_Rel
#ifdef __MIPSEB__
#define ELFDATAM ELFDATA2MSB
#endif
#ifdef __MIPSEL__
#define ELFDATAM ELFDATA2LSB
#endif
#elif defined(__i386__) #elif defined(__i386__)
/* presumably we can use these for anything but the SH and ARM*/ /* presumably we can use these for anything but the SH and ARM*/
@ -594,6 +616,15 @@ struct arch_got_entry {
}; };
#endif #endif
#if defined(__mips__)
struct mips_hi16
{
struct mips_hi16 *next;
Elf32_Addr *addr;
Elf32_Addr value;
};
#endif
struct arch_file { struct arch_file {
struct obj_file root; struct obj_file root;
#if defined(BB_USE_PLT_ENTRIES) #if defined(BB_USE_PLT_ENTRIES)
@ -602,6 +633,9 @@ struct arch_file {
#if defined(BB_USE_GOT_ENTRIES) #if defined(BB_USE_GOT_ENTRIES)
struct obj_section *got; struct obj_section *got;
#endif #endif
#if defined(__mips__)
struct mips_hi16 *mips_hi16_list;
#endif
}; };
struct arch_symbol { struct arch_symbol {
@ -724,6 +758,9 @@ struct obj_file *arch_new_file(void)
#if defined(BB_USE_GOT_ENTRIES) #if defined(BB_USE_GOT_ENTRIES)
f->got = NULL; f->got = NULL;
#endif #endif
#if defined(__mips__)
f->mips_hi16_list = NULL;
#endif
return &f->root; return &f->root;
} }
@ -783,6 +820,8 @@ arch_apply_relocation(struct obj_file *f,
case R_386_NONE: case R_386_NONE:
#elif defined(__powerpc__) #elif defined(__powerpc__)
case R_PPC_NONE: case R_PPC_NONE:
#elif defined(__mips__)
case R_MIPS_NONE:
#endif #endif
break; break;
@ -794,6 +833,8 @@ arch_apply_relocation(struct obj_file *f,
case R_386_32: case R_386_32:
#elif defined(__powerpc__) #elif defined(__powerpc__)
case R_PPC_ADDR32: case R_PPC_ADDR32:
#elif defined(__mips__)
case R_MIPS_32:
#endif #endif
*loc += v; *loc += v;
break; break;
@ -812,6 +853,86 @@ arch_apply_relocation(struct obj_file *f,
break; break;
#endif #endif
#if defined(__mips__)
case R_MIPS_26:
if (v % 4)
ret = obj_reloc_dangerous;
if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
ret = obj_reloc_overflow;
*loc =
(*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
0x03ffffff);
break;
case R_MIPS_HI16:
{
struct mips_hi16 *n;
/* We cannot relocate this one now because we don't know the value
of the carry we need to add. Save the information, and let LO16
do the actual relocation. */
n = (struct mips_hi16 *) xmalloc(sizeof *n);
n->addr = loc;
n->value = v;
n->next = ifile->mips_hi16_list;
ifile->mips_hi16_list = n;
break;
}
case R_MIPS_LO16:
{
unsigned long insnlo = *loc;
Elf32_Addr val, vallo;
/* Sign extend the addend we extract from the lo insn. */
vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
if (ifile->mips_hi16_list != NULL) {
struct mips_hi16 *l;
l = ifile->mips_hi16_list;
while (l != NULL) {
struct mips_hi16 *next;
unsigned long insn;
/* The value for the HI16 had best be the same. */
assert(v == l->value);
/* Do the HI16 relocation. Note that we actually don't
need to know anything about the LO16 itself, except where
to find the low 16 bits of the addend needed by the LO16. */
insn = *l->addr;
val =
((insn & 0xffff) << 16) +
vallo;
val += v;
/* Account for the sign extension that will happen in the
low bits. */
val =
((val >> 16) +
((val & 0x8000) !=
0)) & 0xffff;
insn = (insn & ~0xffff) | val;
*l->addr = insn;
next = l->next;
free(l);
l = next;
}
ifile->mips_hi16_list = NULL;
}
/* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
val = v + vallo;
insnlo = (insnlo & ~0xffff) | (val & 0xffff);
*loc = insnlo;
break;
}
#endif
#if defined(__arm__) #if defined(__arm__)
#elif defined(__sh__) #elif defined(__sh__)
case R_SH_REL32: case R_SH_REL32:
@ -977,6 +1098,7 @@ arch_apply_relocation(struct obj_file *f,
int arch_create_got(struct obj_file *f) int arch_create_got(struct obj_file *f)
{ {
#if defined(BB_USE_GOT_ENTRIES) || defined(BB_USE_PLT_ENTRIES)
struct arch_file *ifile = (struct arch_file *) f; struct arch_file *ifile = (struct arch_file *) f;
int i; int i;
#if defined(BB_USE_GOT_ENTRIES) #if defined(BB_USE_GOT_ENTRIES)
@ -1097,6 +1219,7 @@ int arch_create_got(struct obj_file *f)
ifile->plt = obj_create_alloced_section(f, ".plt", ifile->plt = obj_create_alloced_section(f, ".plt",
BB_PLT_ENTRY_SIZE, BB_PLT_ENTRY_SIZE,
plt_offset); plt_offset);
#endif
#endif #endif
return 1; return 1;
} }
@ -2772,7 +2895,7 @@ int obj_create_image(struct obj_file *f, char *image)
for (sec = f->load_order; sec; sec = sec->load_next) { for (sec = f->load_order; sec; sec = sec->load_next) {
char *secimg; char *secimg;
if (sec->header.sh_size == 0) if (sec->contents == 0 || sec->header.sh_size == 0)
continue; continue;
secimg = image + (sec->header.sh_addr - base); secimg = image + (sec->header.sh_addr - base);
@ -2857,7 +2980,7 @@ struct obj_file *obj_load(FILE * fp)
sec->header = section_headers[i]; sec->header = section_headers[i];
sec->idx = i; sec->idx = i;
switch (sec->header.sh_type) { if(sec->header.sh_size) switch (sec->header.sh_type) {
case SHT_NULL: case SHT_NULL:
case SHT_NOTE: case SHT_NOTE:
case SHT_NOBITS: case SHT_NOBITS: