diff options
author | Eric Andersen <andersen@codepoet.org> | 2002-05-24 06:50:15 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2002-05-24 06:50:15 +0000 |
commit | cffd5022c5fe5511a456461e9cc5c8da8b90dd61 (patch) | |
tree | 7ed88f9131287e9f844fd451b88fcc43d40c8c97 /modutils | |
parent | d11edf98094533af3e322c5f42e756e2e786ba0c (diff) | |
download | busybox-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.c | 869 |
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 |
141 | static const int MODUTILS_MODULE_H = 1; | 234 | static 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 |
358 | static const int MODUTILS_OBJ_H = 1; | 455 | static 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 | ||
622 | static int arch_create_got (struct obj_file *f); | 631 | static void arch_create_got (struct obj_file *f); |
623 | 632 | ||
624 | #ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE | 633 | #ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE |
625 | static int arch_init_module (struct obj_file *f, struct new_module *); | 634 | static 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 | 667 | struct arch_list_entry | |
665 | |||
666 | #if defined(CONFIG_USE_PLT_ENTRIES) | ||
667 | struct 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) |
676 | struct arch_got_entry { | 678 | |
679 | struct 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 { | |||
705 | struct arch_symbol { | 710 | struct 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: | 1238 | static 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: | 1265 | static 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 | |||
1281 | static 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 | ||
1208 | static int arch_create_got(struct obj_file *f) | 1301 | #endif |
1302 | |||
1303 | static 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 |