diff options
| author | andersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2000-09-24 03:44:29 +0000 |
|---|---|---|
| committer | andersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2000-09-24 03:44:29 +0000 |
| commit | c4c1f0c2dcbccc4a50e55bcffd021c79276d8c7a (patch) | |
| tree | 56e4ec25687b69b34f6f97901fbf7d11773df30e /modutils | |
| parent | 838aeeeaacbd86763574b3183a5bd79f2954ce49 (diff) | |
| download | busybox-w32-c4c1f0c2dcbccc4a50e55bcffd021c79276d8c7a.tar.gz busybox-w32-c4c1f0c2dcbccc4a50e55bcffd021c79276d8c7a.tar.bz2 busybox-w32-c4c1f0c2dcbccc4a50e55bcffd021c79276d8c7a.zip | |
modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4
git-svn-id: svn://busybox.net/trunk/busybox@1113 69ca8d6d-28ef-0310-b511-8ec308f3f277
Diffstat (limited to 'modutils')
| -rw-r--r-- | modutils/insmod.c | 165 |
1 files changed, 149 insertions, 16 deletions
diff --git a/modutils/insmod.c b/modutils/insmod.c index b0e797af7..136f9f062 100644 --- a/modutils/insmod.c +++ b/modutils/insmod.c | |||
| @@ -6,6 +6,13 @@ | |||
| 6 | * Written by Erik Andersen <andersen@lineo.com> | 6 | * Written by Erik Andersen <andersen@lineo.com> |
| 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 | ||
| 10 | * and (theoretically) SH3. Note that there is still no true | ||
| 11 | * multiple architecture support. You just get SH3|SH4|i386, despite | ||
| 12 | * the mention of ARM and m68k--which may or may not work (but | ||
| 13 | * almost certainly do not, due to at least MATCH_MACHINE). I have | ||
| 14 | * only tested SH4 in little endian mode. | ||
| 15 | * | ||
| 9 | * Based almost entirely on the Linux modutils-2.3.11 implementation. | 16 | * Based almost entirely on the Linux modutils-2.3.11 implementation. |
| 10 | * Copyright 1996, 1997 Linux International. | 17 | * Copyright 1996, 1997 Linux International. |
| 11 | * New implementation contributed by Richard Henderson <rth@tamu.edu> | 18 | * New implementation contributed by Richard Henderson <rth@tamu.edu> |
| @@ -70,7 +77,7 @@ | |||
| 70 | #ifndef MODUTILS_MODULE_H | 77 | #ifndef MODUTILS_MODULE_H |
| 71 | #define MODUTILS_MODULE_H 1 | 78 | #define MODUTILS_MODULE_H 1 |
| 72 | 79 | ||
| 73 | #ident "$Id: insmod.c,v 1.23 2000/09/22 00:38:07 andersen Exp $" | 80 | #ident "$Id: insmod.c,v 1.24 2000/09/24 03:44:29 andersen Exp $" |
| 74 | 81 | ||
| 75 | /* This file contains the structures used by the 2.0 and 2.1 kernels. | 82 | /* This file contains the structures used by the 2.0 and 2.1 kernels. |
| 76 | We do not use the kernel headers directly because we do not wish | 83 | We do not use the kernel headers directly because we do not wish |
| @@ -276,7 +283,7 @@ int delete_module(const char *); | |||
| 276 | #ifndef MODUTILS_OBJ_H | 283 | #ifndef MODUTILS_OBJ_H |
| 277 | #define MODUTILS_OBJ_H 1 | 284 | #define MODUTILS_OBJ_H 1 |
| 278 | 285 | ||
| 279 | #ident "$Id: insmod.c,v 1.23 2000/09/22 00:38:07 andersen Exp $" | 286 | #ident "$Id: insmod.c,v 1.24 2000/09/24 03:44:29 andersen Exp $" |
| 280 | 287 | ||
| 281 | /* The relocatable object is manipulated using elfin types. */ | 288 | /* The relocatable object is manipulated using elfin types. */ |
| 282 | 289 | ||
| @@ -286,14 +293,41 @@ int delete_module(const char *); | |||
| 286 | 293 | ||
| 287 | /* Machine-specific elf macros for i386 et al. */ | 294 | /* Machine-specific elf macros for i386 et al. */ |
| 288 | 295 | ||
| 296 | /* the SH changes have only been tested on the SH4 in =little endian= mode */ | ||
| 297 | /* I'm not sure about big endian, so let's warn: */ | ||
| 298 | |||
| 299 | #if (defined(__SH4__) || defined(__SH3__)) && defined(__BIG_ENDIAN__) | ||
| 300 | #error insmod.c may require changes for use on big endian SH4/SH3 | ||
| 301 | #endif | ||
| 302 | |||
| 303 | /* it may or may not work on the SH1/SH2... So let's error on those | ||
| 304 | also */ | ||
| 305 | #if (defined(__sh__) && (!(defined(__SH3__) || defined(__SH4__)))) | ||
| 306 | #error insmod.c may require changes for non-SH3/SH4 use | ||
| 307 | #endif | ||
| 308 | |||
| 289 | #define ELFCLASSM ELFCLASS32 | 309 | #define ELFCLASSM ELFCLASS32 |
| 290 | #define ELFDATAM ELFDATA2LSB | 310 | #define ELFDATAM ELFDATA2LSB |
| 291 | 311 | ||
| 292 | #define MATCH_MACHINE(x) (x == EM_386 || x == EM_486) | ||
| 293 | 312 | ||
| 313 | |||
| 314 | #if defined(__sh__) | ||
| 315 | |||
| 316 | #define MATCH_MACHINE(x) (x == EM_SH) | ||
| 317 | #define SHT_RELM SHT_RELA | ||
| 318 | #define Elf32_RelM Elf32_Rela | ||
| 319 | |||
| 320 | #else | ||
| 321 | |||
| 322 | /* presumably we can use these for anything but the SH */ | ||
| 323 | /* this is the previous behavior, but it does result in | ||
| 324 | insmod.c being broken on anything except i386 */ | ||
| 325 | |||
| 326 | #define MATCH_MACHINE(x) (x == EM_386 || x == EM_486) | ||
| 294 | #define SHT_RELM SHT_REL | 327 | #define SHT_RELM SHT_REL |
| 295 | #define Elf32_RelM Elf32_Rel | 328 | #define Elf32_RelM Elf32_Rel |
| 296 | 329 | ||
| 330 | #endif | ||
| 297 | 331 | ||
| 298 | #ifndef ElfW | 332 | #ifndef ElfW |
| 299 | # if ELFCLASSM == ELFCLASS32 | 333 | # if ELFCLASSM == ELFCLASS32 |
| @@ -486,24 +520,29 @@ int flag_export = 1; | |||
| 486 | 520 | ||
| 487 | /*======================================================================*/ | 521 | /*======================================================================*/ |
| 488 | 522 | ||
| 489 | struct i386_got_entry { | 523 | /* previously, these were named i386_* but since we could be |
| 524 | compiling for the sh, I've renamed them to the more general | ||
| 525 | arch_* These structures are the same between the x86 and SH, | ||
| 526 | and we can't support anything else right now anyway. In the | ||
| 527 | future maybe they should be #if defined'd */ | ||
| 528 | |||
| 529 | struct arch_got_entry { | ||
| 490 | int offset; | 530 | int offset; |
| 491 | unsigned offset_done:1; | 531 | unsigned offset_done:1; |
| 492 | unsigned reloc_done:1; | 532 | unsigned reloc_done:1; |
| 493 | }; | 533 | }; |
| 494 | 534 | ||
| 495 | struct i386_file { | 535 | struct arch_file { |
| 496 | struct obj_file root; | 536 | struct obj_file root; |
| 497 | struct obj_section *got; | 537 | struct obj_section *got; |
| 498 | }; | 538 | }; |
| 499 | 539 | ||
| 500 | struct i386_symbol { | 540 | struct arch_symbol { |
| 501 | struct obj_symbol root; | 541 | struct obj_symbol root; |
| 502 | struct i386_got_entry gotent; | 542 | struct arch_got_entry gotent; |
| 503 | }; | 543 | }; |
| 504 | 544 | ||
| 505 | 545 | ||
| 506 | |||
| 507 | struct external_module { | 546 | struct external_module { |
| 508 | const char *name; | 547 | const char *name; |
| 509 | ElfW(Addr) addr; | 548 | ElfW(Addr) addr; |
| @@ -535,6 +574,17 @@ _syscall1(int, delete_module, const char *, name) | |||
| 535 | extern int delete_module(const char *); | 574 | extern int delete_module(const char *); |
| 536 | #endif | 575 | #endif |
| 537 | 576 | ||
| 577 | /* This is kind of troublesome. See, we don't actually support | ||
| 578 | the m68k or the arm the same way we support i386 and (now) | ||
| 579 | sh. In doing my SH patch, I just assumed that whatever works | ||
| 580 | for i386 also works for m68k and arm since currently insmod.c | ||
| 581 | does nothing special for them. If this isn't true, the below | ||
| 582 | line is rather misleading IMHO, and someone should either | ||
| 583 | change it or add more proper architecture-dependent support | ||
| 584 | for these boys. | ||
| 585 | |||
| 586 | -- Bryan Rittmeyer <bryan@ixiacom.com> */ | ||
| 587 | |||
| 538 | #if defined(__i386__) || defined(__m68k__) || defined(__arm__) | 588 | #if defined(__i386__) || defined(__m68k__) || defined(__arm__) |
| 539 | /* Jump through hoops to fixup error return codes */ | 589 | /* Jump through hoops to fixup error return codes */ |
| 540 | #define __NR__create_module __NR_create_module | 590 | #define __NR__create_module __NR_create_module |
| @@ -588,7 +638,7 @@ static int findNamedModule(const char *fileName, struct stat *statbuf, | |||
| 588 | 638 | ||
| 589 | struct obj_file *arch_new_file(void) | 639 | struct obj_file *arch_new_file(void) |
| 590 | { | 640 | { |
| 591 | struct i386_file *f; | 641 | struct arch_file *f; |
| 592 | f = xmalloc(sizeof(*f)); | 642 | f = xmalloc(sizeof(*f)); |
| 593 | f->got = NULL; | 643 | f->got = NULL; |
| 594 | return &f->root; | 644 | return &f->root; |
| @@ -601,20 +651,25 @@ struct obj_section *arch_new_section(void) | |||
| 601 | 651 | ||
| 602 | struct obj_symbol *arch_new_symbol(void) | 652 | struct obj_symbol *arch_new_symbol(void) |
| 603 | { | 653 | { |
| 604 | struct i386_symbol *sym; | 654 | struct arch_symbol *sym; |
| 605 | sym = xmalloc(sizeof(*sym)); | 655 | sym = xmalloc(sizeof(*sym)); |
| 606 | memset(&sym->gotent, 0, sizeof(sym->gotent)); | 656 | memset(&sym->gotent, 0, sizeof(sym->gotent)); |
| 607 | return &sym->root; | 657 | return &sym->root; |
| 608 | } | 658 | } |
| 659 | |||
| 609 | enum obj_reloc | 660 | enum obj_reloc |
| 610 | arch_apply_relocation(struct obj_file *f, | 661 | arch_apply_relocation(struct obj_file *f, |
| 611 | struct obj_section *targsec, | 662 | struct obj_section *targsec, |
| 612 | struct obj_section *symsec, | 663 | struct obj_section *symsec, |
| 613 | struct obj_symbol *sym, | 664 | struct obj_symbol *sym, |
| 665 | #if defined(__sh__) | ||
| 666 | Elf32_Rela * rel, Elf32_Addr v) | ||
| 667 | #else | ||
| 614 | Elf32_Rel * rel, Elf32_Addr v) | 668 | Elf32_Rel * rel, Elf32_Addr v) |
| 669 | #endif | ||
| 615 | { | 670 | { |
| 616 | struct i386_file *ifile = (struct i386_file *) f; | 671 | struct arch_file *ifile = (struct arch_file *) f; |
| 617 | struct i386_symbol *isym = (struct i386_symbol *) sym; | 672 | struct arch_symbol *isym = (struct arch_symbol *) sym; |
| 618 | 673 | ||
| 619 | Elf32_Addr *loc = (Elf32_Addr *) (targsec->contents + rel->r_offset); | 674 | Elf32_Addr *loc = (Elf32_Addr *) (targsec->contents + rel->r_offset); |
| 620 | Elf32_Addr dot = targsec->header.sh_addr + rel->r_offset; | 675 | Elf32_Addr dot = targsec->header.sh_addr + rel->r_offset; |
| @@ -623,32 +678,86 @@ arch_apply_relocation(struct obj_file *f, | |||
| 623 | enum obj_reloc ret = obj_reloc_ok; | 678 | enum obj_reloc ret = obj_reloc_ok; |
| 624 | 679 | ||
| 625 | switch (ELF32_R_TYPE(rel->r_info)) { | 680 | switch (ELF32_R_TYPE(rel->r_info)) { |
| 681 | |||
| 682 | /* even though these constants seem to be the same for | ||
| 683 | the i386 and the sh, we "#if define" them for clarity | ||
| 684 | and in case that ever changes */ | ||
| 685 | #if defined(__sh__) | ||
| 686 | case R_SH_NONE: | ||
| 687 | #else | ||
| 626 | case R_386_NONE: | 688 | case R_386_NONE: |
| 689 | #endif | ||
| 627 | break; | 690 | break; |
| 628 | 691 | ||
| 692 | #if defined(__sh__) | ||
| 693 | case R_SH_DIR32: | ||
| 694 | #else | ||
| 629 | case R_386_32: | 695 | case R_386_32: |
| 696 | #endif | ||
| 630 | *loc += v; | 697 | *loc += v; |
| 631 | break; | 698 | break; |
| 632 | 699 | ||
| 700 | #if defined(__sh__) | ||
| 701 | case R_SH_REL32: | ||
| 702 | #else | ||
| 633 | case R_386_PLT32: | 703 | case R_386_PLT32: |
| 634 | case R_386_PC32: | 704 | case R_386_PC32: |
| 705 | #endif | ||
| 635 | *loc += v - dot; | 706 | *loc += v - dot; |
| 636 | break; | 707 | break; |
| 637 | 708 | ||
| 709 | #if defined(__sh__) | ||
| 710 | case R_SH_PLT32: | ||
| 711 | *loc = v - dot; | ||
| 712 | break; | ||
| 713 | #endif | ||
| 714 | |||
| 715 | |||
| 716 | #if defined(__sh__) | ||
| 717 | case R_SH_GLOB_DAT: | ||
| 718 | case R_SH_JMP_SLOT: | ||
| 719 | *loc = v; | ||
| 720 | break; | ||
| 721 | #else | ||
| 638 | case R_386_GLOB_DAT: | 722 | case R_386_GLOB_DAT: |
| 639 | case R_386_JMP_SLOT: | 723 | case R_386_JMP_SLOT: |
| 640 | *loc = v; | 724 | *loc = v; |
| 641 | break; | 725 | break; |
| 726 | #endif | ||
| 642 | 727 | ||
| 643 | case R_386_RELATIVE: | 728 | #if defined(__sh__) |
| 729 | case R_SH_RELATIVE: | ||
| 730 | *loc += f->baseaddr + rel->r_addend; | ||
| 731 | break; | ||
| 732 | #else | ||
| 733 | case R_386_RELATIVE: | ||
| 644 | *loc += f->baseaddr; | 734 | *loc += f->baseaddr; |
| 645 | break; | 735 | break; |
| 736 | #endif | ||
| 646 | 737 | ||
| 738 | #if defined(__sh__) | ||
| 739 | case R_SH_GOTPC: | ||
| 740 | assert(got != 0); | ||
| 741 | *loc += got - dot + rel->r_addend;; | ||
| 742 | break; | ||
| 743 | #else | ||
| 647 | case R_386_GOTPC: | 744 | case R_386_GOTPC: |
| 648 | assert(got != 0); | 745 | assert(got != 0); |
| 649 | *loc += got - dot; | 746 | *loc += got - dot; |
| 650 | break; | 747 | break; |
| 748 | #endif | ||
| 651 | 749 | ||
| 750 | #if defined(__sh__) | ||
| 751 | case R_SH_GOT32: | ||
| 752 | assert(isym != NULL); | ||
| 753 | if (!isym->gotent.reloc_done) { | ||
| 754 | isym->gotent.reloc_done = 1; | ||
| 755 | *(Elf32_Addr *) (ifile->got->contents + isym->gotent.offset) = | ||
| 756 | v; | ||
| 757 | } | ||
| 758 | *loc += isym->gotent.offset + rel->r_addend; | ||
| 759 | break; | ||
| 760 | #else | ||
| 652 | case R_386_GOT32: | 761 | case R_386_GOT32: |
| 653 | assert(isym != NULL); | 762 | assert(isym != NULL); |
| 654 | if (!isym->gotent.reloc_done) { | 763 | if (!isym->gotent.reloc_done) { |
| @@ -658,8 +767,13 @@ arch_apply_relocation(struct obj_file *f, | |||
| 658 | } | 767 | } |
| 659 | *loc += isym->gotent.offset; | 768 | *loc += isym->gotent.offset; |
| 660 | break; | 769 | break; |
| 770 | #endif | ||
| 661 | 771 | ||
| 772 | #if defined(__sh__) | ||
| 773 | case R_SH_GOTOFF: | ||
| 774 | #else | ||
| 662 | case R_386_GOTOFF: | 775 | case R_386_GOTOFF: |
| 776 | #endif | ||
| 663 | assert(got != 0); | 777 | assert(got != 0); |
| 664 | *loc += v - got; | 778 | *loc += v - got; |
| 665 | break; | 779 | break; |
| @@ -674,13 +788,17 @@ arch_apply_relocation(struct obj_file *f, | |||
| 674 | 788 | ||
| 675 | int arch_create_got(struct obj_file *f) | 789 | int arch_create_got(struct obj_file *f) |
| 676 | { | 790 | { |
| 677 | struct i386_file *ifile = (struct i386_file *) f; | 791 | struct arch_file *ifile = (struct arch_file *) f; |
| 678 | int i, n, offset = 0, gotneeded = 0; | 792 | int i, n, offset = 0, gotneeded = 0; |
| 679 | 793 | ||
| 680 | n = ifile->root.header.e_shnum; | 794 | n = ifile->root.header.e_shnum; |
| 681 | for (i = 0; i < n; ++i) { | 795 | for (i = 0; i < n; ++i) { |
| 682 | struct obj_section *relsec, *symsec, *strsec; | 796 | struct obj_section *relsec, *symsec, *strsec; |
| 797 | #if defined(__sh__) | ||
| 798 | Elf32_Rela *rel, *relend; | ||
| 799 | #else | ||
| 683 | Elf32_Rel *rel, *relend; | 800 | Elf32_Rel *rel, *relend; |
| 801 | #endif | ||
| 684 | Elf32_Sym *symtab; | 802 | Elf32_Sym *symtab; |
| 685 | const char *strtab; | 803 | const char *strtab; |
| 686 | 804 | ||
| @@ -691,24 +809,39 @@ int arch_create_got(struct obj_file *f) | |||
| 691 | symsec = ifile->root.sections[relsec->header.sh_link]; | 809 | symsec = ifile->root.sections[relsec->header.sh_link]; |
| 692 | strsec = ifile->root.sections[symsec->header.sh_link]; | 810 | strsec = ifile->root.sections[symsec->header.sh_link]; |
| 693 | 811 | ||
| 812 | |||
| 813 | #if defined(__sh__) | ||
| 814 | rel = (Elf32_Rela *) relsec->contents; | ||
| 815 | relend = rel + (relsec->header.sh_size / sizeof(Elf32_Rela)); | ||
| 816 | #else | ||
| 694 | rel = (Elf32_Rel *) relsec->contents; | 817 | rel = (Elf32_Rel *) relsec->contents; |
| 695 | relend = rel + (relsec->header.sh_size / sizeof(Elf32_Rel)); | 818 | relend = rel + (relsec->header.sh_size / sizeof(Elf32_Rel)); |
| 819 | #endif | ||
| 696 | symtab = (Elf32_Sym *) symsec->contents; | 820 | symtab = (Elf32_Sym *) symsec->contents; |
| 697 | strtab = (const char *) strsec->contents; | 821 | strtab = (const char *) strsec->contents; |
| 698 | 822 | ||
| 699 | for (; rel < relend; ++rel) { | 823 | for (; rel < relend; ++rel) { |
| 700 | Elf32_Sym *extsym; | 824 | Elf32_Sym *extsym; |
| 701 | struct i386_symbol *intsym; | 825 | struct arch_symbol *intsym; |
| 702 | const char *name; | 826 | const char *name; |
| 703 | 827 | ||
| 704 | switch (ELF32_R_TYPE(rel->r_info)) { | 828 | switch (ELF32_R_TYPE(rel->r_info)) { |
| 829 | #if defined(__sh__) | ||
| 830 | case R_SH_GOTPC: | ||
| 831 | case R_SH_GOTOFF: | ||
| 832 | #else | ||
| 705 | case R_386_GOTPC: | 833 | case R_386_GOTPC: |
| 706 | case R_386_GOTOFF: | 834 | case R_386_GOTOFF: |
| 835 | #endif | ||
| 707 | gotneeded = 1; | 836 | gotneeded = 1; |
| 708 | default: | 837 | default: |
| 709 | continue; | 838 | continue; |
| 710 | 839 | ||
| 840 | #if defined(__sh__) | ||
| 841 | case R_SH_GOT32: | ||
| 842 | #else | ||
| 711 | case R_386_GOT32: | 843 | case R_386_GOT32: |
| 844 | #endif | ||
| 712 | break; | 845 | break; |
| 713 | } | 846 | } |
| 714 | 847 | ||
| @@ -718,7 +851,7 @@ int arch_create_got(struct obj_file *f) | |||
| 718 | else | 851 | else |
| 719 | name = f->sections[extsym->st_shndx]->name; | 852 | name = f->sections[extsym->st_shndx]->name; |
| 720 | intsym = | 853 | intsym = |
| 721 | (struct i386_symbol *) obj_find_symbol(&ifile->root, name); | 854 | (struct arch_symbol *) obj_find_symbol(&ifile->root, name); |
| 722 | 855 | ||
| 723 | if (!intsym->gotent.offset_done) { | 856 | if (!intsym->gotent.offset_done) { |
| 724 | intsym->gotent.offset_done = 1; | 857 | intsym->gotent.offset_done = 1; |
