diff options
Diffstat (limited to 'modutils/insmod.c')
-rw-r--r-- | modutils/insmod.c | 131 |
1 files changed, 127 insertions, 4 deletions
diff --git a/modutils/insmod.c b/modutils/insmod.c index 7af135902..50f272edb 100644 --- a/modutils/insmod.c +++ b/modutils/insmod.c @@ -20,6 +20,12 @@ * I've only tested the code on mpc8xx platforms in big-endian mode. * 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. * Copyright 1996, 1997 Linux International. * New implementation contributed by Richard Henderson <rth@tamu.edu> @@ -80,6 +86,10 @@ #define BB_GOT_ENTRY_SIZE 4 #endif +#if defined(__mips__) +// neither used +#endif + //---------------------------------------------------------------------------- //--------modutils module.h, lines 45-242 //---------------------------------------------------------------------------- @@ -109,7 +119,7 @@ #ifndef MODUTILS_MODULE_H 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. 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 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. */ @@ -361,6 +371,18 @@ static const int MODUTILS_OBJ_H = 1; #define Elf32_RelM Elf32_Rela #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__) /* presumably we can use these for anything but the SH and ARM*/ @@ -594,6 +616,15 @@ struct arch_got_entry { }; #endif +#if defined(__mips__) +struct mips_hi16 +{ + struct mips_hi16 *next; + Elf32_Addr *addr; + Elf32_Addr value; +}; +#endif + struct arch_file { struct obj_file root; #if defined(BB_USE_PLT_ENTRIES) @@ -602,6 +633,9 @@ struct arch_file { #if defined(BB_USE_GOT_ENTRIES) struct obj_section *got; #endif +#if defined(__mips__) + struct mips_hi16 *mips_hi16_list; +#endif }; struct arch_symbol { @@ -724,6 +758,9 @@ struct obj_file *arch_new_file(void) #if defined(BB_USE_GOT_ENTRIES) f->got = NULL; #endif +#if defined(__mips__) + f->mips_hi16_list = NULL; +#endif return &f->root; } @@ -783,6 +820,8 @@ arch_apply_relocation(struct obj_file *f, case R_386_NONE: #elif defined(__powerpc__) case R_PPC_NONE: +#elif defined(__mips__) + case R_MIPS_NONE: #endif break; @@ -794,6 +833,8 @@ arch_apply_relocation(struct obj_file *f, case R_386_32: #elif defined(__powerpc__) case R_PPC_ADDR32: +#elif defined(__mips__) + case R_MIPS_32: #endif *loc += v; break; @@ -812,6 +853,86 @@ arch_apply_relocation(struct obj_file *f, break; #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__) #elif defined(__sh__) case R_SH_REL32: @@ -977,6 +1098,7 @@ arch_apply_relocation(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; int i; #if defined(BB_USE_GOT_ENTRIES) @@ -1098,6 +1220,7 @@ int arch_create_got(struct obj_file *f) BB_PLT_ENTRY_SIZE, plt_offset); #endif +#endif 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) { char *secimg; - if (sec->header.sh_size == 0) + if (sec->contents == 0 || sec->header.sh_size == 0) continue; secimg = image + (sec->header.sh_addr - base); @@ -2857,7 +2980,7 @@ struct obj_file *obj_load(FILE * fp) sec->header = section_headers[i]; sec->idx = i; - switch (sec->header.sh_type) { + if(sec->header.sh_size) switch (sec->header.sh_type) { case SHT_NULL: case SHT_NOTE: case SHT_NOBITS: |