xref: /linux/tools/lib/symbol/kallsyms.c (revision 088e88be5a380cc4e81963a9a02815da465d144f)
1 // SPDX-License-Identifier: GPL-2.0
2 #include "symbol/kallsyms.h"
3 #include <stdio.h>
4 #include <stdlib.h>
5 
6 u8 kallsyms2elf_type(char type)
7 {
8 	type = tolower(type);
9 	return (type == 't' || type == 'w') ? STT_FUNC : STT_OBJECT;
10 }
11 
12 bool kallsyms__is_function(char symbol_type)
13 {
14 	symbol_type = toupper(symbol_type);
15 	return symbol_type == 'T' || symbol_type == 'W';
16 }
17 
18 /*
19  * While we find nice hex chars, build a long_val.
20  * Return number of chars processed.
21  */
22 int hex2u64(const char *ptr, u64 *long_val)
23 {
24 	char *p;
25 
26 	*long_val = strtoull(ptr, &p, 16);
27 
28 	return p - ptr;
29 }
30 
31 int kallsyms__parse(const char *filename, void *arg,
32 		    int (*process_symbol)(void *arg, const char *name,
33 					  char type, u64 start))
34 {
35 	char *line = NULL;
36 	size_t n;
37 	int err = -1;
38 	FILE *file = fopen(filename, "r");
39 
40 	if (file == NULL)
41 		goto out_failure;
42 
43 	err = 0;
44 
45 	while (!feof(file)) {
46 		u64 start;
47 		int line_len, len;
48 		char symbol_type;
49 		char *symbol_name;
50 
51 		line_len = getline(&line, &n, file);
52 		if (line_len < 0 || !line)
53 			break;
54 
55 		line[--line_len] = '\0'; /* \n */
56 
57 		len = hex2u64(line, &start);
58 
59 		/* Skip the line if we failed to parse the address. */
60 		if (!len)
61 			continue;
62 
63 		len++;
64 		if (len + 2 >= line_len)
65 			continue;
66 
67 		symbol_type = line[len];
68 		len += 2;
69 		symbol_name = line + len;
70 		len = line_len - len;
71 
72 		if (len >= KSYM_NAME_LEN) {
73 			err = -1;
74 			break;
75 		}
76 
77 		err = process_symbol(arg, symbol_name, symbol_type, start);
78 		if (err)
79 			break;
80 	}
81 
82 	free(line);
83 	fclose(file);
84 	return err;
85 
86 out_failure:
87 	return -1;
88 }
89