1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61#include "libbb.h"
62#include "modutils.h"
63#include <libgen.h>
64#include <sys/utsname.h>
65
66#if ENABLE_FEATURE_INSMOD_LOADINKMEM
67#define LOADBITS 0
68#else
69#define LOADBITS 1
70#endif
71
72
73#if defined(__alpha__)
74#define MATCH_MACHINE(x) (x == EM_ALPHA)
75#define SHT_RELM SHT_RELA
76#define Elf64_RelM Elf64_Rela
77#define ELFCLASSM ELFCLASS64
78#endif
79
80
81#if defined(__arm__)
82#define MATCH_MACHINE(x) (x == EM_ARM)
83#define SHT_RELM SHT_REL
84#define Elf32_RelM Elf32_Rel
85#define ELFCLASSM ELFCLASS32
86#define USE_PLT_ENTRIES
87#define PLT_ENTRY_SIZE 8
88#define USE_GOT_ENTRIES
89#define GOT_ENTRY_SIZE 8
90#define USE_SINGLE
91#endif
92
93
94#if defined(__nds32__) || defined(__NDS32__)
95#define CONFIG_USE_GOT_ENTRIES
96#define CONFIG_GOT_ENTRY_SIZE 4
97#define CONFIG_USE_SINGLE
98
99#if defined(__NDS32_EB__)
100#define MATCH_MACHINE(x) (x == EM_NDS32)
101#define SHT_RELM SHT_RELA
102#define Elf32_RelM Elf32_Rela
103#define ELFCLASSM ELFCLASS32
104#endif
105
106#if defined(__NDS32_EL__)
107#define MATCH_MACHINE(x) (x == EM_NDS32)
108#define SHT_RELM SHT_RELA
109#define Elf32_RelM Elf32_Rela
110#define ELFCLASSM ELFCLASS32
111#endif
112#endif
113
114
115#if defined(BFIN)
116#define MATCH_MACHINE(x) (x == EM_BLACKFIN)
117#define SHT_RELM SHT_RELA
118#define Elf32_RelM Elf32_Rela
119#define ELFCLASSM ELFCLASS32
120#endif
121
122
123#if defined(__cris__)
124#define MATCH_MACHINE(x) (x == EM_CRIS)
125#define SHT_RELM SHT_RELA
126#define Elf32_RelM Elf32_Rela
127#define ELFCLASSM ELFCLASS32
128#ifndef EM_CRIS
129#define EM_CRIS 76
130#define R_CRIS_NONE 0
131#define R_CRIS_32 3
132#endif
133#endif
134
135
136#if defined(__H8300H__) || defined(__H8300S__)
137#define MATCH_MACHINE(x) (x == EM_H8_300)
138#define SHT_RELM SHT_RELA
139#define Elf32_RelM Elf32_Rela
140#define ELFCLASSM ELFCLASS32
141#define USE_SINGLE
142#define SYMBOL_PREFIX "_"
143#endif
144
145
146#if defined(__hppa__)
147#define MATCH_MACHINE(x) (x == EM_PARISC)
148#define SHT_RELM SHT_RELA
149#if defined(__LP64__)
150#define Elf64_RelM Elf64_Rela
151#define ELFCLASSM ELFCLASS64
152#else
153#define Elf32_RelM Elf32_Rela
154#define ELFCLASSM ELFCLASS32
155#endif
156#endif
157
158
159#if defined(__i386__)
160#ifndef EM_486
161#define MATCH_MACHINE(x) (x == EM_386)
162#else
163#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
164#endif
165#define SHT_RELM SHT_REL
166#define Elf32_RelM Elf32_Rel
167#define ELFCLASSM ELFCLASS32
168#define USE_GOT_ENTRIES
169#define GOT_ENTRY_SIZE 4
170#define USE_SINGLE
171#endif
172
173
174#if defined(__ia64__)
175#define MATCH_MACHINE(x) (x == EM_IA_64)
176#define SHT_RELM SHT_RELA
177#define Elf64_RelM Elf64_Rela
178#define ELFCLASSM ELFCLASS64
179#endif
180
181
182#if defined(__mc68000__)
183#define MATCH_MACHINE(x) (x == EM_68K)
184#define SHT_RELM SHT_RELA
185#define Elf32_RelM Elf32_Rela
186#define ELFCLASSM ELFCLASS32
187#define USE_GOT_ENTRIES
188#define GOT_ENTRY_SIZE 4
189#define USE_SINGLE
190#endif
191
192
193#if defined(__microblaze__)
194#define USE_SINGLE
195#include <linux/elf-em.h>
196#define MATCH_MACHINE(x) (x == EM_XILINX_MICROBLAZE)
197#define SHT_RELM SHT_RELA
198#define Elf32_RelM Elf32_Rela
199#define ELFCLASSM ELFCLASS32
200#endif
201
202
203#if defined(__mips__)
204#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
205#define SHT_RELM SHT_REL
206#define Elf32_RelM Elf32_Rel
207#define ELFCLASSM ELFCLASS32
208
209#ifndef EM_MIPS_RS3_LE
210#ifdef EM_MIPS_RS4_BE
211#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
212#else
213#define EM_MIPS_RS3_LE 10
214#endif
215#endif
216#define ARCHDATAM "__dbe_table"
217#endif
218
219
220#if defined(__nios2__)
221#define MATCH_MACHINE(x) (x == EM_ALTERA_NIOS2)
222#define SHT_RELM SHT_RELA
223#define Elf32_RelM Elf32_Rela
224#define ELFCLASSM ELFCLASS32
225#endif
226
227
228#if defined(__powerpc64__)
229#define MATCH_MACHINE(x) (x == EM_PPC64)
230#define SHT_RELM SHT_RELA
231#define Elf64_RelM Elf64_Rela
232#define ELFCLASSM ELFCLASS64
233#elif defined(__powerpc__)
234#define MATCH_MACHINE(x) (x == EM_PPC)
235#define SHT_RELM SHT_RELA
236#define Elf32_RelM Elf32_Rela
237#define ELFCLASSM ELFCLASS32
238#define USE_PLT_ENTRIES
239#define PLT_ENTRY_SIZE 16
240#define USE_PLT_LIST
241#define LIST_ARCHTYPE ElfW(Addr)
242#define USE_LIST
243#define ARCHDATAM "__ftr_fixup"
244#endif
245
246
247#if defined(__s390__)
248#define MATCH_MACHINE(x) (x == EM_S390)
249#define SHT_RELM SHT_RELA
250#define Elf32_RelM Elf32_Rela
251#define ELFCLASSM ELFCLASS32
252#define USE_PLT_ENTRIES
253#define PLT_ENTRY_SIZE 8
254#define USE_GOT_ENTRIES
255#define GOT_ENTRY_SIZE 8
256#define USE_SINGLE
257#endif
258
259
260#if defined(__sh__)
261#define MATCH_MACHINE(x) (x == EM_SH)
262#define SHT_RELM SHT_RELA
263#define Elf32_RelM Elf32_Rela
264#define ELFCLASSM ELFCLASS32
265#define USE_GOT_ENTRIES
266#define GOT_ENTRY_SIZE 4
267#define USE_SINGLE
268
269
270#if defined(__sh__) && BB_BIG_ENDIAN
271# error insmod.c may require changes for use on big endian SH
272#endif
273
274#if ((!(defined(__SH3__) || defined(__SH4__) || defined(__SH5__)))) && (defined(__sh__))
275#error insmod.c may require changes for SH1 or SH2 use
276#endif
277#endif
278
279
280#if defined(__sparc__)
281#define MATCH_MACHINE(x) (x == EM_SPARC)
282#define SHT_RELM SHT_RELA
283#define Elf32_RelM Elf32_Rela
284#define ELFCLASSM ELFCLASS32
285#endif
286
287
288#if defined(__v850e__)
289#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
290#define SHT_RELM SHT_RELA
291#define Elf32_RelM Elf32_Rela
292#define ELFCLASSM ELFCLASS32
293#define USE_PLT_ENTRIES
294#define PLT_ENTRY_SIZE 8
295#define USE_SINGLE
296#ifndef EM_CYGNUS_V850
297#define EM_CYGNUS_V850 0x9080
298#endif
299#define SYMBOL_PREFIX "_"
300#endif
301
302
303#if defined(__x86_64__)
304#define MATCH_MACHINE(x) (x == EM_X86_64)
305#define SHT_RELM SHT_RELA
306#define USE_GOT_ENTRIES
307#define GOT_ENTRY_SIZE 8
308#define USE_SINGLE
309#define Elf64_RelM Elf64_Rela
310#define ELFCLASSM ELFCLASS64
311#endif
312
313#ifndef SHT_RELM
314#error Sorry, but insmod.c does not yet support this architecture...
315#endif
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344#ifndef MODUTILS_MODULE_H
345
346
347
348
349
350#define tgt_sizeof_char sizeof(char)
351#define tgt_sizeof_short sizeof(short)
352#define tgt_sizeof_int sizeof(int)
353#define tgt_sizeof_long sizeof(long)
354#define tgt_sizeof_char_p sizeof(char *)
355#define tgt_sizeof_void_p sizeof(void *)
356#define tgt_long long
357
358#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
359#undef tgt_sizeof_long
360#undef tgt_sizeof_char_p
361#undef tgt_sizeof_void_p
362#undef tgt_long
363enum {
364 tgt_sizeof_long = 8,
365 tgt_sizeof_char_p = 8,
366 tgt_sizeof_void_p = 8
367};
368#define tgt_long long long
369#endif
370
371
372
373
374
375struct new_module_symbol {
376 unsigned long value;
377 unsigned long name;
378};
379
380struct new_module_persist;
381
382struct new_module_ref {
383 unsigned tgt_long dep;
384 unsigned tgt_long ref;
385 unsigned tgt_long next_ref;
386};
387
388struct new_module {
389 unsigned tgt_long size_of_struct;
390 unsigned tgt_long next;
391 unsigned tgt_long name;
392 unsigned tgt_long size;
393
394 tgt_long usecount;
395 unsigned tgt_long flags;
396
397 unsigned nsyms;
398 unsigned ndeps;
399
400 unsigned tgt_long syms;
401 unsigned tgt_long deps;
402 unsigned tgt_long refs;
403 unsigned tgt_long init;
404 unsigned tgt_long cleanup;
405 unsigned tgt_long ex_table_start;
406 unsigned tgt_long ex_table_end;
407#ifdef __alpha__
408 unsigned tgt_long gp;
409#endif
410
411 unsigned tgt_long persist_start;
412 unsigned tgt_long persist_end;
413 unsigned tgt_long can_unload;
414 unsigned tgt_long runsize;
415 const char *kallsyms_start;
416 const char *kallsyms_end;
417 const char *archdata_start;
418 const char *archdata_end;
419 const char *kernel_data;
420};
421
422#ifdef ARCHDATAM
423#define ARCHDATA_SEC_NAME ARCHDATAM
424#else
425#define ARCHDATA_SEC_NAME "__archdata"
426#endif
427#define KALLSYMS_SEC_NAME "__kallsyms"
428
429
430struct new_module_info {
431 unsigned long addr;
432 unsigned long size;
433 unsigned long flags;
434 long usecount;
435};
436
437
438enum {
439 NEW_MOD_RUNNING = 1,
440 NEW_MOD_DELETED = 2,
441 NEW_MOD_AUTOCLEAN = 4,
442 NEW_MOD_VISITED = 8,
443 NEW_MOD_USED_ONCE = 16
444};
445
446int init_module(const char *name, const struct new_module *);
447int query_module(const char *name, int which, void *buf,
448 size_t bufsize, size_t *ret);
449
450
451enum {
452 QM_MODULES = 1,
453 QM_DEPS = 2,
454 QM_REFS = 3,
455 QM_SYMBOLS = 4,
456 QM_INFO = 5
457};
458
459
460
461
462unsigned long create_module(const char *, size_t);
463int delete_module(const char *module, unsigned int flags);
464
465
466#endif
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500#ifndef MODUTILS_OBJ_H
501
502
503
504#include <elf.h>
505#include <endian.h>
506
507#ifndef ElfW
508# if ELFCLASSM == ELFCLASS32
509# define ElfW(x) Elf32_ ## x
510# define ELFW(x) ELF32_ ## x
511# else
512# define ElfW(x) Elf64_ ## x
513# define ELFW(x) ELF64_ ## x
514# endif
515#endif
516
517
518#ifndef ELF32_ST_INFO
519# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
520#endif
521
522#ifndef ELF64_ST_INFO
523# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
524#endif
525
526#define ELF_ST_BIND(info) ELFW(ST_BIND)(info)
527#define ELF_ST_TYPE(info) ELFW(ST_TYPE)(info)
528#define ELF_ST_INFO(bind, type) ELFW(ST_INFO)(bind, type)
529#define ELF_R_TYPE(val) ELFW(R_TYPE)(val)
530#define ELF_R_SYM(val) ELFW(R_SYM)(val)
531
532struct obj_string_patch;
533struct obj_symbol_patch;
534
535struct obj_section {
536 ElfW(Shdr) header;
537 const char *name;
538 char *contents;
539 struct obj_section *load_next;
540 int idx;
541};
542
543struct obj_symbol {
544 struct obj_symbol *next;
545 const char *name;
546 unsigned long value;
547 unsigned long size;
548 int secidx;
549 int info;
550 int ksymidx;
551 int referenced;
552};
553
554
555
556
557
558#define HASH_BUCKETS 521
559
560struct obj_file {
561 ElfW(Ehdr) header;
562 ElfW(Addr) baseaddr;
563 struct obj_section **sections;
564 struct obj_section *load_order;
565 struct obj_section **load_order_search_start;
566 struct obj_string_patch *string_patches;
567 struct obj_symbol_patch *symbol_patches;
568 int (*symbol_cmp)(const char *, const char *);
569 unsigned long (*symbol_hash)(const char *) FAST_FUNC;
570 unsigned long local_symtab_size;
571 struct obj_symbol **local_symtab;
572 struct obj_symbol *symtab[HASH_BUCKETS];
573};
574
575enum obj_reloc {
576 obj_reloc_ok,
577 obj_reloc_overflow,
578 obj_reloc_dangerous,
579 obj_reloc_unhandled
580};
581
582struct obj_string_patch {
583 struct obj_string_patch *next;
584 int reloc_secidx;
585 ElfW(Addr) reloc_offset;
586 ElfW(Addr) string_offset;
587};
588
589struct obj_symbol_patch {
590 struct obj_symbol_patch *next;
591 int reloc_secidx;
592 ElfW(Addr) reloc_offset;
593 struct obj_symbol *sym;
594};
595
596
597
598
599static unsigned long FAST_FUNC obj_elf_hash(const char *);
600
601static unsigned long obj_elf_hash_n(const char *, unsigned long len);
602
603static struct obj_symbol *obj_find_symbol(struct obj_file *f,
604 const char *name);
605
606static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
607 struct obj_symbol *sym);
608
609#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
610static void obj_set_symbol_compare(struct obj_file *f,
611 int (*cmp)(const char *, const char *),
612 unsigned long (*hash)(const char *) FAST_FUNC);
613#endif
614
615static struct obj_section *obj_find_section(struct obj_file *f,
616 const char *name);
617
618static void obj_insert_section_load_order(struct obj_file *f,
619 struct obj_section *sec);
620
621static struct obj_section *obj_create_alloced_section(struct obj_file *f,
622 const char *name,
623 unsigned long align,
624 unsigned long size);
625
626static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
627 const char *name,
628 unsigned long align,
629 unsigned long size);
630
631static void *obj_extend_section(struct obj_section *sec, unsigned long more);
632
633static void obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
634 const char *string);
635
636static void obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
637 struct obj_symbol *sym);
638
639static void obj_check_undefineds(struct obj_file *f);
640
641static void obj_allocate_commons(struct obj_file *f);
642
643static unsigned long obj_load_size(struct obj_file *f);
644
645static int obj_relocate(struct obj_file *f, ElfW(Addr) base);
646
647#if !LOADBITS
648#define obj_load(image, image_size, loadprogbits) \
649 obj_load(image, image_size)
650#endif
651static struct obj_file *obj_load(char *image, size_t image_size, int loadprogbits);
652
653static int obj_create_image(struct obj_file *f, char *image);
654
655
656
657static struct obj_file *arch_new_file(void);
658
659static struct obj_section *arch_new_section(void);
660
661static struct obj_symbol *arch_new_symbol(void);
662
663static enum obj_reloc arch_apply_relocation(struct obj_file *f,
664 struct obj_section *targsec,
665
666 struct obj_symbol *sym,
667 ElfW(RelM) *rel, ElfW(Addr) value);
668
669static void arch_create_got(struct obj_file *f);
670#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
671static int obj_gpl_license(struct obj_file *f, const char **license);
672#endif
673#endif
674
675
676
677
678
679
680#ifdef SYMBOL_PREFIX
681#define SPFX SYMBOL_PREFIX
682#else
683#define SPFX ""
684#endif
685
686enum { STRVERSIONLEN = 64 };
687
688
689
690#define flag_force_load (option_mask32 & INSMOD_OPT_FORCE)
691#define flag_autoclean (option_mask32 & INSMOD_OPT_KERNELD)
692#define flag_verbose (option_mask32 & INSMOD_OPT_VERBOSE)
693#define flag_quiet (option_mask32 & INSMOD_OPT_SILENT)
694#define flag_noexport (option_mask32 & INSMOD_OPT_NO_EXPORT)
695#define flag_print_load_map (option_mask32 & INSMOD_OPT_PRINT_MAP)
696
697
698
699#if defined(USE_LIST)
700
701struct arch_list_entry {
702 struct arch_list_entry *next;
703 LIST_ARCHTYPE addend;
704 int offset;
705 int inited : 1;
706};
707
708#endif
709
710#if defined(USE_SINGLE)
711
712struct arch_single_entry {
713 int offset;
714 int inited : 1;
715 int allocated : 1;
716};
717
718#endif
719
720#if defined(__mips__)
721struct mips_hi16 {
722 struct mips_hi16 *next;
723 ElfW(Addr) *addr;
724 ElfW(Addr) value;
725};
726#endif
727
728struct arch_file {
729 struct obj_file root;
730#if defined(USE_PLT_ENTRIES)
731 struct obj_section *plt;
732#endif
733#if defined(USE_GOT_ENTRIES)
734 struct obj_section *got;
735#endif
736#if defined(__mips__)
737 struct mips_hi16 *mips_hi16_list;
738#endif
739};
740
741struct arch_symbol {
742 struct obj_symbol root;
743#if defined(USE_PLT_ENTRIES)
744#if defined(USE_PLT_LIST)
745 struct arch_list_entry *pltent;
746#else
747 struct arch_single_entry pltent;
748#endif
749#endif
750#if defined(USE_GOT_ENTRIES)
751 struct arch_single_entry gotent;
752#endif
753};
754
755
756struct external_module {
757 const char *name;
758 ElfW(Addr) addr;
759 int used;
760 size_t nsyms;
761 struct new_module_symbol *syms;
762};
763
764static struct new_module_symbol *ksyms;
765static size_t nksyms;
766
767static struct external_module *ext_modules;
768static int n_ext_modules;
769static int n_ext_modules_used;
770
771
772
773
774static struct obj_file *arch_new_file(void)
775{
776 struct arch_file *f;
777 f = xzalloc(sizeof(*f));
778 return &f->root;
779}
780
781static struct obj_section *arch_new_section(void)
782{
783 return xzalloc(sizeof(struct obj_section));
784}
785
786static struct obj_symbol *arch_new_symbol(void)
787{
788 struct arch_symbol *sym;
789 sym = xzalloc(sizeof(*sym));
790 return &sym->root;
791}
792
793static enum obj_reloc
794arch_apply_relocation(struct obj_file *f,
795 struct obj_section *targsec,
796
797 struct obj_symbol *sym,
798 ElfW(RelM) *rel, ElfW(Addr) v)
799{
800#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) \
801 || defined(__sh__) || defined(__s390__) || defined(__x86_64__) \
802 || defined(__powerpc__) || defined(__mips__)
803 struct arch_file *ifile = (struct arch_file *) f;
804#endif
805 enum obj_reloc ret = obj_reloc_ok;
806 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
807#if defined(__arm__) || defined(__H8300H__) || defined(__H8300S__) \
808 || defined(__i386__) || defined(__mc68000__) || defined(__microblaze__) \
809 || defined(__mips__) || defined(__nios2__) || defined(__powerpc__) \
810 || defined(__s390__) || defined(__sh__) || defined(__x86_64__)
811 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
812#endif
813#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
814 struct arch_symbol *isym = (struct arch_symbol *) sym;
815#endif
816#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) \
817 || defined(__sh__) || defined(__s390__)
818#if defined(USE_GOT_ENTRIES)
819 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
820#endif
821#endif
822#if defined(USE_PLT_ENTRIES)
823 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
824 unsigned long *ip;
825# if defined(USE_PLT_LIST)
826 struct arch_list_entry *pe;
827# else
828 struct arch_single_entry *pe;
829# endif
830#endif
831
832 switch (ELF_R_TYPE(rel->r_info)) {
833
834#if defined(__arm__)
835
836 case R_ARM_NONE:
837 break;
838
839 case R_ARM_ABS32:
840 *loc += v;
841 break;
842
843 case R_ARM_GOT32:
844 goto bb_use_got;
845
846 case R_ARM_GOTPC:
847
848
849
850
851 *loc += got - dot;
852 break;
853
854 case R_ARM_PC24:
855 case R_ARM_PLT32:
856 goto bb_use_plt;
857
858 case R_ARM_GOTOFF:
859 *loc += v - got;
860 break;
861
862#elif defined(__cris__)
863
864 case R_CRIS_NONE:
865 break;
866
867 case R_CRIS_32:
868
869
870
871 *loc = v;
872 break;
873
874#elif defined(__H8300H__) || defined(__H8300S__)
875
876 case R_H8_DIR24R8:
877 loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1);
878 *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
879 break;
880 case R_H8_DIR24A8:
881 *loc += v;
882 break;
883 case R_H8_DIR32:
884 case R_H8_DIR32A16:
885 *loc += v;
886 break;
887 case R_H8_PCREL16:
888 v -= dot + 2;
889 if ((ElfW(Sword))v > 0x7fff
890 || (ElfW(Sword))v < -(ElfW(Sword))0x8000
891 ) {
892 ret = obj_reloc_overflow;
893 } else {
894 *(unsigned short *)loc = v;
895 }
896 break;
897 case R_H8_PCREL8:
898 v -= dot + 1;
899 if ((ElfW(Sword))v > 0x7f
900 || (ElfW(Sword))v < -(ElfW(Sword))0x80
901 ) {
902 ret = obj_reloc_overflow;
903 } else {
904 *(unsigned char *)loc = v;
905 }
906 break;
907
908#elif defined(__i386__)
909
910 case R_386_NONE:
911 break;
912
913 case R_386_32:
914 *loc += v;
915 break;
916
917 case R_386_PLT32:
918 case R_386_PC32:
919 case R_386_GOTOFF:
920 *loc += v - dot;
921 break;
922
923 case R_386_GLOB_DAT:
924 case R_386_JMP_SLOT:
925 *loc = v;
926 break;
927
928 case R_386_RELATIVE:
929 *loc += f->baseaddr;
930 break;
931
932 case R_386_GOTPC:
933 *loc += got - dot;
934 break;
935
936 case R_386_GOT32:
937 goto bb_use_got;
938 break;
939
940#elif defined(__microblaze__)
941 case R_MICROBLAZE_NONE:
942 case R_MICROBLAZE_64_NONE:
943 case R_MICROBLAZE_32_SYM_OP_SYM:
944 case R_MICROBLAZE_32_PCREL:
945 break;
946
947 case R_MICROBLAZE_64_PCREL: {
948
949
950
951
952
953
954
955
956
957 unsigned int temp = (loc[0] & 0xFFFF) << 16 |
958 (loc[1] & 0xFFFF);
959
960
961
962
963
964 temp += v - dot - 4;
965
966
967 loc[0] = (loc[0] & 0xFFFF0000) | temp >> 16;
968 loc[1] = (loc[1] & 0xFFFF0000) | (temp & 0xFFFF);
969
970 break;
971 }
972
973 case R_MICROBLAZE_32:
974 *loc += v;
975 break;
976
977 case R_MICROBLAZE_64: {
978
979 unsigned int temp1 = (loc[0] & 0xFFFF) << 16 |
980 (loc[1] & 0xFFFF);
981
982
983 temp1+=v;
984
985
986 loc[0] = (loc[0] & 0xFFFF0000) | temp1 >> 16;
987 loc[1] = (loc[1] & 0xFFFF0000) | (temp1 & 0xFFFF);
988
989 break;
990 }
991
992 case R_MICROBLAZE_32_PCREL_LO:
993 case R_MICROBLAZE_32_LO:
994 case R_MICROBLAZE_SRO32:
995 case R_MICROBLAZE_SRW32:
996 ret = obj_reloc_unhandled;
997 break;
998
999#elif defined(__mc68000__)
1000
1001 case R_68K_NONE:
1002 break;
1003
1004 case R_68K_32:
1005 *loc += v;
1006 break;
1007
1008 case R_68K_8:
1009 if (v > 0xff) {
1010 ret = obj_reloc_overflow;
1011 }
1012 *(char *)loc = v;
1013 break;
1014
1015 case R_68K_16:
1016 if (v > 0xffff) {
1017 ret = obj_reloc_overflow;
1018 }
1019 *(short *)loc = v;
1020 break;
1021
1022 case R_68K_PC8:
1023 v -= dot;
1024 if ((ElfW(Sword))v > 0x7f
1025 || (ElfW(Sword))v < -(ElfW(Sword))0x80
1026 ) {
1027 ret = obj_reloc_overflow;
1028 }
1029 *(char *)loc = v;
1030 break;
1031
1032 case R_68K_PC16:
1033 v -= dot;
1034 if ((ElfW(Sword))v > 0x7fff
1035 || (ElfW(Sword))v < -(ElfW(Sword))0x8000
1036 ) {
1037 ret = obj_reloc_overflow;
1038 }
1039 *(short *)loc = v;
1040 break;
1041
1042 case R_68K_PC32:
1043 *(int *)loc = v - dot;
1044 break;
1045
1046 case R_68K_GLOB_DAT:
1047 case R_68K_JMP_SLOT:
1048 *loc = v;
1049 break;
1050
1051 case R_68K_RELATIVE:
1052 *(int *)loc += f->baseaddr;
1053 break;
1054
1055 case R_68K_GOT32:
1056 goto bb_use_got;
1057
1058# ifdef R_68K_GOTOFF
1059 case R_68K_GOTOFF:
1060 *loc += v - got;
1061 break;
1062# endif
1063
1064#elif defined(__mips__)
1065
1066 case R_MIPS_NONE:
1067 break;
1068
1069 case R_MIPS_32:
1070 *loc += v;
1071 break;
1072
1073 case R_MIPS_26:
1074 if (v % 4)
1075 ret = obj_reloc_dangerous;
1076 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
1077 ret = obj_reloc_overflow;
1078 *loc =
1079 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
1080 0x03ffffff);
1081 break;
1082
1083 case R_MIPS_HI16:
1084 {
1085 struct mips_hi16 *n;
1086
1087
1088
1089
1090 n = xmalloc(sizeof *n);
1091 n->addr = loc;
1092 n->value = v;
1093 n->next = ifile->mips_hi16_list;
1094 ifile->mips_hi16_list = n;
1095 break;
1096 }
1097
1098 case R_MIPS_LO16:
1099 {
1100 unsigned long insnlo = *loc;
1101 ElfW(Addr) val, vallo;
1102
1103
1104 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
1105
1106 if (ifile->mips_hi16_list != NULL) {
1107 struct mips_hi16 *l;
1108
1109 l = ifile->mips_hi16_list;
1110 while (l != NULL) {
1111 struct mips_hi16 *next;
1112 unsigned long insn;
1113
1114
1115
1116
1117 insn = *l->addr;
1118 val =
1119 ((insn & 0xffff) << 16) +
1120 vallo;
1121 val += v;
1122
1123
1124
1125 val =
1126 ((val >> 16) +
1127 ((val & 0x8000) !=
1128 0)) & 0xffff;
1129
1130 insn = (insn & ~0xffff) | val;
1131 *l->addr = insn;
1132
1133 next = l->next;
1134 free(l);
1135 l = next;
1136 }
1137
1138 ifile->mips_hi16_list = NULL;
1139 }
1140
1141
1142 val = v + vallo;
1143 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1144 *loc = insnlo;
1145 break;
1146 }
1147
1148#elif defined(__nios2__)
1149
1150 case R_NIOS2_NONE:
1151 break;
1152
1153 case R_NIOS2_BFD_RELOC_32:
1154 *loc += v;
1155 break;
1156
1157 case R_NIOS2_BFD_RELOC_16:
1158 if (v > 0xffff) {
1159 ret = obj_reloc_overflow;
1160 }
1161 *(short *)loc = v;
1162 break;
1163
1164 case R_NIOS2_BFD_RELOC_8:
1165 if (v > 0xff) {
1166 ret = obj_reloc_overflow;
1167 }
1168 *(char *)loc = v;
1169 break;
1170
1171 case R_NIOS2_S16:
1172 {
1173 Elf32_Addr word;
1174
1175 if ((Elf32_Sword)v > 0x7fff
1176 || (Elf32_Sword)v < -(Elf32_Sword)0x8000
1177 ) {
1178 ret = obj_reloc_overflow;
1179 }
1180
1181 word = *loc;
1182 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1183 (word & 0x3f);
1184 }
1185 break;
1186
1187 case R_NIOS2_U16:
1188 {
1189 Elf32_Addr word;
1190
1191 if (v > 0xffff) {
1192 ret = obj_reloc_overflow;
1193 }
1194
1195 word = *loc;
1196 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1197 (word & 0x3f);
1198 }
1199 break;
1200
1201 case R_NIOS2_PCREL16:
1202 {
1203 Elf32_Addr word;
1204
1205 v -= dot + 4;
1206 if ((Elf32_Sword)v > 0x7fff
1207 || (Elf32_Sword)v < -(Elf32_Sword)0x8000
1208 ) {
1209 ret = obj_reloc_overflow;
1210 }
1211
1212 word = *loc;
1213 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1214 }
1215 break;
1216
1217 case R_NIOS2_GPREL:
1218 {
1219 Elf32_Addr word, gp;
1220
1221 gp = obj_symbol_final_value(f, obj_find_symbol(f, SPFX "_gp"));
1222 v -= gp;
1223 if ((Elf32_Sword)v > 0x7fff
1224 || (Elf32_Sword)v < -(Elf32_Sword)0x8000
1225 ) {
1226 ret = obj_reloc_overflow;
1227 }
1228
1229 word = *loc;
1230 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1231 }
1232 break;
1233
1234 case R_NIOS2_CALL26:
1235 if (v & 3)
1236 ret = obj_reloc_dangerous;
1237 if ((v >> 28) != (dot >> 28))
1238 ret = obj_reloc_overflow;
1239 *loc = (*loc & 0x3f) | ((v >> 2) << 6);
1240 break;
1241
1242 case R_NIOS2_IMM5:
1243 {
1244 Elf32_Addr word;
1245
1246 if (v > 0x1f) {
1247 ret = obj_reloc_overflow;
1248 }
1249
1250 word = *loc & ~0x7c0;
1251 *loc = word | ((v & 0x1f) << 6);
1252 }
1253 break;
1254
1255 case R_NIOS2_IMM6:
1256 {
1257 Elf32_Addr word;
1258
1259 if (v > 0x3f) {
1260 ret = obj_reloc_overflow;
1261 }
1262
1263 word = *loc & ~0xfc0;
1264 *loc = word | ((v & 0x3f) << 6);
1265 }
1266 break;
1267
1268 case R_NIOS2_IMM8:
1269 {
1270 Elf32_Addr word;
1271
1272 if (v > 0xff) {
1273 ret = obj_reloc_overflow;
1274 }
1275
1276 word = *loc & ~0x3fc0;
1277 *loc = word | ((v & 0xff) << 6);
1278 }
1279 break;
1280
1281 case R_NIOS2_HI16:
1282 {
1283 Elf32_Addr word;
1284
1285 word = *loc;
1286 *loc = ((((word >> 22) << 16) | ((v >>16) & 0xffff)) << 6) |
1287 (word & 0x3f);
1288 }
1289 break;
1290
1291 case R_NIOS2_LO16:
1292 {
1293 Elf32_Addr word;
1294
1295 word = *loc;
1296 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1297 (word & 0x3f);
1298 }
1299 break;
1300
1301 case R_NIOS2_HIADJ16:
1302 {
1303 Elf32_Addr word1, word2;
1304
1305 word1 = *loc;
1306 word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff;
1307 *loc = ((((word1 >> 22) << 16) | word2) << 6) |
1308 (word1 & 0x3f);
1309 }
1310 break;
1311
1312#elif defined(__powerpc64__)
1313
1314
1315#elif defined(__powerpc__)
1316
1317 case R_PPC_ADDR16_HA:
1318 *(unsigned short *)loc = (v + 0x8000) >> 16;
1319 break;
1320
1321 case R_PPC_ADDR16_HI:
1322 *(unsigned short *)loc = v >> 16;
1323 break;
1324
1325 case R_PPC_ADDR16_LO:
1326 *(unsigned short *)loc = v;
1327 break;
1328
1329 case R_PPC_REL24:
1330 goto bb_use_plt;
1331
1332 case R_PPC_REL32:
1333 *loc = v - dot;
1334 break;
1335
1336 case R_PPC_ADDR32:
1337 *loc = v;
1338 break;
1339
1340#elif defined(__s390__)
1341
1342 case R_390_32:
1343 *(unsigned int *) loc += v;
1344 break;
1345 case R_390_16:
1346 *(unsigned short *) loc += v;
1347 break;
1348 case R_390_8:
1349 *(unsigned char *) loc += v;
1350 break;
1351
1352 case R_390_PC32:
1353 *(unsigned int *) loc += v - dot;
1354 break;
1355 case R_390_PC16DBL:
1356 *(unsigned short *) loc += (v - dot) >> 1;
1357 break;
1358 case R_390_PC16:
1359 *(unsigned short *) loc += v - dot;
1360 break;
1361
1362 case R_390_PLT32:
1363 case R_390_PLT16DBL:
1364
1365 pe = (struct arch_single_entry *) &isym->pltent;
1366 if (pe->inited == 0) {
1367 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
1368 ip[0] = 0x0d105810;
1369 ip[1] = 0x100607f1;
1370 if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1371 ip[2] = v - 2;
1372 else
1373 ip[2] = v;
1374 pe->inited = 1;
1375 }
1376
1377
1378 v = plt + pe->offset - dot;
1379 if (ELF_R_TYPE(rel->r_info) == R_390_PLT32)
1380 *(unsigned int *) loc = (unsigned int) v;
1381 else if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1382 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
1383 break;
1384
1385 case R_390_GLOB_DAT:
1386 case R_390_JMP_SLOT:
1387 *loc = v;
1388 break;
1389
1390 case R_390_RELATIVE:
1391 *loc += f->baseaddr;
1392 break;
1393
1394 case R_390_GOTPC:
1395 *(unsigned long *) loc += got - dot;
1396 break;
1397
1398 case R_390_GOT12:
1399 case R_390_GOT16:
1400 case R_390_GOT32:
1401 if (!isym->gotent.inited)
1402 {
1403 isym->gotent.inited = 1;
1404 *(ElfW(Addr) *)(ifile->got->contents + isym->gotent.offset) = v;
1405 }
1406 if (ELF_R_TYPE(rel->r_info) == R_390_GOT12)
1407 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
1408 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT16)
1409 *(unsigned short *) loc += isym->gotent.offset;
1410 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT32)
1411 *(unsigned int *) loc += isym->gotent.offset;
1412 break;
1413
1414# ifndef R_390_GOTOFF32
1415# define R_390_GOTOFF32 R_390_GOTOFF
1416# endif
1417 case R_390_GOTOFF32:
1418 *loc += v - got;
1419 break;
1420
1421#elif defined(__sh__)
1422
1423 case R_SH_NONE:
1424 break;
1425
1426 case R_SH_DIR32:
1427 *loc += v;
1428 break;
1429
1430 case R_SH_REL32:
1431 *loc += v - dot;
1432 break;
1433
1434 case R_SH_PLT32:
1435 *loc = v - dot;
1436 break;
1437
1438 case R_SH_GLOB_DAT:
1439 case R_SH_JMP_SLOT:
1440 *loc = v;
1441 break;
1442
1443 case R_SH_RELATIVE:
1444 *loc = f->baseaddr + rel->r_addend;
1445 break;
1446
1447 case R_SH_GOTPC:
1448 *loc = got - dot + rel->r_addend;
1449 break;
1450
1451 case R_SH_GOT32:
1452 goto bb_use_got;
1453
1454 case R_SH_GOTOFF:
1455 *loc = v - got;
1456 break;
1457
1458# if defined(__SH5__)
1459 case R_SH_IMM_MEDLOW16:
1460 case R_SH_IMM_LOW16:
1461 {
1462 ElfW(Addr) word;
1463
1464 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
1465 v >>= 16;
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475 word = *loc & ~0x3fffc00;
1476 word |= (v & 0xffff) << 10;
1477
1478 *loc = word;
1479
1480 break;
1481 }
1482
1483 case R_SH_IMM_MEDLOW16_PCREL:
1484 case R_SH_IMM_LOW16_PCREL:
1485 {
1486 ElfW(Addr) word;
1487
1488 word = *loc & ~0x3fffc00;
1489
1490 v -= dot;
1491
1492 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
1493 v >>= 16;
1494
1495 word |= (v & 0xffff) << 10;
1496
1497 *loc = word;
1498
1499 break;
1500 }
1501# endif
1502
1503#elif defined(__v850e__)
1504
1505 case R_V850_NONE:
1506 break;
1507
1508 case R_V850_32:
1509
1510
1511
1512 v += ((unsigned short *)loc)[0];
1513 v += ((unsigned short *)loc)[1] << 16;
1514 ((unsigned short *)loc)[0] = v & 0xffff;
1515 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1516 break;
1517
1518 case R_V850_22_PCREL:
1519 goto bb_use_plt;
1520
1521#elif defined(__x86_64__)
1522
1523 case R_X86_64_NONE:
1524 break;
1525
1526 case R_X86_64_64:
1527 *loc += v;
1528 break;
1529
1530 case R_X86_64_32:
1531 *(unsigned int *) loc += v;
1532 if (v > 0xffffffff)
1533 {
1534 ret = obj_reloc_overflow;
1535
1536 }
1537 break;
1538
1539 case R_X86_64_32S:
1540 *(signed int *) loc += v;
1541 break;
1542
1543 case R_X86_64_16:
1544 *(unsigned short *) loc += v;
1545 break;
1546
1547 case R_X86_64_8:
1548 *(unsigned char *) loc += v;
1549 break;
1550
1551 case R_X86_64_PC32:
1552 *(unsigned int *) loc += v - dot;
1553 break;
1554
1555 case R_X86_64_PC16:
1556 *(unsigned short *) loc += v - dot;
1557 break;
1558
1559 case R_X86_64_PC8:
1560 *(unsigned char *) loc += v - dot;
1561 break;
1562
1563 case R_X86_64_GLOB_DAT:
1564 case R_X86_64_JUMP_SLOT:
1565 *loc = v;
1566 break;
1567
1568 case R_X86_64_RELATIVE:
1569 *loc += f->baseaddr;
1570 break;
1571
1572 case R_X86_64_GOT32:
1573 case R_X86_64_GOTPCREL:
1574 goto bb_use_got;
1575# if 0
1576 if (!isym->gotent.reloc_done)
1577 {
1578 isym->gotent.reloc_done = 1;
1579 *(Elf64_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
1580 }
1581
1582 if (ELF64_R_TYPE(rel->r_info) == R_X86_64_GOTPCREL)
1583 *(unsigned int *) loc += v + isym->gotent.offset;
1584 else
1585 *loc += isym->gotent.offset;
1586 break;
1587# endif
1588
1589#else
1590# warning "no idea how to handle relocations on your arch"
1591#endif
1592
1593 default:
1594 printf("Warning: unhandled reloc %d\n", (int)ELF_R_TYPE(rel->r_info));
1595 ret = obj_reloc_unhandled;
1596 break;
1597
1598#if defined(USE_PLT_ENTRIES)
1599
1600bb_use_plt:
1601
1602
1603
1604#if defined(USE_PLT_LIST)
1605 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1606 pe = pe->next;
1607#else
1608 pe = &isym->pltent;
1609#endif
1610
1611 if (! pe->inited) {
1612 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
1613
1614
1615
1616#if defined(__arm__)
1617 ip[0] = 0xe51ff004;
1618 ip[1] = v;
1619#endif
1620#if defined(__powerpc__)
1621 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16);
1622 ip[1] = 0x396b0000 + (v & 0xffff);
1623 ip[2] = 0x7d6903a6;
1624 ip[3] = 0x4e800420;
1625#endif
1626#if defined(__v850e__)
1627
1628
1629
1630 ip[0] = 0x0621 + ((v & 0xffff) << 16);
1631 ip[1] = ((v >> 16) & 0xffff) + 0x610000;
1632#endif
1633 pe->inited = 1;
1634 }
1635
1636
1637 v -= dot;
1638
1639#if defined(__arm__) || defined(__powerpc__)
1640 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
1641#elif defined(__v850e__)
1642 if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000)
1643#endif
1644
1645 v = plt + pe->offset - dot;
1646
1647#if defined(__v850e__)
1648 if (v & 1)
1649#else
1650 if (v & 3)
1651#endif
1652 ret = obj_reloc_dangerous;
1653
1654
1655#if defined(__arm__)
1656
1657 v >>= 2;
1658
1659 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
1660#endif
1661#if defined(__powerpc__)
1662 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
1663#endif
1664#if defined(__v850e__)
1665
1666
1667
1668 ((unsigned short *)loc)[0] =
1669 (*(unsigned short *)loc & 0xffc0)
1670 | ((v >> 16) & 0x3f);
1671 ((unsigned short *)loc)[1] =
1672 (v & 0xffff);
1673#endif
1674 break;
1675#endif
1676
1677#if defined(USE_GOT_ENTRIES)
1678bb_use_got:
1679
1680
1681 if (!isym->gotent.inited) {
1682 isym->gotent.inited = 1;
1683 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1684 }
1685
1686#if defined(__sh__)
1687 *loc += isym->gotent.offset + rel->r_addend;
1688#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
1689 *loc += isym->gotent.offset;
1690#endif
1691 break;
1692
1693#endif
1694 }
1695
1696 return ret;
1697}
1698
1699
1700#if defined(USE_LIST)
1701
1702static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1703 int offset, int size)
1704{
1705 struct arch_list_entry *pe;
1706
1707 for (pe = *list; pe != NULL; pe = pe->next) {
1708 if (pe->addend == rel->r_addend) {
1709 break;
1710 }
1711 }
1712
1713 if (pe == NULL) {
1714 pe = xzalloc(sizeof(struct arch_list_entry));
1715 pe->next = *list;
1716 pe->addend = rel->r_addend;
1717 pe->offset = offset;
1718
1719 *list = pe;
1720 return size;
1721 }
1722 return 0;
1723}
1724
1725#endif
1726
1727#if defined(USE_SINGLE)
1728
1729static int arch_single_init( struct arch_single_entry *single,
1730 int offset, int size)
1731{
1732 if (single->allocated == 0) {
1733 single->allocated = 1;
1734 single->offset = offset;
1735 single->inited = 0;
1736 return size;
1737 }
1738 return 0;
1739}
1740
1741#endif
1742
1743#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
1744
1745static struct obj_section *arch_xsect_init(struct obj_file *f, const char *name,
1746 int offset, int size)
1747{
1748 struct obj_section *myrelsec = obj_find_section(f, name);
1749
1750 if (offset == 0) {
1751 offset += size;
1752 }
1753
1754 if (myrelsec) {
1755 obj_extend_section(myrelsec, offset);
1756 } else {
1757 myrelsec = obj_create_alloced_section(f, name,
1758 size, offset);
1759 }
1760
1761 return myrelsec;
1762}
1763
1764#endif
1765
1766static void arch_create_got(struct obj_file *f)
1767{
1768#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
1769 struct arch_file *ifile = (struct arch_file *) f;
1770 int i;
1771#if defined(USE_GOT_ENTRIES)
1772 int got_offset = 0, got_needed = 0, got_allocate;
1773#endif
1774#if defined(USE_PLT_ENTRIES)
1775 int plt_offset = 0, plt_needed = 0, plt_allocate;
1776#endif
1777 struct obj_section *relsec, *symsec, *strsec;
1778 ElfW(RelM) *rel, *relend;
1779 ElfW(Sym) *symtab, *extsym;
1780 const char *strtab, *name;
1781 struct arch_symbol *intsym;
1782
1783 for (i = 0; i < f->header.e_shnum; ++i) {
1784 relsec = f->sections[i];
1785 if (relsec->header.sh_type != SHT_RELM)
1786 continue;
1787
1788 symsec = f->sections[relsec->header.sh_link];
1789 strsec = f->sections[symsec->header.sh_link];
1790
1791 rel = (ElfW(RelM) *) relsec->contents;
1792 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1793 symtab = (ElfW(Sym) *) symsec->contents;
1794 strtab = (const char *) strsec->contents;
1795
1796 for (; rel < relend; ++rel) {
1797 extsym = &symtab[ELF_R_SYM(rel->r_info)];
1798
1799#if defined(USE_GOT_ENTRIES)
1800 got_allocate = 0;
1801#endif
1802#if defined(USE_PLT_ENTRIES)
1803 plt_allocate = 0;
1804#endif
1805
1806 switch (ELF_R_TYPE(rel->r_info)) {
1807#if defined(__arm__)
1808 case R_ARM_PC24:
1809 case R_ARM_PLT32:
1810 plt_allocate = 1;
1811 break;
1812
1813 case R_ARM_GOTOFF:
1814 case R_ARM_GOTPC:
1815 got_needed = 1;
1816 continue;
1817
1818 case R_ARM_GOT32:
1819 got_allocate = 1;
1820 break;
1821
1822#elif defined(__i386__)
1823 case R_386_GOTPC:
1824 case R_386_GOTOFF:
1825 got_needed = 1;
1826 continue;
1827
1828 case R_386_GOT32:
1829 got_allocate = 1;
1830 break;
1831
1832#elif defined(__powerpc__)
1833 case R_PPC_REL24:
1834 plt_allocate = 1;
1835 break;
1836
1837#elif defined(__mc68000__)
1838 case R_68K_GOT32:
1839 got_allocate = 1;
1840 break;
1841
1842#ifdef R_68K_GOTOFF
1843 case R_68K_GOTOFF:
1844 got_needed = 1;
1845 continue;
1846#endif
1847
1848#elif defined(__sh__)
1849 case R_SH_GOT32:
1850 got_allocate = 1;
1851 break;
1852
1853 case R_SH_GOTPC:
1854 case R_SH_GOTOFF:
1855 got_needed = 1;
1856 continue;
1857
1858#elif defined(__v850e__)
1859 case R_V850_22_PCREL:
1860 plt_needed = 1;
1861 break;
1862
1863#endif
1864 default:
1865 continue;
1866 }
1867
1868 if (extsym->st_name != 0) {
1869 name = strtab + extsym->st_name;
1870 } else {
1871 name = f->sections[extsym->st_shndx]->name;
1872 }
1873 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
1874#if defined(USE_GOT_ENTRIES)
1875 if (got_allocate) {
1876 got_offset += arch_single_init(
1877 &intsym->gotent,
1878 got_offset, GOT_ENTRY_SIZE);
1879
1880 got_needed = 1;
1881 }
1882#endif
1883#if defined(USE_PLT_ENTRIES)
1884 if (plt_allocate) {
1885#if defined(USE_PLT_LIST)
1886 plt_offset += arch_list_add(
1887 rel, &intsym->pltent,
1888 plt_offset, PLT_ENTRY_SIZE);
1889#else
1890 plt_offset += arch_single_init(
1891 &intsym->pltent,
1892 plt_offset, PLT_ENTRY_SIZE);
1893#endif
1894 plt_needed = 1;
1895 }
1896#endif
1897 }
1898 }
1899
1900#if defined(USE_GOT_ENTRIES)
1901 if (got_needed) {
1902 ifile->got = arch_xsect_init(f, ".got", got_offset,
1903 GOT_ENTRY_SIZE);
1904 }
1905#endif
1906
1907#if defined(USE_PLT_ENTRIES)
1908 if (plt_needed) {
1909 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
1910 PLT_ENTRY_SIZE);
1911 }
1912#endif
1913
1914#endif
1915}
1916
1917
1918
1919
1920static unsigned long obj_elf_hash_n(const char *name, unsigned long n)
1921{
1922 unsigned long h = 0;
1923 unsigned long g;
1924 unsigned char ch;
1925
1926 while (n > 0) {
1927 ch = *name++;
1928 h = (h << 4) + ch;
1929 g = (h & 0xf0000000);
1930 if (g != 0) {
1931 h ^= g >> 24;
1932 h &= ~g;
1933 }
1934 n--;
1935 }
1936 return h;
1937}
1938
1939static unsigned long FAST_FUNC obj_elf_hash(const char *name)
1940{
1941 return obj_elf_hash_n(name, strlen(name));
1942}
1943
1944#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
1945
1946
1947static int ncv_strcmp(const char *a, const char *b)
1948{
1949 size_t alen = strlen(a), blen = strlen(b);
1950
1951 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1952 return strncmp(a, b, alen);
1953 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1954 return strncmp(a, b, blen);
1955 else
1956 return strcmp(a, b);
1957}
1958
1959
1960
1961
1962static unsigned long FAST_FUNC ncv_symbol_hash(const char *str)
1963{
1964 size_t len = strlen(str);
1965 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1966 len -= 10;
1967 return obj_elf_hash_n(str, len);
1968}
1969
1970static void
1971obj_set_symbol_compare(struct obj_file *f,
1972 int (*cmp) (const char *, const char *),
1973 unsigned long (*hash) (const char *) FAST_FUNC)
1974{
1975 if (cmp)
1976 f->symbol_cmp = cmp;
1977 if (hash) {
1978 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1979 int i;
1980
1981 f->symbol_hash = hash;
1982
1983 memcpy(tmptab, f->symtab, sizeof(tmptab));
1984 memset(f->symtab, 0, sizeof(f->symtab));
1985
1986 for (i = 0; i < HASH_BUCKETS; ++i) {
1987 for (sym = tmptab[i]; sym; sym = next) {
1988 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1989 next = sym->next;
1990 sym->next = f->symtab[h];
1991 f->symtab[h] = sym;
1992 }
1993 }
1994 }
1995}
1996
1997#endif
1998
1999static struct obj_symbol *
2000obj_add_symbol(struct obj_file *f, const char *name,
2001 unsigned long symidx, int info,
2002 int secidx, ElfW(Addr) value,
2003 unsigned long size)
2004{
2005 struct obj_symbol *sym;
2006 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
2007 int n_type = ELF_ST_TYPE(info);
2008 int n_binding = ELF_ST_BIND(info);
2009
2010 for (sym = f->symtab[hash]; sym; sym = sym->next) {
2011 if (f->symbol_cmp(sym->name, name) == 0) {
2012 int o_secidx = sym->secidx;
2013 int o_info = sym->info;
2014 int o_type = ELF_ST_TYPE(o_info);
2015 int o_binding = ELF_ST_BIND(o_info);
2016
2017
2018
2019 if (secidx == SHN_UNDEF)
2020 return sym;
2021 else if (o_secidx == SHN_UNDEF)
2022 goto found;
2023 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
2024
2025
2026
2027
2028
2029
2030 struct obj_symbol *nsym, **p;
2031
2032 nsym = arch_new_symbol();
2033 nsym->next = sym->next;
2034 nsym->ksymidx = -1;
2035
2036
2037 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
2038 continue;
2039 *p = sym = nsym;
2040 goto found;
2041 } else if (n_binding == STB_LOCAL) {
2042
2043
2044 sym = arch_new_symbol();
2045 sym->next = NULL;
2046 sym->ksymidx = -1;
2047 f->local_symtab[symidx] = sym;
2048 goto found;
2049 } else if (n_binding == STB_WEAK)
2050 return sym;
2051 else if (o_binding == STB_WEAK)
2052 goto found;
2053
2054
2055 else if (secidx == SHN_COMMON
2056 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
2057 return sym;
2058 else if (o_secidx == SHN_COMMON
2059 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
2060 goto found;
2061 else {
2062
2063
2064 if (secidx <= SHN_HIRESERVE)
2065 bb_error_msg("%s multiply defined", name);
2066 return sym;
2067 }
2068 }
2069 }
2070
2071
2072 sym = arch_new_symbol();
2073 sym->next = f->symtab[hash];
2074 f->symtab[hash] = sym;
2075 sym->ksymidx = -1;
2076 if (ELF_ST_BIND(info) == STB_LOCAL && symidx != (unsigned long)(-1)) {
2077 if (symidx >= f->local_symtab_size)
2078 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
2079 name, (long) symidx, (long) f->local_symtab_size);
2080 else
2081 f->local_symtab[symidx] = sym;
2082 }
2083
2084found:
2085 sym->name = name;
2086 sym->value = value;
2087 sym->size = size;
2088 sym->secidx = secidx;
2089 sym->info = info;
2090
2091 return sym;
2092}
2093
2094static struct obj_symbol *
2095obj_find_symbol(struct obj_file *f, const char *name)
2096{
2097 struct obj_symbol *sym;
2098 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
2099
2100 for (sym = f->symtab[hash]; sym; sym = sym->next)
2101 if (f->symbol_cmp(sym->name, name) == 0)
2102 return sym;
2103 return NULL;
2104}
2105
2106static ElfW(Addr) obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
2107{
2108 if (sym) {
2109 if (sym->secidx >= SHN_LORESERVE)
2110 return sym->value;
2111 return sym->value + f->sections[sym->secidx]->header.sh_addr;
2112 }
2113
2114 return 0;
2115}
2116
2117static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
2118{
2119 int i, n = f->header.e_shnum;
2120
2121 for (i = 0; i < n; ++i)
2122 if (strcmp(f->sections[i]->name, name) == 0)
2123 return f->sections[i];
2124 return NULL;
2125}
2126
2127static int obj_load_order_prio(struct obj_section *a)
2128{
2129 unsigned long af, ac;
2130
2131 af = a->header.sh_flags;
2132
2133 ac = 0;
2134 if (a->name[0] != '.' || strlen(a->name) != 10
2135 || strcmp(a->name + 5, ".init") != 0
2136 ) {
2137 ac |= 32;
2138 }
2139 if (af & SHF_ALLOC)
2140 ac |= 16;
2141 if (!(af & SHF_WRITE))
2142 ac |= 8;
2143 if (af & SHF_EXECINSTR)
2144 ac |= 4;
2145 if (a->header.sh_type != SHT_NOBITS)
2146 ac |= 2;
2147
2148 return ac;
2149}
2150
2151static void
2152obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
2153{
2154 struct obj_section **p;
2155 int prio = obj_load_order_prio(sec);
2156 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
2157 if (obj_load_order_prio(*p) < prio)
2158 break;
2159 sec->load_next = *p;
2160 *p = sec;
2161}
2162
2163static struct obj_section *helper_create_alloced_section(struct obj_file *f,
2164 const char *name,
2165 unsigned long align,
2166 unsigned long size)
2167{
2168 int newidx = f->header.e_shnum++;
2169 struct obj_section *sec;
2170
2171 f->sections = xrealloc_vector(f->sections, 2, newidx);
2172 f->sections[newidx] = sec = arch_new_section();
2173
2174 sec->header.sh_type = SHT_PROGBITS;
2175 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2176 sec->header.sh_size = size;
2177 sec->header.sh_addralign = align;
2178 sec->name = name;
2179 sec->idx = newidx;
2180 if (size)
2181 sec->contents = xzalloc(size);
2182
2183 return sec;
2184}
2185
2186static struct obj_section *obj_create_alloced_section(struct obj_file *f,
2187 const char *name,
2188 unsigned long align,
2189 unsigned long size)
2190{
2191 struct obj_section *sec;
2192
2193 sec = helper_create_alloced_section(f, name, align, size);
2194 obj_insert_section_load_order(f, sec);
2195 return sec;
2196}
2197
2198static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
2199 const char *name,
2200 unsigned long align,
2201 unsigned long size)
2202{
2203 struct obj_section *sec;
2204
2205 sec = helper_create_alloced_section(f, name, align, size);
2206 sec->load_next = f->load_order;
2207 f->load_order = sec;
2208 if (f->load_order_search_start == &f->load_order)
2209 f->load_order_search_start = &sec->load_next;
2210
2211 return sec;
2212}
2213
2214static void *obj_extend_section(struct obj_section *sec, unsigned long more)
2215{
2216 unsigned long oldsize = sec->header.sh_size;
2217 if (more) {
2218 sec->header.sh_size += more;
2219 sec->contents = xrealloc(sec->contents, sec->header.sh_size);
2220 }
2221 return sec->contents + oldsize;
2222}
2223
2224
2225
2226
2227
2228static int add_symbols_from(struct obj_file *f,
2229 int idx,
2230 struct new_module_symbol *syms,
2231 size_t nsyms)
2232{
2233 struct new_module_symbol *s;
2234 size_t i;
2235 int used = 0;
2236#ifdef SYMBOL_PREFIX
2237 char *name_buf = NULL;
2238 size_t name_alloced_size = 0;
2239#endif
2240#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
2241 int gpl;
2242
2243 gpl = obj_gpl_license(f, NULL) == 0;
2244#endif
2245 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
2246
2247
2248
2249
2250 struct obj_symbol *sym;
2251 char *name;
2252
2253
2254
2255
2256
2257
2258
2259 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
2260#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
2261 if (gpl)
2262 s->name += 8;
2263 else
2264#endif
2265 continue;
2266 }
2267 name = (char *)s->name;
2268
2269#ifdef SYMBOL_PREFIX
2270
2271
2272
2273 size_t extra = sizeof SYMBOL_PREFIX;
2274 size_t name_size = strlen(name) + extra;
2275 if (name_size > name_alloced_size) {
2276 name_alloced_size = name_size * 2;
2277 name_buf = alloca(name_alloced_size);
2278 }
2279 strcpy(name_buf, SYMBOL_PREFIX);
2280 strcpy(name_buf + extra - 1, name);
2281 name = name_buf;
2282#endif
2283
2284 sym = obj_find_symbol(f, name);
2285 if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
2286#ifdef SYMBOL_PREFIX
2287
2288 name = xmalloc(name_size);
2289 strcpy(name, name_buf);
2290#endif
2291 sym = obj_add_symbol(f, name, -1,
2292 ELF_ST_INFO(STB_GLOBAL,
2293 STT_NOTYPE),
2294 idx, s->value, 0);
2295
2296
2297 if (sym->secidx == idx)
2298 used = 1;
2299 }
2300 }
2301
2302 return used;
2303}
2304
2305static void add_kernel_symbols(struct obj_file *f)
2306{
2307 struct external_module *m;
2308 int i, nused = 0;
2309
2310
2311
2312 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m) {
2313 if (m->nsyms
2314 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms, m->nsyms)
2315 ) {
2316 m->used = 1;
2317 ++nused;
2318 }
2319 }
2320
2321 n_ext_modules_used = nused;
2322
2323
2324
2325 if (nksyms)
2326 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2327}
2328
2329static char *get_modinfo_value(struct obj_file *f, const char *key)
2330{
2331 struct obj_section *sec;
2332 char *p, *v, *n, *ep;
2333 size_t klen = strlen(key);
2334
2335 sec = obj_find_section(f, ".modinfo");
2336 if (sec == NULL)
2337 return NULL;
2338 p = sec->contents;
2339 ep = p + sec->header.sh_size;
2340 while (p < ep) {
2341 v = strchr(p, '=');
2342 n = strchr(p, '\0');
2343 if (v) {
2344 if (p + klen == v && strncmp(p, key, klen) == 0)
2345 return v + 1;
2346 } else {
2347 if (p + klen == n && strcmp(p, key) == 0)
2348 return n;
2349 }
2350 p = n + 1;
2351 }
2352
2353 return NULL;
2354}
2355
2356
2357
2358
2359
2360
2361
2362
2363static char *next_arg(char *args, char **param, char **val)
2364{
2365 unsigned int i, equals = 0;
2366 int in_quote = 0, quoted = 0;
2367 char *next;
2368
2369 if (*args == '"') {
2370 args++;
2371 in_quote = 1;
2372 quoted = 1;
2373 }
2374
2375 for (i = 0; args[i]; i++) {
2376 if (args[i] == ' ' && !in_quote)
2377 break;
2378 if (equals == 0) {
2379 if (args[i] == '=')
2380 equals = i;
2381 }
2382 if (args[i] == '"')
2383 in_quote = !in_quote;
2384 }
2385
2386 *param = args;
2387 if (!equals)
2388 *val = NULL;
2389 else {
2390 args[equals] = '\0';
2391 *val = args + equals + 1;
2392
2393
2394 if (**val == '"') {
2395 (*val)++;
2396 if (args[i-1] == '"')
2397 args[i-1] = '\0';
2398 }
2399 if (quoted && args[i-1] == '"')
2400 args[i-1] = '\0';
2401 }
2402
2403 if (args[i]) {
2404 args[i] = '\0';
2405 next = args + i + 1;
2406 } else
2407 next = args + i;
2408
2409
2410 return skip_whitespace(next);
2411}
2412
2413static void
2414new_process_module_arguments(struct obj_file *f, const char *options)
2415{
2416 char *xoptions, *pos;
2417 char *param, *val;
2418
2419 xoptions = pos = xstrdup(skip_whitespace(options));
2420 while (*pos) {
2421 unsigned long charssize = 0;
2422 char *tmp, *contents, *loc, *pinfo, *p;
2423 struct obj_symbol *sym;
2424 int min, max, n, len;
2425
2426 pos = next_arg(pos, ¶m, &val);
2427
2428 tmp = xasprintf("parm_%s", param);
2429 pinfo = get_modinfo_value(f, tmp);
2430 free(tmp);
2431 if (pinfo == NULL)
2432 bb_error_msg_and_die("invalid parameter %s", param);
2433
2434#ifdef SYMBOL_PREFIX
2435 tmp = xasprintf(SYMBOL_PREFIX "%s", param);
2436 sym = obj_find_symbol(f, tmp);
2437 free(tmp);
2438#else
2439 sym = obj_find_symbol(f, param);
2440#endif
2441
2442
2443 if (sym == NULL || sym->secidx > SHN_HIRESERVE)
2444 bb_error_msg_and_die("symbol for parameter %s not found", param);
2445
2446
2447 if (isdigit(*pinfo)) {
2448 min = strtoul(pinfo, &pinfo, 10);
2449 if (*pinfo == '-')
2450 max = strtoul(pinfo + 1, &pinfo, 10);
2451 else
2452 max = min;
2453 } else
2454 min = max = 1;
2455
2456 contents = f->sections[sym->secidx]->contents;
2457 loc = contents + sym->value;
2458
2459 if (*pinfo == 'c') {
2460 if (!isdigit(pinfo[1])) {
2461 bb_error_msg_and_die("parameter type 'c' for %s must be followed by"
2462 " the maximum size", param);
2463 }
2464 charssize = strtoul(pinfo + 1, NULL, 10);
2465 }
2466
2467 if (val == NULL) {
2468 if (*pinfo != 'b')
2469 bb_error_msg_and_die("argument expected for parameter %s", param);
2470 val = (char *) "1";
2471 }
2472
2473
2474 n = 0;
2475 p = val;
2476 while (*p != 0) {
2477 char *endp;
2478
2479 if (++n > max)
2480 bb_error_msg_and_die("too many values for %s (max %d)", param, max);
2481
2482 switch (*pinfo) {
2483 case 's':
2484 len = strcspn(p, ",");
2485 p[len] = 0;
2486 obj_string_patch(f, sym->secidx,
2487 loc - contents, p);
2488 loc += tgt_sizeof_char_p;
2489 p += len;
2490 break;
2491 case 'c':
2492 len = strcspn(p, ",");
2493 p[len] = 0;
2494 if (len >= charssize)
2495 bb_error_msg_and_die("string too long for %s (max %ld)", param,
2496 charssize - 1);
2497 strcpy((char *) loc, p);
2498 loc += charssize;
2499 p += len;
2500 break;
2501 case 'b':
2502 *loc++ = strtoul(p, &endp, 0);
2503 p = endp;
2504 break;
2505 case 'h':
2506 *(short *) loc = strtoul(p, &endp, 0);
2507 loc += tgt_sizeof_short;
2508 p = endp;
2509 break;
2510 case 'i':
2511 *(int *) loc = strtoul(p, &endp, 0);
2512 loc += tgt_sizeof_int;
2513 p = endp;
2514 break;
2515 case 'l':
2516 *(long *) loc = strtoul(p, &endp, 0);
2517 loc += tgt_sizeof_long;
2518 p = endp;
2519 break;
2520 default:
2521 bb_error_msg_and_die("unknown parameter type '%c' for %s",
2522 *pinfo, param);
2523 }
2524
2525 p = skip_whitespace(p);
2526 if (*p != ',')
2527 break;
2528 p = skip_whitespace(p + 1);
2529 }
2530
2531 if (n < min)
2532 bb_error_msg_and_die("parameter %s requires at least %d arguments", param, min);
2533 if (*p != '\0')
2534 bb_error_msg_and_die("invalid argument syntax for %s", param);
2535 }
2536
2537 free(xoptions);
2538}
2539
2540#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
2541static int new_is_module_checksummed(struct obj_file *f)
2542{
2543 const char *p = get_modinfo_value(f, "using_checksums");
2544 if (p)
2545 return xatoi(p);
2546 return 0;
2547}
2548
2549
2550
2551static int
2552new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2553{
2554 char *p, *q;
2555 int a, b, c;
2556
2557 p = get_modinfo_value(f, "kernel_version");
2558 if (p == NULL)
2559 return -1;
2560 safe_strncpy(str, p, STRVERSIONLEN);
2561
2562 a = strtoul(p, &p, 10);
2563 if (*p != '.')
2564 return -1;
2565 b = strtoul(p + 1, &p, 10);
2566 if (*p != '.')
2567 return -1;
2568 c = strtoul(p + 1, &q, 10);
2569 if (p + 1 == q)
2570 return -1;
2571
2572 return a << 16 | b << 8 | c;
2573}
2574
2575#endif
2576
2577
2578
2579
2580static void new_get_kernel_symbols(void)
2581{
2582 char *module_names, *mn;
2583 struct external_module *modules, *m;
2584 struct new_module_symbol *syms, *s;
2585 size_t ret, bufsize, nmod, nsyms, i, j;
2586
2587
2588
2589 bufsize = 256;
2590 module_names = xmalloc(bufsize);
2591
2592 retry_modules_load:
2593 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
2594 if (errno == ENOSPC && bufsize < ret) {
2595 bufsize = ret;
2596 module_names = xrealloc(module_names, bufsize);
2597 goto retry_modules_load;
2598 }
2599 bb_perror_msg_and_die("QM_MODULES");
2600 }
2601
2602 n_ext_modules = nmod = ret;
2603
2604
2605
2606 if (nmod) {
2607 ext_modules = modules = xzalloc(nmod * sizeof(*modules));
2608 for (i = 0, mn = module_names, m = modules;
2609 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
2610 struct new_module_info info;
2611
2612 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2613 if (errno == ENOENT) {
2614
2615 continue;
2616 }
2617 bb_perror_msg_and_die("query_module: QM_INFO: %s", mn);
2618 }
2619
2620 bufsize = 1024;
2621 syms = xmalloc(bufsize);
2622 retry_mod_sym_load:
2623 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2624 switch (errno) {
2625 case ENOSPC:
2626 bufsize = ret;
2627 syms = xrealloc(syms, bufsize);
2628 goto retry_mod_sym_load;
2629 case ENOENT:
2630
2631 continue;
2632 default:
2633 bb_perror_msg_and_die("query_module: QM_SYMBOLS: %s", mn);
2634 }
2635 }
2636 nsyms = ret;
2637
2638 m->name = mn;
2639 m->addr = info.addr;
2640 m->nsyms = nsyms;
2641 m->syms = syms;
2642
2643 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2644 s->name += (unsigned long) syms;
2645 }
2646 }
2647 }
2648
2649
2650
2651 bufsize = 16 * 1024;
2652 syms = xmalloc(bufsize);
2653 retry_kern_sym_load:
2654 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
2655 if (errno == ENOSPC && bufsize < ret) {
2656 bufsize = ret;
2657 syms = xrealloc(syms, bufsize);
2658 goto retry_kern_sym_load;
2659 }
2660 bb_perror_msg_and_die("kernel: QM_SYMBOLS");
2661 }
2662 nksyms = nsyms = ret;
2663 ksyms = syms;
2664
2665 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2666 s->name += (unsigned long) syms;
2667 }
2668}
2669
2670
2671
2672
2673static int new_is_kernel_checksummed(void)
2674{
2675 struct new_module_symbol *s;
2676 size_t i;
2677
2678
2679
2680 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2681 if (strcmp((char *) s->name, "Using_Versions") == 0)
2682 return s->value;
2683
2684 return 0;
2685}
2686
2687
2688static void new_create_this_module(struct obj_file *f, const char *m_name)
2689{
2690 struct obj_section *sec;
2691
2692 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
2693 sizeof(struct new_module));
2694
2695
2696
2697 obj_add_symbol(f, SPFX "__this_module", -1,
2698 ELF_ST_INFO(STB_LOCAL, STT_OBJECT), sec->idx, 0,
2699 sizeof(struct new_module));
2700
2701 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
2702 m_name);
2703}
2704
2705#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
2706
2707static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2708{
2709 struct obj_section *sec;
2710 ElfW(Addr) ofs;
2711
2712
2713
2714
2715
2716
2717 sec = obj_find_section(f, "__ksymtab");
2718 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2719 *((char *)(sec->name)) = 'x';
2720 sec = NULL;
2721 }
2722 if (!sec)
2723 sec = obj_create_alloced_section(f, "__ksymtab",
2724 tgt_sizeof_void_p, 0);
2725 if (!sec)
2726 return;
2727 sec->header.sh_flags |= SHF_ALLOC;
2728
2729 sec->header.sh_addralign = tgt_sizeof_void_p;
2730 ofs = sec->header.sh_size;
2731 obj_symbol_patch(f, sec->idx, ofs, sym);
2732 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2733 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2734}
2735#endif
2736
2737static int new_create_module_ksymtab(struct obj_file *f)
2738{
2739 struct obj_section *sec;
2740 int i;
2741
2742
2743
2744 if (n_ext_modules_used) {
2745 struct new_module_ref *dep;
2746 struct obj_symbol *tm;
2747
2748 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
2749 (sizeof(struct new_module_ref)
2750 * n_ext_modules_used));
2751 if (!sec)
2752 return 0;
2753
2754 tm = obj_find_symbol(f, SPFX "__this_module");
2755 dep = (struct new_module_ref *) sec->contents;
2756 for (i = 0; i < n_ext_modules; ++i)
2757 if (ext_modules[i].used) {
2758 dep->dep = ext_modules[i].addr;
2759 obj_symbol_patch(f, sec->idx,
2760 (char *) &dep->ref - sec->contents, tm);
2761 dep->next_ref = 0;
2762 ++dep;
2763 }
2764 }
2765
2766 if (!flag_noexport && !obj_find_section(f, "__ksymtab")) {
2767 size_t nsyms;
2768 int *loaded;
2769
2770 sec = obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p, 0);
2771
2772
2773
2774
2775 i = f->header.e_shnum;
2776 loaded = alloca(sizeof(int) * i);
2777 while (--i >= 0)
2778 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2779
2780 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2781 struct obj_symbol *sym;
2782 for (sym = f->symtab[i]; sym; sym = sym->next) {
2783 if (ELF_ST_BIND(sym->info) != STB_LOCAL
2784 && sym->secidx <= SHN_HIRESERVE
2785 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx])
2786 ) {
2787 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2788
2789 obj_symbol_patch(f, sec->idx, ofs, sym);
2790 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
2791 sym->name);
2792 nsyms++;
2793 }
2794 }
2795 }
2796
2797 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2798 }
2799
2800 return 1;
2801}
2802
2803
2804static int
2805new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
2806{
2807 struct new_module *module;
2808 struct obj_section *sec;
2809 void *image;
2810 int ret;
2811 tgt_long m_addr;
2812
2813 sec = obj_find_section(f, ".this");
2814 if (!sec || !sec->contents) {
2815 bb_perror_msg_and_die("corrupt module %s?", m_name);
2816 }
2817 module = (struct new_module *) sec->contents;
2818 m_addr = sec->header.sh_addr;
2819
2820 module->size_of_struct = sizeof(*module);
2821 module->size = m_size;
2822 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2823
2824 sec = obj_find_section(f, "__ksymtab");
2825 if (sec && sec->header.sh_size) {
2826 module->syms = sec->header.sh_addr;
2827 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2828 }
2829
2830 if (n_ext_modules_used) {
2831 sec = obj_find_section(f, ".kmodtab");
2832 module->deps = sec->header.sh_addr;
2833 module->ndeps = n_ext_modules_used;
2834 }
2835
2836 module->init = obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
2837 module->cleanup = obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
2838
2839 sec = obj_find_section(f, "__ex_table");
2840 if (sec) {
2841 module->ex_table_start = sec->header.sh_addr;
2842 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2843 }
2844
2845 sec = obj_find_section(f, ".text.init");
2846 if (sec) {
2847 module->runsize = sec->header.sh_addr - m_addr;
2848 }
2849 sec = obj_find_section(f, ".data.init");
2850 if (sec) {
2851 if (!module->runsize
2852 || module->runsize > sec->header.sh_addr - m_addr
2853 ) {
2854 module->runsize = sec->header.sh_addr - m_addr;
2855 }
2856 }
2857 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2858 if (sec && sec->header.sh_size) {
2859 module->archdata_start = (void*)sec->header.sh_addr;
2860 module->archdata_end = module->archdata_start + sec->header.sh_size;
2861 }
2862 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2863 if (sec && sec->header.sh_size) {
2864 module->kallsyms_start = (void*)sec->header.sh_addr;
2865 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2866 }
2867
2868
2869
2870
2871 image = xmalloc(m_size);
2872 obj_create_image(f, image);
2873
2874 ret = init_module(m_name, (struct new_module *) image);
2875 if (ret)
2876 bb_perror_msg("init_module: %s", m_name);
2877
2878 free(image);
2879
2880 return ret == 0;
2881}
2882
2883
2884
2885
2886static void
2887obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2888 const char *string)
2889{
2890 struct obj_string_patch *p;
2891 struct obj_section *strsec;
2892 size_t len = strlen(string) + 1;
2893 char *loc;
2894
2895 p = xzalloc(sizeof(*p));
2896 p->next = f->string_patches;
2897 p->reloc_secidx = secidx;
2898 p->reloc_offset = offset;
2899 f->string_patches = p;
2900
2901 strsec = obj_find_section(f, ".kstrtab");
2902 if (strsec == NULL) {
2903 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2904
2905 loc = strsec->contents;
2906 } else {
2907 p->string_offset = strsec->header.sh_size;
2908 loc = obj_extend_section(strsec, len);
2909 }
2910 memcpy(loc, string, len);
2911}
2912
2913static void
2914obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2915 struct obj_symbol *sym)
2916{
2917 struct obj_symbol_patch *p;
2918
2919 p = xmalloc(sizeof(*p));
2920 p->next = f->symbol_patches;
2921 p->reloc_secidx = secidx;
2922 p->reloc_offset = offset;
2923 p->sym = sym;
2924 f->symbol_patches = p;
2925}
2926
2927static void obj_check_undefineds(struct obj_file *f)
2928{
2929 unsigned i;
2930
2931 for (i = 0; i < HASH_BUCKETS; ++i) {
2932 struct obj_symbol *sym;
2933 for (sym = f->symtab[i]; sym; sym = sym->next) {
2934 if (sym->secidx == SHN_UNDEF) {
2935 if (ELF_ST_BIND(sym->info) == STB_WEAK) {
2936 sym->secidx = SHN_ABS;
2937 sym->value = 0;
2938 } else {
2939 if (!flag_quiet)
2940 bb_error_msg_and_die("unresolved symbol %s", sym->name);
2941 }
2942 }
2943 }
2944 }
2945}
2946
2947static void obj_allocate_commons(struct obj_file *f)
2948{
2949 struct common_entry {
2950 struct common_entry *next;
2951 struct obj_symbol *sym;
2952 } *common_head = NULL;
2953
2954 unsigned long i;
2955
2956 for (i = 0; i < HASH_BUCKETS; ++i) {
2957 struct obj_symbol *sym;
2958 for (sym = f->symtab[i]; sym; sym = sym->next) {
2959 if (sym->secidx == SHN_COMMON) {
2960
2961
2962 struct common_entry **p, *n;
2963 for (p = &common_head; *p; p = &(*p)->next)
2964 if (sym->size <= (*p)->sym->size)
2965 break;
2966 n = alloca(sizeof(*n));
2967 n->next = *p;
2968 n->sym = sym;
2969 *p = n;
2970 }
2971 }
2972 }
2973
2974 for (i = 1; i < f->local_symtab_size; ++i) {
2975 struct obj_symbol *sym = f->local_symtab[i];
2976 if (sym && sym->secidx == SHN_COMMON) {
2977 struct common_entry **p, *n;
2978 for (p = &common_head; *p; p = &(*p)->next) {
2979 if (sym == (*p)->sym)
2980 break;
2981 if (sym->size < (*p)->sym->size) {
2982 n = alloca(sizeof(*n));
2983 n->next = *p;
2984 n->sym = sym;
2985 *p = n;
2986 break;
2987 }
2988 }
2989 }
2990 }
2991
2992 if (common_head) {
2993
2994 for (i = 0; i < f->header.e_shnum; ++i)
2995 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2996 break;
2997
2998
2999 if (i == f->header.e_shnum) {
3000 struct obj_section *sec;
3001
3002 f->header.e_shnum++;
3003 f->sections = xrealloc_vector(f->sections, 2, i);
3004 f->sections[i] = sec = arch_new_section();
3005
3006 sec->header.sh_type = SHT_PROGBITS;
3007 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
3008 sec->name = ".bss";
3009 sec->idx = i;
3010 }
3011
3012
3013 {
3014 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
3015 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
3016 struct common_entry *c;
3017
3018 for (c = common_head; c; c = c->next) {
3019 ElfW(Addr) align = c->sym->value;
3020
3021 if (align > max_align)
3022 max_align = align;
3023 if (bss_size & (align - 1))
3024 bss_size = (bss_size | (align - 1)) + 1;
3025
3026 c->sym->secidx = i;
3027 c->sym->value = bss_size;
3028
3029 bss_size += c->sym->size;
3030 }
3031
3032 f->sections[i]->header.sh_size = bss_size;
3033 f->sections[i]->header.sh_addralign = max_align;
3034 }
3035 }
3036
3037
3038
3039
3040 for (i = 0; i < f->header.e_shnum; ++i) {
3041 struct obj_section *s = f->sections[i];
3042 if (s->header.sh_type == SHT_NOBITS) {
3043 s->contents = NULL;
3044 if (s->header.sh_size != 0)
3045 s->contents = xzalloc(s->header.sh_size);
3046 s->header.sh_type = SHT_PROGBITS;
3047 }
3048 }
3049}
3050
3051static unsigned long obj_load_size(struct obj_file *f)
3052{
3053 unsigned long dot = 0;
3054 struct obj_section *sec;
3055
3056
3057
3058 for (sec = f->load_order; sec; sec = sec->load_next) {
3059 ElfW(Addr) align;
3060
3061 align = sec->header.sh_addralign;
3062 if (align && (dot & (align - 1)))
3063 dot = (dot | (align - 1)) + 1;
3064
3065 sec->header.sh_addr = dot;
3066 dot += sec->header.sh_size;
3067 }
3068
3069 return dot;
3070}
3071
3072static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
3073{
3074 int i, n = f->header.e_shnum;
3075 int ret = 1;
3076
3077
3078
3079 f->baseaddr = base;
3080 for (i = 0; i < n; ++i)
3081 f->sections[i]->header.sh_addr += base;
3082
3083
3084
3085 for (i = 0; i < n; ++i) {
3086 struct obj_section *relsec, *symsec, *targsec, *strsec;
3087 ElfW(RelM) * rel, *relend;
3088 ElfW(Sym) * symtab;
3089 const char *strtab;
3090
3091 relsec = f->sections[i];
3092 if (relsec->header.sh_type != SHT_RELM)
3093 continue;
3094
3095 symsec = f->sections[relsec->header.sh_link];
3096 targsec = f->sections[relsec->header.sh_info];
3097 strsec = f->sections[symsec->header.sh_link];
3098
3099 rel = (ElfW(RelM) *) relsec->contents;
3100 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3101 symtab = (ElfW(Sym) *) symsec->contents;
3102 strtab = (const char *) strsec->contents;
3103
3104 for (; rel < relend; ++rel) {
3105 ElfW(Addr) value = 0;
3106 struct obj_symbol *intsym = NULL;
3107 unsigned long symndx;
3108 ElfW(Sym) *extsym = NULL;
3109 const char *errmsg;
3110
3111
3112
3113 symndx = ELF_R_SYM(rel->r_info);
3114 if (symndx) {
3115
3116
3117 extsym = &symtab[symndx];
3118 if (ELF_ST_BIND(extsym->st_info) == STB_LOCAL) {
3119
3120
3121 intsym = f->local_symtab[symndx];
3122 } else {
3123
3124 const char *name;
3125 if (extsym->st_name)
3126 name = strtab + extsym->st_name;
3127 else
3128 name = f->sections[extsym->st_shndx]->name;
3129 intsym = obj_find_symbol(f, name);
3130 }
3131
3132 value = obj_symbol_final_value(f, intsym);
3133 intsym->referenced = 1;
3134 }
3135#if SHT_RELM == SHT_RELA
3136#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3137
3138 if (!extsym || !extsym->st_name
3139 || ELF_ST_BIND(extsym->st_info) != STB_LOCAL)
3140#endif
3141 value += rel->r_addend;
3142#endif
3143
3144
3145 switch (arch_apply_relocation
3146 (f, targsec, intsym, rel, value)
3147 ) {
3148 case obj_reloc_ok:
3149 break;
3150
3151 case obj_reloc_overflow:
3152 errmsg = "Relocation overflow";
3153 goto bad_reloc;
3154 case obj_reloc_dangerous:
3155 errmsg = "Dangerous relocation";
3156 goto bad_reloc;
3157 case obj_reloc_unhandled:
3158 errmsg = "Unhandled relocation";
3159bad_reloc:
3160 if (extsym) {
3161 bb_error_msg("%s of type %ld for %s", errmsg,
3162 (long) ELF_R_TYPE(rel->r_info),
3163 strtab + extsym->st_name);
3164 } else {
3165 bb_error_msg("%s of type %ld", errmsg,
3166 (long) ELF_R_TYPE(rel->r_info));
3167 }
3168 ret = 0;
3169 break;
3170 }
3171 }
3172 }
3173
3174
3175
3176 if (f->string_patches) {
3177 struct obj_string_patch *p;
3178 struct obj_section *strsec;
3179 ElfW(Addr) strsec_base;
3180 strsec = obj_find_section(f, ".kstrtab");
3181 strsec_base = strsec->header.sh_addr;
3182
3183 for (p = f->string_patches; p; p = p->next) {
3184 struct obj_section *targsec = f->sections[p->reloc_secidx];
3185 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3186 = strsec_base + p->string_offset;
3187 }
3188 }
3189
3190 if (f->symbol_patches) {
3191 struct obj_symbol_patch *p;
3192
3193 for (p = f->symbol_patches; p; p = p->next) {
3194 struct obj_section *targsec = f->sections[p->reloc_secidx];
3195 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3196 = obj_symbol_final_value(f, p->sym);
3197 }
3198 }
3199
3200 return ret;
3201}
3202
3203static int obj_create_image(struct obj_file *f, char *image)
3204{
3205 struct obj_section *sec;
3206 ElfW(Addr) base = f->baseaddr;
3207
3208 for (sec = f->load_order; sec; sec = sec->load_next) {
3209 char *secimg;
3210
3211 if (sec->contents == 0 || sec->header.sh_size == 0)
3212 continue;
3213
3214 secimg = image + (sec->header.sh_addr - base);
3215
3216
3217 memcpy(secimg, sec->contents, sec->header.sh_size);
3218 }
3219
3220 return 1;
3221}
3222
3223
3224
3225static struct obj_file *obj_load(char *image, size_t image_size, int loadprogbits)
3226{
3227 typedef uint32_t aliased_uint32_t FIX_ALIASING;
3228#if BB_LITTLE_ENDIAN
3229# define ELFMAG_U32 ((uint32_t)(ELFMAG0 + 0x100 * (ELFMAG1 + (0x100 * (ELFMAG2 + 0x100 * ELFMAG3)))))
3230#else
3231# define ELFMAG_U32 ((uint32_t)((((ELFMAG0 * 0x100) + ELFMAG1) * 0x100 + ELFMAG2) * 0x100 + ELFMAG3))
3232#endif
3233 struct obj_file *f;
3234 ElfW(Shdr) * section_headers;
3235 size_t shnum, i;
3236 char *shstrtab;
3237
3238
3239
3240 f = arch_new_file();
3241 f->symbol_cmp = strcmp;
3242 f->symbol_hash = obj_elf_hash;
3243 f->load_order_search_start = &f->load_order;
3244
3245 if (image_size < sizeof(f->header))
3246 bb_error_msg_and_die("error while loading ELF header");
3247 memcpy(&f->header, image, sizeof(f->header));
3248
3249 if (*(aliased_uint32_t*)(&f->header.e_ident) != ELFMAG_U32) {
3250 bb_error_msg_and_die("not an ELF file");
3251 }
3252 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
3253 || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB)
3254 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3255 || !MATCH_MACHINE(f->header.e_machine)
3256 ) {
3257 bb_error_msg_and_die("ELF file not for this architecture");
3258 }
3259 if (f->header.e_type != ET_REL) {
3260 bb_error_msg_and_die("ELF file not a relocatable object");
3261 }
3262
3263
3264
3265 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
3266 bb_error_msg_and_die("section header size mismatch: %lu != %lu",
3267 (unsigned long) f->header.e_shentsize,
3268 (unsigned long) sizeof(ElfW(Shdr)));
3269 }
3270
3271 shnum = f->header.e_shnum;
3272
3273
3274
3275 f->sections = xzalloc(sizeof(f->sections[0]) * (shnum + 4));
3276
3277 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3278 if (image_size < f->header.e_shoff + sizeof(ElfW(Shdr)) * shnum)
3279 bb_error_msg_and_die("error while loading section headers");
3280 memcpy(section_headers, image + f->header.e_shoff, sizeof(ElfW(Shdr)) * shnum);
3281
3282
3283
3284 for (i = 0; i < shnum; ++i) {
3285 struct obj_section *sec;
3286
3287 f->sections[i] = sec = arch_new_section();
3288
3289 sec->header = section_headers[i];
3290 sec->idx = i;
3291
3292 if (sec->header.sh_size) {
3293 switch (sec->header.sh_type) {
3294 case SHT_NULL:
3295 case SHT_NOTE:
3296 case SHT_NOBITS:
3297
3298 break;
3299 case SHT_PROGBITS:
3300#if LOADBITS
3301 if (!loadprogbits) {
3302 sec->contents = NULL;
3303 break;
3304 }
3305#endif
3306 case SHT_SYMTAB:
3307 case SHT_STRTAB:
3308 case SHT_RELM:
3309#if defined(__mips__)
3310 case SHT_MIPS_DWARF:
3311#endif
3312 sec->contents = NULL;
3313 if (sec->header.sh_size > 0) {
3314 sec->contents = xmalloc(sec->header.sh_size);
3315 if (image_size < (sec->header.sh_offset + sec->header.sh_size))
3316 bb_error_msg_and_die("error while loading section data");
3317 memcpy(sec->contents, image + sec->header.sh_offset, sec->header.sh_size);
3318 }
3319 break;
3320#if SHT_RELM == SHT_REL
3321 case SHT_RELA:
3322 bb_error_msg_and_die("RELA relocations not supported on this architecture");
3323#else
3324 case SHT_REL:
3325 bb_error_msg_and_die("REL relocations not supported on this architecture");
3326#endif
3327 default:
3328 if (sec->header.sh_type >= SHT_LOPROC) {
3329
3330
3331
3332
3333 break;
3334 }
3335
3336 bb_error_msg_and_die("can't handle sections of type %ld",
3337 (long) sec->header.sh_type);
3338 }
3339 }
3340 }
3341
3342
3343
3344 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3345
3346 for (i = 0; i < shnum; ++i) {
3347 struct obj_section *sec = f->sections[i];
3348 sec->name = shstrtab + sec->header.sh_name;
3349 }
3350
3351 for (i = 0; i < shnum; ++i) {
3352 struct obj_section *sec = f->sections[i];
3353
3354
3355
3356
3357 if (strcmp(sec->name, ".modinfo") == 0)
3358 sec->header.sh_flags &= ~SHF_ALLOC;
3359
3360 if (sec->header.sh_flags & SHF_ALLOC)
3361 obj_insert_section_load_order(f, sec);
3362
3363 switch (sec->header.sh_type) {
3364 case SHT_SYMTAB:
3365 {
3366 unsigned long nsym, j;
3367 char *strtab;
3368 ElfW(Sym) * sym;
3369
3370 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
3371 bb_error_msg_and_die("symbol size mismatch: %lu != %lu",
3372 (unsigned long) sec->header.sh_entsize,
3373 (unsigned long) sizeof(ElfW(Sym)));
3374 }
3375
3376 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3377 strtab = f->sections[sec->header.sh_link]->contents;
3378 sym = (ElfW(Sym) *) sec->contents;
3379
3380
3381 j = f->local_symtab_size = sec->header.sh_info;
3382 f->local_symtab = xzalloc(j * sizeof(struct obj_symbol *));
3383
3384
3385 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3386 ElfW(Addr) val = sym->st_value;
3387 const char *name;
3388 if (sym->st_name)
3389 name = strtab + sym->st_name;
3390 else if (sym->st_shndx < shnum)
3391 name = f->sections[sym->st_shndx]->name;
3392 else
3393 continue;
3394#if defined(__SH5__)
3395
3396
3397
3398
3399
3400
3401
3402 val |= sym->st_other & 4;
3403#endif
3404 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3405 val, sym->st_size);
3406 }
3407 }
3408 break;
3409
3410 case SHT_RELM:
3411 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
3412 bb_error_msg_and_die("relocation entry size mismatch: %lu != %lu",
3413 (unsigned long) sec->header.sh_entsize,
3414 (unsigned long) sizeof(ElfW(RelM)));
3415 }
3416 break;
3417
3418
3419
3420
3421 }
3422 }
3423
3424 return f;
3425}
3426
3427#if ENABLE_FEATURE_INSMOD_LOADINKMEM
3428
3429
3430
3431
3432
3433static int obj_load_progbits(char *image, size_t image_size, struct obj_file *f, char *imagebase)
3434{
3435 ElfW(Addr) base = f->baseaddr;
3436 struct obj_section* sec;
3437
3438 for (sec = f->load_order; sec; sec = sec->load_next) {
3439
3440 if (sec->contents != NULL)
3441 continue;
3442 if (sec->header.sh_size == 0)
3443 continue;
3444 sec->contents = imagebase + (sec->header.sh_addr - base);
3445 if (image_size < (sec->header.sh_offset + sec->header.sh_size)) {
3446 bb_error_msg("error reading ELF section data");
3447 return 0;
3448 }
3449 memcpy(sec->contents, image + sec->header.sh_offset, sec->header.sh_size);
3450 }
3451 return 1;
3452}
3453#endif
3454
3455static void hide_special_symbols(struct obj_file *f)
3456{
3457 static const char *const specials[] = {
3458 SPFX "cleanup_module",
3459 SPFX "init_module",
3460 SPFX "kernel_version",
3461 NULL
3462 };
3463
3464 struct obj_symbol *sym;
3465 const char *const *p;
3466
3467 for (p = specials; *p; ++p) {
3468 sym = obj_find_symbol(f, *p);
3469 if (sym != NULL)
3470 sym->info = ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info));
3471 }
3472}
3473
3474
3475#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
3476static int obj_gpl_license(struct obj_file *f, const char **license)
3477{
3478 struct obj_section *sec;
3479
3480
3481
3482
3483 static const char *const gpl_licenses[] = {
3484 "GPL",
3485 "GPL v2",
3486 "GPL and additional rights",
3487 "Dual BSD/GPL",
3488 "Dual MPL/GPL"
3489 };
3490
3491 sec = obj_find_section(f, ".modinfo");
3492 if (sec) {
3493 const char *value, *ptr, *endptr;
3494 ptr = sec->contents;
3495 endptr = ptr + sec->header.sh_size;
3496 while (ptr < endptr) {
3497 value = strchr(ptr, '=');
3498 if (value && strncmp(ptr, "license", value-ptr) == 0) {
3499 unsigned i;
3500 if (license)
3501 *license = value+1;
3502 for (i = 0; i < ARRAY_SIZE(gpl_licenses); ++i) {
3503 if (strcmp(value+1, gpl_licenses[i]) == 0)
3504 return 0;
3505 }
3506 return 2;
3507 }
3508 ptr = strchr(ptr, '\0');
3509 if (ptr)
3510 ptr++;
3511 else
3512 ptr = endptr;
3513 }
3514 }
3515 return 1;
3516}
3517
3518#define TAINT_FILENAME "/proc/sys/kernel/tainted"
3519#define TAINT_PROPRIETORY_MODULE (1 << 0)
3520#define TAINT_FORCED_MODULE (1 << 1)
3521#define TAINT_UNSAFE_SMP (1 << 2)
3522#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
3523
3524static void set_tainted(int fd, const char *m_name,
3525 int kernel_has_tainted, int taint,
3526 const char *text1, const char *text2)
3527{
3528 static smallint printed_info;
3529
3530 char buf[80];
3531 int oldval;
3532
3533 if (fd < 0 && !kernel_has_tainted)
3534 return;
3535 printf("Warning: loading %s will taint the kernel: %s%s\n",
3536 m_name, text1, text2);
3537 if (!printed_info) {
3538 printf(" See %s for information about tainted modules\n", TAINT_URL);
3539 printed_info = 1;
3540 }
3541 if (fd >= 0) {
3542 read(fd, buf, sizeof(buf)-1);
3543 buf[sizeof(buf)-1] = '\0';
3544 oldval = strtoul(buf, NULL, 10);
3545 sprintf(buf, "%d\n", oldval | taint);
3546 xwrite_str(fd, buf);
3547 }
3548}
3549
3550
3551static void check_tainted_module(struct obj_file *f, const char *m_name)
3552{
3553 int fd, kernel_has_tainted;
3554 const char *ptr;
3555
3556 kernel_has_tainted = 1;
3557 fd = open(TAINT_FILENAME, O_RDWR);
3558 if (fd < 0) {
3559 if (errno == ENOENT)
3560 kernel_has_tainted = 0;
3561 else if (errno == EACCES)
3562 kernel_has_tainted = 1;
3563 else {
3564 bb_simple_perror_msg(TAINT_FILENAME);
3565 kernel_has_tainted = 0;
3566 }
3567 }
3568
3569 switch (obj_gpl_license(f, &ptr)) {
3570 case 0:
3571 break;
3572 case 1:
3573 set_tainted(fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
3574 break;
3575 default:
3576
3577
3578
3579
3580 set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
3581 break;
3582 }
3583
3584 if (flag_force_load)
3585 set_tainted(fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
3586
3587 if (fd >= 0)
3588 close(fd);
3589}
3590#else
3591#define check_tainted_module(x, y) do { } while (0);
3592#endif
3593
3594#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
3595
3596
3597
3598
3599#if !ENABLE_FEATURE_INSMOD_VERSION_CHECKING
3600#define get_module_version(f, str) get_module_version(str)
3601#endif
3602static int
3603get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3604{
3605#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
3606 return new_get_module_version(f, str);
3607#else
3608 strncpy(str, "???", sizeof(str));
3609 return -1;
3610#endif
3611}
3612
3613
3614
3615
3616
3617static void
3618add_ksymoops_symbols(struct obj_file *f, const char *filename,
3619 const char *m_name)
3620{
3621 static const char symprefix[] ALIGN1 = "__insmod_";
3622 static const char section_names[][8] = {
3623 ".text",
3624 ".rodata",
3625 ".data",
3626 ".bss",
3627 ".sbss"
3628 };
3629
3630 struct obj_section *sec;
3631 struct obj_symbol *sym;
3632 char *name, *absolute_filename;
3633 char str[STRVERSIONLEN];
3634 unsigned i;
3635 int lm_name, lfilename, use_ksymtab, version;
3636 struct stat statbuf;
3637
3638
3639
3640 absolute_filename = xmalloc_readlink(filename);
3641 if (!absolute_filename)
3642 absolute_filename = xstrdup(filename);
3643
3644 lm_name = strlen(m_name);
3645 lfilename = strlen(absolute_filename);
3646
3647
3648
3649
3650
3651 use_ksymtab = obj_find_section(f, "__ksymtab") || flag_noexport;
3652
3653 sec = obj_find_section(f, ".this");
3654 if (sec) {
3655
3656
3657
3658
3659
3660 if (stat(absolute_filename, &statbuf) != 0)
3661 statbuf.st_mtime = 0;
3662 version = get_module_version(f, str);
3663 name = xasprintf("%s%s_O%s_M%0*lX_V%d",
3664 symprefix, m_name, absolute_filename,
3665 (int)(2 * sizeof(statbuf.st_mtime)),
3666 (long)statbuf.st_mtime,
3667 version);
3668 sym = obj_add_symbol(f, name, -1,
3669 ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
3670 sec->idx, sec->header.sh_addr, 0);
3671 if (use_ksymtab)
3672 new_add_ksymtab(f, sym);
3673 }
3674 free(absolute_filename);
3675#ifdef _NOT_SUPPORTED_
3676
3677 if (f->persist) {
3678 name = xasprintf("%s%s_P%s",
3679 symprefix, m_name, f->persist);
3680 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
3681 sec->idx, sec->header.sh_addr, 0);
3682 if (use_ksymtab)
3683 new_add_ksymtab(f, sym);
3684 }
3685#endif
3686
3687 for (i = 0; i < ARRAY_SIZE(section_names); ++i) {
3688 sec = obj_find_section(f, section_names[i]);
3689 if (sec && sec->header.sh_size) {
3690 name = xasprintf("%s%s_S%s_L%ld",
3691 symprefix, m_name, sec->name,
3692 (long)sec->header.sh_size);
3693 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
3694 sec->idx, sec->header.sh_addr, 0);
3695 if (use_ksymtab)
3696 new_add_ksymtab(f, sym);
3697 }
3698 }
3699}
3700#endif
3701
3702#if ENABLE_FEATURE_INSMOD_LOAD_MAP
3703static void print_load_map(struct obj_file *f)
3704{
3705 struct obj_section *sec;
3706#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
3707 struct obj_symbol **all, **p;
3708 int i, nsyms;
3709 char *loaded;
3710 struct obj_symbol *sym;
3711#endif
3712
3713 printf("Sections: Size %-*s Align\n",
3714 (int) (2 * sizeof(void *)), "Address");
3715
3716 for (sec = f->load_order; sec; sec = sec->load_next) {
3717 int a;
3718 unsigned long tmp;
3719
3720 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3721 tmp >>= 1;
3722 if (a == -1)
3723 a = 0;
3724
3725 printf("%-15s %08lx %0*lx 2**%d\n",
3726 sec->name,
3727 (long)sec->header.sh_size,
3728 (int) (2 * sizeof(void *)),
3729 (long)sec->header.sh_addr,
3730 a);
3731 }
3732#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
3733
3734 i = f->header.e_shnum;
3735 loaded = alloca(i * sizeof(loaded[0]));
3736 while (--i >= 0)
3737 loaded[i] = ((f->sections[i]->header.sh_flags & SHF_ALLOC) != 0);
3738
3739
3740 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3741 for (sym = f->symtab[i]; sym; sym = sym->next)
3742 if (sym->secidx <= SHN_HIRESERVE
3743 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx])
3744 ) {
3745 ++nsyms;
3746 }
3747
3748 all = alloca(nsyms * sizeof(all[0]));
3749
3750 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3751 for (sym = f->symtab[i]; sym; sym = sym->next)
3752 if (sym->secidx <= SHN_HIRESERVE
3753 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx])
3754 ) {
3755 *p++ = sym;
3756 }
3757
3758
3759 printf("\nSymbols:\n");
3760 for (p = all; p < all + nsyms; ++p) {
3761 char type = '?';
3762 unsigned long value;
3763
3764 sym = *p;
3765 if (sym->secidx == SHN_ABS) {
3766 type = 'A';
3767 value = sym->value;
3768 } else if (sym->secidx == SHN_UNDEF) {
3769 type = 'U';
3770 value = 0;
3771 } else {
3772 sec = f->sections[sym->secidx];
3773
3774 if (sec->header.sh_type == SHT_NOBITS)
3775 type = 'B';
3776 else if (sec->header.sh_flags & SHF_ALLOC) {
3777 if (sec->header.sh_flags & SHF_EXECINSTR)
3778 type = 'T';
3779 else if (sec->header.sh_flags & SHF_WRITE)
3780 type = 'D';
3781 else
3782 type = 'R';
3783 }
3784 value = sym->value + sec->header.sh_addr;
3785 }
3786
3787 if (ELF_ST_BIND(sym->info) == STB_LOCAL)
3788 type |= 0x20;
3789
3790 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3791 type, sym->name);
3792 }
3793#endif
3794}
3795#else
3796static void print_load_map(struct obj_file *f UNUSED_PARAM)
3797{
3798}
3799#endif
3800
3801int FAST_FUNC bb_init_module_24(const char *m_filename, const char *options)
3802{
3803 int k_crcs;
3804 unsigned long m_size;
3805 ElfW(Addr) m_addr;
3806 struct obj_file *f;
3807 int exit_status = EXIT_FAILURE;
3808 char *m_name;
3809#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
3810 int m_has_modinfo;
3811#endif
3812 char *image;
3813 size_t image_size;
3814 bool mmaped;
3815
3816 image_size = INT_MAX - 4095;
3817 mmaped = 0;
3818 image = try_to_mmap_module(m_filename, &image_size);
3819 if (image) {
3820 mmaped = 1;
3821 } else {
3822
3823 image = xmalloc_open_zipped_read_close(m_filename, &image_size);
3824 if (!image)
3825 return EXIT_FAILURE;
3826 }
3827
3828 m_name = xstrdup(bb_basename(m_filename));
3829
3830 *strchrnul(m_name, '.') = '\0';
3831
3832 f = obj_load(image, image_size, LOADBITS);
3833
3834#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
3835
3836 m_has_modinfo = (get_modinfo_value(f, "kernel_version") != NULL);
3837 if (!flag_quiet) {
3838 char m_strversion[STRVERSIONLEN];
3839 struct utsname uts;
3840
3841 if (m_has_modinfo) {
3842 int m_version = new_get_module_version(f, m_strversion);
3843 if (m_version == -1) {
3844 bb_error_msg_and_die("can't find the kernel version "
3845 "the module was compiled for");
3846 }
3847 }
3848
3849 uname(&uts);
3850 if (strncmp(uts.release, m_strversion, STRVERSIONLEN) != 0) {
3851 bb_error_msg("%skernel-module version mismatch\n"
3852 "\t%s was compiled for kernel version %s\n"
3853 "\twhile this kernel is version %s",
3854 flag_force_load ? "warning: " : "",
3855 m_name, m_strversion, uts.release);
3856 if (!flag_force_load)
3857 goto out;
3858 }
3859 }
3860#endif
3861
3862 if (query_module(NULL, 0, NULL, 0, NULL))
3863 bb_error_msg_and_die("old (unsupported) kernel");
3864 new_get_kernel_symbols();
3865 k_crcs = new_is_kernel_checksummed();
3866
3867#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
3868 {
3869 int m_crcs = 0;
3870 if (m_has_modinfo)
3871 m_crcs = new_is_module_checksummed(f);
3872 if (m_crcs != k_crcs)
3873 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
3874 }
3875#endif
3876
3877
3878 add_kernel_symbols(f);
3879
3880
3881 new_create_this_module(f, m_name);
3882 obj_check_undefineds(f);
3883 obj_allocate_commons(f);
3884 check_tainted_module(f, m_name);
3885
3886
3887 new_process_module_arguments(f, options);
3888
3889 arch_create_got(f);
3890 hide_special_symbols(f);
3891
3892#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
3893 add_ksymoops_symbols(f, m_filename, m_name);
3894#endif
3895
3896 new_create_module_ksymtab(f);
3897
3898
3899 m_size = obj_load_size(f);
3900
3901 m_addr = create_module(m_name, m_size);
3902 if (m_addr == (ElfW(Addr))(-1)) switch (errno) {
3903 case EEXIST:
3904 bb_error_msg_and_die("a module named %s already exists", m_name);
3905 case ENOMEM:
3906 bb_error_msg_and_die("can't allocate kernel memory for module; needed %lu bytes",
3907 m_size);
3908 default:
3909 bb_perror_msg_and_die("create_module: %s", m_name);
3910 }
3911
3912#if !LOADBITS
3913
3914
3915
3916
3917 if (!obj_load_progbits(image, image_size, f, (char*)m_addr)) {
3918 delete_module(m_name, 0);
3919 goto out;
3920 }
3921#endif
3922
3923 if (!obj_relocate(f, m_addr)) {
3924 delete_module(m_name, 0);
3925 goto out;
3926 }
3927
3928 if (!new_init_module(m_name, f, m_size)) {
3929 delete_module(m_name, 0);
3930 goto out;
3931 }
3932
3933 if (flag_print_load_map)
3934 print_load_map(f);
3935
3936 exit_status = EXIT_SUCCESS;
3937
3938 out:
3939 if (mmaped)
3940 munmap(image, image_size);
3941 else
3942 free(image);
3943 free(m_name);
3944
3945 return exit_status;
3946}
3947