Patch from Paul Mundt (lethal) adding sh64 insmod support for busybox

This commit is contained in:
Eric Andersen 2003-08-13 19:56:33 +00:00
parent 4456f25e8f
commit bf83355dda

View File

@ -2,7 +2,7 @@
/* /*
* Mini insmod implementation for busybox * Mini insmod implementation for busybox
* *
* This version of insmod supports x86, ARM, SH3/4, powerpc, m68k, * This version of insmod supports x86, ARM, SH3/4/5, powerpc, m68k,
* MIPS, and v850e. * MIPS, and v850e.
* *
* Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen
@ -19,6 +19,11 @@
* very minor changes required to also work with StrongArm and presumably * very minor changes required to also work with StrongArm and presumably
* all ARM based systems. * all ARM based systems.
* *
* Paul Mundt <lethal@linux-sh.org> 08-Aug-2003.
* Integrated support for sh64 (SH-5), from preliminary modutils
* patches from Benedict Gaster <benedict.gaster@superh.com>.
* Currently limited to support for 32bit ABI.
*
* Magnus Damm <damm@opensource.se> 22-May-2002. * Magnus Damm <damm@opensource.se> 22-May-2002.
* The plt and got code are now using the same structs. * The plt and got code are now using the same structs.
* Added generic linked list code to fully support PowerPC. * Added generic linked list code to fully support PowerPC.
@ -182,17 +187,18 @@
#define Elf32_RelM Elf32_Rela #define Elf32_RelM Elf32_Rela
#define ELFCLASSM ELFCLASS32 #define ELFCLASSM ELFCLASS32
/* the SH changes have only been tested on the SH4 in =little endian= mode */ /* the SH changes have only been tested in =little endian= mode */
/* I'm not sure about big endian, so let's warn: */ /* I'm not sure about big endian, so let's warn: */
#if (defined(__SH4__) || defined(__SH3__)) && defined(__BIG_ENDIAN__) #if defined(__sh__) && defined(__BIG_ENDIAN__)
#error insmod.c may require changes for use on big endian SH4/SH3 #error insmod.c may require changes for use on big endian SH
#endif #endif
/* it may or may not work on the SH1/SH2... So let's error on those /* it may or may not work on the SH1/SH2... So let's error on those
also */ also */
#if (defined(__sh__) && (!(defined(__SH3__) || defined(__SH4__)))) #if ((!(defined(__SH3__) || defined(__SH4__) || defined(__SH5__)))) && \
#error insmod.c may require changes for non-SH3/SH4 use (defined(__sh__))
#error insmod.c may require changes for SH1 or SH2 use
#endif #endif
#endif #endif
@ -247,7 +253,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.99 2003/07/22 08:56:50 andersen Exp $" #ident "$Id: insmod.c,v 1.100 2003/08/13 19:56:33 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
@ -468,7 +474,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.99 2003/07/22 08:56:50 andersen Exp $" #ident "$Id: insmod.c,v 1.100 2003/08/13 19:56:33 andersen Exp $"
/* The relocatable object is manipulated using elfin types. */ /* The relocatable object is manipulated using elfin types. */
@ -1201,7 +1207,51 @@ arch_apply_relocation(struct obj_file *f,
*loc = v - got; *loc = v - got;
break; break;
#endif #if defined(__SH5__)
case R_SH_IMM_MEDLOW16:
case R_SH_IMM_LOW16:
{
Elf32_Addr word;
if (ELF32_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
v >>= 16;
/*
* movi and shori have the format:
*
* | op | imm | reg | reserved |
* 31..26 25..10 9.. 4 3 .. 0
*
* so we simply mask and or in imm.
*/
word = *loc & ~0x3fffc00;
word |= (v & 0xffff) << 10;
*loc = word;
break;
}
case R_SH_IMM_MEDLOW16_PCREL:
case R_SH_IMM_LOW16_PCREL:
{
Elf32_Addr word;
word = *loc & ~0x3fffc00;
v -= dot;
if (ELF32_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
v >>= 16;
word |= (v & 0xffff) << 10;
*loc = word;
break;
}
#endif /* __SH5__ */
#endif /* __sh__ */
default: default:
printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info)); printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
@ -3470,14 +3520,26 @@ static struct obj_file *obj_load(FILE * fp, int loadprogbits)
/* Insert all symbols into the hash table. */ /* Insert all symbols into the hash table. */
for (j = 1, ++sym; j < nsym; ++j, ++sym) { for (j = 1, ++sym; j < nsym; ++j, ++sym) {
ElfW(Addr) val = sym->st_value;
const char *name; const char *name;
if (sym->st_name) if (sym->st_name)
name = strtab + sym->st_name; name = strtab + sym->st_name;
else else
name = f->sections[sym->st_shndx]->name; name = f->sections[sym->st_shndx]->name;
#if defined(__SH5__)
/*
* For sh64 it is possible that the target of a branch
* requires a mode switch (32 to 16 and back again).
*
* This is implied by the lsb being set in the target
* address for SHmedia mode and clear for SHcompact.
*/
val |= sym->st_other & 4;
#endif
obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx, obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
sym->st_value, sym->st_size); val, sym->st_size);
} }
} }
break; break;