diff options
| author | Eric Andersen <andersen@codepoet.org> | 2001-02-24 20:01:53 +0000 |
|---|---|---|
| committer | Eric Andersen <andersen@codepoet.org> | 2001-02-24 20:01:53 +0000 |
| commit | 2bf658d5cd4460a0e0a8a8f3c8dc3b71be05d1ba (patch) | |
| tree | 197b3919ea1f13ac6595f6ddb57b105be4c21333 /modutils | |
| parent | afeb96547fabc8c63e883f7c24aab5638cafbd50 (diff) | |
| download | busybox-w32-2bf658d5cd4460a0e0a8a8f3c8dc3b71be05d1ba.tar.gz busybox-w32-2bf658d5cd4460a0e0a8a8f3c8dc3b71be05d1ba.tar.bz2 busybox-w32-2bf658d5cd4460a0e0a8a8f3c8dc3b71be05d1ba.zip | |
This patch, from Quinn Jensen <jensenq@lineo.com>, adds MIPS support
to busybox insmod. Thanks Quinn!!!
-Erik
Diffstat (limited to 'modutils')
| -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 @@ | |||
| 20 | * I've only tested the code on mpc8xx platforms in big-endian mode. | 20 | * I've only tested the code on mpc8xx platforms in big-endian mode. |
| 21 | * Did some cleanup and added BB_USE_xxx_ENTRIES... | 21 | * Did some cleanup and added BB_USE_xxx_ENTRIES... |
| 22 | * | 22 | * |
| 23 | * Quinn Jensen <jensenq@lineo.com> added MIPS support 23-Feb-2001. | ||
| 24 | * based on modutils-2.4.2 | ||
| 25 | * MIPS specific support for Elf loading and relocation. | ||
| 26 | * Copyright 1996, 1997 Linux International. | ||
| 27 | * Contributed by Ralf Baechle <ralf@gnu.ai.mit.edu> | ||
| 28 | * | ||
| 23 | * Based almost entirely on the Linux modutils-2.3.11 implementation. | 29 | * Based almost entirely on the Linux modutils-2.3.11 implementation. |
| 24 | * Copyright 1996, 1997 Linux International. | 30 | * Copyright 1996, 1997 Linux International. |
| 25 | * New implementation contributed by Richard Henderson <rth@tamu.edu> | 31 | * New implementation contributed by Richard Henderson <rth@tamu.edu> |
| @@ -80,6 +86,10 @@ | |||
| 80 | #define BB_GOT_ENTRY_SIZE 4 | 86 | #define BB_GOT_ENTRY_SIZE 4 |
| 81 | #endif | 87 | #endif |
| 82 | 88 | ||
| 89 | #if defined(__mips__) | ||
| 90 | // neither used | ||
| 91 | #endif | ||
| 92 | |||
| 83 | //---------------------------------------------------------------------------- | 93 | //---------------------------------------------------------------------------- |
| 84 | //--------modutils module.h, lines 45-242 | 94 | //--------modutils module.h, lines 45-242 |
| 85 | //---------------------------------------------------------------------------- | 95 | //---------------------------------------------------------------------------- |
| @@ -109,7 +119,7 @@ | |||
| 109 | #ifndef MODUTILS_MODULE_H | 119 | #ifndef MODUTILS_MODULE_H |
| 110 | static const int MODUTILS_MODULE_H = 1; | 120 | static const int MODUTILS_MODULE_H = 1; |
| 111 | 121 | ||
| 112 | #ident "$Id: insmod.c,v 1.49 2001/02/20 20:47:08 andersen Exp $" | 122 | #ident "$Id: insmod.c,v 1.50 2001/02/24 20:01:53 andersen Exp $" |
| 113 | 123 | ||
| 114 | /* This file contains the structures used by the 2.0 and 2.1 kernels. | 124 | /* This file contains the structures used by the 2.0 and 2.1 kernels. |
| 115 | We do not use the kernel headers directly because we do not wish | 125 | We do not use the kernel headers directly because we do not wish |
| @@ -315,7 +325,7 @@ int delete_module(const char *); | |||
| 315 | #ifndef MODUTILS_OBJ_H | 325 | #ifndef MODUTILS_OBJ_H |
| 316 | static const int MODUTILS_OBJ_H = 1; | 326 | static const int MODUTILS_OBJ_H = 1; |
| 317 | 327 | ||
| 318 | #ident "$Id: insmod.c,v 1.49 2001/02/20 20:47:08 andersen Exp $" | 328 | #ident "$Id: insmod.c,v 1.50 2001/02/24 20:01:53 andersen Exp $" |
| 319 | 329 | ||
| 320 | /* The relocatable object is manipulated using elfin types. */ | 330 | /* The relocatable object is manipulated using elfin types. */ |
| 321 | 331 | ||
| @@ -361,6 +371,18 @@ static const int MODUTILS_OBJ_H = 1; | |||
| 361 | #define Elf32_RelM Elf32_Rela | 371 | #define Elf32_RelM Elf32_Rela |
| 362 | #define ELFDATAM ELFDATA2MSB | 372 | #define ELFDATAM ELFDATA2MSB |
| 363 | 373 | ||
| 374 | #elif defined(__mips__) | ||
| 375 | |||
| 376 | #define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE) | ||
| 377 | #define SHT_RELM SHT_REL | ||
| 378 | #define Elf32_RelM Elf32_Rel | ||
| 379 | #ifdef __MIPSEB__ | ||
| 380 | #define ELFDATAM ELFDATA2MSB | ||
| 381 | #endif | ||
| 382 | #ifdef __MIPSEL__ | ||
| 383 | #define ELFDATAM ELFDATA2LSB | ||
| 384 | #endif | ||
| 385 | |||
| 364 | #elif defined(__i386__) | 386 | #elif defined(__i386__) |
| 365 | 387 | ||
| 366 | /* presumably we can use these for anything but the SH and ARM*/ | 388 | /* presumably we can use these for anything but the SH and ARM*/ |
| @@ -594,6 +616,15 @@ struct arch_got_entry { | |||
| 594 | }; | 616 | }; |
| 595 | #endif | 617 | #endif |
| 596 | 618 | ||
| 619 | #if defined(__mips__) | ||
| 620 | struct mips_hi16 | ||
| 621 | { | ||
| 622 | struct mips_hi16 *next; | ||
| 623 | Elf32_Addr *addr; | ||
| 624 | Elf32_Addr value; | ||
| 625 | }; | ||
| 626 | #endif | ||
| 627 | |||
| 597 | struct arch_file { | 628 | struct arch_file { |
| 598 | struct obj_file root; | 629 | struct obj_file root; |
| 599 | #if defined(BB_USE_PLT_ENTRIES) | 630 | #if defined(BB_USE_PLT_ENTRIES) |
| @@ -602,6 +633,9 @@ struct arch_file { | |||
| 602 | #if defined(BB_USE_GOT_ENTRIES) | 633 | #if defined(BB_USE_GOT_ENTRIES) |
| 603 | struct obj_section *got; | 634 | struct obj_section *got; |
| 604 | #endif | 635 | #endif |
| 636 | #if defined(__mips__) | ||
| 637 | struct mips_hi16 *mips_hi16_list; | ||
| 638 | #endif | ||
| 605 | }; | 639 | }; |
| 606 | 640 | ||
| 607 | struct arch_symbol { | 641 | struct arch_symbol { |
| @@ -724,6 +758,9 @@ struct obj_file *arch_new_file(void) | |||
| 724 | #if defined(BB_USE_GOT_ENTRIES) | 758 | #if defined(BB_USE_GOT_ENTRIES) |
| 725 | f->got = NULL; | 759 | f->got = NULL; |
| 726 | #endif | 760 | #endif |
| 761 | #if defined(__mips__) | ||
| 762 | f->mips_hi16_list = NULL; | ||
| 763 | #endif | ||
| 727 | 764 | ||
| 728 | return &f->root; | 765 | return &f->root; |
| 729 | } | 766 | } |
| @@ -783,6 +820,8 @@ arch_apply_relocation(struct obj_file *f, | |||
| 783 | case R_386_NONE: | 820 | case R_386_NONE: |
| 784 | #elif defined(__powerpc__) | 821 | #elif defined(__powerpc__) |
| 785 | case R_PPC_NONE: | 822 | case R_PPC_NONE: |
| 823 | #elif defined(__mips__) | ||
| 824 | case R_MIPS_NONE: | ||
| 786 | #endif | 825 | #endif |
| 787 | break; | 826 | break; |
| 788 | 827 | ||
| @@ -794,6 +833,8 @@ arch_apply_relocation(struct obj_file *f, | |||
| 794 | case R_386_32: | 833 | case R_386_32: |
| 795 | #elif defined(__powerpc__) | 834 | #elif defined(__powerpc__) |
| 796 | case R_PPC_ADDR32: | 835 | case R_PPC_ADDR32: |
| 836 | #elif defined(__mips__) | ||
| 837 | case R_MIPS_32: | ||
| 797 | #endif | 838 | #endif |
| 798 | *loc += v; | 839 | *loc += v; |
| 799 | break; | 840 | break; |
| @@ -812,6 +853,86 @@ arch_apply_relocation(struct obj_file *f, | |||
| 812 | break; | 853 | break; |
| 813 | #endif | 854 | #endif |
| 814 | 855 | ||
| 856 | #if defined(__mips__) | ||
| 857 | case R_MIPS_26: | ||
| 858 | if (v % 4) | ||
| 859 | ret = obj_reloc_dangerous; | ||
| 860 | if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000)) | ||
| 861 | ret = obj_reloc_overflow; | ||
| 862 | *loc = | ||
| 863 | (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) & | ||
| 864 | 0x03ffffff); | ||
| 865 | break; | ||
| 866 | |||
| 867 | case R_MIPS_HI16: | ||
| 868 | { | ||
| 869 | struct mips_hi16 *n; | ||
| 870 | |||
| 871 | /* We cannot relocate this one now because we don't know the value | ||
| 872 | of the carry we need to add. Save the information, and let LO16 | ||
| 873 | do the actual relocation. */ | ||
| 874 | n = (struct mips_hi16 *) xmalloc(sizeof *n); | ||
| 875 | n->addr = loc; | ||
| 876 | n->value = v; | ||
| 877 | n->next = ifile->mips_hi16_list; | ||
| 878 | ifile->mips_hi16_list = n; | ||
| 879 | break; | ||
| 880 | } | ||
| 881 | |||
| 882 | case R_MIPS_LO16: | ||
| 883 | { | ||
| 884 | unsigned long insnlo = *loc; | ||
| 885 | Elf32_Addr val, vallo; | ||
| 886 | |||
| 887 | /* Sign extend the addend we extract from the lo insn. */ | ||
| 888 | vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000; | ||
| 889 | |||
| 890 | if (ifile->mips_hi16_list != NULL) { | ||
| 891 | struct mips_hi16 *l; | ||
| 892 | |||
| 893 | l = ifile->mips_hi16_list; | ||
| 894 | while (l != NULL) { | ||
| 895 | struct mips_hi16 *next; | ||
| 896 | unsigned long insn; | ||
| 897 | |||
| 898 | /* The value for the HI16 had best be the same. */ | ||
| 899 | assert(v == l->value); | ||
| 900 | |||
| 901 | /* Do the HI16 relocation. Note that we actually don't | ||
| 902 | need to know anything about the LO16 itself, except where | ||
| 903 | to find the low 16 bits of the addend needed by the LO16. */ | ||
| 904 | insn = *l->addr; | ||
| 905 | val = | ||
| 906 | ((insn & 0xffff) << 16) + | ||
| 907 | vallo; | ||
| 908 | val += v; | ||
| 909 | |||
| 910 | /* Account for the sign extension that will happen in the | ||
| 911 | low bits. */ | ||
| 912 | val = | ||
| 913 | ((val >> 16) + | ||
| 914 | ((val & 0x8000) != | ||
| 915 | 0)) & 0xffff; | ||
| 916 | |||
| 917 | insn = (insn & ~0xffff) | val; | ||
| 918 | *l->addr = insn; | ||
| 919 | |||
| 920 | next = l->next; | ||
| 921 | free(l); | ||
| 922 | l = next; | ||
| 923 | } | ||
| 924 | |||
| 925 | ifile->mips_hi16_list = NULL; | ||
| 926 | } | ||
| 927 | |||
| 928 | /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */ | ||
| 929 | val = v + vallo; | ||
| 930 | insnlo = (insnlo & ~0xffff) | (val & 0xffff); | ||
| 931 | *loc = insnlo; | ||
| 932 | break; | ||
| 933 | } | ||
| 934 | #endif | ||
| 935 | |||
| 815 | #if defined(__arm__) | 936 | #if defined(__arm__) |
| 816 | #elif defined(__sh__) | 937 | #elif defined(__sh__) |
| 817 | case R_SH_REL32: | 938 | case R_SH_REL32: |
| @@ -977,6 +1098,7 @@ arch_apply_relocation(struct obj_file *f, | |||
| 977 | 1098 | ||
| 978 | int arch_create_got(struct obj_file *f) | 1099 | int arch_create_got(struct obj_file *f) |
| 979 | { | 1100 | { |
| 1101 | #if defined(BB_USE_GOT_ENTRIES) || defined(BB_USE_PLT_ENTRIES) | ||
| 980 | struct arch_file *ifile = (struct arch_file *) f; | 1102 | struct arch_file *ifile = (struct arch_file *) f; |
| 981 | int i; | 1103 | int i; |
| 982 | #if defined(BB_USE_GOT_ENTRIES) | 1104 | #if defined(BB_USE_GOT_ENTRIES) |
| @@ -1098,6 +1220,7 @@ int arch_create_got(struct obj_file *f) | |||
| 1098 | BB_PLT_ENTRY_SIZE, | 1220 | BB_PLT_ENTRY_SIZE, |
| 1099 | plt_offset); | 1221 | plt_offset); |
| 1100 | #endif | 1222 | #endif |
| 1223 | #endif | ||
| 1101 | return 1; | 1224 | return 1; |
| 1102 | } | 1225 | } |
| 1103 | 1226 | ||
| @@ -2772,7 +2895,7 @@ int obj_create_image(struct obj_file *f, char *image) | |||
| 2772 | for (sec = f->load_order; sec; sec = sec->load_next) { | 2895 | for (sec = f->load_order; sec; sec = sec->load_next) { |
| 2773 | char *secimg; | 2896 | char *secimg; |
| 2774 | 2897 | ||
| 2775 | if (sec->header.sh_size == 0) | 2898 | if (sec->contents == 0 || sec->header.sh_size == 0) |
| 2776 | continue; | 2899 | continue; |
| 2777 | 2900 | ||
| 2778 | secimg = image + (sec->header.sh_addr - base); | 2901 | secimg = image + (sec->header.sh_addr - base); |
| @@ -2857,7 +2980,7 @@ struct obj_file *obj_load(FILE * fp) | |||
| 2857 | sec->header = section_headers[i]; | 2980 | sec->header = section_headers[i]; |
| 2858 | sec->idx = i; | 2981 | sec->idx = i; |
| 2859 | 2982 | ||
| 2860 | switch (sec->header.sh_type) { | 2983 | if(sec->header.sh_size) switch (sec->header.sh_type) { |
| 2861 | case SHT_NULL: | 2984 | case SHT_NULL: |
| 2862 | case SHT_NOTE: | 2985 | case SHT_NOTE: |
| 2863 | case SHT_NOBITS: | 2986 | case SHT_NOBITS: |
