1919 *
2020 */
2121
22+ #include <errno.h>
2223#include <getopt.h>
2324#include <stdbool.h>
2425#include <stdio.h>
2930
3031#define ARRAY_SIZE (arr ) (sizeof(arr) / sizeof(arr[0]))
3132
32- #define _stringify_1 (x ) #x
33- #define _stringify (x ) _stringify_1(x)
34-
3533#define KSYM_NAME_LEN 512
3634
37- /*
38- * A substantially bigger size than the current maximum.
39- *
40- * It cannot be defined as an expression because it gets stringified
41- * for the fscanf() format string. Therefore, a _Static_assert() is
42- * used instead to maintain the relationship with KSYM_NAME_LEN.
43- */
44- #define KSYM_NAME_LEN_BUFFER 2048
45- _Static_assert (
46- KSYM_NAME_LEN_BUFFER == KSYM_NAME_LEN * 4 ,
47- "Please keep KSYM_NAME_LEN_BUFFER in sync with KSYM_NAME_LEN"
48- );
49-
5035struct sym_entry {
5136 unsigned long long addr ;
5237 unsigned int len ;
@@ -136,24 +121,40 @@ static void check_symbol_range(const char *sym, unsigned long long addr,
136121 }
137122}
138123
139- static struct sym_entry * read_symbol (FILE * in )
124+ static struct sym_entry * read_symbol (FILE * in , char * * buf , size_t * buf_len )
140125{
141- char name [ KSYM_NAME_LEN_BUFFER + 1 ] , type ;
126+ char * name , type , * p ;
142127 unsigned long long addr ;
143- unsigned int len ;
128+ size_t len ;
129+ ssize_t readlen ;
144130 struct sym_entry * sym ;
145- int rc ;
146131
147- rc = fscanf (in , "%llx %c %" _stringify (KSYM_NAME_LEN_BUFFER ) "s\n" , & addr , & type , name );
148- if (rc != 3 ) {
149- if (rc != EOF && fgets (name , ARRAY_SIZE (name ), in ) == NULL )
150- fprintf (stderr , "Read error or end of file.\n" );
132+ readlen = getline (buf , buf_len , in );
133+ if (readlen < 0 ) {
134+ if (errno ) {
135+ perror ("read_symbol" );
136+ exit (EXIT_FAILURE );
137+ }
151138 return NULL ;
152139 }
153- if (strlen (name ) >= KSYM_NAME_LEN ) {
140+
141+ if ((* buf )[readlen - 1 ] == '\n' )
142+ (* buf )[readlen - 1 ] = 0 ;
143+
144+ addr = strtoull (* buf , & p , 16 );
145+
146+ if (* buf == p || * p ++ != ' ' || !isascii ((type = * p ++ )) || * p ++ != ' ' ) {
147+ fprintf (stderr , "line format error\n" );
148+ exit (EXIT_FAILURE );
149+ }
150+
151+ name = p ;
152+ len = strlen (name );
153+
154+ if (len >= KSYM_NAME_LEN ) {
154155 fprintf (stderr , "Symbol %s too long for kallsyms (%zu >= %d).\n"
155156 "Please increase KSYM_NAME_LEN both in kernel and kallsyms.c\n" ,
156- name , strlen ( name ) , KSYM_NAME_LEN );
157+ name , len , KSYM_NAME_LEN );
157158 return NULL ;
158159 }
159160
@@ -169,8 +170,7 @@ static struct sym_entry *read_symbol(FILE *in)
169170
170171 /* include the type field in the symbol name, so that it gets
171172 * compressed together */
172-
173- len = strlen (name ) + 1 ;
173+ len ++ ;
174174
175175 sym = malloc (sizeof (* sym ) + len + 1 );
176176 if (!sym ) {
@@ -257,6 +257,8 @@ static void read_map(const char *in)
257257{
258258 FILE * fp ;
259259 struct sym_entry * sym ;
260+ char * buf = NULL ;
261+ size_t buflen = 0 ;
260262
261263 fp = fopen (in , "r" );
262264 if (!fp ) {
@@ -265,7 +267,7 @@ static void read_map(const char *in)
265267 }
266268
267269 while (!feof (fp )) {
268- sym = read_symbol (fp );
270+ sym = read_symbol (fp , & buf , & buflen );
269271 if (!sym )
270272 continue ;
271273
@@ -284,6 +286,7 @@ static void read_map(const char *in)
284286 table [table_cnt ++ ] = sym ;
285287 }
286288
289+ free (buf );
287290 fclose (fp );
288291}
289292
0 commit comments