summaryrefslogtreecommitdiff
path: root/modutils
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2002-05-24 06:50:15 +0000
committerEric Andersen <andersen@codepoet.org>2002-05-24 06:50:15 +0000
commitcffd5022c5fe5511a456461e9cc5c8da8b90dd61 (patch)
tree7ed88f9131287e9f844fd451b88fcc43d40c8c97 /modutils
parentd11edf98094533af3e322c5f42e756e2e786ba0c (diff)
downloadbusybox-w32-cffd5022c5fe5511a456461e9cc5c8da8b90dd61.tar.gz
busybox-w32-cffd5022c5fe5511a456461e9cc5c8da8b90dd61.tar.bz2
busybox-w32-cffd5022c5fe5511a456461e9cc5c8da8b90dd61.zip
Patch from Magnus Damm <damm@opensource.se> to rework things
greatly, and keep the arch specific relocations together, fixes R_PPC_ADDR32 handling so powerpc can work, and changes the tlb tables to be linked lists (again so powerpc can work).
Diffstat (limited to 'modutils')
-rw-r--r--modutils/insmod.c869
1 files changed, 488 insertions, 381 deletions
diff --git a/modutils/insmod.c b/modutils/insmod.c
index a2d718eb5..cab2cc204 100644
--- a/modutils/insmod.c
+++ b/modutils/insmod.c
@@ -19,6 +19,13 @@
19 * very minor changes required to also work with StrongArm and presumably 19 * very minor changes required to also work with StrongArm and presumably
20 * all ARM based systems. 20 * all ARM based systems.
21 * 21 *
22 * Magnus Damm <damm@opensource.se> 22-May-2002.
23 * The plt and got code are now using the same structs.
24 * Added generic linked list code to fully support PowerPC.
25 * Replaced the mess in arch_apply_relocation() with architecture blocks.
26 * The arch_create_got() function got cleaned up with architecture blocks.
27 * These blocks should be easy maintain and sync with obj_xxx.c in modutils.
28 *
22 * Magnus Damm <damm@opensource.se> added PowerPC support 20-Feb-2001. 29 * Magnus Damm <damm@opensource.se> added PowerPC support 20-Feb-2001.
23 * PowerPC specific code stolen from modutils-2.3.16, 30 * PowerPC specific code stolen from modutils-2.3.16,
24 * written by Paul Mackerras, Copyright 1996, 1997 Linux International. 31 * written by Paul Mackerras, Copyright 1996, 1997 Linux International.
@@ -80,37 +87,123 @@
80#define LOADBITS 1 87#define LOADBITS 1
81#endif 88#endif
82 89
83#if defined(__powerpc__)
84#define CONFIG_USE_PLT_ENTRIES
85#define CONFIG_PLT_ENTRY_SIZE 16
86#endif
87 90
88#if defined(__arm__) 91#if defined(__arm__)
89#define CONFIG_USE_PLT_ENTRIES 92#define CONFIG_USE_PLT_ENTRIES
90#define CONFIG_PLT_ENTRY_SIZE 8 93#define CONFIG_PLT_ENTRY_SIZE 8
91#define CONFIG_USE_GOT_ENTRIES 94#define CONFIG_USE_GOT_ENTRIES
92#define CONFIG_GOT_ENTRY_SIZE 8 95#define CONFIG_GOT_ENTRY_SIZE 8
96#define CONFIG_USE_SINGLE
97
98#define MATCH_MACHINE(x) (x == EM_ARM)
99#define SHT_RELM SHT_REL
100#define Elf32_RelM Elf32_Rel
101#define ELFCLASSM ELFCLASS32
93#endif 102#endif
94 103
95#if defined(__sh__) 104#if defined(__i386__)
96#define CONFIG_USE_GOT_ENTRIES 105#define CONFIG_USE_GOT_ENTRIES
97#define CONFIG_GOT_ENTRY_SIZE 4 106#define CONFIG_GOT_ENTRY_SIZE 4
107#define CONFIG_USE_SINGLE
108
109#ifndef EM_486
110#define MATCH_MACHINE(x) (x == EM_386)
111#else
112#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
98#endif 113#endif
99 114
100#if defined(__i386__) 115#define SHT_RELM SHT_REL
116#define Elf32_RelM Elf32_Rel
117#define ELFCLASSM ELFCLASS32
118#endif
119
120#if defined(__mc68000__)
101#define CONFIG_USE_GOT_ENTRIES 121#define CONFIG_USE_GOT_ENTRIES
102#define CONFIG_GOT_ENTRY_SIZE 4 122#define CONFIG_GOT_ENTRY_SIZE 4
123#define CONFIG_USE_SINGLE
124
125#define MATCH_MACHINE(x) (x == EM_68K)
126#define SHT_RELM SHT_RELA
127#define Elf32_RelM Elf32_Rela
103#endif 128#endif
104 129
105#if defined(__mips__) 130#if defined(__mips__)
106// neither used 131/* Account for ELF spec changes. */
132#ifndef EM_MIPS_RS3_LE
133#ifdef EM_MIPS_RS4_BE
134#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
135#else
136#define EM_MIPS_RS3_LE 10
137#endif
138#endif /* !EM_MIPS_RS3_LE */
139
140#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
141#define SHT_RELM SHT_REL
142#define Elf32_RelM Elf32_Rel
143#define ELFCLASSM ELFCLASS32
144#define ARCHDATAM "__dbe_table"
145#endif
146
147#if defined(__powerpc__)
148#define CONFIG_USE_PLT_ENTRIES
149#define CONFIG_PLT_ENTRY_SIZE 16
150#define CONFIG_USE_PLT_LIST
151#define CONFIG_LIST_ARCHTYPE ElfW(Addr)
152#define CONFIG_USE_LIST
153
154#define MATCH_MACHINE(x) (x == EM_PPC)
155#define SHT_RELM SHT_RELA
156#define Elf32_RelM Elf32_Rela
157#define ELFCLASSM ELFCLASS32
158#define ARCHDATAM "__ftr_fixup"
159#endif
160
161#if defined(__sh__)
162#define CONFIG_USE_GOT_ENTRIES
163#define CONFIG_GOT_ENTRY_SIZE 4
164#define CONFIG_USE_SINGLE
165
166#define MATCH_MACHINE(x) (x == EM_SH)
167#define SHT_RELM SHT_RELA
168#define Elf32_RelM Elf32_Rela
169#define ELFCLASSM ELFCLASS32
170
171/* the SH changes have only been tested on the SH4 in =little endian= mode */
172/* I'm not sure about big endian, so let's warn: */
173
174#if (defined(__SH4__) || defined(__SH3__)) && defined(__BIG_ENDIAN__)
175#error insmod.c may require changes for use on big endian SH4/SH3
176#endif
177
178/* it may or may not work on the SH1/SH2... So let's error on those
179 also */
180#if (defined(__sh__) && (!(defined(__SH3__) || defined(__SH4__))))
181#error insmod.c may require changes for non-SH3/SH4 use
182#endif
107#endif 183#endif
108 184
109#if defined (__v850e__) 185#if defined (__v850e__)
110#define CONFIG_USE_PLT_ENTRIES 186#define CONFIG_USE_PLT_ENTRIES
111#define CONFIG_PLT_ENTRY_SIZE 8 187#define CONFIG_PLT_ENTRY_SIZE 8
188#define CONFIG_USE_SINGLE
189
190#ifndef EM_CYGNUS_V850 /* grumble */
191#define EM_CYGNUS_V850 0x9080
192#endif
193
194#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
195#define SHT_RELM SHT_RELA
196#define Elf32_RelM Elf32_Rela
197#define ELFCLASSM ELFCLASS32
198
199#define SYMBOL_PREFIX "_"
200#endif
201
202#ifndef SHT_RELM
203#error Sorry, but insmod.c does not yet support this architecture...
112#endif 204#endif
113 205
206
114//---------------------------------------------------------------------------- 207//----------------------------------------------------------------------------
115//--------modutils module.h, lines 45-242 208//--------modutils module.h, lines 45-242
116//---------------------------------------------------------------------------- 209//----------------------------------------------------------------------------
@@ -140,7 +233,7 @@
140#ifndef MODUTILS_MODULE_H 233#ifndef MODUTILS_MODULE_H
141static const int MODUTILS_MODULE_H = 1; 234static const int MODUTILS_MODULE_H = 1;
142 235
143#ident "$Id: insmod.c,v 1.82 2002/05/03 10:34:35 andersen Exp $" 236#ident "$Id: insmod.c,v 1.83 2002/05/24 06:50:15 andersen Exp $"
144 237
145/* This file contains the structures used by the 2.0 and 2.1 kernels. 238/* This file contains the structures used by the 2.0 and 2.1 kernels.
146 We do not use the kernel headers directly because we do not wish 239 We do not use the kernel headers directly because we do not wish
@@ -282,7 +375,11 @@ struct new_module
282#endif 375#endif
283}; 376};
284 377
378#ifdef ARCHDATAM
379#define ARCHDATA_SEC_NAME ARCHDATAM
380#else
285#define ARCHDATA_SEC_NAME "__archdata" 381#define ARCHDATA_SEC_NAME "__archdata"
382#endif
286#define KALLSYMS_SEC_NAME "__kallsyms" 383#define KALLSYMS_SEC_NAME "__kallsyms"
287 384
288 385
@@ -357,7 +454,7 @@ int delete_module(const char *);
357#ifndef MODUTILS_OBJ_H 454#ifndef MODUTILS_OBJ_H
358static const int MODUTILS_OBJ_H = 1; 455static const int MODUTILS_OBJ_H = 1;
359 456
360#ident "$Id: insmod.c,v 1.82 2002/05/03 10:34:35 andersen Exp $" 457#ident "$Id: insmod.c,v 1.83 2002/05/24 06:50:15 andersen Exp $"
361 458
362/* The relocatable object is manipulated using elfin types. */ 459/* The relocatable object is manipulated using elfin types. */
363 460
@@ -371,94 +468,6 @@ static const int MODUTILS_OBJ_H = 1;
371#define ELFDATAM ELFDATA2MSB 468#define ELFDATAM ELFDATA2MSB
372#endif 469#endif
373 470
374
375/* Machine-specific elf macros for i386 et al. */
376
377/* the SH changes have only been tested on the SH4 in =little endian= mode */
378/* I'm not sure about big endian, so let's warn: */
379
380#if (defined(__SH4__) || defined(__SH3__)) && defined(__BIG_ENDIAN__)
381#error insmod.c may require changes for use on big endian SH4/SH3
382#endif
383
384/* it may or may not work on the SH1/SH2... So let's error on those
385 also */
386#if (defined(__sh__) && (!(defined(__SH3__) || defined(__SH4__))))
387#error insmod.c may require changes for non-SH3/SH4 use
388#endif
389
390#define ELFCLASSM ELFCLASS32
391
392
393#if defined(__sh__)
394
395#define MATCH_MACHINE(x) (x == EM_SH)
396#define SHT_RELM SHT_RELA
397#define Elf32_RelM Elf32_Rela
398
399#elif defined(__arm__)
400
401#define MATCH_MACHINE(x) (x == EM_ARM)
402#define SHT_RELM SHT_REL
403#define Elf32_RelM Elf32_Rel
404
405#elif defined(__powerpc__)
406
407#define MATCH_MACHINE(x) (x == EM_PPC)
408#define SHT_RELM SHT_RELA
409#define Elf32_RelM Elf32_Rela
410
411#elif defined(__mips__)
412
413/* Account for ELF spec changes. */
414#ifndef EM_MIPS_RS3_LE
415#ifdef EM_MIPS_RS4_BE
416#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
417#else
418#define EM_MIPS_RS3_LE 10
419#endif
420#endif /* !EM_MIPS_RS3_LE */
421
422#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
423#define SHT_RELM SHT_REL
424#define Elf32_RelM Elf32_Rel
425
426#elif defined(__i386__)
427
428/* presumably we can use these for anything but the SH and ARM*/
429/* this is the previous behavior, but it does result in
430 insmod.c being broken on anything except i386 */
431#ifndef EM_486
432#define MATCH_MACHINE(x) (x == EM_386)
433#else
434#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
435#endif
436
437#define SHT_RELM SHT_REL
438#define Elf32_RelM Elf32_Rel
439
440#elif defined(__mc68000__)
441
442#define MATCH_MACHINE(x) (x == EM_68K)
443#define SHT_RELM SHT_RELA
444#define Elf32_RelM Elf32_Rela
445
446#elif defined (__v850e__)
447
448#ifndef EM_CYGNUS_V850 /* grumble */
449#define EM_CYGNUS_V850 0x9080
450#endif
451
452#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
453#define SHT_RELM SHT_RELA
454#define Elf32_RelM Elf32_Rela
455
456#define SYMBOL_PREFIX "_"
457
458#else
459#error Sorry, but insmod.c does not yet support this architecture...
460#endif
461
462#ifndef ElfW 471#ifndef ElfW
463# if ELFCLASSM == ELFCLASS32 472# if ELFCLASSM == ELFCLASS32
464# define ElfW(x) Elf32_ ## x 473# define ElfW(x) Elf32_ ## x
@@ -619,7 +628,7 @@ static enum obj_reloc arch_apply_relocation (struct obj_file *f,
619 struct obj_symbol *sym, 628 struct obj_symbol *sym,
620 ElfW(RelM) *rel, ElfW(Addr) value); 629 ElfW(RelM) *rel, ElfW(Addr) value);
621 630
622static int arch_create_got (struct obj_file *f); 631static void arch_create_got (struct obj_file *f);
623 632
624#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE 633#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
625static int arch_init_module (struct obj_file *f, struct new_module *); 634static int arch_init_module (struct obj_file *f, struct new_module *);
@@ -653,31 +662,27 @@ static int flag_export = 1;
653 662
654/*======================================================================*/ 663/*======================================================================*/
655 664
656/* previously, these were named i386_* but since we could be 665#if defined(CONFIG_USE_LIST)
657 compiling for the sh, I've renamed them to the more general
658 arch_* These structures are the same between the x86 and SH,
659 and we can't support anything else right now anyway. In the
660 future maybe they should be #if defined'd */
661
662/* Done ;-) */
663 666
664 667struct arch_list_entry
665
666#if defined(CONFIG_USE_PLT_ENTRIES)
667struct arch_plt_entry
668{ 668{
669 int offset; 669 struct arch_list_entry *next;
670 int allocated:1; 670 CONFIG_LIST_ARCHTYPE addend;
671 int inited:1; /* has been set up */ 671 int offset;
672 int inited : 1;
672}; 673};
674
673#endif 675#endif
674 676
675#if defined(CONFIG_USE_GOT_ENTRIES) 677#if defined(CONFIG_USE_SINGLE)
676struct arch_got_entry { 678
679struct arch_single_entry
680{
677 int offset; 681 int offset;
678 unsigned offset_done:1; 682 int inited : 1;
679 unsigned reloc_done:1; 683 int allocated : 1;
680}; 684};
685
681#endif 686#endif
682 687
683#if defined(__mips__) 688#if defined(__mips__)
@@ -705,10 +710,14 @@ struct arch_file {
705struct arch_symbol { 710struct arch_symbol {
706 struct obj_symbol root; 711 struct obj_symbol root;
707#if defined(CONFIG_USE_PLT_ENTRIES) 712#if defined(CONFIG_USE_PLT_ENTRIES)
708 struct arch_plt_entry pltent; 713#if defined(CONFIG_USE_PLT_LIST)
714 struct arch_list_entry *pltent;
715#else
716 struct arch_single_entry pltent;
717#endif
709#endif 718#endif
710#if defined(CONFIG_USE_GOT_ENTRIES) 719#if defined(CONFIG_USE_GOT_ENTRIES)
711 struct arch_got_entry gotent; 720 struct arch_single_entry gotent;
712#endif 721#endif
713}; 722};
714 723
@@ -766,15 +775,7 @@ static struct obj_file *arch_new_file(void)
766 struct arch_file *f; 775 struct arch_file *f;
767 f = xmalloc(sizeof(*f)); 776 f = xmalloc(sizeof(*f));
768 777
769#if defined(CONFIG_USE_PLT_ENTRIES) 778 memset(f, 0, sizeof(*f));
770 f->plt = NULL;
771#endif
772#if defined(CONFIG_USE_GOT_ENTRIES)
773 f->got = NULL;
774#endif
775#if defined(__mips__)
776 f->mips_hi16_list = NULL;
777#endif
778 779
779 return &f->root; 780 return &f->root;
780} 781}
@@ -789,12 +790,7 @@ static struct obj_symbol *arch_new_symbol(void)
789 struct arch_symbol *sym; 790 struct arch_symbol *sym;
790 sym = xmalloc(sizeof(*sym)); 791 sym = xmalloc(sizeof(*sym));
791 792
792#if defined(CONFIG_USE_PLT_ENTRIES) 793 memset(sym, 0, sizeof(*sym));
793 memset(&sym->pltent, 0, sizeof(sym->pltent));
794#endif
795#if defined(CONFIG_USE_GOT_ENTRIES)
796 memset(&sym->gotent, 0, sizeof(sym->gotent));
797#endif
798 794
799 return &sym->root; 795 return &sym->root;
800} 796}
@@ -807,100 +803,164 @@ arch_apply_relocation(struct obj_file *f,
807 ElfW(RelM) *rel, ElfW(Addr) v) 803 ElfW(RelM) *rel, ElfW(Addr) v)
808{ 804{
809 struct arch_file *ifile = (struct arch_file *) f; 805 struct arch_file *ifile = (struct arch_file *) f;
810#if !(defined(__mips__)) 806 enum obj_reloc ret = obj_reloc_ok;
811 struct arch_symbol *isym = (struct arch_symbol *) sym;
812#endif
813
814 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset); 807 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
815 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset; 808 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
809#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
810 struct arch_symbol *isym = (struct arch_symbol *) sym;
811#endif
816#if defined(CONFIG_USE_GOT_ENTRIES) 812#if defined(CONFIG_USE_GOT_ENTRIES)
817 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0; 813 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
818#endif 814#endif
819#if defined(CONFIG_USE_PLT_ENTRIES) 815#if defined(CONFIG_USE_PLT_ENTRIES)
820 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0; 816 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
821 struct arch_plt_entry *pe;
822 unsigned long *ip; 817 unsigned long *ip;
818#if defined(CONFIG_USE_PLT_LIST)
819 struct arch_list_entry *pe;
820#else
821 struct arch_single_entry *pe;
822#endif
823#endif 823#endif
824 enum obj_reloc ret = obj_reloc_ok;
825 824
826 switch (ELF32_R_TYPE(rel->r_info)) { 825 switch (ELF32_R_TYPE(rel->r_info)) {
827 826
828/* even though these constants seem to be the same for 827
829 the i386 and the sh, we "#if define" them for clarity 828#if defined(__arm__)
830 and in case that ever changes */
831#if defined(__sh__)
832 case R_SH_NONE:
833#elif defined(__arm__)
834 case R_ARM_NONE: 829 case R_ARM_NONE:
830 break;
831
832 case R_ARM_ABS32:
833 *loc += v;
834 break;
835
836 case R_ARM_GOT32:
837 goto bb_use_got;
838
839 case R_ARM_GOTPC:
840 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
841 * (which is .got) similar to branch,
842 * but is full 32 bits relative */
843
844 assert(got);
845 *loc += got - dot;
846 break;
847
848 case R_ARM_PC24:
849 case R_ARM_PLT32:
850 goto bb_use_plt;
851
852 case R_ARM_GOTOFF: /* address relative to the got */
853 assert(got);
854 *loc += v - got;
855 break;
856
835#elif defined(__i386__) 857#elif defined(__i386__)
858
836 case R_386_NONE: 859 case R_386_NONE:
837#elif defined(__mc68000__)
838 case R_68K_NONE:
839#elif defined(__powerpc__)
840 case R_PPC_NONE:
841#elif defined(__mips__)
842 case R_MIPS_NONE:
843#elif defined (__v850e__)
844 case R_V850_NONE:
845#endif
846 break; 860 break;
847 861
848#if defined (__v850e__) 862 case R_386_32:
849 case R_V850_32: 863 *loc += v;
850 /* We write two shorts instead of a long because even
851 32-bit insns only need half-word alignment, but
852 32-bit data needs to be long-word aligned. */
853 v += ((unsigned short *)loc)[0];
854 v += ((unsigned short *)loc)[1] << 16;
855 ((unsigned short *)loc)[0] = v & 0xffff;
856 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
857 break; 864 break;
858#else /* !__v850e__ */ 865
859#if defined(__sh__) 866 case R_386_PLT32:
860 case R_SH_DIR32: 867 case R_386_PC32:
861#elif defined(__arm__) 868 *loc += v - dot;
862 case R_ARM_ABS32: 869 break;
863#elif defined(__i386__) 870
864 case R_386_32: 871 case R_386_GLOB_DAT:
865#elif defined(__mc68000__) 872 case R_386_JMP_SLOT:
873 *loc = v;
874 break;
875
876 case R_386_RELATIVE:
877 *loc += f->baseaddr;
878 break;
879
880 case R_386_GOTPC:
881 assert(got != 0);
882 *loc += got - dot;
883 break;
884
885 case R_386_GOT32:
886 goto bb_use_got;
887
888 case R_386_GOTOFF:
889 assert(got != 0);
890 *loc += v - got;
891 break;
892
893#elif defined(__mc68000__)
894
895 case R_68K_NONE:
896 break;
897
866 case R_68K_32: 898 case R_68K_32:
867#elif defined(__powerpc__)
868 case R_PPC_ADDR32:
869#elif defined(__mips__)
870 case R_MIPS_32:
871#endif
872 *loc += v; 899 *loc += v;
873 break; 900 break;
874#endif /* __v850e__ */
875 901
876#if defined(__mc68000__) 902 case R_68K_8:
877 case R_68K_8: 903 if (v > 0xff) {
878 if (v > 0xff) 904 ret = obj_reloc_overflow;
879 ret = obj_reloc_overflow; 905 }
880 *(char *)loc = v; 906 *(char *)loc = v;
881 break; 907 break;
882 case R_68K_16: 908
883 if (v > 0xffff) 909 case R_68K_16:
884 ret = obj_reloc_overflow; 910 if (v > 0xffff) {
911 ret = obj_reloc_overflow;
912 }
885 *(short *)loc = v; 913 *(short *)loc = v;
886 break; 914 break;
887#endif /* __mc68000__ */
888 915
889#if defined(__powerpc__) 916 case R_68K_PC8:
890 case R_PPC_ADDR16_HA: 917 v -= dot;
891 *(unsigned short *)loc = (v + 0x8000) >> 16; 918 if ((Elf32_Sword)v > 0x7f ||
919 (Elf32_Sword)v < -(Elf32_Sword)0x80) {
920 ret = obj_reloc_overflow;
921 }
922 *(char *)loc = v;
892 break; 923 break;
893 924
894 case R_PPC_ADDR16_HI: 925 case R_68K_PC16:
895 *(unsigned short *)loc = v >> 16; 926 v -= dot;
927 if ((Elf32_Sword)v > 0x7fff ||
928 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
929 ret = obj_reloc_overflow;
930 }
931 *(short *)loc = v;
896 break; 932 break;
897 933
898 case R_PPC_ADDR16_LO: 934 case R_68K_PC32:
899 *(unsigned short *)loc = v; 935 *(int *)loc = v - dot;
936 break;
937
938 case R_68K_GLOB_DAT:
939 case R_68K_JMP_SLOT:
940 *loc = v;
941 break;
942
943 case R_68K_RELATIVE:
944 *(int *)loc += f->baseaddr;
945 break;
946
947 case R_68K_GOT32:
948 goto bb_use_got;
949
950 case R_68K_GOTOFF:
951 assert(got != 0);
952 *loc += v - got;
953 break;
954
955#elif defined(__mips__)
956
957 case R_MIPS_NONE:
958 break;
959
960 case R_MIPS_32:
961 *loc += v;
900 break; 962 break;
901#endif
902 963
903#if defined(__mips__)
904 case R_MIPS_26: 964 case R_MIPS_26:
905 if (v % 4) 965 if (v % 4)
906 ret = obj_reloc_dangerous; 966 ret = obj_reloc_dangerous;
@@ -978,63 +1038,110 @@ arch_apply_relocation(struct obj_file *f,
978 *loc = insnlo; 1038 *loc = insnlo;
979 break; 1039 break;
980 } 1040 }
981#endif
982 1041
983#if defined(__arm__) 1042#elif defined(__powerpc__)
1043
1044 case R_PPC_ADDR16_HA:
1045 *(unsigned short *)loc = (v + 0x8000) >> 16;
1046 break;
1047
1048 case R_PPC_ADDR16_HI:
1049 *(unsigned short *)loc = v >> 16;
1050 break;
1051
1052 case R_PPC_ADDR16_LO:
1053 *(unsigned short *)loc = v;
1054 break;
1055
1056 case R_PPC_REL24:
1057 goto bb_use_plt;
1058
1059 case R_PPC_REL32:
1060 *loc = v - dot;
1061 break;
1062
1063 case R_PPC_ADDR32:
1064 *loc = v;
1065 break;
1066
984#elif defined(__sh__) 1067#elif defined(__sh__)
985 case R_SH_REL32: 1068
986 *loc += v - dot; 1069 case R_SH_NONE:
987 break; 1070 break;
988#elif defined(__i386__) 1071
989 case R_386_PLT32: 1072 case R_SH_DIR32:
990 case R_386_PC32: 1073 *loc += v;
1074 break;
1075
1076 case R_SH_REL32:
991 *loc += v - dot; 1077 *loc += v - dot;
992 break; 1078 break;
993#elif defined(__mc68000__) 1079
994 case R_68K_PC8: 1080 case R_SH_PLT32:
995 v -= dot; 1081 *loc = v - dot;
996 if ((Elf32_Sword)v > 0x7f || (Elf32_Sword)v < -(Elf32_Sword)0x80)
997 ret = obj_reloc_overflow;
998 *(char *)loc = v;
999 break;
1000 case R_68K_PC16:
1001 v -= dot;
1002 if ((Elf32_Sword)v > 0x7fff || (Elf32_Sword)v < -(Elf32_Sword)0x8000)
1003 ret = obj_reloc_overflow;
1004 *(short *)loc = v;
1005 break; 1082 break;
1006 case R_68K_PC32: 1083
1007 *(int *)loc = v - dot; 1084 case R_SH_GLOB_DAT:
1085 case R_SH_JMP_SLOT:
1086 *loc = v;
1008 break; 1087 break;
1009#elif defined(__powerpc__) 1088
1010 case R_PPC_REL32: 1089 case R_SH_RELATIVE:
1011 *loc = v - dot; 1090 *loc = f->baseaddr + rel->r_addend;
1012 break; 1091 break;
1013#endif
1014 1092
1015#if defined(__sh__) 1093 case R_SH_GOTPC:
1016 case R_SH_PLT32: 1094 assert(got != 0);
1017 *loc = v - dot; 1095 *loc = got - dot + rel->r_addend;
1018 break; 1096 break;
1019#elif defined(__i386__)
1020#endif
1021 1097
1022#if defined(CONFIG_USE_PLT_ENTRIES) 1098 case R_SH_GOT32:
1099 goto bb_use_got;
1100
1101 case R_SH_GOTOFF:
1102 assert(got != 0);
1103 *loc = v - got;
1104 break;
1023 1105
1024#if defined(__arm__)
1025 case R_ARM_PC24:
1026 case R_ARM_PLT32:
1027#endif
1028#if defined(__powerpc__)
1029 case R_PPC_REL24:
1030#endif 1106#endif
1107
1108 default:
1109 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
1110 ret = obj_reloc_unhandled;
1111 break;
1112
1031#if defined (__v850e__) 1113#if defined (__v850e__)
1114 case R_V850_NONE:
1115 break;
1116
1117 case R_V850_32:
1118 /* We write two shorts instead of a long because even
1119 32-bit insns only need half-word alignment, but
1120 32-bit data needs to be long-word aligned. */
1121 v += ((unsigned short *)loc)[0];
1122 v += ((unsigned short *)loc)[1] << 16;
1123 ((unsigned short *)loc)[0] = v & 0xffff;
1124 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1125 break;
1126
1032 case R_V850_22_PCREL: 1127 case R_V850_22_PCREL:
1128 goto bb_use_plt;
1033#endif 1129#endif
1130
1131#if defined(CONFIG_USE_PLT_ENTRIES)
1132
1133 bb_use_plt:
1134
1034 /* find the plt entry and initialize it if necessary */ 1135 /* find the plt entry and initialize it if necessary */
1035 assert(isym != NULL); 1136 assert(isym != NULL);
1036 1137
1037 pe = (struct arch_plt_entry*) &isym->pltent; 1138#if defined(CONFIG_USE_PLT_LIST)
1139 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1140 pe = pe->next;
1141 assert(pe != NULL);
1142#else
1143 pe = &isym->pltent;
1144#endif
1038 1145
1039 if (! pe->inited) { 1146 if (! pe->inited) {
1040 ip = (unsigned long *) (ifile->plt->contents + pe->offset); 1147 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
@@ -1065,19 +1172,19 @@ arch_apply_relocation(struct obj_file *f,
1065 v -= dot; 1172 v -= dot;
1066 /* if the target is too far away.... */ 1173 /* if the target is too far away.... */
1067#if defined (__arm__) || defined (__powerpc__) 1174#if defined (__arm__) || defined (__powerpc__)
1068 if ((int)v < -0x02000000 || (int)v >= 0x02000000) 1175 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
1069#elif defined (__v850e__) 1176#elif defined (__v850e__)
1070 if ((Elf32_Sword)v > 0x1fffff || (Elf32_Sword)v < (Elf32_Sword)-0x200000) 1177 if ((Elf32_Sword)v > 0x1fffff || (Elf32_Sword)v < (Elf32_Sword)-0x200000)
1071#endif 1178#endif
1072 /* go via the plt */ 1179 /* go via the plt */
1073 v = plt + pe->offset - dot; 1180 v = plt + pe->offset - dot;
1074 1181
1075#if defined (__v850e__) 1182#if defined (__v850e__)
1076 if (v & 1) 1183 if (v & 1)
1077#else 1184#else
1078 if (v & 3) 1185 if (v & 3)
1079#endif 1186#endif
1080 ret = obj_reloc_dangerous; 1187 ret = obj_reloc_dangerous;
1081 1188
1082 /* merge the offset into the instruction. */ 1189 /* merge the offset into the instruction. */
1083#if defined(__arm__) 1190#if defined(__arm__)
@@ -1099,75 +1206,16 @@ arch_apply_relocation(struct obj_file *f,
1099 ((unsigned short *)loc)[1] = 1206 ((unsigned short *)loc)[1] =
1100 (v & 0xffff); /* offs low part */ 1207 (v & 0xffff); /* offs low part */
1101#endif 1208#endif
1102
1103 break; 1209 break;
1104#endif /* CONFIG_USE_PLT_ENTRIES */ 1210#endif /* CONFIG_USE_PLT_ENTRIES */
1105 1211
1106#if defined(__arm__)
1107#elif defined(__sh__)
1108 case R_SH_GLOB_DAT:
1109 case R_SH_JMP_SLOT:
1110 *loc = v;
1111 break;
1112#elif defined(__i386__)
1113 case R_386_GLOB_DAT:
1114 case R_386_JMP_SLOT:
1115 *loc = v;
1116 break;
1117#elif defined(__mc68000__)
1118 case R_68K_GLOB_DAT:
1119 case R_68K_JMP_SLOT:
1120 *loc = v;
1121 break;
1122#endif
1123
1124#if defined(__arm__)
1125#elif defined(__sh__)
1126 case R_SH_RELATIVE:
1127 *loc += f->baseaddr + rel->r_addend;
1128 break;
1129#elif defined(__i386__)
1130 case R_386_RELATIVE:
1131 *loc += f->baseaddr;
1132 break;
1133#elif defined(__mc68000__)
1134 case R_68K_RELATIVE:
1135 *(int *)loc += f->baseaddr;
1136 break;
1137#endif
1138
1139#if defined(CONFIG_USE_GOT_ENTRIES) 1212#if defined(CONFIG_USE_GOT_ENTRIES)
1213 bb_use_got:
1140 1214
1141#if !defined(__68k__)
1142#if defined(__sh__)
1143 case R_SH_GOTPC:
1144#elif defined(__arm__)
1145 case R_ARM_GOTPC:
1146#elif defined(__i386__)
1147 case R_386_GOTPC:
1148#endif
1149 assert(got != 0);
1150#if defined(__sh__)
1151 *loc += got - dot + rel->r_addend;;
1152#elif defined(__i386__) || defined(__arm__) || defined(__m68k_)
1153 *loc += got - dot;
1154#endif
1155 break;
1156#endif // __68k__
1157
1158#if defined(__sh__)
1159 case R_SH_GOT32:
1160#elif defined(__arm__)
1161 case R_ARM_GOT32:
1162#elif defined(__i386__)
1163 case R_386_GOT32:
1164#elif defined(__mc68000__)
1165 case R_68K_GOT32:
1166#endif
1167 assert(isym != NULL); 1215 assert(isym != NULL);
1168 /* needs an entry in the .got: set it, once */ 1216 /* needs an entry in the .got: set it, once */
1169 if (!isym->gotent.reloc_done) { 1217 if (!isym->gotent.inited) {
1170 isym->gotent.reloc_done = 1; 1218 isym->gotent.inited = 1;
1171 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v; 1219 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1172 } 1220 }
1173 /* make the reloc with_respect_to_.got */ 1221 /* make the reloc with_respect_to_.got */
@@ -1178,43 +1226,90 @@ arch_apply_relocation(struct obj_file *f,
1178#endif 1226#endif
1179 break; 1227 break;
1180 1228
1181 /* address relative to the got */ 1229#endif /* CONFIG_USE_GOT_ENTRIES */
1182#if !defined(__mc68000__) 1230 }
1183#if defined(__sh__) 1231
1184 case R_SH_GOTOFF: 1232 return ret;
1185#elif defined(__arm__) 1233}
1186 case R_ARM_GOTOFF: 1234
1187#elif defined(__i386__) 1235
1188 case R_386_GOTOFF: 1236#if defined(CONFIG_USE_LIST)
1189#elif defined(__mc68000__) 1237
1190 case R_68K_GOTOFF: 1238static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1239 int offset, int size)
1240{
1241 struct arch_list_entry *pe;
1242
1243 for (pe = *list; pe != NULL; pe = pe->next) {
1244 if (pe->addend == rel->r_addend) {
1245 break;
1246 }
1247 }
1248
1249 if (pe == NULL) {
1250 pe = xmalloc(sizeof(struct arch_list_entry));
1251 pe->next = *list;
1252 pe->addend = rel->r_addend;
1253 pe->offset = offset;
1254 pe->inited = 0;
1255 *list = pe;
1256 return size;
1257 }
1258 return 0;
1259}
1260
1191#endif 1261#endif
1192 assert(got != 0);
1193 *loc += v - got;
1194 break;
1195#endif // __mc68000__
1196 1262
1197#endif /* CONFIG_USE_GOT_ENTRIES */ 1263#if defined(CONFIG_USE_SINGLE)
1198 1264
1199 default: 1265static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
1200 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info)); 1266 int offset, int size)
1201 ret = obj_reloc_unhandled; 1267{
1202 break; 1268 if (single->allocated == 0) {
1269 single->allocated = 1;
1270 single->offset = offset;
1271 single->inited = 0;
1272 return size;
1203 } 1273 }
1274 return 0;
1275}
1204 1276
1205 return ret; 1277#endif
1278
1279#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
1280
1281static struct obj_section *arch_xsect_init(struct obj_file *f, char *name,
1282 int offset, int size)
1283{
1284 struct obj_section *myrelsec = obj_find_section(f, name);
1285
1286 if (offset == 0) {
1287 offset += size;
1288 }
1289
1290 if (myrelsec) {
1291 obj_extend_section(myrelsec, offset);
1292 } else {
1293 myrelsec = obj_create_alloced_section(f, name,
1294 size, offset);
1295 assert(myrelsec);
1296 }
1297
1298 return myrelsec;
1206} 1299}
1207 1300
1208static int arch_create_got(struct obj_file *f) 1301#endif
1302
1303static void arch_create_got(struct obj_file *f)
1209{ 1304{
1210#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) 1305#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
1211 struct arch_file *ifile = (struct arch_file *) f; 1306 struct arch_file *ifile = (struct arch_file *) f;
1212 int i; 1307 int i;
1213#if defined(CONFIG_USE_GOT_ENTRIES) 1308#if defined(CONFIG_USE_GOT_ENTRIES)
1214 int got_offset = 0, gotneeded = 0; 1309 int got_offset = 0, got_needed = 0, got_allocate;
1215#endif 1310#endif
1216#if defined(CONFIG_USE_PLT_ENTRIES) 1311#if defined(CONFIG_USE_PLT_ENTRIES)
1217 int plt_offset = 0, pltneeded = 0; 1312 int plt_offset = 0, plt_needed = 0, plt_allocate;
1218#endif 1313#endif
1219 struct obj_section *relsec, *symsec, *strsec; 1314 struct obj_section *relsec, *symsec, *strsec;
1220 ElfW(RelM) *rel, *relend; 1315 ElfW(RelM) *rel, *relend;
@@ -1238,54 +1333,69 @@ static int arch_create_got(struct obj_file *f)
1238 for (; rel < relend; ++rel) { 1333 for (; rel < relend; ++rel) {
1239 extsym = &symtab[ELF32_R_SYM(rel->r_info)]; 1334 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
1240 1335
1336#if defined(CONFIG_USE_GOT_ENTRIES)
1337 got_allocate = 0;
1338#endif
1339#if defined(CONFIG_USE_PLT_ENTRIES)
1340 plt_allocate = 0;
1341#endif
1342
1241 switch (ELF32_R_TYPE(rel->r_info)) { 1343 switch (ELF32_R_TYPE(rel->r_info)) {
1242#if defined(__arm__) 1344#if defined(__arm__)
1243 case R_ARM_GOT32: 1345 case R_ARM_PC24:
1346 case R_ARM_PLT32:
1347 plt_allocate = 1;
1244 break; 1348 break;
1245#elif defined(__sh__) 1349
1246 case R_SH_GOT32: 1350 case R_ARM_GOTOFF:
1351 case R_ARM_GOTPC:
1352 got_needed = 1;
1353 continue;
1354
1355 case R_ARM_GOT32:
1356 got_allocate = 1;
1247 break; 1357 break;
1358
1248#elif defined(__i386__) 1359#elif defined(__i386__)
1360 case R_386_GOTPC:
1361 case R_386_GOTOFF:
1362 got_needed = 1;
1363 continue;
1364
1249 case R_386_GOT32: 1365 case R_386_GOT32:
1366 got_allocate = 1;
1250 break; 1367 break;
1251#elif defined(__mc68000__)
1252 case R_68K_GOT32:
1253 break;
1254#endif
1255 1368
1256#if defined(__powerpc__) 1369#elif defined(__powerpc__)
1257 case R_PPC_REL24: 1370 case R_PPC_REL24:
1258 pltneeded = 1; 1371 plt_allocate = 1;
1259 break; 1372 break;
1260#endif
1261 1373
1262#if defined (__v850e__) 1374#elif defined(__mc68000__)
1263 case R_V850_22_PCREL: 1375 case R_68K_GOT32:
1264 pltneeded = 1; 1376 got_allocate = 1;
1265 break; 1377 break;
1266#endif
1267 1378
1268#if defined(__arm__) 1379 case R_68K_GOTOFF:
1269 case R_ARM_PC24: 1380 got_needed = 1;
1270 case R_ARM_PLT32: 1381 continue;
1271 pltneeded = 1;
1272 break;
1273 1382
1274 case R_ARM_GOTPC:
1275 case R_ARM_GOTOFF:
1276 gotneeded = 1;
1277 if (got_offset == 0)
1278 got_offset = 4;
1279#elif defined(__sh__) 1383#elif defined(__sh__)
1384 case R_SH_GOT32:
1385 got_allocate = 1;
1386 break;
1387
1280 case R_SH_GOTPC: 1388 case R_SH_GOTPC:
1281 case R_SH_GOTOFF: 1389 case R_SH_GOTOFF:
1282 gotneeded = 1; 1390 got_needed = 1;
1283#elif defined(__i386__) 1391 continue;
1284 case R_386_GOTPC: 1392
1285 case R_386_GOTOFF: 1393#elif defined (__v850e__)
1286 gotneeded = 1; 1394 case R_V850_22_PCREL:
1287#endif 1395 plt_needed = 1;
1396 break;
1288 1397
1398#endif
1289 default: 1399 default:
1290 continue; 1400 continue;
1291 } 1401 }
@@ -1297,49 +1407,46 @@ static int arch_create_got(struct obj_file *f)
1297 } 1407 }
1298 intsym = (struct arch_symbol *) obj_find_symbol(f, name); 1408 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
1299#if defined(CONFIG_USE_GOT_ENTRIES) 1409#if defined(CONFIG_USE_GOT_ENTRIES)
1300 if (!intsym->gotent.offset_done) { 1410 if (got_allocate) {
1301 intsym->gotent.offset_done = 1; 1411 got_offset += arch_single_init(
1302 intsym->gotent.offset = got_offset; 1412 rel, &intsym->gotent,
1303 got_offset += CONFIG_GOT_ENTRY_SIZE; 1413 got_offset, CONFIG_GOT_ENTRY_SIZE);
1414
1415 got_needed = 1;
1304 } 1416 }
1305#endif 1417#endif
1306#if defined(CONFIG_USE_PLT_ENTRIES) 1418#if defined(CONFIG_USE_PLT_ENTRIES)
1307 if (pltneeded && intsym->pltent.allocated == 0) { 1419 if (plt_allocate) {
1308 intsym->pltent.allocated = 1; 1420#if defined(CONFIG_USE_PLT_LIST)
1309 intsym->pltent.offset = plt_offset; 1421 plt_offset += arch_list_add(
1310 plt_offset += CONFIG_PLT_ENTRY_SIZE; 1422 rel, &intsym->pltent,
1311 intsym->pltent.inited = 0; 1423 plt_offset, CONFIG_PLT_ENTRY_SIZE);
1312 pltneeded = 0; 1424#else
1425 plt_offset += arch_single_init(
1426 rel, &intsym->pltent,
1427 plt_offset, CONFIG_PLT_ENTRY_SIZE);
1428#endif
1429 plt_needed = 1;
1313 } 1430 }
1314#endif 1431#endif
1315 } 1432 }
1316 } 1433 }
1317 1434
1318#if defined(CONFIG_USE_GOT_ENTRIES) 1435#if defined(CONFIG_USE_GOT_ENTRIES)
1319 if (got_offset) { 1436 if (got_needed) {
1320 struct obj_section* myrelsec = obj_find_section(f, ".got"); 1437 ifile->got = arch_xsect_init(f, ".got", got_offset,
1321 1438 CONFIG_GOT_ENTRY_SIZE);
1322 if (myrelsec) {
1323 obj_extend_section(myrelsec, got_offset);
1324 } else {
1325 myrelsec = obj_create_alloced_section(f, ".got",
1326 CONFIG_GOT_ENTRY_SIZE,
1327 got_offset);
1328 assert(myrelsec);
1329 }
1330
1331 ifile->got = myrelsec;
1332 } 1439 }
1333#endif 1440#endif
1334 1441
1335#if defined(CONFIG_USE_PLT_ENTRIES) 1442#if defined(CONFIG_USE_PLT_ENTRIES)
1336 if (plt_offset) 1443 if (plt_needed) {
1337 ifile->plt = obj_create_alloced_section(f, ".plt", 1444 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
1338 CONFIG_PLT_ENTRY_SIZE, 1445 CONFIG_PLT_ENTRY_SIZE);
1339 plt_offset); 1446 }
1340#endif
1341#endif 1447#endif
1342 return 1; 1448
1449#endif /* defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) */
1343} 1450}
1344 1451
1345#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE 1452#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE