Do not use assignment in if condition.
[ksplice.git] / kmodsrc / ksplice.h
blobfc2f1c3ece3265755c2c7fe2cb64cac90c74a8ec
1 #include <linux/module.h>
2 #include <linux/pagemap.h>
3 #include <linux/sched.h>
4 #include <linux/version.h>
6 enum ksplice_state_enum {
7 KSPLICE_PREPARING, KSPLICE_APPLIED, KSPLICE_REVERSED
8 };
10 struct ksplice_reloc {
11 char *sym_name;
12 char *blank_sect_name;
13 long blank_sect_addr;
14 long blank_offset;
15 long num_sym_addrs;
16 long *sym_addrs;
17 long num_sect_addrs;
18 long *sect_addrs;
19 int pcrel;
20 long addend;
21 long size;
24 struct ksplice_size {
25 char *name;
26 long size;
27 long thismod_addr;
28 long num_sym_addrs;
29 long *sym_addrs;
32 struct ksplice_patch {
33 char *oldstr;
34 char *replstr;
35 long oldaddr;
36 long repladdr;
37 char *saved;
40 struct module_pack {
41 const char *name;
42 int helper;
43 long map_printk;
44 enum ksplice_state_enum state;
45 struct ksplice_reloc *primary_relocs;
46 struct ksplice_size *primary_sizes;
47 struct ksplice_reloc *helper_relocs;
48 struct ksplice_size *helper_sizes;
49 struct ksplice_patch *patches;
50 struct list_head *reloc_addrmaps;
51 struct list_head *reloc_namevals;
52 struct list_head *safety_records;
55 struct reloc_nameval {
56 struct list_head list;
57 char *name;
58 long val;
59 enum { NOVAL, TEMP, VAL } status;
62 struct reloc_addrmap {
63 struct list_head list;
64 long addr;
65 long addend;
66 int pcrel;
67 struct reloc_nameval *nameval;
68 int size;
71 static inline int virtual_address_mapped(long addr)
73 pgd_t *pgd;
74 #if defined(pud_page)
75 pud_t *pud;
76 #endif
77 pmd_t *pmd;
78 pte_t *ptep;
80 if (addr > init_mm.start_code && addr < init_mm.end_code)
81 return 1;
83 pgd = pgd_offset_k(addr);
84 if (pgd_none(*pgd))
85 return 0;
87 #if defined(pud_page)
88 pud = pud_offset(pgd, addr);
89 pmd = pmd_offset(pud, addr);
90 #else
91 pmd = pmd_offset(pgd, addr);
92 #endif
94 if (pmd_none(*pmd))
95 return 0;
96 ptep = pte_offset_map(pmd, addr);
97 if (!pte_present(*ptep)) {
98 pte_unmap(ptep);
99 return 0;
101 pte_unmap(ptep);
103 return 1;
106 struct reloc_nameval *find_nameval(struct module_pack *pack, char *name,
107 int create);
108 struct reloc_addrmap *find_addrmap(struct module_pack *pack, long addr);
109 int handle_myst_reloc(long pre_addr, int *pre_z, long run_addr,
110 int *run_z, struct reloc_addrmap *map, int rerun);
112 struct safety_record {
113 struct list_head list;
114 long addr;
115 int size;
116 int care;
119 struct candidate_val {
120 struct list_head list;
121 long val;
124 #define singular(list) (!list_empty(list) && (list)->next->next == (list))
125 #define failed_to_find(sym_name) \
126 printk(KERN_ERR "ksplice: Failed to find symbol %s at %s:%d\n", \
127 sym_name, __FILE__, __LINE__)
129 static inline void print_abort(const char *str)
131 printk(KERN_ERR "ksplice: Aborted. (%s)\n", str);
134 #define ksplice_debug(level, fmt, ...) \
135 do { if (debug >= (level)) printk(fmt, ## __VA_ARGS__); } while (0)
137 int process_ksplice_relocs(struct module_pack *pack,
138 struct ksplice_reloc *relocs);
139 int process_reloc(struct module_pack *pack, struct ksplice_reloc *r);
140 int compute_address(struct module_pack *pack, char *sym_name,
141 struct list_head *vals);
143 #ifndef KSPLICE_STANDALONE
144 int accumulate_matching_names(void *data, const char *sym_name, long sym_val);
145 #endif
147 #ifdef CONFIG_KALLSYMS
148 #if defined KSPLICE_STANDALONE && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
149 long ksplice_kallsyms_expand_symbol(unsigned long off, char *result);
150 #endif
151 int kernel_lookup(const char *name_wlabel, struct list_head *vals);
152 int other_module_lookup(const char *name_wlabel, struct list_head *vals,
153 const char *ksplice_name);
154 int ksplice_mod_find_sym(struct module *m, const char *name,
155 struct list_head *vals);
156 #endif
158 int add_candidate_val(struct list_head *vals, long val);
159 void release_vals(struct list_head *vals);
160 void set_temp_myst_relocs(struct module_pack *pack, int status_val);
161 int starts_with(const char *str, const char *prefix);
162 int ends_with(const char *str, const char *suffix);
163 int label_offset(const char *sym_name);
164 const char *dup_wolabel(const char *sym_name);
166 #define clear_list(head, type, member) \
167 do { \
168 struct list_head *_pos, *_n; \
169 list_for_each_safe(_pos, _n, head) { \
170 list_del(_pos); \
171 kfree(list_entry(_pos, type, member)); \
173 } while (0)
175 int init_module(void);
176 void cleanup_module(void);
177 int init_ksplice_module(struct module_pack *pack);
178 void cleanup_ksplice_module(struct module_pack *pack);
180 /* primary */
181 int activate_primary(struct module_pack *pack);
182 int resolve_patch_symbols(struct module_pack *pack);
183 int procfile_read(char *buffer, char **buffer_location, off_t offset,
184 int buffer_length, int *eof, void *data);
185 int procfile_write(struct file *file, const char *buffer,
186 unsigned long count, void *data);
187 int __apply_patches(void *packptr);
188 int __reverse_patches(void *packptr);
189 int check_each_task(struct module_pack *pack);
190 int check_task(struct module_pack *pack, struct task_struct *t);
191 int check_stack(struct module_pack *pack, struct thread_info *tinfo,
192 long *stack);
193 int check_address_for_conflict(struct module_pack *pack, long addr);
194 int valid_stack_ptr(struct thread_info *tinfo, void *p);
196 /* helper */
197 int activate_helper(struct module_pack *pack);
198 int search_for_match(struct module_pack *pack, struct ksplice_size *s);
199 int try_addr(struct module_pack *pack, struct ksplice_size *s, long run_addr,
200 long pre_addr, int create_nameval);
202 #ifdef KSPLICE_STANDALONE
203 void *ksplice_kcalloc(int size);
204 void brute_search_all_mods(struct module_pack *pack, struct ksplice_size *s);
206 static inline int brute_search(struct module_pack *pack, struct ksplice_size *s,
207 void *start, long len)
209 long addr;
210 char run, pre;
212 for (addr = (long)start; addr < (long)start + len; addr++) {
213 if (addr % 100000 == 0)
214 yield();
216 if (!virtual_address_mapped(addr))
217 return 1;
219 run = *(unsigned char *)(addr);
220 pre = *(unsigned char *)(s->thismod_addr);
222 if (run != pre)
223 return 1;
225 if (addr == s->thismod_addr)
226 return 1;
228 if (try_addr(pack, s, addr, s->thismod_addr, 1))
229 return 0;
232 return 1;
234 #endif /* KSPLICE_STANDALONE */