aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2001-02-20 20:47:08 +0000
committerEric Andersen <andersen@codepoet.org>2001-02-20 20:47:08 +0000
commit90fe7fea10b69d85c4d53e7061aaf85657136530 (patch)
tree880d32c3fe6684570da9eaedd0e1f86437c329b3
parent477aedd77f5e4abeefbf686e21f395686aca16d3 (diff)
downloadbusybox-w32-90fe7fea10b69d85c4d53e7061aaf85657136530.tar.gz
busybox-w32-90fe7fea10b69d85c4d53e7061aaf85657136530.tar.bz2
busybox-w32-90fe7fea10b69d85c4d53e7061aaf85657136530.zip
Apply a patch from Magnus Damm <damm@opensource.se> to support
powerpc with busybox insmod -Erik
-rw-r--r--insmod.c199
-rw-r--r--modutils/insmod.c199
2 files changed, 322 insertions, 76 deletions
diff --git a/insmod.c b/insmod.c
index 166f0fc4b..7af135902 100644
--- a/insmod.c
+++ b/insmod.c
@@ -14,6 +14,12 @@
14 * very minor changes required to also work with StrongArm and presumably 14 * very minor changes required to also work with StrongArm and presumably
15 * all ARM based systems. 15 * all ARM based systems.
16 * 16 *
17 * Magnus Damm <damm@opensource.se> added PowerPC support 20-Feb-2001.
18 * PowerPC specific code stolen from modutils-2.3.16,
19 * written by Paul Mackerras, Copyright 1996, 1997 Linux International.
20 * I've only tested the code on mpc8xx platforms in big-endian mode.
21 * Did some cleanup and added BB_USE_xxx_ENTRIES...
22 *
17 * Based almost entirely on the Linux modutils-2.3.11 implementation. 23 * Based almost entirely on the Linux modutils-2.3.11 implementation.
18 * Copyright 1996, 1997 Linux International. 24 * Copyright 1996, 1997 Linux International.
19 * New implementation contributed by Richard Henderson <rth@tamu.edu> 25 * New implementation contributed by Richard Henderson <rth@tamu.edu>
@@ -52,6 +58,28 @@
52#include <linux/unistd.h> 58#include <linux/unistd.h>
53#include "busybox.h" 59#include "busybox.h"
54 60
61#if defined(__powerpc__)
62#define BB_USE_PLT_ENTRIES
63#define BB_PLT_ENTRY_SIZE 16
64#endif
65
66#if defined(__arm__)
67#define BB_USE_PLT_ENTRIES
68#define BB_PLT_ENTRY_SIZE 8
69#define BB_USE_GOT_ENTRIES
70#define BB_GOT_ENTRY_SIZE 8
71#endif
72
73#if defined(__sh__)
74#define BB_USE_GOT_ENTRIES
75#define BB_GOT_ENTRY_SIZE 4
76#endif
77
78#if defined(__i386__)
79#define BB_USE_GOT_ENTRIES
80#define BB_GOT_ENTRY_SIZE 4
81#endif
82
55//---------------------------------------------------------------------------- 83//----------------------------------------------------------------------------
56//--------modutils module.h, lines 45-242 84//--------modutils module.h, lines 45-242
57//---------------------------------------------------------------------------- 85//----------------------------------------------------------------------------
@@ -81,7 +109,7 @@
81#ifndef MODUTILS_MODULE_H 109#ifndef MODUTILS_MODULE_H
82static const int MODUTILS_MODULE_H = 1; 110static const int MODUTILS_MODULE_H = 1;
83 111
84#ident "$Id: insmod.c,v 1.48 2001/02/20 06:14:07 andersen Exp $" 112#ident "$Id: insmod.c,v 1.49 2001/02/20 20:47:08 andersen Exp $"
85 113
86/* This file contains the structures used by the 2.0 and 2.1 kernels. 114/* This file contains the structures used by the 2.0 and 2.1 kernels.
87 We do not use the kernel headers directly because we do not wish 115 We do not use the kernel headers directly because we do not wish
@@ -287,7 +315,7 @@ int delete_module(const char *);
287#ifndef MODUTILS_OBJ_H 315#ifndef MODUTILS_OBJ_H
288static const int MODUTILS_OBJ_H = 1; 316static const int MODUTILS_OBJ_H = 1;
289 317
290#ident "$Id: insmod.c,v 1.48 2001/02/20 06:14:07 andersen Exp $" 318#ident "$Id: insmod.c,v 1.49 2001/02/20 20:47:08 andersen Exp $"
291 319
292/* The relocatable object is manipulated using elfin types. */ 320/* The relocatable object is manipulated using elfin types. */
293 321
@@ -311,21 +339,27 @@ static const int MODUTILS_OBJ_H = 1;
311#endif 339#endif
312 340
313#define ELFCLASSM ELFCLASS32 341#define ELFCLASSM ELFCLASS32
314#define ELFDATAM ELFDATA2LSB
315
316
317 342
318#if defined(__sh__) 343#if defined(__sh__)
319 344
320#define MATCH_MACHINE(x) (x == EM_SH) 345#define MATCH_MACHINE(x) (x == EM_SH)
321#define SHT_RELM SHT_RELA 346#define SHT_RELM SHT_RELA
322#define Elf32_RelM Elf32_Rela 347#define Elf32_RelM Elf32_Rela
348#define ELFDATAM ELFDATA2LSB
323 349
324#elif defined(__arm__) 350#elif defined(__arm__)
325 351
326#define MATCH_MACHINE(x) (x == EM_ARM) 352#define MATCH_MACHINE(x) (x == EM_ARM)
327#define SHT_RELM SHT_REL 353#define SHT_RELM SHT_REL
328#define Elf32_RelM Elf32_Rel 354#define Elf32_RelM Elf32_Rel
355#define ELFDATAM ELFDATA2LSB
356
357#elif defined(__powerpc__)
358
359#define MATCH_MACHINE(x) (x == EM_PPC)
360#define SHT_RELM SHT_RELA
361#define Elf32_RelM Elf32_Rela
362#define ELFDATAM ELFDATA2MSB
329 363
330#elif defined(__i386__) 364#elif defined(__i386__)
331 365
@@ -340,6 +374,7 @@ static const int MODUTILS_OBJ_H = 1;
340 374
341#define SHT_RELM SHT_REL 375#define SHT_RELM SHT_REL
342#define Elf32_RelM Elf32_Rel 376#define Elf32_RelM Elf32_Rel
377#define ELFDATAM ELFDATA2LSB
343 378
344#else 379#else
345#error Sorry, but insmod.c does not yet support this architecture... 380#error Sorry, but insmod.c does not yet support this architecture...
@@ -540,8 +575,10 @@ int flag_export = 1;
540 575
541/* Done ;-) */ 576/* Done ;-) */
542 577
543#if defined(__arm__) 578
544struct arm_plt_entry 579
580#if defined(BB_USE_PLT_ENTRIES)
581struct arch_plt_entry
545{ 582{
546 int offset; 583 int offset;
547 int allocated:1; 584 int allocated:1;
@@ -549,26 +586,32 @@ struct arm_plt_entry
549}; 586};
550#endif 587#endif
551 588
589#if defined(BB_USE_GOT_ENTRIES)
552struct arch_got_entry { 590struct arch_got_entry {
553 int offset; 591 int offset;
554 unsigned offset_done:1; 592 unsigned offset_done:1;
555 unsigned reloc_done:1; 593 unsigned reloc_done:1;
556}; 594};
595#endif
557 596
558struct arch_file { 597struct arch_file {
559 struct obj_file root; 598 struct obj_file root;
560#if defined(__arm__) 599#if defined(BB_USE_PLT_ENTRIES)
561 struct obj_section *plt; 600 struct obj_section *plt;
562#endif 601#endif
602#if defined(BB_USE_GOT_ENTRIES)
563 struct obj_section *got; 603 struct obj_section *got;
604#endif
564}; 605};
565 606
566struct arch_symbol { 607struct arch_symbol {
567 struct obj_symbol root; 608 struct obj_symbol root;
568#if defined(__arm__) 609#if defined(BB_USE_PLT_ENTRIES)
569 struct arm_plt_entry pltent; 610 struct arch_plt_entry pltent;
570#endif 611#endif
612#if defined(BB_USE_GOT_ENTRIES)
571 struct arch_got_entry gotent; 613 struct arch_got_entry gotent;
614#endif
572}; 615};
573 616
574 617
@@ -618,7 +661,8 @@ extern int delete_module(const char *);
618_syscall1(int, get_kernel_syms, struct old_kernel_sym *, ks) 661_syscall1(int, get_kernel_syms, struct old_kernel_sym *, ks)
619#endif 662#endif
620 663
621#if defined(__i386__) || defined(__m68k__) || defined(__arm__) 664#if defined(__i386__) || defined(__m68k__) || defined(__arm__) \
665 || defined(__powerpc__)
622/* Jump through hoops to fixup error return codes */ 666/* Jump through hoops to fixup error return codes */
623#define __NR__create_module __NR_create_module 667#define __NR__create_module __NR_create_module
624static inline _syscall2(long, _create_module, const char *, name, size_t, 668static inline _syscall2(long, _create_module, const char *, name, size_t,
@@ -673,7 +717,14 @@ struct obj_file *arch_new_file(void)
673{ 717{
674 struct arch_file *f; 718 struct arch_file *f;
675 f = xmalloc(sizeof(*f)); 719 f = xmalloc(sizeof(*f));
720
721#if defined(BB_USE_PLT_ENTRIES)
722 f->plt = NULL;
723#endif
724#if defined(BB_USE_GOT_ENTRIES)
676 f->got = NULL; 725 f->got = NULL;
726#endif
727
677 return &f->root; 728 return &f->root;
678} 729}
679 730
@@ -686,7 +737,14 @@ struct obj_symbol *arch_new_symbol(void)
686{ 737{
687 struct arch_symbol *sym; 738 struct arch_symbol *sym;
688 sym = xmalloc(sizeof(*sym)); 739 sym = xmalloc(sizeof(*sym));
740
741#if defined(BB_USE_PLT_ENTRIES)
742 memset(&sym->pltent, 0, sizeof(sym->pltent));
743#endif
744#if defined(BB_USE_GOT_ENTRIES)
689 memset(&sym->gotent, 0, sizeof(sym->gotent)); 745 memset(&sym->gotent, 0, sizeof(sym->gotent));
746#endif
747
690 return &sym->root; 748 return &sym->root;
691} 749}
692 750
@@ -702,14 +760,14 @@ arch_apply_relocation(struct obj_file *f,
702 760
703 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset); 761 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
704 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset; 762 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
763#if defined(BB_USE_GOT_ENTRIES)
705 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0; 764 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
706#if defined(__arm__) 765#endif
766#if defined(BB_USE_PLT_ENTRIES)
707 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0; 767 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
708 768 struct arch_plt_entry *pe;
709 struct arm_plt_entry *pe;
710 unsigned long *ip; 769 unsigned long *ip;
711#endif 770#endif
712
713 enum obj_reloc ret = obj_reloc_ok; 771 enum obj_reloc ret = obj_reloc_ok;
714 772
715 switch (ELF32_R_TYPE(rel->r_info)) { 773 switch (ELF32_R_TYPE(rel->r_info)) {
@@ -723,6 +781,8 @@ arch_apply_relocation(struct obj_file *f,
723 case R_ARM_NONE: 781 case R_ARM_NONE:
724#elif defined(__i386__) 782#elif defined(__i386__)
725 case R_386_NONE: 783 case R_386_NONE:
784#elif defined(__powerpc__)
785 case R_PPC_NONE:
726#endif 786#endif
727 break; 787 break;
728 788
@@ -731,11 +791,27 @@ arch_apply_relocation(struct obj_file *f,
731#elif defined(__arm__) 791#elif defined(__arm__)
732 case R_ARM_ABS32: 792 case R_ARM_ABS32:
733#elif defined(__i386__) 793#elif defined(__i386__)
734 case R_386_32: 794 case R_386_32:
795#elif defined(__powerpc__)
796 case R_PPC_ADDR32:
735#endif 797#endif
736 *loc += v; 798 *loc += v;
737 break; 799 break;
738 800
801#if defined(__powerpc__)
802 case R_PPC_ADDR16_HA:
803 *(unsigned short *)loc = (v + 0x8000) >> 16;
804 break;
805
806 case R_PPC_ADDR16_HI:
807 *(unsigned short *)loc = v >> 16;
808 break;
809
810 case R_PPC_ADDR16_LO:
811 *(unsigned short *)loc = v;
812 break;
813#endif
814
739#if defined(__arm__) 815#if defined(__arm__)
740#elif defined(__sh__) 816#elif defined(__sh__)
741 case R_SH_REL32: 817 case R_SH_REL32:
@@ -746,22 +822,48 @@ arch_apply_relocation(struct obj_file *f,
746 case R_386_PC32: 822 case R_386_PC32:
747 *loc += v - dot; 823 *loc += v - dot;
748 break; 824 break;
825#elif defined(__powerpc__)
826 case R_PPC_REL32:
827 *loc = v - dot;
828 break;
749#endif 829#endif
750 830
751#if defined(__sh__) 831#if defined(__sh__)
752 case R_SH_PLT32: 832 case R_SH_PLT32:
753 *loc = v - dot; 833 *loc = v - dot;
754 break; 834 break;
755#elif defined(__arm__) 835#elif defined(__i386__)
836#endif
837
838#if defined(BB_USE_PLT_ENTRIES)
839
840#if defined(__arm__)
756 case R_ARM_PC24: 841 case R_ARM_PC24:
757 case R_ARM_PLT32: 842 case R_ARM_PLT32:
843#endif
844#if defined(__powerpc__)
845 case R_PPC_REL24:
846#endif
758 /* find the plt entry and initialize it if necessary */ 847 /* find the plt entry and initialize it if necessary */
759 assert(isym != NULL); 848 assert(isym != NULL);
760 pe = (struct arm_plt_entry*) &isym->pltent; 849
850 pe = (struct arch_plt_entry*) &isym->pltent;
851
761 if (! pe->inited) { 852 if (! pe->inited) {
762 ip = (unsigned long *) (ifile->plt->contents + pe->offset); 853 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
854
855 /* generate some machine code */
856
857#if defined(__arm__)
763 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */ 858 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
764 ip[1] = v; /* sym@ */ 859 ip[1] = v; /* sym@ */
860#endif
861#if defined(__powerpc__)
862 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
863 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
864 ip[2] = 0x7d6903a6; /* mtctr r11 */
865 ip[3] = 0x4e800420; /* bctr */
866#endif
765 pe->inited = 1; 867 pe->inited = 1;
766 } 868 }
767 869
@@ -775,15 +877,18 @@ arch_apply_relocation(struct obj_file *f,
775 if (v & 3) 877 if (v & 3)
776 ret = obj_reloc_dangerous; 878 ret = obj_reloc_dangerous;
777 879
880 /* merge the offset into the instruction. */
881#if defined(__arm__)
778 /* Convert to words. */ 882 /* Convert to words. */
779 v >>= 2; 883 v >>= 2;
780 884
781 /* merge the offset into the instruction. */
782 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff); 885 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
783 break;
784#elif defined(__i386__)
785#endif 886#endif
786 887#if defined(__powerpc__)
888 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
889#endif
890 break;
891#endif /* BB_USE_PLT_ENTRIES */
787 892
788#if defined(__arm__) 893#if defined(__arm__)
789#elif defined(__sh__) 894#elif defined(__sh__)
@@ -809,6 +914,8 @@ arch_apply_relocation(struct obj_file *f,
809 break; 914 break;
810#endif 915#endif
811 916
917#if defined(BB_USE_GOT_ENTRIES)
918
812#if defined(__sh__) 919#if defined(__sh__)
813 case R_SH_GOTPC: 920 case R_SH_GOTPC:
814#elif defined(__arm__) 921#elif defined(__arm__)
@@ -827,7 +934,7 @@ arch_apply_relocation(struct obj_file *f,
827#if defined(__sh__) 934#if defined(__sh__)
828 case R_SH_GOT32: 935 case R_SH_GOT32:
829#elif defined(__arm__) 936#elif defined(__arm__)
830 case R_ARM_GOT32: 937 case R_ARM_GOT32:
831#elif defined(__i386__) 938#elif defined(__i386__)
832 case R_386_GOT32: 939 case R_386_GOT32:
833#endif 940#endif
@@ -849,7 +956,7 @@ arch_apply_relocation(struct obj_file *f,
849#if defined(__sh__) 956#if defined(__sh__)
850 case R_SH_GOTOFF: 957 case R_SH_GOTOFF:
851#elif defined(__arm__) 958#elif defined(__arm__)
852 case R_ARM_GOTOFF: 959 case R_ARM_GOTOFF:
853#elif defined(__i386__) 960#elif defined(__i386__)
854 case R_386_GOTOFF: 961 case R_386_GOTOFF:
855#endif 962#endif
@@ -857,6 +964,8 @@ arch_apply_relocation(struct obj_file *f,
857 *loc += v - got; 964 *loc += v - got;
858 break; 965 break;
859 966
967#endif /* BB_USE_GOT_ENTRIES */
968
860 default: 969 default:
861 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info)); 970 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
862 ret = obj_reloc_unhandled; 971 ret = obj_reloc_unhandled;
@@ -869,8 +978,11 @@ arch_apply_relocation(struct obj_file *f,
869int arch_create_got(struct obj_file *f) 978int arch_create_got(struct obj_file *f)
870{ 979{
871 struct arch_file *ifile = (struct arch_file *) f; 980 struct arch_file *ifile = (struct arch_file *) f;
872 int i, got_offset = 0, gotneeded = 0; 981 int i;
873#if defined(__arm__) 982#if defined(BB_USE_GOT_ENTRIES)
983 int got_offset = 0, gotneeded = 0;
984#endif
985#if defined(BB_USE_PLT_ENTRIES)
874 int plt_offset = 0, pltneeded = 0; 986 int plt_offset = 0, pltneeded = 0;
875#endif 987#endif
876 struct obj_section *relsec, *symsec, *strsec; 988 struct obj_section *relsec, *symsec, *strsec;
@@ -898,12 +1010,20 @@ int arch_create_got(struct obj_file *f)
898 switch (ELF32_R_TYPE(rel->r_info)) { 1010 switch (ELF32_R_TYPE(rel->r_info)) {
899#if defined(__arm__) 1011#if defined(__arm__)
900 case R_ARM_GOT32: 1012 case R_ARM_GOT32:
1013 break;
901#elif defined(__sh__) 1014#elif defined(__sh__)
902 case R_SH_GOT32: 1015 case R_SH_GOT32:
1016 break;
903#elif defined(__i386__) 1017#elif defined(__i386__)
904 case R_386_GOT32: 1018 case R_386_GOT32:
1019 break;
905#endif 1020#endif
1021
1022#if defined(__powerpc__)
1023 case R_PPC_REL24:
1024 pltneeded = 1;
906 break; 1025 break;
1026#endif
907 1027
908#if defined(__arm__) 1028#if defined(__arm__)
909 case R_ARM_PC24: 1029 case R_ARM_PC24:
@@ -936,17 +1056,18 @@ int arch_create_got(struct obj_file *f)
936 name = f->sections[extsym->st_shndx]->name; 1056 name = f->sections[extsym->st_shndx]->name;
937 } 1057 }
938 intsym = (struct arch_symbol *) obj_find_symbol(f, name); 1058 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
939 1059#if defined(BB_USE_GOT_ENTRIES)
940 if (!intsym->gotent.offset_done) { 1060 if (!intsym->gotent.offset_done) {
941 intsym->gotent.offset_done = 1; 1061 intsym->gotent.offset_done = 1;
942 intsym->gotent.offset = got_offset; 1062 intsym->gotent.offset = got_offset;
943 got_offset += 4; 1063 got_offset += BB_GOT_ENTRY_SIZE;
944 } 1064 }
945#if defined(__arm__) 1065#endif
1066#if defined(BB_USE_PLT_ENTRIES)
946 if (pltneeded && intsym->pltent.allocated == 0) { 1067 if (pltneeded && intsym->pltent.allocated == 0) {
947 intsym->pltent.allocated = 1; 1068 intsym->pltent.allocated = 1;
948 intsym->pltent.offset = plt_offset; 1069 intsym->pltent.offset = plt_offset;
949 plt_offset += 8; 1070 plt_offset += BB_PLT_ENTRY_SIZE;
950 intsym->pltent.inited = 0; 1071 intsym->pltent.inited = 0;
951 pltneeded = 0; 1072 pltneeded = 0;
952 } 1073 }
@@ -954,27 +1075,29 @@ int arch_create_got(struct obj_file *f)
954 } 1075 }
955 } 1076 }
956 1077
957#if defined(__arm__) 1078#if defined(BB_USE_GOT_ENTRIES)
958 if (got_offset) { 1079 if (got_offset) {
959 struct obj_section* relsec = obj_find_section(f, ".got"); 1080 struct obj_section* relsec = obj_find_section(f, ".got");
960 1081
961 if (relsec) { 1082 if (relsec) {
962 obj_extend_section(relsec, got_offset); 1083 obj_extend_section(relsec, got_offset);
963 } else { 1084 } else {
964 relsec = obj_create_alloced_section(f, ".got", 8, got_offset); 1085 relsec = obj_create_alloced_section(f, ".got",
1086 BB_GOT_ENTRY_SIZE,
1087 got_offset);
965 assert(relsec); 1088 assert(relsec);
966 } 1089 }
967 1090
968 ifile->got = relsec; 1091 ifile->got = relsec;
969 } 1092 }
1093#endif
970 1094
1095#if defined(BB_USE_PLT_ENTRIES)
971 if (plt_offset) 1096 if (plt_offset)
972 ifile->plt = obj_create_alloced_section(f, ".plt", 8, plt_offset); 1097 ifile->plt = obj_create_alloced_section(f, ".plt",
973#else 1098 BB_PLT_ENTRY_SIZE,
974 if (got_offset > 0 || gotneeded) 1099 plt_offset);
975 ifile->got = obj_create_alloced_section(f, ".got", 4, got_offset);
976#endif 1100#endif
977
978 return 1; 1101 return 1;
979} 1102}
980 1103
diff --git a/modutils/insmod.c b/modutils/insmod.c
index 166f0fc4b..7af135902 100644
--- a/modutils/insmod.c
+++ b/modutils/insmod.c
@@ -14,6 +14,12 @@
14 * very minor changes required to also work with StrongArm and presumably 14 * very minor changes required to also work with StrongArm and presumably
15 * all ARM based systems. 15 * all ARM based systems.
16 * 16 *
17 * Magnus Damm <damm@opensource.se> added PowerPC support 20-Feb-2001.
18 * PowerPC specific code stolen from modutils-2.3.16,
19 * written by Paul Mackerras, Copyright 1996, 1997 Linux International.
20 * I've only tested the code on mpc8xx platforms in big-endian mode.
21 * Did some cleanup and added BB_USE_xxx_ENTRIES...
22 *
17 * Based almost entirely on the Linux modutils-2.3.11 implementation. 23 * Based almost entirely on the Linux modutils-2.3.11 implementation.
18 * Copyright 1996, 1997 Linux International. 24 * Copyright 1996, 1997 Linux International.
19 * New implementation contributed by Richard Henderson <rth@tamu.edu> 25 * New implementation contributed by Richard Henderson <rth@tamu.edu>
@@ -52,6 +58,28 @@
52#include <linux/unistd.h> 58#include <linux/unistd.h>
53#include "busybox.h" 59#include "busybox.h"
54 60
61#if defined(__powerpc__)
62#define BB_USE_PLT_ENTRIES
63#define BB_PLT_ENTRY_SIZE 16
64#endif
65
66#if defined(__arm__)
67#define BB_USE_PLT_ENTRIES
68#define BB_PLT_ENTRY_SIZE 8
69#define BB_USE_GOT_ENTRIES
70#define BB_GOT_ENTRY_SIZE 8
71#endif
72
73#if defined(__sh__)
74#define BB_USE_GOT_ENTRIES
75#define BB_GOT_ENTRY_SIZE 4
76#endif
77
78#if defined(__i386__)
79#define BB_USE_GOT_ENTRIES
80#define BB_GOT_ENTRY_SIZE 4
81#endif
82
55//---------------------------------------------------------------------------- 83//----------------------------------------------------------------------------
56//--------modutils module.h, lines 45-242 84//--------modutils module.h, lines 45-242
57//---------------------------------------------------------------------------- 85//----------------------------------------------------------------------------
@@ -81,7 +109,7 @@
81#ifndef MODUTILS_MODULE_H 109#ifndef MODUTILS_MODULE_H
82static const int MODUTILS_MODULE_H = 1; 110static const int MODUTILS_MODULE_H = 1;
83 111
84#ident "$Id: insmod.c,v 1.48 2001/02/20 06:14:07 andersen Exp $" 112#ident "$Id: insmod.c,v 1.49 2001/02/20 20:47:08 andersen Exp $"
85 113
86/* This file contains the structures used by the 2.0 and 2.1 kernels. 114/* This file contains the structures used by the 2.0 and 2.1 kernels.
87 We do not use the kernel headers directly because we do not wish 115 We do not use the kernel headers directly because we do not wish
@@ -287,7 +315,7 @@ int delete_module(const char *);
287#ifndef MODUTILS_OBJ_H 315#ifndef MODUTILS_OBJ_H
288static const int MODUTILS_OBJ_H = 1; 316static const int MODUTILS_OBJ_H = 1;
289 317
290#ident "$Id: insmod.c,v 1.48 2001/02/20 06:14:07 andersen Exp $" 318#ident "$Id: insmod.c,v 1.49 2001/02/20 20:47:08 andersen Exp $"
291 319
292/* The relocatable object is manipulated using elfin types. */ 320/* The relocatable object is manipulated using elfin types. */
293 321
@@ -311,21 +339,27 @@ static const int MODUTILS_OBJ_H = 1;
311#endif 339#endif
312 340
313#define ELFCLASSM ELFCLASS32 341#define ELFCLASSM ELFCLASS32
314#define ELFDATAM ELFDATA2LSB
315
316
317 342
318#if defined(__sh__) 343#if defined(__sh__)
319 344
320#define MATCH_MACHINE(x) (x == EM_SH) 345#define MATCH_MACHINE(x) (x == EM_SH)
321#define SHT_RELM SHT_RELA 346#define SHT_RELM SHT_RELA
322#define Elf32_RelM Elf32_Rela 347#define Elf32_RelM Elf32_Rela
348#define ELFDATAM ELFDATA2LSB
323 349
324#elif defined(__arm__) 350#elif defined(__arm__)
325 351
326#define MATCH_MACHINE(x) (x == EM_ARM) 352#define MATCH_MACHINE(x) (x == EM_ARM)
327#define SHT_RELM SHT_REL 353#define SHT_RELM SHT_REL
328#define Elf32_RelM Elf32_Rel 354#define Elf32_RelM Elf32_Rel
355#define ELFDATAM ELFDATA2LSB
356
357#elif defined(__powerpc__)
358
359#define MATCH_MACHINE(x) (x == EM_PPC)
360#define SHT_RELM SHT_RELA
361#define Elf32_RelM Elf32_Rela
362#define ELFDATAM ELFDATA2MSB
329 363
330#elif defined(__i386__) 364#elif defined(__i386__)
331 365
@@ -340,6 +374,7 @@ static const int MODUTILS_OBJ_H = 1;
340 374
341#define SHT_RELM SHT_REL 375#define SHT_RELM SHT_REL
342#define Elf32_RelM Elf32_Rel 376#define Elf32_RelM Elf32_Rel
377#define ELFDATAM ELFDATA2LSB
343 378
344#else 379#else
345#error Sorry, but insmod.c does not yet support this architecture... 380#error Sorry, but insmod.c does not yet support this architecture...
@@ -540,8 +575,10 @@ int flag_export = 1;
540 575
541/* Done ;-) */ 576/* Done ;-) */
542 577
543#if defined(__arm__) 578
544struct arm_plt_entry 579
580#if defined(BB_USE_PLT_ENTRIES)
581struct arch_plt_entry
545{ 582{
546 int offset; 583 int offset;
547 int allocated:1; 584 int allocated:1;
@@ -549,26 +586,32 @@ struct arm_plt_entry
549}; 586};
550#endif 587#endif
551 588
589#if defined(BB_USE_GOT_ENTRIES)
552struct arch_got_entry { 590struct arch_got_entry {
553 int offset; 591 int offset;
554 unsigned offset_done:1; 592 unsigned offset_done:1;
555 unsigned reloc_done:1; 593 unsigned reloc_done:1;
556}; 594};
595#endif
557 596
558struct arch_file { 597struct arch_file {
559 struct obj_file root; 598 struct obj_file root;
560#if defined(__arm__) 599#if defined(BB_USE_PLT_ENTRIES)
561 struct obj_section *plt; 600 struct obj_section *plt;
562#endif 601#endif
602#if defined(BB_USE_GOT_ENTRIES)
563 struct obj_section *got; 603 struct obj_section *got;
604#endif
564}; 605};
565 606
566struct arch_symbol { 607struct arch_symbol {
567 struct obj_symbol root; 608 struct obj_symbol root;
568#if defined(__arm__) 609#if defined(BB_USE_PLT_ENTRIES)
569 struct arm_plt_entry pltent; 610 struct arch_plt_entry pltent;
570#endif 611#endif
612#if defined(BB_USE_GOT_ENTRIES)
571 struct arch_got_entry gotent; 613 struct arch_got_entry gotent;
614#endif
572}; 615};
573 616
574 617
@@ -618,7 +661,8 @@ extern int delete_module(const char *);
618_syscall1(int, get_kernel_syms, struct old_kernel_sym *, ks) 661_syscall1(int, get_kernel_syms, struct old_kernel_sym *, ks)
619#endif 662#endif
620 663
621#if defined(__i386__) || defined(__m68k__) || defined(__arm__) 664#if defined(__i386__) || defined(__m68k__) || defined(__arm__) \
665 || defined(__powerpc__)
622/* Jump through hoops to fixup error return codes */ 666/* Jump through hoops to fixup error return codes */
623#define __NR__create_module __NR_create_module 667#define __NR__create_module __NR_create_module
624static inline _syscall2(long, _create_module, const char *, name, size_t, 668static inline _syscall2(long, _create_module, const char *, name, size_t,
@@ -673,7 +717,14 @@ struct obj_file *arch_new_file(void)
673{ 717{
674 struct arch_file *f; 718 struct arch_file *f;
675 f = xmalloc(sizeof(*f)); 719 f = xmalloc(sizeof(*f));
720
721#if defined(BB_USE_PLT_ENTRIES)
722 f->plt = NULL;
723#endif
724#if defined(BB_USE_GOT_ENTRIES)
676 f->got = NULL; 725 f->got = NULL;
726#endif
727
677 return &f->root; 728 return &f->root;
678} 729}
679 730
@@ -686,7 +737,14 @@ struct obj_symbol *arch_new_symbol(void)
686{ 737{
687 struct arch_symbol *sym; 738 struct arch_symbol *sym;
688 sym = xmalloc(sizeof(*sym)); 739 sym = xmalloc(sizeof(*sym));
740
741#if defined(BB_USE_PLT_ENTRIES)
742 memset(&sym->pltent, 0, sizeof(sym->pltent));
743#endif
744#if defined(BB_USE_GOT_ENTRIES)
689 memset(&sym->gotent, 0, sizeof(sym->gotent)); 745 memset(&sym->gotent, 0, sizeof(sym->gotent));
746#endif
747
690 return &sym->root; 748 return &sym->root;
691} 749}
692 750
@@ -702,14 +760,14 @@ arch_apply_relocation(struct obj_file *f,
702 760
703 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset); 761 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
704 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset; 762 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
763#if defined(BB_USE_GOT_ENTRIES)
705 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0; 764 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
706#if defined(__arm__) 765#endif
766#if defined(BB_USE_PLT_ENTRIES)
707 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0; 767 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
708 768 struct arch_plt_entry *pe;
709 struct arm_plt_entry *pe;
710 unsigned long *ip; 769 unsigned long *ip;
711#endif 770#endif
712
713 enum obj_reloc ret = obj_reloc_ok; 771 enum obj_reloc ret = obj_reloc_ok;
714 772
715 switch (ELF32_R_TYPE(rel->r_info)) { 773 switch (ELF32_R_TYPE(rel->r_info)) {
@@ -723,6 +781,8 @@ arch_apply_relocation(struct obj_file *f,
723 case R_ARM_NONE: 781 case R_ARM_NONE:
724#elif defined(__i386__) 782#elif defined(__i386__)
725 case R_386_NONE: 783 case R_386_NONE:
784#elif defined(__powerpc__)
785 case R_PPC_NONE:
726#endif 786#endif
727 break; 787 break;
728 788
@@ -731,11 +791,27 @@ arch_apply_relocation(struct obj_file *f,
731#elif defined(__arm__) 791#elif defined(__arm__)
732 case R_ARM_ABS32: 792 case R_ARM_ABS32:
733#elif defined(__i386__) 793#elif defined(__i386__)
734 case R_386_32: 794 case R_386_32:
795#elif defined(__powerpc__)
796 case R_PPC_ADDR32:
735#endif 797#endif
736 *loc += v; 798 *loc += v;
737 break; 799 break;
738 800
801#if defined(__powerpc__)
802 case R_PPC_ADDR16_HA:
803 *(unsigned short *)loc = (v + 0x8000) >> 16;
804 break;
805
806 case R_PPC_ADDR16_HI:
807 *(unsigned short *)loc = v >> 16;
808 break;
809
810 case R_PPC_ADDR16_LO:
811 *(unsigned short *)loc = v;
812 break;
813#endif
814
739#if defined(__arm__) 815#if defined(__arm__)
740#elif defined(__sh__) 816#elif defined(__sh__)
741 case R_SH_REL32: 817 case R_SH_REL32:
@@ -746,22 +822,48 @@ arch_apply_relocation(struct obj_file *f,
746 case R_386_PC32: 822 case R_386_PC32:
747 *loc += v - dot; 823 *loc += v - dot;
748 break; 824 break;
825#elif defined(__powerpc__)
826 case R_PPC_REL32:
827 *loc = v - dot;
828 break;
749#endif 829#endif
750 830
751#if defined(__sh__) 831#if defined(__sh__)
752 case R_SH_PLT32: 832 case R_SH_PLT32:
753 *loc = v - dot; 833 *loc = v - dot;
754 break; 834 break;
755#elif defined(__arm__) 835#elif defined(__i386__)
836#endif
837
838#if defined(BB_USE_PLT_ENTRIES)
839
840#if defined(__arm__)
756 case R_ARM_PC24: 841 case R_ARM_PC24:
757 case R_ARM_PLT32: 842 case R_ARM_PLT32:
843#endif
844#if defined(__powerpc__)
845 case R_PPC_REL24:
846#endif
758 /* find the plt entry and initialize it if necessary */ 847 /* find the plt entry and initialize it if necessary */
759 assert(isym != NULL); 848 assert(isym != NULL);
760 pe = (struct arm_plt_entry*) &isym->pltent; 849
850 pe = (struct arch_plt_entry*) &isym->pltent;
851
761 if (! pe->inited) { 852 if (! pe->inited) {
762 ip = (unsigned long *) (ifile->plt->contents + pe->offset); 853 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
854
855 /* generate some machine code */
856
857#if defined(__arm__)
763 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */ 858 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
764 ip[1] = v; /* sym@ */ 859 ip[1] = v; /* sym@ */
860#endif
861#if defined(__powerpc__)
862 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
863 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
864 ip[2] = 0x7d6903a6; /* mtctr r11 */
865 ip[3] = 0x4e800420; /* bctr */
866#endif
765 pe->inited = 1; 867 pe->inited = 1;
766 } 868 }
767 869
@@ -775,15 +877,18 @@ arch_apply_relocation(struct obj_file *f,
775 if (v & 3) 877 if (v & 3)
776 ret = obj_reloc_dangerous; 878 ret = obj_reloc_dangerous;
777 879
880 /* merge the offset into the instruction. */
881#if defined(__arm__)
778 /* Convert to words. */ 882 /* Convert to words. */
779 v >>= 2; 883 v >>= 2;
780 884
781 /* merge the offset into the instruction. */
782 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff); 885 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
783 break;
784#elif defined(__i386__)
785#endif 886#endif
786 887#if defined(__powerpc__)
888 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
889#endif
890 break;
891#endif /* BB_USE_PLT_ENTRIES */
787 892
788#if defined(__arm__) 893#if defined(__arm__)
789#elif defined(__sh__) 894#elif defined(__sh__)
@@ -809,6 +914,8 @@ arch_apply_relocation(struct obj_file *f,
809 break; 914 break;
810#endif 915#endif
811 916
917#if defined(BB_USE_GOT_ENTRIES)
918
812#if defined(__sh__) 919#if defined(__sh__)
813 case R_SH_GOTPC: 920 case R_SH_GOTPC:
814#elif defined(__arm__) 921#elif defined(__arm__)
@@ -827,7 +934,7 @@ arch_apply_relocation(struct obj_file *f,
827#if defined(__sh__) 934#if defined(__sh__)
828 case R_SH_GOT32: 935 case R_SH_GOT32:
829#elif defined(__arm__) 936#elif defined(__arm__)
830 case R_ARM_GOT32: 937 case R_ARM_GOT32:
831#elif defined(__i386__) 938#elif defined(__i386__)
832 case R_386_GOT32: 939 case R_386_GOT32:
833#endif 940#endif
@@ -849,7 +956,7 @@ arch_apply_relocation(struct obj_file *f,
849#if defined(__sh__) 956#if defined(__sh__)
850 case R_SH_GOTOFF: 957 case R_SH_GOTOFF:
851#elif defined(__arm__) 958#elif defined(__arm__)
852 case R_ARM_GOTOFF: 959 case R_ARM_GOTOFF:
853#elif defined(__i386__) 960#elif defined(__i386__)
854 case R_386_GOTOFF: 961 case R_386_GOTOFF:
855#endif 962#endif
@@ -857,6 +964,8 @@ arch_apply_relocation(struct obj_file *f,
857 *loc += v - got; 964 *loc += v - got;
858 break; 965 break;
859 966
967#endif /* BB_USE_GOT_ENTRIES */
968
860 default: 969 default:
861 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info)); 970 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
862 ret = obj_reloc_unhandled; 971 ret = obj_reloc_unhandled;
@@ -869,8 +978,11 @@ arch_apply_relocation(struct obj_file *f,
869int arch_create_got(struct obj_file *f) 978int arch_create_got(struct obj_file *f)
870{ 979{
871 struct arch_file *ifile = (struct arch_file *) f; 980 struct arch_file *ifile = (struct arch_file *) f;
872 int i, got_offset = 0, gotneeded = 0; 981 int i;
873#if defined(__arm__) 982#if defined(BB_USE_GOT_ENTRIES)
983 int got_offset = 0, gotneeded = 0;
984#endif
985#if defined(BB_USE_PLT_ENTRIES)
874 int plt_offset = 0, pltneeded = 0; 986 int plt_offset = 0, pltneeded = 0;
875#endif 987#endif
876 struct obj_section *relsec, *symsec, *strsec; 988 struct obj_section *relsec, *symsec, *strsec;
@@ -898,12 +1010,20 @@ int arch_create_got(struct obj_file *f)
898 switch (ELF32_R_TYPE(rel->r_info)) { 1010 switch (ELF32_R_TYPE(rel->r_info)) {
899#if defined(__arm__) 1011#if defined(__arm__)
900 case R_ARM_GOT32: 1012 case R_ARM_GOT32:
1013 break;
901#elif defined(__sh__) 1014#elif defined(__sh__)
902 case R_SH_GOT32: 1015 case R_SH_GOT32:
1016 break;
903#elif defined(__i386__) 1017#elif defined(__i386__)
904 case R_386_GOT32: 1018 case R_386_GOT32:
1019 break;
905#endif 1020#endif
1021
1022#if defined(__powerpc__)
1023 case R_PPC_REL24:
1024 pltneeded = 1;
906 break; 1025 break;
1026#endif
907 1027
908#if defined(__arm__) 1028#if defined(__arm__)
909 case R_ARM_PC24: 1029 case R_ARM_PC24:
@@ -936,17 +1056,18 @@ int arch_create_got(struct obj_file *f)
936 name = f->sections[extsym->st_shndx]->name; 1056 name = f->sections[extsym->st_shndx]->name;
937 } 1057 }
938 intsym = (struct arch_symbol *) obj_find_symbol(f, name); 1058 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
939 1059#if defined(BB_USE_GOT_ENTRIES)
940 if (!intsym->gotent.offset_done) { 1060 if (!intsym->gotent.offset_done) {
941 intsym->gotent.offset_done = 1; 1061 intsym->gotent.offset_done = 1;
942 intsym->gotent.offset = got_offset; 1062 intsym->gotent.offset = got_offset;
943 got_offset += 4; 1063 got_offset += BB_GOT_ENTRY_SIZE;
944 } 1064 }
945#if defined(__arm__) 1065#endif
1066#if defined(BB_USE_PLT_ENTRIES)
946 if (pltneeded && intsym->pltent.allocated == 0) { 1067 if (pltneeded && intsym->pltent.allocated == 0) {
947 intsym->pltent.allocated = 1; 1068 intsym->pltent.allocated = 1;
948 intsym->pltent.offset = plt_offset; 1069 intsym->pltent.offset = plt_offset;
949 plt_offset += 8; 1070 plt_offset += BB_PLT_ENTRY_SIZE;
950 intsym->pltent.inited = 0; 1071 intsym->pltent.inited = 0;
951 pltneeded = 0; 1072 pltneeded = 0;
952 } 1073 }
@@ -954,27 +1075,29 @@ int arch_create_got(struct obj_file *f)
954 } 1075 }
955 } 1076 }
956 1077
957#if defined(__arm__) 1078#if defined(BB_USE_GOT_ENTRIES)
958 if (got_offset) { 1079 if (got_offset) {
959 struct obj_section* relsec = obj_find_section(f, ".got"); 1080 struct obj_section* relsec = obj_find_section(f, ".got");
960 1081
961 if (relsec) { 1082 if (relsec) {
962 obj_extend_section(relsec, got_offset); 1083 obj_extend_section(relsec, got_offset);
963 } else { 1084 } else {
964 relsec = obj_create_alloced_section(f, ".got", 8, got_offset); 1085 relsec = obj_create_alloced_section(f, ".got",
1086 BB_GOT_ENTRY_SIZE,
1087 got_offset);
965 assert(relsec); 1088 assert(relsec);
966 } 1089 }
967 1090
968 ifile->got = relsec; 1091 ifile->got = relsec;
969 } 1092 }
1093#endif
970 1094
1095#if defined(BB_USE_PLT_ENTRIES)
971 if (plt_offset) 1096 if (plt_offset)
972 ifile->plt = obj_create_alloced_section(f, ".plt", 8, plt_offset); 1097 ifile->plt = obj_create_alloced_section(f, ".plt",
973#else 1098 BB_PLT_ENTRY_SIZE,
974 if (got_offset > 0 || gotneeded) 1099 plt_offset);
975 ifile->got = obj_create_alloced_section(f, ".got", 4, got_offset);
976#endif 1100#endif
977
978 return 1; 1101 return 1;
979} 1102}
980 1103