1 /* Copyright (C) 2008 Jeffrey Brian Arnold <jbarnold@mit.edu>
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License, version 2.
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
17 #include <linux/module.h>
18 #include <linux/errno.h>
19 #include <linux/kallsyms.h>
20 #include <linux/kthread.h>
21 #include <linux/proc_fs.h>
22 #include <linux/sched.h>
23 #include <linux/stop_machine.h>
24 #include <linux/time.h>
25 #ifdef KSPLICE_STANDALONE
26 /* linux/uaccess.h doesn't exist in kernels before 2.6.18 */
27 #include <linux/version.h>
28 #include <asm/uaccess.h>
30 #include "ksplice-run-pre.h"
32 #include <linux/uaccess.h>
34 #include <asm/ksplice-run-pre.h>
37 #ifdef KSPLICE_STANDALONE
39 /* Old kernels do not have kcalloc */
40 #define kcalloc(n, size, flags) ksplice_kcalloc(n)
42 #ifndef task_thread_info
43 #define task_thread_info(task) (task)->thread_info
44 #endif /* task_thread_info */
46 #ifdef __ASM_X86_PROCESSOR_H
47 #define KSPLICE_EIP(x) ((x)->thread.ip)
48 #define KSPLICE_ESP(x) ((x)->thread.sp)
49 #elif BITS_PER_LONG == 32
50 #define KSPLICE_EIP(x) ((x)->thread.eip)
51 #define KSPLICE_ESP(x) ((x)->thread.esp)
52 #elif BITS_PER_LONG == 64
53 #define KSPLICE_EIP(x) (KSTK_EIP(x))
54 #define KSPLICE_ESP(x) ((x)->thread.rsp)
55 #endif /* __ASM_X86_PROCESSOR_H */
57 static int bootstrapped
= 0;
59 #ifdef CONFIG_KALLSYMS
60 extern unsigned long kallsyms_addresses
[], kallsyms_num_syms
;
61 extern u8 kallsyms_names
[];
62 #endif /* CONFIG_KALLSYMS */
64 /* defined by ksplice-create */
65 extern struct ksplice_reloc ksplice_init_relocs
;
67 #else /* KSPLICE_STANDALONE */
68 #define KSPLICE_EIP(x) ((x)->thread.ip)
69 #define KSPLICE_ESP(x) ((x)->thread.sp)
70 #endif /* KSPLICE_STANDALONE */
73 module_param(debug
, int, 0600);
75 /* THIS_MODULE everywhere is wrong! */
77 void cleanup_ksplice_module(struct module_pack
*pack
)
79 remove_proc_entry(pack
->name
, &proc_root
);
82 int activate_primary(struct module_pack
*pack
)
85 struct proc_dir_entry
*proc_entry
;
89 if (process_ksplice_relocs(pack
, pack
->primary_relocs
) != 0)
92 if (resolve_patch_symbols(pack
) != 0)
95 proc_entry
= create_proc_entry(pack
->name
, 0644, NULL
);
96 if (proc_entry
== NULL
) {
97 print_abort("primary module: could not create proc entry");
101 proc_entry
->read_proc
= procfile_read
;
102 proc_entry
->write_proc
= procfile_write
;
103 proc_entry
->data
= pack
;
104 proc_entry
->owner
= THIS_MODULE
;
105 proc_entry
->mode
= S_IFREG
| S_IRUSR
| S_IWUSR
;
108 proc_entry
->size
= 0;
110 for (i
= 0; i
< 5; i
++) {
112 ret
= stop_machine_run(__apply_patches
, pack
, NR_CPUS
);
116 set_current_state(TASK_INTERRUPTIBLE
);
117 schedule_timeout(msecs_to_jiffies(1000));
119 if (pack
->state
!= KSPLICE_APPLIED
) {
120 remove_proc_entry(pack
->name
, &proc_root
);
122 print_abort("stack check: to-be-replaced code is busy");
126 printk(KERN_INFO
"ksplice: Update %s applied successfully\n",
131 int resolve_patch_symbols(struct module_pack
*pack
)
133 struct ksplice_patch
*p
;
137 for (p
= pack
->patches
; p
->oldstr
; p
++) {
138 p
->saved
= kmalloc(5, GFP_KERNEL
);
139 if (p
->saved
== NULL
) {
140 print_abort("out of memory");
144 if (p
->oldaddr
!= 0) {
145 ret
= add_candidate_val(&vals
, p
->oldaddr
);
150 ret
= compute_address(pack
, p
->oldstr
, &vals
);
154 if (!singular(&vals
)) {
156 failed_to_find(p
->oldstr
);
160 list_entry(vals
.next
, struct candidate_val
, list
)->val
;
167 int procfile_read(char *buffer
, char **buffer_location
,
168 off_t offset
, int buffer_length
, int *eof
, void *data
)
173 int procfile_write(struct file
*file
, const char *buffer
, unsigned long count
,
177 struct module_pack
*pack
= data
;
178 printk(KERN_INFO
"ksplice: Preparing to reverse %s\n", pack
->name
);
180 if (pack
->state
!= KSPLICE_APPLIED
)
183 for (i
= 0; i
< 5; i
++) {
185 ret
= stop_machine_run(__reverse_patches
, pack
, NR_CPUS
);
189 set_current_state(TASK_INTERRUPTIBLE
);
190 schedule_timeout(msecs_to_jiffies(1000));
193 print_abort("stack check: to-be-reversed code is busy");
195 printk(KERN_INFO
"ksplice: Update %s reversed successfully\n",
201 int __apply_patches(void *packptr
)
203 struct module_pack
*pack
= packptr
;
204 struct ksplice_patch
*p
;
205 struct safety_record
*rec
;
207 list_for_each_entry(rec
, pack
->safety_records
, list
) {
208 for (p
= pack
->patches
; p
->oldstr
; p
++) {
209 if (p
->oldaddr
== rec
->addr
)
214 if (check_each_task(pack
) < 0)
217 if (!try_module_get(THIS_MODULE
))
220 pack
->state
= KSPLICE_APPLIED
;
222 for (p
= pack
->patches
; p
->oldstr
; p
++) {
223 memcpy((void *)p
->saved
, (void *)p
->oldaddr
, 5);
224 *((u8
*) p
->oldaddr
) = 0xE9;
225 *((u32
*) (p
->oldaddr
+ 1)) = p
->repladdr
- (p
->oldaddr
+ 5);
230 int __reverse_patches(void *packptr
)
232 struct module_pack
*pack
= packptr
;
233 struct ksplice_patch
*p
;
235 if (pack
->state
!= KSPLICE_APPLIED
)
238 if (check_each_task(pack
) < 0)
241 clear_list(pack
->safety_records
, struct safety_record
, list
);
242 pack
->state
= KSPLICE_REVERSED
;
243 module_put(THIS_MODULE
);
246 for (; p
->oldstr
; p
++) {
247 memcpy((void *)p
->oldaddr
, (void *)p
->saved
, 5);
249 *((u8
*) p
->repladdr
) = 0xE9;
250 *((u32
*) (p
->repladdr
+ 1)) = p
->oldaddr
- (p
->repladdr
+ 5);
256 int check_each_task(struct module_pack
*pack
)
258 struct task_struct
*g
, *p
;
260 read_lock(&tasklist_lock
);
261 do_each_thread(g
, p
) {
262 /* do_each_thread is a double loop! */
263 if (check_task(pack
, p
) < 0) {
272 while_each_thread(g
, p
);
273 read_unlock(&tasklist_lock
);
277 int check_task(struct module_pack
*pack
, struct task_struct
*t
)
281 ksplice_debug(2, KERN_DEBUG
"ksplice: stack check: pid %d (%s) eip "
282 "%08lx ", t
->pid
, t
->comm
, KSPLICE_EIP(t
));
283 status
= check_address_for_conflict(pack
, KSPLICE_EIP(t
));
284 ksplice_debug(2, ": ");
287 ret
= check_stack(pack
, task_thread_info(t
),
288 (long *)__builtin_frame_address(0));
291 } else if (!task_curr(t
)) {
292 ret
= check_stack(pack
, task_thread_info(t
),
293 (long *)KSPLICE_ESP(t
));
296 } else if (strcmp(t
->comm
, "kstopmachine") != 0) {
297 ksplice_debug(2, "unexpected running task!");
300 ksplice_debug(2, "\n");
304 /* Modified version of Linux's print_context_stack */
305 int check_stack(struct module_pack
*pack
, struct thread_info
*tinfo
,
311 while (valid_stack_ptr(tinfo
, stack
)) {
313 if (__kernel_text_address(addr
)) {
314 ksplice_debug(2, "%08lx ", addr
);
315 if (check_address_for_conflict(pack
, addr
) < 0)
322 int check_address_for_conflict(struct module_pack
*pack
, long addr
)
324 struct ksplice_size
*s
= pack
->primary_sizes
;
325 struct safety_record
*rec
;
327 /* It is safe for addr to point to the beginning of a patched
328 function, because that location will be overwritten with a
330 list_for_each_entry(rec
, pack
->safety_records
, list
) {
331 if (rec
->care
== 1 && addr
> rec
->addr
332 && addr
< rec
->addr
+ rec
->size
) {
333 ksplice_debug(2, "[<-- CONFLICT] ");
337 for (; s
->name
!= NULL
; s
++) {
338 if (addr
>= s
->thismod_addr
339 && addr
< s
->thismod_addr
+ s
->size
) {
340 ksplice_debug(2, "[<-- CONFLICT] ");
347 /* Modified version of Linux's valid_stack_ptr */
348 int valid_stack_ptr(struct thread_info
*tinfo
, void *p
)
350 return p
> (void *)tinfo
351 && p
<= (void *)tinfo
+ THREAD_SIZE
- sizeof(long);
354 int init_ksplice_module(struct module_pack
*pack
)
357 #ifdef KSPLICE_STANDALONE
358 if (process_ksplice_relocs(pack
, &ksplice_init_relocs
) != 0)
363 printk(KERN_INFO
"ksplice_h: Preparing and checking %s\n", pack
->name
);
365 if (activate_helper(pack
) != 0 || activate_primary(pack
) != 0)
368 clear_list(pack
->reloc_namevals
, struct reloc_nameval
, list
);
369 clear_list(pack
->reloc_addrmaps
, struct reloc_addrmap
, list
);
370 if (pack
->state
== KSPLICE_PREPARING
)
371 clear_list(pack
->safety_records
, struct safety_record
, list
);
376 int activate_helper(struct module_pack
*pack
)
378 struct ksplice_size
*s
;
379 int i
, record_count
= 0, ret
;
381 int numfinished
, oldfinished
= 0;
382 int restart_count
= 0;
386 if (process_ksplice_relocs(pack
, pack
->helper_relocs
) != 0)
389 for (s
= pack
->helper_sizes
; s
->name
!= NULL
; s
++)
392 finished
= kcalloc(record_count
, 1, GFP_KERNEL
);
393 if (finished
== NULL
) {
394 print_abort("out of memory");
399 for (s
= pack
->helper_sizes
, i
= 0; s
->name
!= NULL
; s
++, i
++) {
405 ret
= search_for_match(pack
, s
);
409 } else if (ret
> 0) {
415 for (i
= 0; i
< record_count
; i
++) {
419 if (numfinished
== record_count
) {
424 if (oldfinished
== numfinished
) {
425 print_abort("run-pre: could not match some sections");
429 oldfinished
= numfinished
;
431 if (restart_count
< 20) {
435 print_abort("run-pre: restart limit exceeded");
440 int search_for_match(struct module_pack
*pack
, struct ksplice_size
*s
)
443 #ifdef KSPLICE_STANDALONE
448 struct candidate_val
*v
;
450 for (i
= 0; i
< s
->num_sym_addrs
; i
++) {
451 ret
= add_candidate_val(&vals
, s
->sym_addrs
[i
]);
456 ret
= compute_address(pack
, s
->name
, &vals
);
460 ksplice_debug(3, KERN_DEBUG
"ksplice_h: run-pre: starting sect search "
461 "for %s\n", s
->name
);
463 list_for_each_entry(v
, &vals
, list
) {
467 ret
= try_addr(pack
, s
, run_addr
, s
->thismod_addr
,
470 /* we've encountered a match (> 0) or an error (< 0) */
477 #ifdef KSPLICE_STANDALONE
480 brute_search_all_mods(pack
, s
);
486 int try_addr(struct module_pack
*pack
, struct ksplice_size
*s
, long run_addr
,
487 long pre_addr
, int create_nameval
)
489 struct safety_record
*tmp
;
490 struct reloc_nameval
*nv
;
492 if (run_pre_cmp(pack
, run_addr
, pre_addr
, s
->size
, 0) != 0) {
493 set_temp_myst_relocs(pack
, NOVAL
);
494 ksplice_debug(1, KERN_DEBUG
"ksplice_h: run-pre: sect %s does "
495 "not match ", s
->name
);
496 ksplice_debug(1, "(r_a=%08lx p_a=%08lx s=%ld)\n",
497 run_addr
, pre_addr
, s
->size
);
498 ksplice_debug(1, "ksplice_h: run-pre: ");
500 run_pre_cmp(pack
, run_addr
, pre_addr
, s
->size
, 1);
501 ksplice_debug(1, "\n");
503 set_temp_myst_relocs(pack
, VAL
);
505 ksplice_debug(3, KERN_DEBUG
"ksplice_h: run-pre: found sect "
506 "%s=%08lx\n", s
->name
, run_addr
);
508 tmp
= kmalloc(sizeof(*tmp
), GFP_KERNEL
);
510 print_abort("out of memory");
513 tmp
->addr
= run_addr
;
516 list_add(&tmp
->list
, pack
->safety_records
);
518 if (create_nameval
) {
519 nv
= find_nameval(pack
, s
->name
, 1);
531 int handle_myst_reloc(long pre_addr
, int *pre_o
, long run_addr
,
532 int *run_o
, struct reloc_addrmap
*map
, int rerun
)
535 int offset
= (int)(pre_addr
+ *pre_o
- map
->addr
);
538 run_reloc_addr
= run_addr
+ *run_o
- offset
;
540 run_reloc
= *(int *)run_reloc_addr
;
541 else if (map
->size
== 8)
542 run_reloc
= *(long long *)run_reloc_addr
;
546 if (debug
>= 3 && !rerun
) {
547 printk(KERN_DEBUG
"ksplice_h: run-pre: reloc at r_a=%08lx "
548 "p_o=%08x: ", run_addr
, *pre_o
);
549 printk("%s=%08lx (A=%08lx *r=%08lx)\n",
550 map
->nameval
->name
, map
->nameval
->val
,
551 map
->addend
, run_reloc
);
554 if (!starts_with(map
->nameval
->name
, ".rodata.str")) {
555 expected
= run_reloc
- map
->addend
;
556 if ((int)run_reloc
== 0x77777777)
559 expected
+= run_reloc_addr
;
560 if (map
->nameval
->status
== NOVAL
) {
561 map
->nameval
->val
= expected
;
562 map
->nameval
->status
= TEMP
;
563 } else if (map
->nameval
->val
!= expected
) {
566 printk(KERN_DEBUG
"ksplice_h: pre-run reloc: Expected "
567 "%s=%08x!\n", map
->nameval
->name
, expected
);
572 *pre_o
+= map
->size
- offset
;
573 *run_o
+= map
->size
- offset
;
577 int process_ksplice_relocs(struct module_pack
*pack
,
578 struct ksplice_reloc
*relocs
)
580 struct ksplice_reloc
*r
;
581 for (r
= relocs
; r
->sym_name
!= NULL
; r
++) {
582 if (process_reloc(pack
, r
) != 0)
588 int process_reloc(struct module_pack
*pack
, struct ksplice_reloc
*r
)
592 struct reloc_addrmap
*map
;
593 const long blank_addr
= r
->blank_sect_addr
+ r
->blank_offset
;
595 #ifdef KSPLICE_STANDALONE
596 /* run_pre_reloc: will this reloc be used for run-pre matching? */
597 const int run_pre_reloc
= pack
->helper
&& bootstrapped
;
598 #ifndef CONFIG_KALLSYMS
601 goto skip_using_system_map
;
602 #endif /* CONFIG_KALLSYMS */
603 #endif /* KSPLICE_STANDALONE */
605 /* Some Fedora kernel releases have System.map files whose symbol
606 * addresses disagree with the running kernel by a constant address
607 * offset because of the CONFIG_PHYSICAL_START and CONFIG_PHYSICAL_ALIGN
608 * values used to compile these kernels. This constant address offset
609 * is always a multiple of 0x100000.
611 * If we observe an offset that is NOT a multiple of 0x100000, then the
612 * user provided us with an incorrect System.map file, and we should
614 * If we observe an offset that is a multiple of 0x100000, then we can
615 * adjust the System.map address values accordingly and proceed.
617 off
= (long)printk
- pack
->map_printk
;
619 print_abort("System.map does not match kernel");
622 for (i
= 0; i
< r
->num_sym_addrs
; i
++) {
623 ret
= add_candidate_val(&vals
, r
->sym_addrs
[i
] + off
);
627 #ifndef CONFIG_KALLSYMS
628 skip_using_system_map
:
631 if ((r
->size
== 4 && *(int *)blank_addr
!= 0x77777777)
633 *(long long *)blank_addr
!= 0x7777777777777777ll
)) {
634 ksplice_debug(4, KERN_DEBUG
"ksplice%s: reloc: skipped %s:%08lx"
635 " (altinstr)\n", (pack
->helper
? "_h" : ""),
636 r
->sym_name
, r
->blank_offset
);
641 ret
= compute_address(pack
, r
->sym_name
, &vals
);
644 if (!singular(&vals
)) {
646 #ifdef KSPLICE_STANDALONE
647 if (!run_pre_reloc
) {
651 failed_to_find(r
->sym_name
);
655 ksplice_debug(4, KERN_DEBUG
"ksplice: reloc: deferred %s:%08lx "
656 "to run-pre\n", r
->sym_name
, r
->blank_offset
);
658 map
= kmalloc(sizeof(*map
), GFP_KERNEL
);
660 print_abort("out of memory");
663 map
->addr
= blank_addr
;
664 map
->nameval
= find_nameval(pack
, r
->sym_name
, 1);
665 if (map
->nameval
== NULL
)
667 map
->addend
= r
->addend
;
668 map
->pcrel
= r
->pcrel
;
670 list_add(&map
->list
, pack
->reloc_addrmaps
);
673 sym_addr
= list_entry(vals
.next
, struct candidate_val
, list
)->val
;
676 #ifdef KSPLICE_STANDALONE
677 if (r
->pcrel
&& run_pre_reloc
) {
679 if (r
->pcrel
&& pack
->helper
) {
681 map
= kmalloc(sizeof(*map
), GFP_KERNEL
);
683 print_abort("out of memory");
686 map
->addr
= blank_addr
;
687 map
->nameval
= find_nameval(pack
, "ksplice_zero", 1);
688 if (map
->nameval
== NULL
)
690 map
->nameval
->val
= 0;
691 map
->nameval
->status
= VAL
;
692 map
->addend
= sym_addr
+ r
->addend
;
694 map
->pcrel
= r
->pcrel
;
695 list_add(&map
->list
, pack
->reloc_addrmaps
);
700 val
= sym_addr
+ r
->addend
- blank_addr
;
702 val
= sym_addr
+ r
->addend
;
704 *(int *)blank_addr
= val
;
705 else if (r
->size
== 8)
706 *(long long *)blank_addr
= val
;
711 ksplice_debug(4, KERN_DEBUG
"ksplice%s: reloc: %s:%08lx ",
712 (pack
->helper
? "_h" : ""), r
->sym_name
, r
->blank_offset
);
713 ksplice_debug(4, "(S=%08lx A=%08lx ", sym_addr
, r
->addend
);
715 ksplice_debug(4, "aft=%08x)\n", *(int *)blank_addr
);
716 else if (r
->size
== 8)
717 ksplice_debug(4, "aft=%016llx)\n", *(long long *)blank_addr
);
723 int compute_address(struct module_pack
*pack
, char *sym_name
,
724 struct list_head
*vals
)
727 const char *prefix
[] = { ".text.", ".bss.", ".data.", NULL
};
728 #ifdef KSPLICE_STANDALONE
734 struct reloc_nameval
*nv
= find_nameval(pack
, sym_name
, 0);
735 if (nv
!= NULL
&& nv
->status
!= NOVAL
) {
737 ret
= add_candidate_val(vals
, nv
->val
);
740 ksplice_debug(1, KERN_DEBUG
"ksplice: using detected "
741 "sym %s=%08lx\n", sym_name
, nv
->val
);
746 if (starts_with(sym_name
, ".rodata"))
749 #ifdef CONFIG_KALLSYMS
750 ret
= kernel_lookup(sym_name
, vals
);
753 ret
= other_module_lookup(sym_name
, vals
, pack
->name
);
758 for (i
= 0; prefix
[i
] != NULL
; i
++) {
759 if (starts_with(sym_name
, prefix
[i
])) {
760 ret
= compute_address(pack
, sym_name
+
761 strlen(prefix
[i
]), vals
);
769 #ifdef KSPLICE_STANDALONE
770 void brute_search_all_mods(struct module_pack
*pack
, struct ksplice_size
*s
)
773 list_for_each_entry(m
, &(THIS_MODULE
->list
), list
) {
774 if (!starts_with(m
->name
, pack
->name
)
775 && !ends_with(m
->name
, "_helper")) {
776 if (brute_search(pack
, s
, m
->module_core
, m
->core_size
)
779 if (brute_search(pack
, s
, m
->module_init
, m
->init_size
)
786 /* old kernels do not have kcalloc */
787 void *ksplice_kcalloc(int size
)
789 char *mem
= kmalloc(size
, GFP_KERNEL
);
791 memset(mem
, 0, size
);
795 #ifdef CONFIG_KALLSYMS
796 /* Modified version of Linux's kallsyms_lookup_name */
797 int kernel_lookup(const char *name_wlabel
, struct list_head
*vals
)
800 char namebuf
[KSYM_NAME_LEN
+ 1];
802 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
804 #endif /* LINUX_VERSION_CODE */
806 const char *name
= dup_wolabel(name_wlabel
);
810 /* kallsyms compression was added by 5648d78927ca65e74aadc88a2b1d6431e55e78ec
811 * 2.6.10 was the first release after this commit
813 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
814 for (i
= 0, off
= 0; i
< kallsyms_num_syms
; i
++) {
815 off
= ksplice_kallsyms_expand_symbol(off
, namebuf
);
817 if (strcmp(namebuf
, name
) == 0) {
818 ret
= add_candidate_val(vals
, kallsyms_addresses
[i
]);
823 #else /* LINUX_VERSION_CODE */
826 for (i
= 0, knames
= kallsyms_names
; i
< kallsyms_num_syms
; i
++) {
827 unsigned prefix
= *knames
++;
829 strlcpy(namebuf
+ prefix
, knames
, KSYM_NAME_LEN
- prefix
);
831 if (strcmp(namebuf
, name
) == 0) {
832 ret
= add_candidate_val(vals
, kallsyms_addresses
[i
]);
837 knames
+= strlen(knames
) + 1;
839 #endif /* LINUX_VERSION_CODE */
845 /* kallsyms compression was added by 5648d78927ca65e74aadc88a2b1d6431e55e78ec
846 * 2.6.10 was the first release after this commit
848 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
849 extern u8 kallsyms_token_table
[];
850 extern u16 kallsyms_token_index
[];
851 /* Modified version of Linux's kallsyms_expand_symbol */
852 long ksplice_kallsyms_expand_symbol(unsigned long off
, char *result
)
854 long len
, skipped_first
= 0;
855 const u8
*tptr
, *data
;
857 data
= &kallsyms_names
[off
];
864 tptr
= &kallsyms_token_table
[kallsyms_token_index
[*data
]];
882 #endif /* LINUX_VERSION_CODE */
884 int other_module_lookup(const char *name_wlabel
, struct list_head
*vals
,
885 const char *ksplice_name
)
889 const char *name
= dup_wolabel(name_wlabel
);
893 list_for_each_entry(m
, &(THIS_MODULE
->list
), list
) {
894 if (!starts_with(m
->name
, ksplice_name
)
895 && !ends_with(m
->name
, "_helper")) {
896 ret
= ksplice_mod_find_sym(m
, name
, vals
);
906 /* Modified version of Linux's mod_find_symname */
908 ksplice_mod_find_sym(struct module
*m
, const char *name
, struct list_head
*vals
)
911 if (strlen(m
->name
) <= 1)
914 for (i
= 0; i
< m
->num_symtab
; i
++) {
915 const char *cursym_name
= m
->strtab
+ m
->symtab
[i
].st_name
;
916 if (strncmp(cursym_name
, name
, strlen(name
)) != 0)
919 cursym_name
= dup_wolabel(cursym_name
);
920 if (cursym_name
== NULL
)
922 if (strcmp(cursym_name
, name
) == 0 &&
923 m
->symtab
[i
].st_value
!= 0) {
924 ret
= add_candidate_val(vals
, m
->symtab
[i
].st_value
);
932 #endif /* CONFIG_KALLSYMS */
933 #else /* KSPLICE_STANDALONE */
934 EXPORT_SYMBOL_GPL(init_ksplice_module
);
935 EXPORT_SYMBOL_GPL(cleanup_ksplice_module
);
937 struct accumulate_struct
{
938 const char *desired_name
;
939 struct list_head
*vals
;
942 int init_module(void)
947 void cleanup_module(void)
951 int accumulate_matching_names(void *data
, const char *sym_name
, long sym_val
)
954 struct accumulate_struct
*acc
= data
;
956 if (strncmp(sym_name
, acc
->desired_name
, strlen(acc
->desired_name
)) !=
960 sym_name
= dup_wolabel(sym_name
);
961 if (sym_name
== NULL
)
963 /* TODO: possibly remove "&& sym_val != 0" */
964 if (strcmp(sym_name
, acc
->desired_name
) == 0 && sym_val
!= 0) {
965 ret
= add_candidate_val(acc
->vals
, sym_val
);
973 int kernel_lookup(const char *name_wlabel
, struct list_head
*vals
)
976 struct accumulate_struct acc
= { dup_wolabel(name_wlabel
), vals
};
977 if (acc
.desired_name
== NULL
)
979 ret
= kallsyms_on_each_symbol(accumulate_matching_names
, &acc
);
982 kfree(acc
.desired_name
);
986 int other_module_lookup(const char *name_wlabel
, struct list_head
*vals
,
987 const char *ksplice_name
)
990 struct accumulate_struct acc
= { dup_wolabel(name_wlabel
), vals
};
993 if (acc
.desired_name
== NULL
)
996 list_for_each_entry(m
, &(THIS_MODULE
->list
), list
) {
997 if (!starts_with(m
->name
, ksplice_name
)
998 && !ends_with(m
->name
, "_helper")) {
999 ret
= module_on_each_symbol(m
,
1000 accumulate_matching_names
,
1007 kfree(acc
.desired_name
);
1010 #endif /* KSPLICE_STANDALONE */
1012 int add_candidate_val(struct list_head
*vals
, long val
)
1014 struct candidate_val
*tmp
, *new;
1016 list_for_each_entry(tmp
, vals
, list
) {
1017 if (tmp
->val
== val
)
1020 new = kmalloc(sizeof(*new), GFP_KERNEL
);
1022 print_abort("out of memory");
1026 list_add(&new->list
, vals
);
1030 void release_vals(struct list_head
*vals
)
1032 clear_list(vals
, struct candidate_val
, list
);
1035 struct reloc_nameval
*find_nameval(struct module_pack
*pack
, char *name
,
1038 struct reloc_nameval
*nv
, *new;
1040 list_for_each_entry(nv
, pack
->reloc_namevals
, list
) {
1042 if (starts_with(newname
, ".text."))
1044 if (strcmp(newname
, name
) == 0)
1050 new = kmalloc(sizeof(*new), GFP_KERNEL
);
1052 print_abort("out of memory");
1057 new->status
= NOVAL
;
1058 list_add(&new->list
, pack
->reloc_namevals
);
1062 struct reloc_addrmap
*find_addrmap(struct module_pack
*pack
, long addr
)
1064 struct reloc_addrmap
*map
;
1065 list_for_each_entry(map
, pack
->reloc_addrmaps
, list
) {
1066 if (addr
>= map
->addr
&& addr
< map
->addr
+ map
->size
)
1072 void set_temp_myst_relocs(struct module_pack
*pack
, int status_val
)
1074 struct reloc_nameval
*nv
;
1075 list_for_each_entry(nv
, pack
->reloc_namevals
, list
) {
1076 if (nv
->status
== TEMP
)
1077 nv
->status
= status_val
;
1081 int starts_with(const char *str
, const char *prefix
)
1083 return strncmp(str
, prefix
, strlen(prefix
)) == 0;
1086 int ends_with(const char *str
, const char *suffix
)
1088 return strlen(str
) >= strlen(suffix
) &&
1089 strcmp(&str
[strlen(str
) - strlen(suffix
)], suffix
) == 0;
1092 int label_offset(const char *sym_name
)
1096 sym_name
[i
] != 0 && sym_name
[i
+ 1] != 0 && sym_name
[i
+ 2] != 0
1097 && sym_name
[i
+ 3] != 0; i
++) {
1098 if (sym_name
[i
] == '_' && sym_name
[i
+ 1] == '_'
1099 && sym_name
[i
+ 2] == '_' && sym_name
[i
+ 3] == '_')
1105 const char *dup_wolabel(const char *sym_name
)
1107 int offset
, entire_strlen
, label_strlen
, new_strlen
;
1110 offset
= label_offset(sym_name
);
1114 label_strlen
= strlen(&sym_name
[offset
]) + strlen("____");
1116 entire_strlen
= strlen(sym_name
);
1117 new_strlen
= entire_strlen
- label_strlen
;
1118 newstr
= kmalloc(new_strlen
+ 1, GFP_KERNEL
);
1119 if (newstr
== NULL
) {
1120 print_abort("out of memory");
1123 memcpy(newstr
, sym_name
, new_strlen
);
1124 newstr
[new_strlen
] = 0;
1128 MODULE_LICENSE("GPL v2");
1129 MODULE_AUTHOR("Jeffrey Brian Arnold <jbarnold@mit.edu>");