2 * @file ksyms/no_ksyms.c
3 * @author Vyacheslav Cherkashin <v.cherkashin@samsung.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 * Copyright (C) Samsung Electronics, 2013
25 * @section DESCRIPTION
27 * SWAP symbols searching implementation.
31 #include "ksyms_init.h"
32 #include <linux/types.h>
33 #include <linux/vmalloc.h>
34 #include <linux/semaphore.h>
36 #include <linux/slab.h>
37 #include <linux/fcntl.h>
41 * Error message define.
43 #define KSYMS_ERR(format, args...) \
46 char *n = strrchr(f, '/'); \
47 printk(KERN_INFO "%s:%u \'%s\' ERROR: " format "\n" , \
48 (n) ? n+1 : f, __LINE__, __func__, ##args); \
52 * @struct sys_map_item
53 * @brief System map list item info.
54 * @var sys_map_item::list
56 * @var sys_map_item::addr
58 * @var sys_map_item::name
62 struct list_head list;
69 module_param(sm_path, charp, 0);
73 * List of sys_map_item.
76 static struct file *file;
78 static int cnt_init_sm;
81 * @var cnt_init_sm_lock
82 * System map items list lock.
84 DEFINE_SEMAPHORE(cnt_init_sm_lock);
86 static int file_open(void)
88 struct file *f = filp_open(sm_path, O_RDONLY, 0);
91 KSYMS_ERR("cannot open file \'%s\'", sm_path);
100 static void file_close(void)
103 int ret = filp_close(file, NULL);
107 KSYMS_ERR("while closing file \'%s\' err=%d",
113 static int file_check(void)
115 int ret = file_open();
122 static long file_size(struct file *file)
125 if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st))
128 if (!S_ISREG(st.mode))
131 if (st.size != (long)st.size)
137 static struct sys_map_item *create_smi(unsigned long addr, const char *name)
139 struct sys_map_item *smi = kmalloc(sizeof(*smi), GFP_KERNEL);
142 KSYMS_ERR("not enough memory");
146 smi->name = kmalloc(strlen(name) + 1, GFP_KERNEL);
147 if (smi->name == NULL) {
149 KSYMS_ERR("not enough memory");
153 INIT_LIST_HEAD(&smi->list);
155 strcpy(smi->name, name);
160 static void free_smi(struct sys_map_item *smi)
166 static void add_smi(struct sys_map_item *smi)
168 list_add_tail(&smi->list, &smi_list);
171 static int is_endline(char c)
173 return c == '\n' || c == '\r' || c == '\0';
176 static int is_symbol_attr(char c)
178 return c == 't' || c == 'T';
181 static struct sys_map_item *get_sys_map_item(char *begin, char *end)
183 struct sys_map_item *smi = NULL;
184 int n, len = end - begin;
186 char attr, name[128], *line;
188 line = kmalloc(len + 1, GFP_KERNEL);
189 memcpy(line, begin, len);
192 n = sscanf(line, "%lx %c %127s", &addr, &attr, name);
196 KSYMS_ERR("parsing line: \"%s\"", line);
202 if (is_symbol_attr(attr))
203 smi = create_smi(addr, name);
209 static void parsing(char *buf, int size)
211 struct sys_map_item *smi;
212 char *start, *end, *c;
217 for (c = start; c < end; ++c) {
218 if (is_endline(*c)) {
219 smi = get_sys_map_item(start, c);
223 for (start = c; c < end; ++c) {
224 if (!is_endline(*c)) {
233 static int create_sys_map(void)
237 int ret = file_open();
242 size = file_size(file);
244 KSYMS_ERR("cannot get file size");
249 data = vmalloc(size);
251 KSYMS_ERR("not enough memory");
256 if (kernel_read(file, 0, data, size) != size) {
257 KSYMS_ERR("reading file %s", sm_path);
273 static void free_sys_map(void)
275 struct sys_map_item *smi, *n;
276 list_for_each_entry_safe(smi, n, &smi_list, list) {
277 list_del(&smi->list);
283 * @brief Generates symbols list.
285 * @return 0 on success.
287 int swap_get_ksyms(void)
291 down(&cnt_init_sm_lock);
292 if (cnt_init_sm == 0)
293 ret = create_sys_map();
296 up(&cnt_init_sm_lock);
300 EXPORT_SYMBOL_GPL(swap_get_ksyms);
303 * @brief Frees symbols list.
307 void swap_put_ksyms(void)
309 down(&cnt_init_sm_lock);
311 if (cnt_init_sm == 0)
314 if (cnt_init_sm < 0) {
315 KSYMS_ERR("cnt_init_sm=%d", cnt_init_sm);
319 up(&cnt_init_sm_lock);
321 EXPORT_SYMBOL_GPL(swap_put_ksyms);
324 * @brief Searches for symbol by its exact name.
326 * @param name Pointer the name string.
327 * @return Symbol's address.
329 unsigned long swap_ksyms(const char *name)
331 struct sys_map_item *smi;
333 list_for_each_entry(smi, &smi_list, list) {
334 if (strcmp(name, smi->name) == 0)
340 EXPORT_SYMBOL_GPL(swap_ksyms);
343 * @brief Searches for symbol by substring of its name.
345 * @param name Pointer to the name substring.
346 * @return Symbol's address.
348 unsigned long swap_ksyms_substr(const char *name)
350 struct sys_map_item *smi;
351 size_t len = strlen(name);
353 list_for_each_entry(smi, &smi_list, list) {
354 if (strncmp(name, smi->name, len) == 0)
360 EXPORT_SYMBOL_GPL(swap_ksyms_substr);
363 * @brief SWAP ksyms module initialization.
365 * @return 0 on success, negative error code on error.
371 if (sm_path == NULL) {
372 KSYMS_ERR("sm_path=NULL");
380 /* TODO: calling func 'swap_get_ksyms' in
381 * module used func 'swap_ksyms' */
388 * @brief SWAP ksyms module deinitialization.
392 void ksyms_exit(void)
394 down(&cnt_init_sm_lock);
399 up(&cnt_init_sm_lock);