diff options
author | Eric Andersen <andersen@codepoet.org> | 2000-09-24 03:44:29 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2000-09-24 03:44:29 +0000 |
commit | fe4208fe93523a464dbc3094a914a2923e66bd3e (patch) | |
tree | 56e4ec25687b69b34f6f97901fbf7d11773df30e | |
parent | 488aac2e2aac229bceb8655ff7c302cda59f1382 (diff) | |
download | busybox-w32-fe4208fe93523a464dbc3094a914a2923e66bd3e.tar.gz busybox-w32-fe4208fe93523a464dbc3094a914a2923e66bd3e.tar.bz2 busybox-w32-fe4208fe93523a464dbc3094a914a2923e66bd3e.zip |
modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4
-rw-r--r-- | insmod.c | 165 | ||||
-rw-r--r-- | modutils/insmod.c | 165 |
2 files changed, 298 insertions, 32 deletions
@@ -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; |
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; |