diff options
author | Eric Andersen <andersen@codepoet.org> | 2000-12-06 18:18:26 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2000-12-06 18:18:26 +0000 |
commit | 21adca750a9a1ae47da2bd058574795089406f25 (patch) | |
tree | 6157527825001c910fa9bd2b2ce519ac212e9e50 | |
parent | e884970c87b921542fb9351b7a907796a0a4de23 (diff) | |
download | busybox-w32-21adca750a9a1ae47da2bd058574795089406f25.tar.gz busybox-w32-21adca750a9a1ae47da2bd058574795089406f25.tar.bz2 busybox-w32-21adca750a9a1ae47da2bd058574795089406f25.zip |
Added insmod support for ARM, and lsmod support for older kernels,
thanks to Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and
Nicolas Ferre <nicolas.ferre@alcove.fr>.
-Erik
-rw-r--r-- | Changelog | 5 | ||||
-rw-r--r-- | Config.h | 6 | ||||
-rw-r--r-- | insmod.c | 301 | ||||
-rw-r--r-- | lsmod.c | 38 | ||||
-rw-r--r-- | modutils/insmod.c | 301 | ||||
-rw-r--r-- | modutils/lsmod.c | 38 |
6 files changed, 498 insertions, 191 deletions
@@ -3,9 +3,12 @@ | |||
3 | * Matt Kraai -- fix all usage of TRUE and FALSE so all apps now | 3 | * Matt Kraai -- fix all usage of TRUE and FALSE so all apps now |
4 | return EXIT_SUCCESS or EXIT_FAILURE to the system. | 4 | return EXIT_SUCCESS or EXIT_FAILURE to the system. |
5 | Now TRUE and FALSE are set to the C standard where TRUE=1. | 5 | Now TRUE and FALSE are set to the C standard where TRUE=1. |
6 | * Fixed uname problem causing the kernel version to be | 6 | * me -- Fixed uname problem causing the kernel version to be |
7 | mis-detected (causing problems with poweroff, init, | 7 | mis-detected (causing problems with poweroff, init, |
8 | and other things). | 8 | and other things). |
9 | * Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and | ||
10 | Nicolas Ferre <nicolas.ferre@alcove.fr> -- insmod support on ARM | ||
11 | and StrongArm, and suport for lsmod on older 2.0.x kernels. | ||
9 | * Kent Robotti -- Renamed unrpm to original rpmunpack, so you can use | 12 | * Kent Robotti -- Renamed unrpm to original rpmunpack, so you can use |
10 | an included shell script called unrpm as a front end to it. There's | 13 | an included shell script called unrpm as a front end to it. There's |
11 | also a shell script called undeb included for debian packages. | 14 | also a shell script called undeb included for debian packages. |
@@ -260,6 +260,12 @@ | |||
260 | // Support installing modules from kernel versions after 2.1.18 | 260 | // Support installing modules from kernel versions after 2.1.18 |
261 | #define BB_FEATURE_INSMOD_NEW_KERNEL | 261 | #define BB_FEATURE_INSMOD_NEW_KERNEL |
262 | // | 262 | // |
263 | // You must enable one or both of these features | ||
264 | // Support modules status from pre 2.1 kernels | ||
265 | //#define BB_FEATURE_LSMOD_OLD_KERNEL | ||
266 | // Support modules status from kernel versions after 2.1.18 | ||
267 | #define BB_FEATURE_LSMOD_NEW_KERNEL | ||
268 | // | ||
263 | // Support module version checking | 269 | // Support module version checking |
264 | //#define BB_FEATURE_INSMOD_VERSION_CHECKING | 270 | //#define BB_FEATURE_INSMOD_VERSION_CHECKING |
265 | // | 271 | // |
@@ -7,11 +7,12 @@ | |||
7 | * and Ron Alder <alder@lineo.com> | 7 | * and Ron Alder <alder@lineo.com> |
8 | * | 8 | * |
9 | * Modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4 | 9 | * Modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4 |
10 | * and (theoretically) SH3. Note that there is still no true | 10 | * and (theoretically) SH3. I have only tested SH4 in little endian mode. |
11 | * multiple architecture support. You just get SH3|SH4|i386, despite | 11 | * |
12 | * the mention of ARM and m68k--which may or may not work (but | 12 | * Modified by Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and |
13 | * almost certainly do not, due to at least MATCH_MACHINE). I have | 13 | * Nicolas Ferre <nicolas.ferre@alcove.fr> to support ARM7TDMI. Only |
14 | * only tested SH4 in little endian mode. | 14 | * very minor changes required to also work with StrongArm and presumably |
15 | * all ARM based systems. | ||
15 | * | 16 | * |
16 | * Based almost entirely on the Linux modutils-2.3.11 implementation. | 17 | * Based almost entirely on the Linux modutils-2.3.11 implementation. |
17 | * Copyright 1996, 1997 Linux International. | 18 | * Copyright 1996, 1997 Linux International. |
@@ -77,7 +78,7 @@ | |||
77 | #ifndef MODUTILS_MODULE_H | 78 | #ifndef MODUTILS_MODULE_H |
78 | #define MODUTILS_MODULE_H 1 | 79 | #define MODUTILS_MODULE_H 1 |
79 | 80 | ||
80 | #ident "$Id: insmod.c,v 1.29 2000/12/01 02:55:13 kraai Exp $" | 81 | #ident "$Id: insmod.c,v 1.30 2000/12/06 18:18:26 andersen Exp $" |
81 | 82 | ||
82 | /* This file contains the structures used by the 2.0 and 2.1 kernels. | 83 | /* This file contains the structures used by the 2.0 and 2.1 kernels. |
83 | We do not use the kernel headers directly because we do not wish | 84 | We do not use the kernel headers directly because we do not wish |
@@ -283,7 +284,7 @@ int delete_module(const char *); | |||
283 | #ifndef MODUTILS_OBJ_H | 284 | #ifndef MODUTILS_OBJ_H |
284 | #define MODUTILS_OBJ_H 1 | 285 | #define MODUTILS_OBJ_H 1 |
285 | 286 | ||
286 | #ident "$Id: insmod.c,v 1.29 2000/12/01 02:55:13 kraai Exp $" | 287 | #ident "$Id: insmod.c,v 1.30 2000/12/06 18:18:26 andersen Exp $" |
287 | 288 | ||
288 | /* The relocatable object is manipulated using elfin types. */ | 289 | /* The relocatable object is manipulated using elfin types. */ |
289 | 290 | ||
@@ -317,12 +318,17 @@ int delete_module(const char *); | |||
317 | #define SHT_RELM SHT_RELA | 318 | #define SHT_RELM SHT_RELA |
318 | #define Elf32_RelM Elf32_Rela | 319 | #define Elf32_RelM Elf32_Rela |
319 | 320 | ||
320 | #else | 321 | #elif defined(__arm__) |
321 | 322 | ||
322 | /* presumably we can use these for anything but the SH */ | 323 | #define MATCH_MACHINE(x) (x == EM_ARM) |
324 | #define SHT_RELM SHT_REL | ||
325 | #define Elf32_RelM Elf32_Rel | ||
326 | |||
327 | #elif defined(__i386__) | ||
328 | |||
329 | /* presumably we can use these for anything but the SH and ARM*/ | ||
323 | /* this is the previous behavior, but it does result in | 330 | /* this is the previous behavior, but it does result in |
324 | insmod.c being broken on anything except i386 */ | 331 | insmod.c being broken on anything except i386 */ |
325 | |||
326 | #ifndef EM_486 | 332 | #ifndef EM_486 |
327 | #define MATCH_MACHINE(x) (x == EM_386) | 333 | #define MATCH_MACHINE(x) (x == EM_386) |
328 | #else | 334 | #else |
@@ -332,6 +338,8 @@ int delete_module(const char *); | |||
332 | #define SHT_RELM SHT_REL | 338 | #define SHT_RELM SHT_REL |
333 | #define Elf32_RelM Elf32_Rel | 339 | #define Elf32_RelM Elf32_Rel |
334 | 340 | ||
341 | #else | ||
342 | #error insmod.c no platform specified | ||
335 | #endif | 343 | #endif |
336 | 344 | ||
337 | #ifndef ElfW | 345 | #ifndef ElfW |
@@ -531,6 +539,17 @@ int flag_export = 1; | |||
531 | and we can't support anything else right now anyway. In the | 539 | and we can't support anything else right now anyway. In the |
532 | future maybe they should be #if defined'd */ | 540 | future maybe they should be #if defined'd */ |
533 | 541 | ||
542 | /* Done ;-) */ | ||
543 | |||
544 | #if defined(__arm__) | ||
545 | struct arm_plt_entry | ||
546 | { | ||
547 | int offset; | ||
548 | int allocated:1; | ||
549 | int inited:1; /* has been set up */ | ||
550 | }; | ||
551 | #endif | ||
552 | |||
534 | struct arch_got_entry { | 553 | struct arch_got_entry { |
535 | int offset; | 554 | int offset; |
536 | unsigned offset_done:1; | 555 | unsigned offset_done:1; |
@@ -539,11 +558,17 @@ struct arch_got_entry { | |||
539 | 558 | ||
540 | struct arch_file { | 559 | struct arch_file { |
541 | struct obj_file root; | 560 | struct obj_file root; |
561 | #if defined(__arm__) | ||
562 | struct obj_section *plt; | ||
563 | #endif | ||
542 | struct obj_section *got; | 564 | struct obj_section *got; |
543 | }; | 565 | }; |
544 | 566 | ||
545 | struct arch_symbol { | 567 | struct arch_symbol { |
546 | struct obj_symbol root; | 568 | struct obj_symbol root; |
569 | #if defined(__arm__) | ||
570 | struct arm_plt_entry pltent; | ||
571 | #endif | ||
547 | struct arch_got_entry gotent; | 572 | struct arch_got_entry gotent; |
548 | }; | 573 | }; |
549 | 574 | ||
@@ -590,6 +615,10 @@ extern int delete_module(const char *); | |||
590 | 615 | ||
591 | -- Bryan Rittmeyer <bryan@ixiacom.com> */ | 616 | -- Bryan Rittmeyer <bryan@ixiacom.com> */ |
592 | 617 | ||
618 | #ifdef BB_FEATURE_INSMOD_OLD_KERNEL | ||
619 | _syscall1(int, get_kernel_syms, struct old_kernel_sym *, ks) | ||
620 | #endif | ||
621 | |||
593 | #if defined(__i386__) || defined(__m68k__) || defined(__arm__) | 622 | #if defined(__i386__) || defined(__m68k__) || defined(__arm__) |
594 | /* Jump through hoops to fixup error return codes */ | 623 | /* Jump through hoops to fixup error return codes */ |
595 | #define __NR__create_module __NR_create_module | 624 | #define __NR__create_module __NR_create_module |
@@ -623,7 +652,7 @@ static int findNamedModule(const char *fileName, struct stat *statbuf, | |||
623 | if (fullName[0] == '\0') | 652 | if (fullName[0] == '\0') |
624 | return (FALSE); | 653 | return (FALSE); |
625 | else { | 654 | else { |
626 | char *tmp = strrchr(fileName, '/'); | 655 | char *tmp = strrchr((char *) fileName, '/'); |
627 | 656 | ||
628 | if (tmp == NULL) | 657 | if (tmp == NULL) |
629 | tmp = (char *) fileName; | 658 | tmp = (char *) fileName; |
@@ -667,18 +696,20 @@ arch_apply_relocation(struct obj_file *f, | |||
667 | struct obj_section *targsec, | 696 | struct obj_section *targsec, |
668 | struct obj_section *symsec, | 697 | struct obj_section *symsec, |
669 | struct obj_symbol *sym, | 698 | struct obj_symbol *sym, |
670 | #if defined(__sh__) | 699 | ElfW(RelM) *rel, ElfW(Addr) v) |
671 | Elf32_Rela * rel, Elf32_Addr v) | ||
672 | #else | ||
673 | Elf32_Rel * rel, Elf32_Addr v) | ||
674 | #endif | ||
675 | { | 700 | { |
676 | struct arch_file *ifile = (struct arch_file *) f; | 701 | struct arch_file *ifile = (struct arch_file *) f; |
677 | struct arch_symbol *isym = (struct arch_symbol *) sym; | 702 | struct arch_symbol *isym = (struct arch_symbol *) sym; |
678 | 703 | ||
679 | Elf32_Addr *loc = (Elf32_Addr *) (targsec->contents + rel->r_offset); | 704 | ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset); |
680 | Elf32_Addr dot = targsec->header.sh_addr + rel->r_offset; | 705 | ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset; |
681 | Elf32_Addr got = ifile->got ? ifile->got->header.sh_addr : 0; | 706 | ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0; |
707 | #if defined(__arm__) | ||
708 | ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0; | ||
709 | |||
710 | struct arm_plt_entry *pe; | ||
711 | unsigned long *ip; | ||
712 | #endif | ||
682 | 713 | ||
683 | enum obj_reloc ret = obj_reloc_ok; | 714 | enum obj_reloc ret = obj_reloc_ok; |
684 | 715 | ||
@@ -689,52 +720,91 @@ arch_apply_relocation(struct obj_file *f, | |||
689 | and in case that ever changes */ | 720 | and in case that ever changes */ |
690 | #if defined(__sh__) | 721 | #if defined(__sh__) |
691 | case R_SH_NONE: | 722 | case R_SH_NONE: |
692 | #else | 723 | #elif defined(__arm__) |
724 | case R_ARM_NONE: | ||
725 | #elif defined(__i386__) | ||
693 | case R_386_NONE: | 726 | case R_386_NONE: |
694 | #endif | 727 | #endif |
695 | break; | 728 | break; |
696 | 729 | ||
697 | #if defined(__sh__) | 730 | #if defined(__sh__) |
698 | case R_SH_DIR32: | 731 | case R_SH_DIR32: |
699 | #else | 732 | #elif defined(__arm__) |
733 | case R_ARM_ABS32: | ||
734 | #elif defined(__i386__) | ||
700 | case R_386_32: | 735 | case R_386_32: |
701 | #endif | 736 | #endif |
702 | *loc += v; | 737 | *loc += v; |
703 | break; | 738 | break; |
704 | 739 | ||
705 | #if defined(__sh__) | 740 | #if defined(__arm__) |
741 | #elif defined(__sh__) | ||
706 | case R_SH_REL32: | 742 | case R_SH_REL32: |
707 | #else | 743 | *loc += v - dot; |
744 | break; | ||
745 | #elif defined(__i386__) | ||
708 | case R_386_PLT32: | 746 | case R_386_PLT32: |
709 | case R_386_PC32: | 747 | case R_386_PC32: |
710 | #endif | ||
711 | *loc += v - dot; | 748 | *loc += v - dot; |
712 | break; | 749 | break; |
750 | #endif | ||
713 | 751 | ||
714 | #if defined(__sh__) | 752 | #if defined(__sh__) |
715 | case R_SH_PLT32: | 753 | case R_SH_PLT32: |
716 | *loc = v - dot; | 754 | *loc = v - dot; |
717 | break; | 755 | break; |
756 | #elif defined(__arm__) | ||
757 | case R_ARM_PC24: | ||
758 | case R_ARM_PLT32: | ||
759 | /* find the plt entry and initialize it if necessary */ | ||
760 | assert(isym != NULL); | ||
761 | pe = (struct arm_plt_entry*) &isym->pltent; | ||
762 | if (! pe->inited) { | ||
763 | ip = (unsigned long *) (ifile->plt->contents + pe->offset); | ||
764 | ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */ | ||
765 | ip[1] = v; /* sym@ */ | ||
766 | pe->inited = 1; | ||
767 | } | ||
768 | |||
769 | /* relative distance to target */ | ||
770 | v -= dot; | ||
771 | /* if the target is too far away.... */ | ||
772 | if ((int)v < -0x02000000 || (int)v >= 0x02000000) { | ||
773 | /* go via the plt */ | ||
774 | v = plt + pe->offset - dot; | ||
775 | } | ||
776 | if (v & 3) | ||
777 | ret = obj_reloc_dangerous; | ||
778 | |||
779 | /* Convert to words. */ | ||
780 | v >>= 2; | ||
781 | |||
782 | /* merge the offset into the instruction. */ | ||
783 | *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff); | ||
784 | break; | ||
785 | #elif defined(__i386__) | ||
718 | #endif | 786 | #endif |
719 | 787 | ||
720 | 788 | ||
721 | #if defined(__sh__) | 789 | #if defined(__arm__) |
790 | #elif defined(__sh__) | ||
722 | case R_SH_GLOB_DAT: | 791 | case R_SH_GLOB_DAT: |
723 | case R_SH_JMP_SLOT: | 792 | case R_SH_JMP_SLOT: |
724 | *loc = v; | 793 | *loc = v; |
725 | break; | 794 | break; |
726 | #else | 795 | #elif defined(__i386__) |
727 | case R_386_GLOB_DAT: | 796 | case R_386_GLOB_DAT: |
728 | case R_386_JMP_SLOT: | 797 | case R_386_JMP_SLOT: |
729 | *loc = v; | 798 | *loc = v; |
730 | break; | 799 | break; |
731 | #endif | 800 | #endif |
732 | 801 | ||
733 | #if defined(__sh__) | 802 | #if defined(__arm__) |
803 | #elif defined(__sh__) | ||
734 | case R_SH_RELATIVE: | 804 | case R_SH_RELATIVE: |
735 | *loc += f->baseaddr + rel->r_addend; | 805 | *loc += f->baseaddr + rel->r_addend; |
736 | break; | 806 | break; |
737 | #else | 807 | #elif defined(__i386__) |
738 | case R_386_RELATIVE: | 808 | case R_386_RELATIVE: |
739 | *loc += f->baseaddr; | 809 | *loc += f->baseaddr; |
740 | break; | 810 | break; |
@@ -742,41 +812,46 @@ arch_apply_relocation(struct obj_file *f, | |||
742 | 812 | ||
743 | #if defined(__sh__) | 813 | #if defined(__sh__) |
744 | case R_SH_GOTPC: | 814 | case R_SH_GOTPC: |
745 | assert(got != 0); | 815 | #elif defined(__arm__) |
746 | *loc += got - dot + rel->r_addend;; | 816 | case R_ARM_GOTPC: |
747 | break; | 817 | #elif defined(__i386__) |
748 | #else | ||
749 | case R_386_GOTPC: | 818 | case R_386_GOTPC: |
819 | #endif | ||
750 | assert(got != 0); | 820 | assert(got != 0); |
821 | #if defined(__sh__) | ||
822 | *loc += got - dot + rel->r_addend;; | ||
823 | #elif defined(__i386__) || defined(__arm__) | ||
751 | *loc += got - dot; | 824 | *loc += got - dot; |
752 | break; | ||
753 | #endif | 825 | #endif |
826 | break; | ||
754 | 827 | ||
755 | #if defined(__sh__) | 828 | #if defined(__sh__) |
756 | case R_SH_GOT32: | 829 | case R_SH_GOT32: |
757 | assert(isym != NULL); | 830 | #elif defined(__arm__) |
758 | if (!isym->gotent.reloc_done) { | 831 | case R_ARM_GOT32: |
759 | isym->gotent.reloc_done = 1; | 832 | #elif defined(__i386__) |
760 | *(Elf32_Addr *) (ifile->got->contents + isym->gotent.offset) = | ||
761 | v; | ||
762 | } | ||
763 | *loc += isym->gotent.offset + rel->r_addend; | ||
764 | break; | ||
765 | #else | ||
766 | case R_386_GOT32: | 833 | case R_386_GOT32: |
834 | #endif | ||
767 | assert(isym != NULL); | 835 | assert(isym != NULL); |
836 | /* needs an entry in the .got: set it, once */ | ||
768 | if (!isym->gotent.reloc_done) { | 837 | if (!isym->gotent.reloc_done) { |
769 | isym->gotent.reloc_done = 1; | 838 | isym->gotent.reloc_done = 1; |
770 | *(Elf32_Addr *) (ifile->got->contents + isym->gotent.offset) = | 839 | *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v; |
771 | v; | ||
772 | } | 840 | } |
841 | /* make the reloc with_respect_to_.got */ | ||
842 | #if defined(__sh__) | ||
843 | *loc += isym->gotent.offset + rel->r_addend; | ||
844 | #elif defined(__i386__) || defined(__arm__) | ||
773 | *loc += isym->gotent.offset; | 845 | *loc += isym->gotent.offset; |
774 | break; | ||
775 | #endif | 846 | #endif |
847 | break; | ||
776 | 848 | ||
849 | /* address relative to the got */ | ||
777 | #if defined(__sh__) | 850 | #if defined(__sh__) |
778 | case R_SH_GOTOFF: | 851 | case R_SH_GOTOFF: |
779 | #else | 852 | #elif defined(__arm__) |
853 | case R_ARM_GOTOFF: | ||
854 | #elif defined(__i386__) | ||
780 | case R_386_GOTOFF: | 855 | case R_386_GOTOFF: |
781 | #endif | 856 | #endif |
782 | assert(got != 0); | 857 | assert(got != 0); |
@@ -784,6 +859,7 @@ arch_apply_relocation(struct obj_file *f, | |||
784 | break; | 859 | break; |
785 | 860 | ||
786 | default: | 861 | default: |
862 | printf("Warning: unhandled reloc %d\n",ELF32_R_TYPE(rel->r_info)); | ||
787 | ret = obj_reloc_unhandled; | 863 | ret = obj_reloc_unhandled; |
788 | break; | 864 | break; |
789 | } | 865 | } |
@@ -794,81 +870,111 @@ arch_apply_relocation(struct obj_file *f, | |||
794 | int arch_create_got(struct obj_file *f) | 870 | int arch_create_got(struct obj_file *f) |
795 | { | 871 | { |
796 | struct arch_file *ifile = (struct arch_file *) f; | 872 | struct arch_file *ifile = (struct arch_file *) f; |
797 | int i, n, offset = 0, gotneeded = 0; | 873 | int i, got_offset = 0, gotneeded = 0; |
798 | 874 | #if defined(__arm__) | |
799 | n = ifile->root.header.e_shnum; | 875 | int plt_offset = 0, pltneeded = 0; |
800 | for (i = 0; i < n; ++i) { | ||
801 | struct obj_section *relsec, *symsec, *strsec; | ||
802 | #if defined(__sh__) | ||
803 | Elf32_Rela *rel, *relend; | ||
804 | #else | ||
805 | Elf32_Rel *rel, *relend; | ||
806 | #endif | 876 | #endif |
807 | Elf32_Sym *symtab; | 877 | struct obj_section *relsec, *symsec, *strsec; |
808 | const char *strtab; | 878 | ElfW(RelM) *rel, *relend; |
879 | ElfW(Sym) *symtab, *extsym; | ||
880 | const char *strtab, *name; | ||
881 | struct arch_symbol *intsym; | ||
809 | 882 | ||
810 | relsec = ifile->root.sections[i]; | 883 | for (i = 0; i < f->header.e_shnum; ++i) { |
811 | if (relsec->header.sh_type != SHT_REL) | 884 | relsec = f->sections[i]; |
885 | if (relsec->header.sh_type != SHT_RELM) | ||
812 | continue; | 886 | continue; |
813 | 887 | ||
814 | symsec = ifile->root.sections[relsec->header.sh_link]; | 888 | symsec = f->sections[relsec->header.sh_link]; |
815 | strsec = ifile->root.sections[symsec->header.sh_link]; | 889 | strsec = f->sections[symsec->header.sh_link]; |
816 | |||
817 | 890 | ||
818 | #if defined(__sh__) | 891 | rel = (ElfW(RelM) *) relsec->contents; |
819 | rel = (Elf32_Rela *) relsec->contents; | 892 | relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM))); |
820 | relend = rel + (relsec->header.sh_size / sizeof(Elf32_Rela)); | 893 | symtab = (ElfW(Sym) *) symsec->contents; |
821 | #else | ||
822 | rel = (Elf32_Rel *) relsec->contents; | ||
823 | relend = rel + (relsec->header.sh_size / sizeof(Elf32_Rel)); | ||
824 | #endif | ||
825 | symtab = (Elf32_Sym *) symsec->contents; | ||
826 | strtab = (const char *) strsec->contents; | 894 | strtab = (const char *) strsec->contents; |
827 | 895 | ||
828 | for (; rel < relend; ++rel) { | 896 | for (; rel < relend; ++rel) { |
829 | Elf32_Sym *extsym; | 897 | extsym = &symtab[ELF32_R_SYM(rel->r_info)]; |
830 | struct arch_symbol *intsym; | ||
831 | const char *name; | ||
832 | 898 | ||
833 | switch (ELF32_R_TYPE(rel->r_info)) { | 899 | switch (ELF32_R_TYPE(rel->r_info)) { |
834 | #if defined(__sh__) | 900 | #if defined(__arm__) |
901 | case R_ARM_GOT32: | ||
902 | #elif defined(__sh__) | ||
903 | case R_SH_GOT32: | ||
904 | #elif defined(__i386__) | ||
905 | case R_386_GOT32: | ||
906 | #endif | ||
907 | break; | ||
908 | |||
909 | #if defined(__arm__) | ||
910 | case R_ARM_PC24: | ||
911 | case R_ARM_PLT32: | ||
912 | pltneeded = 1; | ||
913 | break; | ||
914 | |||
915 | case R_ARM_GOTPC: | ||
916 | case R_ARM_GOTOFF: | ||
917 | gotneeded = 1; | ||
918 | if (got_offset == 0) | ||
919 | got_offset = 4; | ||
920 | #elif defined(__sh__) | ||
835 | case R_SH_GOTPC: | 921 | case R_SH_GOTPC: |
836 | case R_SH_GOTOFF: | 922 | case R_SH_GOTOFF: |
837 | #else | 923 | gotneeded = 1; |
924 | #elif defined(__i386__) | ||
838 | case R_386_GOTPC: | 925 | case R_386_GOTPC: |
839 | case R_386_GOTOFF: | 926 | case R_386_GOTOFF: |
840 | #endif | ||
841 | gotneeded = 1; | 927 | gotneeded = 1; |
928 | #endif | ||
929 | |||
842 | default: | 930 | default: |
843 | continue; | 931 | continue; |
844 | |||
845 | #if defined(__sh__) | ||
846 | case R_SH_GOT32: | ||
847 | #else | ||
848 | case R_386_GOT32: | ||
849 | #endif | ||
850 | break; | ||
851 | } | 932 | } |
852 | 933 | ||
853 | extsym = &symtab[ELF32_R_SYM(rel->r_info)]; | 934 | if (extsym->st_name != 0) { |
854 | if (extsym->st_name) | ||
855 | name = strtab + extsym->st_name; | 935 | name = strtab + extsym->st_name; |
856 | else | 936 | } else { |
857 | name = f->sections[extsym->st_shndx]->name; | 937 | name = f->sections[extsym->st_shndx]->name; |
858 | intsym = | 938 | } |
859 | (struct arch_symbol *) obj_find_symbol(&ifile->root, name); | 939 | intsym = (struct arch_symbol *) obj_find_symbol(f, name); |
860 | 940 | ||
861 | if (!intsym->gotent.offset_done) { | 941 | if (!intsym->gotent.offset_done) { |
862 | intsym->gotent.offset_done = 1; | 942 | intsym->gotent.offset_done = 1; |
863 | intsym->gotent.offset = offset; | 943 | intsym->gotent.offset = got_offset; |
864 | offset += 4; | 944 | got_offset += 4; |
865 | } | 945 | } |
946 | #if defined(__arm__) | ||
947 | if (pltneeded && intsym->pltent.allocated == 0) { | ||
948 | intsym->pltent.allocated = 1; | ||
949 | intsym->pltent.offset = plt_offset; | ||
950 | plt_offset += 8; | ||
951 | intsym->pltent.inited = 0; | ||
952 | pltneeded = 0; | ||
953 | } | ||
954 | #endif | ||
955 | } | ||
956 | } | ||
957 | |||
958 | #if defined(__arm__) | ||
959 | if (got_offset) { | ||
960 | struct obj_section* relsec = obj_find_section(f, ".got"); | ||
961 | |||
962 | if (relsec) { | ||
963 | obj_extend_section(relsec, got_offset); | ||
964 | } else { | ||
965 | relsec = obj_create_alloced_section(f, ".got", 8, got_offset); | ||
966 | assert(relsec); | ||
866 | } | 967 | } |
968 | |||
969 | ifile->got = relsec; | ||
867 | } | 970 | } |
868 | 971 | ||
869 | if (offset > 0 || gotneeded) | 972 | if (plt_offset) |
870 | ifile->got = | 973 | ifile->plt = obj_create_alloced_section(f, ".plt", 8, plt_offset); |
871 | obj_create_alloced_section(&ifile->root, ".got", 4, offset); | 974 | #else |
975 | if (got_offset > 0 || gotneeded) | ||
976 | ifile->got = obj_create_alloced_section(f, ".got", 4, got_offset); | ||
977 | #endif | ||
872 | 978 | ||
873 | return 1; | 979 | return 1; |
874 | } | 980 | } |
@@ -1598,7 +1704,7 @@ old_init_module(const char *m_name, struct obj_file *f, | |||
1598 | ksym->name = | 1704 | ksym->name = |
1599 | (unsigned long) str - (unsigned long) symtab; | 1705 | (unsigned long) str - (unsigned long) symtab; |
1600 | 1706 | ||
1601 | str = stpcpy(str, sym->name) + 1; | 1707 | str = strcpy(str, sym->name) + 1; |
1602 | ksym++; | 1708 | ksym++; |
1603 | } | 1709 | } |
1604 | } | 1710 | } |
@@ -2201,8 +2307,9 @@ new_init_module(const char *m_name, struct obj_file *f, | |||
2201 | #define new_init_module(x, y, z) TRUE | 2307 | #define new_init_module(x, y, z) TRUE |
2202 | #define new_create_this_module(x, y) 0 | 2308 | #define new_create_this_module(x, y) 0 |
2203 | #define new_create_module_ksymtab(x) | 2309 | #define new_create_module_ksymtab(x) |
2310 | #define query_module(v, w, x, y, z) -1 | ||
2204 | 2311 | ||
2205 | #endif /* BB_FEATURE_INSMOD_OLD_KERNEL */ | 2312 | #endif /* BB_FEATURE_INSMOD_NEW_KERNEL */ |
2206 | 2313 | ||
2207 | 2314 | ||
2208 | /*======================================================================*/ | 2315 | /*======================================================================*/ |
@@ -2372,8 +2479,12 @@ void obj_allocate_commons(struct obj_file *f) | |||
2372 | for (i = 0; i < f->header.e_shnum; ++i) { | 2479 | for (i = 0; i < f->header.e_shnum; ++i) { |
2373 | struct obj_section *s = f->sections[i]; | 2480 | struct obj_section *s = f->sections[i]; |
2374 | if (s->header.sh_type == SHT_NOBITS) { | 2481 | if (s->header.sh_type == SHT_NOBITS) { |
2482 | if (s->header.sh_size != 0) | ||
2375 | s->contents = memset(xmalloc(s->header.sh_size), | 2483 | s->contents = memset(xmalloc(s->header.sh_size), |
2376 | 0, s->header.sh_size); | 2484 | 0, s->header.sh_size); |
2485 | else | ||
2486 | s->contents = NULL; | ||
2487 | |||
2377 | s->header.sh_type = SHT_PROGBITS; | 2488 | s->header.sh_type = SHT_PROGBITS; |
2378 | } | 2489 | } |
2379 | } | 2490 | } |
@@ -5,6 +5,10 @@ | |||
5 | * Copyright (C) 1999,2000 by Lineo, inc. | 5 | * Copyright (C) 1999,2000 by Lineo, inc. |
6 | * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> | 6 | * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> |
7 | * | 7 | * |
8 | * Modified by Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and | ||
9 | * Nicolas Ferre <nicolas.ferre@alcove.fr> to support pre 2.1 kernels | ||
10 | * (which lack the query_module() interface). | ||
11 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 13 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation; either version 2 of the License, or | 14 | * the Free Software Foundation; either version 2 of the License, or |
@@ -32,8 +36,15 @@ | |||
32 | #include <assert.h> | 36 | #include <assert.h> |
33 | #include <getopt.h> | 37 | #include <getopt.h> |
34 | #include <sys/utsname.h> | 38 | #include <sys/utsname.h> |
39 | #include <sys/file.h> | ||
40 | |||
35 | 41 | ||
36 | 42 | ||
43 | #if !defined(BB_FEATURE_LSMOD_NEW_KERNEL) && !defined(BB_FEATURE_LSMOD_OLD_KERNEL) | ||
44 | #error "Must have ether BB_FEATURE_LSMOD_NEW_KERNEL or BB_FEATURE_LSMOD_OLD_KERNEL defined" | ||
45 | #endif | ||
46 | |||
47 | #ifdef BB_FEATURE_LSMOD_NEW_KERNEL | ||
37 | 48 | ||
38 | struct module_info | 49 | struct module_info |
39 | { | 50 | { |
@@ -120,3 +131,30 @@ extern int lsmod_main(int argc, char **argv) | |||
120 | 131 | ||
121 | return( 0); | 132 | return( 0); |
122 | } | 133 | } |
134 | |||
135 | #else /*BB_FEATURE_LSMOD_OLD_KERNEL*/ | ||
136 | |||
137 | #if ! defined BB_FEATURE_USE_PROCFS | ||
138 | #error Sorry, I depend on the /proc filesystem right now. | ||
139 | #endif | ||
140 | |||
141 | extern int lsmod_main(int argc, char **argv) | ||
142 | { | ||
143 | int fd, i; | ||
144 | char line[128]; | ||
145 | |||
146 | puts("Module Size Used by"); | ||
147 | fflush(stdout); | ||
148 | |||
149 | if ((fd = open("/proc/modules", O_RDONLY)) >= 0 ) { | ||
150 | while ((i = read(fd, line, sizeof(line))) > 0) { | ||
151 | write(fileno(stdout), line, i); | ||
152 | } | ||
153 | close(fd); | ||
154 | return 0; | ||
155 | } | ||
156 | fatalError("/proc/modules: %s\n", strerror(errno)); | ||
157 | return 1; | ||
158 | } | ||
159 | |||
160 | #endif /*BB_FEATURE_LSMOD_OLD_KERNEL*/ | ||
diff --git a/modutils/insmod.c b/modutils/insmod.c index 6386b9407..0963225fa 100644 --- a/modutils/insmod.c +++ b/modutils/insmod.c | |||
@@ -7,11 +7,12 @@ | |||
7 | * and Ron Alder <alder@lineo.com> | 7 | * and Ron Alder <alder@lineo.com> |
8 | * | 8 | * |
9 | * Modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4 | 9 | * Modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4 |
10 | * and (theoretically) SH3. Note that there is still no true | 10 | * and (theoretically) SH3. I have only tested SH4 in little endian mode. |
11 | * multiple architecture support. You just get SH3|SH4|i386, despite | 11 | * |
12 | * the mention of ARM and m68k--which may or may not work (but | 12 | * Modified by Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and |
13 | * almost certainly do not, due to at least MATCH_MACHINE). I have | 13 | * Nicolas Ferre <nicolas.ferre@alcove.fr> to support ARM7TDMI. Only |
14 | * only tested SH4 in little endian mode. | 14 | * very minor changes required to also work with StrongArm and presumably |
15 | * all ARM based systems. | ||
15 | * | 16 | * |
16 | * Based almost entirely on the Linux modutils-2.3.11 implementation. | 17 | * Based almost entirely on the Linux modutils-2.3.11 implementation. |
17 | * Copyright 1996, 1997 Linux International. | 18 | * Copyright 1996, 1997 Linux International. |
@@ -77,7 +78,7 @@ | |||
77 | #ifndef MODUTILS_MODULE_H | 78 | #ifndef MODUTILS_MODULE_H |
78 | #define MODUTILS_MODULE_H 1 | 79 | #define MODUTILS_MODULE_H 1 |
79 | 80 | ||
80 | #ident "$Id: insmod.c,v 1.29 2000/12/01 02:55:13 kraai Exp $" | 81 | #ident "$Id: insmod.c,v 1.30 2000/12/06 18:18:26 andersen Exp $" |
81 | 82 | ||
82 | /* This file contains the structures used by the 2.0 and 2.1 kernels. | 83 | /* This file contains the structures used by the 2.0 and 2.1 kernels. |
83 | We do not use the kernel headers directly because we do not wish | 84 | We do not use the kernel headers directly because we do not wish |
@@ -283,7 +284,7 @@ int delete_module(const char *); | |||
283 | #ifndef MODUTILS_OBJ_H | 284 | #ifndef MODUTILS_OBJ_H |
284 | #define MODUTILS_OBJ_H 1 | 285 | #define MODUTILS_OBJ_H 1 |
285 | 286 | ||
286 | #ident "$Id: insmod.c,v 1.29 2000/12/01 02:55:13 kraai Exp $" | 287 | #ident "$Id: insmod.c,v 1.30 2000/12/06 18:18:26 andersen Exp $" |
287 | 288 | ||
288 | /* The relocatable object is manipulated using elfin types. */ | 289 | /* The relocatable object is manipulated using elfin types. */ |
289 | 290 | ||
@@ -317,12 +318,17 @@ int delete_module(const char *); | |||
317 | #define SHT_RELM SHT_RELA | 318 | #define SHT_RELM SHT_RELA |
318 | #define Elf32_RelM Elf32_Rela | 319 | #define Elf32_RelM Elf32_Rela |
319 | 320 | ||
320 | #else | 321 | #elif defined(__arm__) |
321 | 322 | ||
322 | /* presumably we can use these for anything but the SH */ | 323 | #define MATCH_MACHINE(x) (x == EM_ARM) |
324 | #define SHT_RELM SHT_REL | ||
325 | #define Elf32_RelM Elf32_Rel | ||
326 | |||
327 | #elif defined(__i386__) | ||
328 | |||
329 | /* presumably we can use these for anything but the SH and ARM*/ | ||
323 | /* this is the previous behavior, but it does result in | 330 | /* this is the previous behavior, but it does result in |
324 | insmod.c being broken on anything except i386 */ | 331 | insmod.c being broken on anything except i386 */ |
325 | |||
326 | #ifndef EM_486 | 332 | #ifndef EM_486 |
327 | #define MATCH_MACHINE(x) (x == EM_386) | 333 | #define MATCH_MACHINE(x) (x == EM_386) |
328 | #else | 334 | #else |
@@ -332,6 +338,8 @@ int delete_module(const char *); | |||
332 | #define SHT_RELM SHT_REL | 338 | #define SHT_RELM SHT_REL |
333 | #define Elf32_RelM Elf32_Rel | 339 | #define Elf32_RelM Elf32_Rel |
334 | 340 | ||
341 | #else | ||
342 | #error insmod.c no platform specified | ||
335 | #endif | 343 | #endif |
336 | 344 | ||
337 | #ifndef ElfW | 345 | #ifndef ElfW |
@@ -531,6 +539,17 @@ int flag_export = 1; | |||
531 | and we can't support anything else right now anyway. In the | 539 | and we can't support anything else right now anyway. In the |
532 | future maybe they should be #if defined'd */ | 540 | future maybe they should be #if defined'd */ |
533 | 541 | ||
542 | /* Done ;-) */ | ||
543 | |||
544 | #if defined(__arm__) | ||
545 | struct arm_plt_entry | ||
546 | { | ||
547 | int offset; | ||
548 | int allocated:1; | ||
549 | int inited:1; /* has been set up */ | ||
550 | }; | ||
551 | #endif | ||
552 | |||
534 | struct arch_got_entry { | 553 | struct arch_got_entry { |
535 | int offset; | 554 | int offset; |
536 | unsigned offset_done:1; | 555 | unsigned offset_done:1; |
@@ -539,11 +558,17 @@ struct arch_got_entry { | |||
539 | 558 | ||
540 | struct arch_file { | 559 | struct arch_file { |
541 | struct obj_file root; | 560 | struct obj_file root; |
561 | #if defined(__arm__) | ||
562 | struct obj_section *plt; | ||
563 | #endif | ||
542 | struct obj_section *got; | 564 | struct obj_section *got; |
543 | }; | 565 | }; |
544 | 566 | ||
545 | struct arch_symbol { | 567 | struct arch_symbol { |
546 | struct obj_symbol root; | 568 | struct obj_symbol root; |
569 | #if defined(__arm__) | ||
570 | struct arm_plt_entry pltent; | ||
571 | #endif | ||
547 | struct arch_got_entry gotent; | 572 | struct arch_got_entry gotent; |
548 | }; | 573 | }; |
549 | 574 | ||
@@ -590,6 +615,10 @@ extern int delete_module(const char *); | |||
590 | 615 | ||
591 | -- Bryan Rittmeyer <bryan@ixiacom.com> */ | 616 | -- Bryan Rittmeyer <bryan@ixiacom.com> */ |
592 | 617 | ||
618 | #ifdef BB_FEATURE_INSMOD_OLD_KERNEL | ||
619 | _syscall1(int, get_kernel_syms, struct old_kernel_sym *, ks) | ||
620 | #endif | ||
621 | |||
593 | #if defined(__i386__) || defined(__m68k__) || defined(__arm__) | 622 | #if defined(__i386__) || defined(__m68k__) || defined(__arm__) |
594 | /* Jump through hoops to fixup error return codes */ | 623 | /* Jump through hoops to fixup error return codes */ |
595 | #define __NR__create_module __NR_create_module | 624 | #define __NR__create_module __NR_create_module |
@@ -623,7 +652,7 @@ static int findNamedModule(const char *fileName, struct stat *statbuf, | |||
623 | if (fullName[0] == '\0') | 652 | if (fullName[0] == '\0') |
624 | return (FALSE); | 653 | return (FALSE); |
625 | else { | 654 | else { |
626 | char *tmp = strrchr(fileName, '/'); | 655 | char *tmp = strrchr((char *) fileName, '/'); |
627 | 656 | ||
628 | if (tmp == NULL) | 657 | if (tmp == NULL) |
629 | tmp = (char *) fileName; | 658 | tmp = (char *) fileName; |
@@ -667,18 +696,20 @@ arch_apply_relocation(struct obj_file *f, | |||
667 | struct obj_section *targsec, | 696 | struct obj_section *targsec, |
668 | struct obj_section *symsec, | 697 | struct obj_section *symsec, |
669 | struct obj_symbol *sym, | 698 | struct obj_symbol *sym, |
670 | #if defined(__sh__) | 699 | ElfW(RelM) *rel, ElfW(Addr) v) |
671 | Elf32_Rela * rel, Elf32_Addr v) | ||
672 | #else | ||
673 | Elf32_Rel * rel, Elf32_Addr v) | ||
674 | #endif | ||
675 | { | 700 | { |
676 | struct arch_file *ifile = (struct arch_file *) f; | 701 | struct arch_file *ifile = (struct arch_file *) f; |
677 | struct arch_symbol *isym = (struct arch_symbol *) sym; | 702 | struct arch_symbol *isym = (struct arch_symbol *) sym; |
678 | 703 | ||
679 | Elf32_Addr *loc = (Elf32_Addr *) (targsec->contents + rel->r_offset); | 704 | ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset); |
680 | Elf32_Addr dot = targsec->header.sh_addr + rel->r_offset; | 705 | ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset; |
681 | Elf32_Addr got = ifile->got ? ifile->got->header.sh_addr : 0; | 706 | ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0; |
707 | #if defined(__arm__) | ||
708 | ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0; | ||
709 | |||
710 | struct arm_plt_entry *pe; | ||
711 | unsigned long *ip; | ||
712 | #endif | ||
682 | 713 | ||
683 | enum obj_reloc ret = obj_reloc_ok; | 714 | enum obj_reloc ret = obj_reloc_ok; |
684 | 715 | ||
@@ -689,52 +720,91 @@ arch_apply_relocation(struct obj_file *f, | |||
689 | and in case that ever changes */ | 720 | and in case that ever changes */ |
690 | #if defined(__sh__) | 721 | #if defined(__sh__) |
691 | case R_SH_NONE: | 722 | case R_SH_NONE: |
692 | #else | 723 | #elif defined(__arm__) |
724 | case R_ARM_NONE: | ||
725 | #elif defined(__i386__) | ||
693 | case R_386_NONE: | 726 | case R_386_NONE: |
694 | #endif | 727 | #endif |
695 | break; | 728 | break; |
696 | 729 | ||
697 | #if defined(__sh__) | 730 | #if defined(__sh__) |
698 | case R_SH_DIR32: | 731 | case R_SH_DIR32: |
699 | #else | 732 | #elif defined(__arm__) |
733 | case R_ARM_ABS32: | ||
734 | #elif defined(__i386__) | ||
700 | case R_386_32: | 735 | case R_386_32: |
701 | #endif | 736 | #endif |
702 | *loc += v; | 737 | *loc += v; |
703 | break; | 738 | break; |
704 | 739 | ||
705 | #if defined(__sh__) | 740 | #if defined(__arm__) |
741 | #elif defined(__sh__) | ||
706 | case R_SH_REL32: | 742 | case R_SH_REL32: |
707 | #else | 743 | *loc += v - dot; |
744 | break; | ||
745 | #elif defined(__i386__) | ||
708 | case R_386_PLT32: | 746 | case R_386_PLT32: |
709 | case R_386_PC32: | 747 | case R_386_PC32: |
710 | #endif | ||
711 | *loc += v - dot; | 748 | *loc += v - dot; |
712 | break; | 749 | break; |
750 | #endif | ||
713 | 751 | ||
714 | #if defined(__sh__) | 752 | #if defined(__sh__) |
715 | case R_SH_PLT32: | 753 | case R_SH_PLT32: |
716 | *loc = v - dot; | 754 | *loc = v - dot; |
717 | break; | 755 | break; |
756 | #elif defined(__arm__) | ||
757 | case R_ARM_PC24: | ||
758 | case R_ARM_PLT32: | ||
759 | /* find the plt entry and initialize it if necessary */ | ||
760 | assert(isym != NULL); | ||
761 | pe = (struct arm_plt_entry*) &isym->pltent; | ||
762 | if (! pe->inited) { | ||
763 | ip = (unsigned long *) (ifile->plt->contents + pe->offset); | ||
764 | ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */ | ||
765 | ip[1] = v; /* sym@ */ | ||
766 | pe->inited = 1; | ||
767 | } | ||
768 | |||
769 | /* relative distance to target */ | ||
770 | v -= dot; | ||
771 | /* if the target is too far away.... */ | ||
772 | if ((int)v < -0x02000000 || (int)v >= 0x02000000) { | ||
773 | /* go via the plt */ | ||
774 | v = plt + pe->offset - dot; | ||
775 | } | ||
776 | if (v & 3) | ||
777 | ret = obj_reloc_dangerous; | ||
778 | |||
779 | /* Convert to words. */ | ||
780 | v >>= 2; | ||
781 | |||
782 | /* merge the offset into the instruction. */ | ||
783 | *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff); | ||
784 | break; | ||
785 | #elif defined(__i386__) | ||
718 | #endif | 786 | #endif |
719 | 787 | ||
720 | 788 | ||
721 | #if defined(__sh__) | 789 | #if defined(__arm__) |
790 | #elif defined(__sh__) | ||
722 | case R_SH_GLOB_DAT: | 791 | case R_SH_GLOB_DAT: |
723 | case R_SH_JMP_SLOT: | 792 | case R_SH_JMP_SLOT: |
724 | *loc = v; | 793 | *loc = v; |
725 | break; | 794 | break; |
726 | #else | 795 | #elif defined(__i386__) |
727 | case R_386_GLOB_DAT: | 796 | case R_386_GLOB_DAT: |
728 | case R_386_JMP_SLOT: | 797 | case R_386_JMP_SLOT: |
729 | *loc = v; | 798 | *loc = v; |
730 | break; | 799 | break; |
731 | #endif | 800 | #endif |
732 | 801 | ||
733 | #if defined(__sh__) | 802 | #if defined(__arm__) |
803 | #elif defined(__sh__) | ||
734 | case R_SH_RELATIVE: | 804 | case R_SH_RELATIVE: |
735 | *loc += f->baseaddr + rel->r_addend; | 805 | *loc += f->baseaddr + rel->r_addend; |
736 | break; | 806 | break; |
737 | #else | 807 | #elif defined(__i386__) |
738 | case R_386_RELATIVE: | 808 | case R_386_RELATIVE: |
739 | *loc += f->baseaddr; | 809 | *loc += f->baseaddr; |
740 | break; | 810 | break; |
@@ -742,41 +812,46 @@ arch_apply_relocation(struct obj_file *f, | |||
742 | 812 | ||
743 | #if defined(__sh__) | 813 | #if defined(__sh__) |
744 | case R_SH_GOTPC: | 814 | case R_SH_GOTPC: |
745 | assert(got != 0); | 815 | #elif defined(__arm__) |
746 | *loc += got - dot + rel->r_addend;; | 816 | case R_ARM_GOTPC: |
747 | break; | 817 | #elif defined(__i386__) |
748 | #else | ||
749 | case R_386_GOTPC: | 818 | case R_386_GOTPC: |
819 | #endif | ||
750 | assert(got != 0); | 820 | assert(got != 0); |
821 | #if defined(__sh__) | ||
822 | *loc += got - dot + rel->r_addend;; | ||
823 | #elif defined(__i386__) || defined(__arm__) | ||
751 | *loc += got - dot; | 824 | *loc += got - dot; |
752 | break; | ||
753 | #endif | 825 | #endif |
826 | break; | ||
754 | 827 | ||
755 | #if defined(__sh__) | 828 | #if defined(__sh__) |
756 | case R_SH_GOT32: | 829 | case R_SH_GOT32: |
757 | assert(isym != NULL); | 830 | #elif defined(__arm__) |
758 | if (!isym->gotent.reloc_done) { | 831 | case R_ARM_GOT32: |
759 | isym->gotent.reloc_done = 1; | 832 | #elif defined(__i386__) |
760 | *(Elf32_Addr *) (ifile->got->contents + isym->gotent.offset) = | ||
761 | v; | ||
762 | } | ||
763 | *loc += isym->gotent.offset + rel->r_addend; | ||
764 | break; | ||
765 | #else | ||
766 | case R_386_GOT32: | 833 | case R_386_GOT32: |
834 | #endif | ||
767 | assert(isym != NULL); | 835 | assert(isym != NULL); |
836 | /* needs an entry in the .got: set it, once */ | ||
768 | if (!isym->gotent.reloc_done) { | 837 | if (!isym->gotent.reloc_done) { |
769 | isym->gotent.reloc_done = 1; | 838 | isym->gotent.reloc_done = 1; |
770 | *(Elf32_Addr *) (ifile->got->contents + isym->gotent.offset) = | 839 | *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v; |
771 | v; | ||
772 | } | 840 | } |
841 | /* make the reloc with_respect_to_.got */ | ||
842 | #if defined(__sh__) | ||
843 | *loc += isym->gotent.offset + rel->r_addend; | ||
844 | #elif defined(__i386__) || defined(__arm__) | ||
773 | *loc += isym->gotent.offset; | 845 | *loc += isym->gotent.offset; |
774 | break; | ||
775 | #endif | 846 | #endif |
847 | break; | ||
776 | 848 | ||
849 | /* address relative to the got */ | ||
777 | #if defined(__sh__) | 850 | #if defined(__sh__) |
778 | case R_SH_GOTOFF: | 851 | case R_SH_GOTOFF: |
779 | #else | 852 | #elif defined(__arm__) |
853 | case R_ARM_GOTOFF: | ||
854 | #elif defined(__i386__) | ||
780 | case R_386_GOTOFF: | 855 | case R_386_GOTOFF: |
781 | #endif | 856 | #endif |
782 | assert(got != 0); | 857 | assert(got != 0); |
@@ -784,6 +859,7 @@ arch_apply_relocation(struct obj_file *f, | |||
784 | break; | 859 | break; |
785 | 860 | ||
786 | default: | 861 | default: |
862 | printf("Warning: unhandled reloc %d\n",ELF32_R_TYPE(rel->r_info)); | ||
787 | ret = obj_reloc_unhandled; | 863 | ret = obj_reloc_unhandled; |
788 | break; | 864 | break; |
789 | } | 865 | } |
@@ -794,81 +870,111 @@ arch_apply_relocation(struct obj_file *f, | |||
794 | int arch_create_got(struct obj_file *f) | 870 | int arch_create_got(struct obj_file *f) |
795 | { | 871 | { |
796 | struct arch_file *ifile = (struct arch_file *) f; | 872 | struct arch_file *ifile = (struct arch_file *) f; |
797 | int i, n, offset = 0, gotneeded = 0; | 873 | int i, got_offset = 0, gotneeded = 0; |
798 | 874 | #if defined(__arm__) | |
799 | n = ifile->root.header.e_shnum; | 875 | int plt_offset = 0, pltneeded = 0; |
800 | for (i = 0; i < n; ++i) { | ||
801 | struct obj_section *relsec, *symsec, *strsec; | ||
802 | #if defined(__sh__) | ||
803 | Elf32_Rela *rel, *relend; | ||
804 | #else | ||
805 | Elf32_Rel *rel, *relend; | ||
806 | #endif | 876 | #endif |
807 | Elf32_Sym *symtab; | 877 | struct obj_section *relsec, *symsec, *strsec; |
808 | const char *strtab; | 878 | ElfW(RelM) *rel, *relend; |
879 | ElfW(Sym) *symtab, *extsym; | ||
880 | const char *strtab, *name; | ||
881 | struct arch_symbol *intsym; | ||
809 | 882 | ||
810 | relsec = ifile->root.sections[i]; | 883 | for (i = 0; i < f->header.e_shnum; ++i) { |
811 | if (relsec->header.sh_type != SHT_REL) | 884 | relsec = f->sections[i]; |
885 | if (relsec->header.sh_type != SHT_RELM) | ||
812 | continue; | 886 | continue; |
813 | 887 | ||
814 | symsec = ifile->root.sections[relsec->header.sh_link]; | 888 | symsec = f->sections[relsec->header.sh_link]; |
815 | strsec = ifile->root.sections[symsec->header.sh_link]; | 889 | strsec = f->sections[symsec->header.sh_link]; |
816 | |||
817 | 890 | ||
818 | #if defined(__sh__) | 891 | rel = (ElfW(RelM) *) relsec->contents; |
819 | rel = (Elf32_Rela *) relsec->contents; | 892 | relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM))); |
820 | relend = rel + (relsec->header.sh_size / sizeof(Elf32_Rela)); | 893 | symtab = (ElfW(Sym) *) symsec->contents; |
821 | #else | ||
822 | rel = (Elf32_Rel *) relsec->contents; | ||
823 | relend = rel + (relsec->header.sh_size / sizeof(Elf32_Rel)); | ||
824 | #endif | ||
825 | symtab = (Elf32_Sym *) symsec->contents; | ||
826 | strtab = (const char *) strsec->contents; | 894 | strtab = (const char *) strsec->contents; |
827 | 895 | ||
828 | for (; rel < relend; ++rel) { | 896 | for (; rel < relend; ++rel) { |
829 | Elf32_Sym *extsym; | 897 | extsym = &symtab[ELF32_R_SYM(rel->r_info)]; |
830 | struct arch_symbol *intsym; | ||
831 | const char *name; | ||
832 | 898 | ||
833 | switch (ELF32_R_TYPE(rel->r_info)) { | 899 | switch (ELF32_R_TYPE(rel->r_info)) { |
834 | #if defined(__sh__) | 900 | #if defined(__arm__) |
901 | case R_ARM_GOT32: | ||
902 | #elif defined(__sh__) | ||
903 | case R_SH_GOT32: | ||
904 | #elif defined(__i386__) | ||
905 | case R_386_GOT32: | ||
906 | #endif | ||
907 | break; | ||
908 | |||
909 | #if defined(__arm__) | ||
910 | case R_ARM_PC24: | ||
911 | case R_ARM_PLT32: | ||
912 | pltneeded = 1; | ||
913 | break; | ||
914 | |||
915 | case R_ARM_GOTPC: | ||
916 | case R_ARM_GOTOFF: | ||
917 | gotneeded = 1; | ||
918 | if (got_offset == 0) | ||
919 | got_offset = 4; | ||
920 | #elif defined(__sh__) | ||
835 | case R_SH_GOTPC: | 921 | case R_SH_GOTPC: |
836 | case R_SH_GOTOFF: | 922 | case R_SH_GOTOFF: |
837 | #else | 923 | gotneeded = 1; |
924 | #elif defined(__i386__) | ||
838 | case R_386_GOTPC: | 925 | case R_386_GOTPC: |
839 | case R_386_GOTOFF: | 926 | case R_386_GOTOFF: |
840 | #endif | ||
841 | gotneeded = 1; | 927 | gotneeded = 1; |
928 | #endif | ||
929 | |||
842 | default: | 930 | default: |
843 | continue; | 931 | continue; |
844 | |||
845 | #if defined(__sh__) | ||
846 | case R_SH_GOT32: | ||
847 | #else | ||
848 | case R_386_GOT32: | ||
849 | #endif | ||
850 | break; | ||
851 | } | 932 | } |
852 | 933 | ||
853 | extsym = &symtab[ELF32_R_SYM(rel->r_info)]; | 934 | if (extsym->st_name != 0) { |
854 | if (extsym->st_name) | ||
855 | name = strtab + extsym->st_name; | 935 | name = strtab + extsym->st_name; |
856 | else | 936 | } else { |
857 | name = f->sections[extsym->st_shndx]->name; | 937 | name = f->sections[extsym->st_shndx]->name; |
858 | intsym = | 938 | } |
859 | (struct arch_symbol *) obj_find_symbol(&ifile->root, name); | 939 | intsym = (struct arch_symbol *) obj_find_symbol(f, name); |
860 | 940 | ||
861 | if (!intsym->gotent.offset_done) { | 941 | if (!intsym->gotent.offset_done) { |
862 | intsym->gotent.offset_done = 1; | 942 | intsym->gotent.offset_done = 1; |
863 | intsym->gotent.offset = offset; | 943 | intsym->gotent.offset = got_offset; |
864 | offset += 4; | 944 | got_offset += 4; |
865 | } | 945 | } |
946 | #if defined(__arm__) | ||
947 | if (pltneeded && intsym->pltent.allocated == 0) { | ||
948 | intsym->pltent.allocated = 1; | ||
949 | intsym->pltent.offset = plt_offset; | ||
950 | plt_offset += 8; | ||
951 | intsym->pltent.inited = 0; | ||
952 | pltneeded = 0; | ||
953 | } | ||
954 | #endif | ||
955 | } | ||
956 | } | ||
957 | |||
958 | #if defined(__arm__) | ||
959 | if (got_offset) { | ||
960 | struct obj_section* relsec = obj_find_section(f, ".got"); | ||
961 | |||
962 | if (relsec) { | ||
963 | obj_extend_section(relsec, got_offset); | ||
964 | } else { | ||
965 | relsec = obj_create_alloced_section(f, ".got", 8, got_offset); | ||
966 | assert(relsec); | ||
866 | } | 967 | } |
968 | |||
969 | ifile->got = relsec; | ||
867 | } | 970 | } |
868 | 971 | ||
869 | if (offset > 0 || gotneeded) | 972 | if (plt_offset) |
870 | ifile->got = | 973 | ifile->plt = obj_create_alloced_section(f, ".plt", 8, plt_offset); |
871 | obj_create_alloced_section(&ifile->root, ".got", 4, offset); | 974 | #else |
975 | if (got_offset > 0 || gotneeded) | ||
976 | ifile->got = obj_create_alloced_section(f, ".got", 4, got_offset); | ||
977 | #endif | ||
872 | 978 | ||
873 | return 1; | 979 | return 1; |
874 | } | 980 | } |
@@ -1598,7 +1704,7 @@ old_init_module(const char *m_name, struct obj_file *f, | |||
1598 | ksym->name = | 1704 | ksym->name = |
1599 | (unsigned long) str - (unsigned long) symtab; | 1705 | (unsigned long) str - (unsigned long) symtab; |
1600 | 1706 | ||
1601 | str = stpcpy(str, sym->name) + 1; | 1707 | str = strcpy(str, sym->name) + 1; |
1602 | ksym++; | 1708 | ksym++; |
1603 | } | 1709 | } |
1604 | } | 1710 | } |
@@ -2201,8 +2307,9 @@ new_init_module(const char *m_name, struct obj_file *f, | |||
2201 | #define new_init_module(x, y, z) TRUE | 2307 | #define new_init_module(x, y, z) TRUE |
2202 | #define new_create_this_module(x, y) 0 | 2308 | #define new_create_this_module(x, y) 0 |
2203 | #define new_create_module_ksymtab(x) | 2309 | #define new_create_module_ksymtab(x) |
2310 | #define query_module(v, w, x, y, z) -1 | ||
2204 | 2311 | ||
2205 | #endif /* BB_FEATURE_INSMOD_OLD_KERNEL */ | 2312 | #endif /* BB_FEATURE_INSMOD_NEW_KERNEL */ |
2206 | 2313 | ||
2207 | 2314 | ||
2208 | /*======================================================================*/ | 2315 | /*======================================================================*/ |
@@ -2372,8 +2479,12 @@ void obj_allocate_commons(struct obj_file *f) | |||
2372 | for (i = 0; i < f->header.e_shnum; ++i) { | 2479 | for (i = 0; i < f->header.e_shnum; ++i) { |
2373 | struct obj_section *s = f->sections[i]; | 2480 | struct obj_section *s = f->sections[i]; |
2374 | if (s->header.sh_type == SHT_NOBITS) { | 2481 | if (s->header.sh_type == SHT_NOBITS) { |
2482 | if (s->header.sh_size != 0) | ||
2375 | s->contents = memset(xmalloc(s->header.sh_size), | 2483 | s->contents = memset(xmalloc(s->header.sh_size), |
2376 | 0, s->header.sh_size); | 2484 | 0, s->header.sh_size); |
2485 | else | ||
2486 | s->contents = NULL; | ||
2487 | |||
2377 | s->header.sh_type = SHT_PROGBITS; | 2488 | s->header.sh_type = SHT_PROGBITS; |
2378 | } | 2489 | } |
2379 | } | 2490 | } |
diff --git a/modutils/lsmod.c b/modutils/lsmod.c index ab4726b9e..6fe505bf6 100644 --- a/modutils/lsmod.c +++ b/modutils/lsmod.c | |||
@@ -5,6 +5,10 @@ | |||
5 | * Copyright (C) 1999,2000 by Lineo, inc. | 5 | * Copyright (C) 1999,2000 by Lineo, inc. |
6 | * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> | 6 | * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> |
7 | * | 7 | * |
8 | * Modified by Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and | ||
9 | * Nicolas Ferre <nicolas.ferre@alcove.fr> to support pre 2.1 kernels | ||
10 | * (which lack the query_module() interface). | ||
11 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 13 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation; either version 2 of the License, or | 14 | * the Free Software Foundation; either version 2 of the License, or |
@@ -32,8 +36,15 @@ | |||
32 | #include <assert.h> | 36 | #include <assert.h> |
33 | #include <getopt.h> | 37 | #include <getopt.h> |
34 | #include <sys/utsname.h> | 38 | #include <sys/utsname.h> |
39 | #include <sys/file.h> | ||
40 | |||
35 | 41 | ||
36 | 42 | ||
43 | #if !defined(BB_FEATURE_LSMOD_NEW_KERNEL) && !defined(BB_FEATURE_LSMOD_OLD_KERNEL) | ||
44 | #error "Must have ether BB_FEATURE_LSMOD_NEW_KERNEL or BB_FEATURE_LSMOD_OLD_KERNEL defined" | ||
45 | #endif | ||
46 | |||
47 | #ifdef BB_FEATURE_LSMOD_NEW_KERNEL | ||
37 | 48 | ||
38 | struct module_info | 49 | struct module_info |
39 | { | 50 | { |
@@ -120,3 +131,30 @@ extern int lsmod_main(int argc, char **argv) | |||
120 | 131 | ||
121 | return( 0); | 132 | return( 0); |
122 | } | 133 | } |
134 | |||
135 | #else /*BB_FEATURE_LSMOD_OLD_KERNEL*/ | ||
136 | |||
137 | #if ! defined BB_FEATURE_USE_PROCFS | ||
138 | #error Sorry, I depend on the /proc filesystem right now. | ||
139 | #endif | ||
140 | |||
141 | extern int lsmod_main(int argc, char **argv) | ||
142 | { | ||
143 | int fd, i; | ||
144 | char line[128]; | ||
145 | |||
146 | puts("Module Size Used by"); | ||
147 | fflush(stdout); | ||
148 | |||
149 | if ((fd = open("/proc/modules", O_RDONLY)) >= 0 ) { | ||
150 | while ((i = read(fd, line, sizeof(line))) > 0) { | ||
151 | write(fileno(stdout), line, i); | ||
152 | } | ||
153 | close(fd); | ||
154 | return 0; | ||
155 | } | ||
156 | fatalError("/proc/modules: %s\n", strerror(errno)); | ||
157 | return 1; | ||
158 | } | ||
159 | |||
160 | #endif /*BB_FEATURE_LSMOD_OLD_KERNEL*/ | ||