X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=insmod.c;h=0a7cb1e4ab3156fd43d177fbca75a3b176e9e173;hb=3a6da8c183142a2681a2382b63e970f457cf807b;hp=7af135902a9e9e49a0af0534bee265355343b076;hpb=90fe7fea10b69d85c4d53e7061aaf85657136530;p=oweals%2Fbusybox.git diff --git a/insmod.c b/insmod.c index 7af135902..0a7cb1e4a 100644 --- a/insmod.c +++ b/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 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 + * * Based almost entirely on the Linux modutils-2.3.11 implementation. * Copyright 1996, 1997 Linux International. * New implementation contributed by Richard Henderson @@ -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.53 2001/03/22 19:01:16 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.53 2001/03/22 19:01:16 andersen Exp $" /* The relocatable object is manipulated using elfin types. */ @@ -361,6 +371,27 @@ static const int MODUTILS_OBJ_H = 1; #define Elf32_RelM Elf32_Rela #define ELFDATAM ELFDATA2MSB +#elif defined(__mips__) + +/* Account for ELF spec changes. */ +#ifndef EM_MIPS_RS3_LE +#ifdef EM_MIPS_RS4_BE +#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE +#else +#define EM_MIPS_RS3_LE 10 +#endif +#endif /* !EM_MIPS_RS3_LE */ + +#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 +625,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 +642,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 { @@ -680,8 +723,8 @@ unsigned long create_module(const char *name, size_t size) #else _syscall2(unsigned long, create_module, const char *, name, size_t, size) #endif -static char m_filename[BUFSIZ + 1] = "\0"; -static char m_fullName[BUFSIZ + 1] = "\0"; +static char m_filename[BUFSIZ + 1]; +static char m_fullName[BUFSIZ + 1]; /*======================================================================*/ @@ -724,6 +767,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; } @@ -756,7 +802,9 @@ arch_apply_relocation(struct obj_file *f, ElfW(RelM) *rel, ElfW(Addr) v) { struct arch_file *ifile = (struct arch_file *) f; +#if !(defined(__mips__)) struct arch_symbol *isym = (struct arch_symbol *) sym; +#endif ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset); ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset; @@ -783,6 +831,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 +844,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 +864,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 +1109,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) @@ -1097,6 +1230,7 @@ int arch_create_got(struct obj_file *f) ifile->plt = obj_create_alloced_section(f, ".plt", BB_PLT_ENTRY_SIZE, plt_offset); +#endif #endif return 1; } @@ -2183,48 +2317,50 @@ static int new_get_kernel_symbols(void) } n_ext_modules = nmod = ret; - ext_modules = modules = xmalloc(nmod * sizeof(*modules)); - memset(modules, 0, nmod * sizeof(*modules)); /* Collect the modules' symbols. */ - for (i = 0, mn = module_names, m = modules; - i < nmod; ++i, ++m, mn += strlen(mn) + 1) { - struct new_module_info info; - - if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) { - if (errno == ENOENT) { - /* The module was removed out from underneath us. */ - continue; - } - perror_msg("query_module: QM_INFO: %s", mn); - return 0; - } - - syms = xmalloc(bufsize = 1024); - retry_mod_sym_load: - if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) { - switch (errno) { - case ENOSPC: - syms = xrealloc(syms, bufsize = ret); - goto retry_mod_sym_load; - case ENOENT: - /* The module was removed out from underneath us. */ - continue; - default: - perror_msg("query_module: QM_SYMBOLS: %s", mn); + if (nmod){ + ext_modules = modules = xmalloc(nmod * sizeof(*modules)); + memset(modules, 0, nmod * sizeof(*modules)); + for (i = 0, mn = module_names, m = modules; + i < nmod; ++i, ++m, mn += strlen(mn) + 1) { + struct new_module_info info; + + if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) { + if (errno == ENOENT) { + /* The module was removed out from underneath us. */ + continue; + } + perror_msg("query_module: QM_INFO: %s", mn); return 0; } - } - nsyms = ret; - - m->name = mn; - m->addr = info.addr; - m->nsyms = nsyms; - m->syms = syms; - - for (j = 0, s = syms; j < nsyms; ++j, ++s) { - s->name += (unsigned long) syms; + + syms = xmalloc(bufsize = 1024); + retry_mod_sym_load: + if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) { + switch (errno) { + case ENOSPC: + syms = xrealloc(syms, bufsize = ret); + goto retry_mod_sym_load; + case ENOENT: + /* The module was removed out from underneath us. */ + continue; + default: + perror_msg("query_module: QM_SYMBOLS: %s", mn); + return 0; + } + } + nsyms = ret; + + m->name = mn; + m->addr = info.addr; + m->nsyms = nsyms; + m->syms = syms; + + for (j = 0, s = syms; j < nsyms; ++j, ++s) { + s->name += (unsigned long) syms; + } } } @@ -2772,7 +2908,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 +2993,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: