~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/kernel/module/kallsyms.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /kernel/module/kallsyms.c (Version linux-6.12-rc7) and /kernel/module/kallsyms.c (Version linux-4.12.14)


  1 // SPDX-License-Identifier: GPL-2.0-or-later        1 
  2 /*                                                
  3  * Module kallsyms support                        
  4  *                                                
  5  * Copyright (C) 2010 Rusty Russell               
  6  */                                               
  7                                                   
  8 #include <linux/module.h>                         
  9 #include <linux/module_symbol.h>                  
 10 #include <linux/kallsyms.h>                       
 11 #include <linux/buildid.h>                        
 12 #include <linux/bsearch.h>                        
 13 #include "internal.h"                             
 14                                                   
 15 /* Lookup exported symbol in given range of ke    
 16 static const struct kernel_symbol *lookup_expo    
 17                                                   
 18                                                   
 19 {                                                 
 20         return bsearch(name, start, stop - sta    
 21                         sizeof(struct kernel_s    
 22 }                                                 
 23                                                   
 24 static int is_exported(const char *name, unsig    
 25                        const struct module *mo    
 26 {                                                 
 27         const struct kernel_symbol *ks;           
 28                                                   
 29         if (!mod)                                 
 30                 ks = lookup_exported_symbol(na    
 31         else                                      
 32                 ks = lookup_exported_symbol(na    
 33                                                   
 34         return ks && kernel_symbol_value(ks) =    
 35 }                                                 
 36                                                   
 37 /* As per nm */                                   
 38 static char elf_type(const Elf_Sym *sym, const    
 39 {                                                 
 40         const Elf_Shdr *sechdrs = info->sechdr    
 41                                                   
 42         if (ELF_ST_BIND(sym->st_info) == STB_W    
 43                 if (ELF_ST_TYPE(sym->st_info)     
 44                         return 'v';               
 45                 else                              
 46                         return 'w';               
 47         }                                         
 48         if (sym->st_shndx == SHN_UNDEF)           
 49                 return 'U';                       
 50         if (sym->st_shndx == SHN_ABS || sym->s    
 51                 return 'a';                       
 52         if (sym->st_shndx >= SHN_LORESERVE)       
 53                 return '?';                       
 54         if (sechdrs[sym->st_shndx].sh_flags &     
 55                 return 't';                       
 56         if (sechdrs[sym->st_shndx].sh_flags &     
 57             sechdrs[sym->st_shndx].sh_type !=     
 58                 if (!(sechdrs[sym->st_shndx].s    
 59                         return 'r';               
 60                 else if (sechdrs[sym->st_shndx    
 61                         return 'g';               
 62                 else                              
 63                         return 'd';               
 64         }                                         
 65         if (sechdrs[sym->st_shndx].sh_type ==     
 66                 if (sechdrs[sym->st_shndx].sh_    
 67                         return 's';               
 68                 else                              
 69                         return 'b';               
 70         }                                         
 71         if (strstarts(info->secstrings + sechd    
 72                       ".debug")) {                
 73                 return 'n';                       
 74         }                                         
 75         return '?';                               
 76 }                                                 
 77                                                   
 78 static bool is_core_symbol(const Elf_Sym *src,    
 79                            unsigned int shnum,    
 80 {                                                 
 81         const Elf_Shdr *sec;                      
 82         enum mod_mem_type type;                   
 83                                                   
 84         if (src->st_shndx == SHN_UNDEF ||         
 85             src->st_shndx >= shnum ||             
 86             !src->st_name)                        
 87                 return false;                     
 88                                                   
 89 #ifdef CONFIG_KALLSYMS_ALL                        
 90         if (src->st_shndx == pcpundx)             
 91                 return true;                      
 92 #endif                                            
 93                                                   
 94         sec = sechdrs + src->st_shndx;            
 95         type = sec->sh_entsize >> SH_ENTSIZE_T    
 96         if (!(sec->sh_flags & SHF_ALLOC)          
 97 #ifndef CONFIG_KALLSYMS_ALL                       
 98             || !(sec->sh_flags & SHF_EXECINSTR    
 99 #endif                                            
100             || mod_mem_type_is_init(type))        
101                 return false;                     
102                                                   
103         return true;                              
104 }                                                 
105                                                   
106 /*                                                
107  * We only allocate and copy the strings neede    
108  * we keep.  This is simple, but has the effec    
109  * copies of duplicates.  We could be more sop    
110  * linux-kernel thread starting with              
111  * <73defb5e4bca04a6431392cc341112b1@localhost    
112  */                                               
113 void layout_symtab(struct module *mod, struct     
114 {                                                 
115         Elf_Shdr *symsect = info->sechdrs + in    
116         Elf_Shdr *strsect = info->sechdrs + in    
117         const Elf_Sym *src;                       
118         unsigned int i, nsrc, ndst, strtab_siz    
119         struct module_memory *mod_mem_data = &    
120         struct module_memory *mod_mem_init_dat    
121                                                   
122         /* Put symbol section at end of init p    
123         symsect->sh_flags |= SHF_ALLOC;           
124         symsect->sh_entsize = module_get_offse    
125                                                   
126         pr_debug("\t%s\n", info->secstrings +     
127                                                   
128         src = (void *)info->hdr + symsect->sh_    
129         nsrc = symsect->sh_size / sizeof(*src)    
130                                                   
131         /* Compute total space required for th    
132         for (ndst = i = 0; i < nsrc; i++) {       
133                 if (i == 0 || is_livepatch_mod    
134                     is_core_symbol(src + i, in    
135                                    info->index    
136                         strtab_size += strlen(    
137                         ndst++;                   
138                 }                                 
139         }                                         
140                                                   
141         /* Append room for core symbols at end    
142         info->symoffs = ALIGN(mod_mem_data->si    
143         info->stroffs = mod_mem_data->size = i    
144         mod_mem_data->size += strtab_size;        
145         /* Note add_kallsyms() computes strtab    
146         info->core_typeoffs = mod_mem_data->si    
147         mod_mem_data->size += ndst * sizeof(ch    
148                                                   
149         /* Put string table section at end of     
150         strsect->sh_flags |= SHF_ALLOC;           
151         strsect->sh_entsize = module_get_offse    
152                                                   
153         pr_debug("\t%s\n", info->secstrings +     
154                                                   
155         /* We'll tack temporary mod_kallsyms o    
156         mod_mem_init_data->size = ALIGN(mod_me    
157                                         __alig    
158         info->mod_kallsyms_init_off = mod_mem_    
159                                                   
160         mod_mem_init_data->size += sizeof(stru    
161         info->init_typeoffs = mod_mem_init_dat    
162         mod_mem_init_data->size += nsrc * size    
163 }                                                 
164                                                   
165 /*                                                
166  * We use the full symtab and strtab which lay    
167  * be appended to the init section.  Later we     
168  * core-only ones.                                
169  */                                               
170 void add_kallsyms(struct module *mod, const st    
171 {                                                 
172         unsigned int i, ndst;                     
173         const Elf_Sym *src;                       
174         Elf_Sym *dst;                             
175         char *s;                                  
176         Elf_Shdr *symsec = &info->sechdrs[info    
177         unsigned long strtab_size;                
178         void *data_base = mod->mem[MOD_DATA].b    
179         void *init_data_base = mod->mem[MOD_IN    
180                                                   
181         /* Set up to point into init section.     
182         mod->kallsyms = (void __rcu *)init_dat    
183                 info->mod_kallsyms_init_off;      
184                                                   
185         rcu_read_lock();                          
186         /* The following is safe since this po    
187         rcu_dereference(mod->kallsyms)->symtab    
188         rcu_dereference(mod->kallsyms)->num_sy    
189         /* Make sure we get permanent strtab:     
190         rcu_dereference(mod->kallsyms)->strtab    
191                 (void *)info->sechdrs[info->in    
192         rcu_dereference(mod->kallsyms)->typeta    
193                                                   
194         /*                                        
195          * Now populate the cut down core kall    
196          * and set types up while we still hav    
197          */                                       
198         mod->core_kallsyms.symtab = dst = data    
199         mod->core_kallsyms.strtab = s = data_b    
200         mod->core_kallsyms.typetab = data_base    
201         strtab_size = info->core_typeoffs - in    
202         src = rcu_dereference(mod->kallsyms)->    
203         for (ndst = i = 0; i < rcu_dereference    
204                 rcu_dereference(mod->kallsyms)    
205                 if (i == 0 || is_livepatch_mod    
206                     is_core_symbol(src + i, in    
207                                    info->index    
208                         ssize_t ret;              
209                                                   
210                         mod->core_kallsyms.typ    
211                             rcu_dereference(mo    
212                         dst[ndst] = src[i];       
213                         dst[ndst++].st_name =     
214                         ret = strscpy(s,          
215                                       &rcu_der    
216                                       strtab_s    
217                         if (ret < 0)              
218                                 break;            
219                         s += ret + 1;             
220                         strtab_size -= ret + 1    
221                 }                                 
222         }                                         
223         rcu_read_unlock();                        
224         mod->core_kallsyms.num_symtab = ndst;     
225 }                                                 
226                                                   
227 #if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID)        
228 void init_build_id(struct module *mod, const s    
229 {                                                 
230         const Elf_Shdr *sechdr;                   
231         unsigned int i;                           
232                                                   
233         for (i = 0; i < info->hdr->e_shnum; i+    
234                 sechdr = &info->sechdrs[i];       
235                 if (!sect_empty(sechdr) && sec    
236                     !build_id_parse_buf((void     
237                                         sechdr    
238                         break;                    
239         }                                         
240 }                                                 
241 #else                                             
242 void init_build_id(struct module *mod, const s    
243 {                                                 
244 }                                                 
245 #endif                                            
246                                                   
247 static const char *kallsyms_symbol_name(struct    
248 {                                                 
249         return kallsyms->strtab + kallsyms->sy    
250 }                                                 
251                                                   
252 /*                                                
253  * Given a module and address, find the corres    
254  * while providing its size and offset if need    
255  */                                               
256 static const char *find_kallsyms_symbol(struct    
257                                         unsign    
258                                         unsign    
259                                         unsign    
260 {                                                 
261         unsigned int i, best = 0;                 
262         unsigned long nextval, bestval;           
263         struct mod_kallsyms *kallsyms = rcu_de    
264         struct module_memory *mod_mem;            
265                                                   
266         /* At worse, next value is at end of m    
267         if (within_module_init(addr, mod))        
268                 mod_mem = &mod->mem[MOD_INIT_T    
269         else                                      
270                 mod_mem = &mod->mem[MOD_TEXT];    
271                                                   
272         nextval = (unsigned long)mod_mem->base    
273                                                   
274         bestval = kallsyms_symbol_value(&kalls    
275                                                   
276         /*                                        
277          * Scan for closest preceding symbol,     
278          * starts real symbols at 1).             
279          */                                       
280         for (i = 1; i < kallsyms->num_symtab;     
281                 const Elf_Sym *sym = &kallsyms    
282                 unsigned long thisval = kallsy    
283                                                   
284                 if (sym->st_shndx == SHN_UNDEF    
285                         continue;                 
286                                                   
287                 /*                                
288                  * We ignore unnamed symbols:     
289                  * and inserted at a whim.        
290                  */                               
291                 if (*kallsyms_symbol_name(kall    
292                     is_mapping_symbol(kallsyms    
293                         continue;                 
294                                                   
295                 if (thisval <= addr && thisval    
296                         best = i;                 
297                         bestval = thisval;        
298                 }                                 
299                 if (thisval > addr && thisval     
300                         nextval = thisval;        
301         }                                         
302                                                   
303         if (!best)                                
304                 return NULL;                      
305                                                   
306         if (size)                                 
307                 *size = nextval - bestval;        
308         if (offset)                               
309                 *offset = addr - bestval;         
310                                                   
311         return kallsyms_symbol_name(kallsyms,     
312 }                                                 
313                                                   
314 void * __weak dereference_module_function_desc    
315                                                   
316 {                                                 
317         return ptr;                               
318 }                                                 
319                                                   
320 /*                                                
321  * For kallsyms to ask for address resolution.    
322  * not to lock to avoid deadlock on oopses, si    
323  */                                               
324 int module_address_lookup(unsigned long addr,     
325                           unsigned long *size,    
326                           unsigned long *offse    
327                           char **modname,         
328                           const unsigned char     
329                           char *namebuf)          
330 {                                                 
331         const char *sym;                          
332         int ret = 0;                              
333         struct module *mod;                       
334                                                   
335         preempt_disable();                        
336         mod = __module_address(addr);             
337         if (mod) {                                
338                 if (modname)                      
339                         *modname = mod->name;     
340                 if (modbuildid) {                 
341 #if IS_ENABLED(CONFIG_STACKTRACE_BUILD_ID)        
342                         *modbuildid = mod->bui    
343 #else                                             
344                         *modbuildid = NULL;       
345 #endif                                            
346                 }                                 
347                                                   
348                 sym = find_kallsyms_symbol(mod    
349                                                   
350                 if (sym)                          
351                         ret = strscpy(namebuf,    
352         }                                         
353         preempt_enable();                         
354                                                   
355         return ret;                               
356 }                                                 
357                                                   
358 int lookup_module_symbol_name(unsigned long ad    
359 {                                                 
360         struct module *mod;                       
361                                                   
362         preempt_disable();                        
363         list_for_each_entry_rcu(mod, &modules,    
364                 if (mod->state == MODULE_STATE    
365                         continue;                 
366                 if (within_module(addr, mod))     
367                         const char *sym;          
368                                                   
369                         sym = find_kallsyms_sy    
370                         if (!sym)                 
371                                 goto out;         
372                                                   
373                         strscpy(symname, sym,     
374                         preempt_enable();         
375                         return 0;                 
376                 }                                 
377         }                                         
378 out:                                              
379         preempt_enable();                         
380         return -ERANGE;                           
381 }                                                 
382                                                   
383 int module_get_kallsym(unsigned int symnum, un    
384                        char *name, char *modul    
385 {                                                 
386         struct module *mod;                       
387                                                   
388         preempt_disable();                        
389         list_for_each_entry_rcu(mod, &modules,    
390                 struct mod_kallsyms *kallsyms;    
391                                                   
392                 if (mod->state == MODULE_STATE    
393                         continue;                 
394                 kallsyms = rcu_dereference_sch    
395                 if (symnum < kallsyms->num_sym    
396                         const Elf_Sym *sym = &    
397                                                   
398                         *value = kallsyms_symb    
399                         *type = kallsyms->type    
400                         strscpy(name, kallsyms    
401                         strscpy(module_name, m    
402                         *exported = is_exporte    
403                         preempt_enable();         
404                         return 0;                 
405                 }                                 
406                 symnum -= kallsyms->num_symtab    
407         }                                         
408         preempt_enable();                         
409         return -ERANGE;                           
410 }                                                 
411                                                   
412 /* Given a module and name of symbol, find and    
413 static unsigned long __find_kallsyms_symbol_va    
414 {                                                 
415         unsigned int i;                           
416         struct mod_kallsyms *kallsyms = rcu_de    
417                                                   
418         for (i = 0; i < kallsyms->num_symtab;     
419                 const Elf_Sym *sym = &kallsyms    
420                                                   
421                 if (strcmp(name, kallsyms_symb    
422                     sym->st_shndx != SHN_UNDEF    
423                         return kallsyms_symbol    
424         }                                         
425         return 0;                                 
426 }                                                 
427                                                   
428 static unsigned long __module_kallsyms_lookup_    
429 {                                                 
430         struct module *mod;                       
431         char *colon;                              
432                                                   
433         colon = strnchr(name, MODULE_NAME_LEN,    
434         if (colon) {                              
435                 mod = find_module_all(name, co    
436                 if (mod)                          
437                         return __find_kallsyms    
438                 return 0;                         
439         }                                         
440                                                   
441         list_for_each_entry_rcu(mod, &modules,    
442                 unsigned long ret;                
443                                                   
444                 if (mod->state == MODULE_STATE    
445                         continue;                 
446                 ret = __find_kallsyms_symbol_v    
447                 if (ret)                          
448                         return ret;               
449         }                                         
450         return 0;                                 
451 }                                                 
452                                                   
453 /* Look for this name: can be of form module:n    
454 unsigned long module_kallsyms_lookup_name(cons    
455 {                                                 
456         unsigned long ret;                        
457                                                   
458         /* Don't lock: we're in enough trouble    
459         preempt_disable();                        
460         ret = __module_kallsyms_lookup_name(na    
461         preempt_enable();                         
462         return ret;                               
463 }                                                 
464                                                   
465 unsigned long find_kallsyms_symbol_value(struc    
466 {                                                 
467         unsigned long ret;                        
468                                                   
469         preempt_disable();                        
470         ret = __find_kallsyms_symbol_value(mod    
471         preempt_enable();                         
472         return ret;                               
473 }                                                 
474                                                   
475 int module_kallsyms_on_each_symbol(const char     
476                                    int (*fn)(v    
477                                    void *data)    
478 {                                                 
479         struct module *mod;                       
480         unsigned int i;                           
481         int ret = 0;                              
482                                                   
483         mutex_lock(&module_mutex);                
484         list_for_each_entry(mod, &modules, lis    
485                 struct mod_kallsyms *kallsyms;    
486                                                   
487                 if (mod->state == MODULE_STATE    
488                         continue;                 
489                                                   
490                 if (modname && strcmp(modname,    
491                         continue;                 
492                                                   
493                 /* Use rcu_dereference_sched()    
494                 preempt_disable();                
495                 kallsyms = rcu_dereference_sch    
496                 preempt_enable();                 
497                                                   
498                 for (i = 0; i < kallsyms->num_    
499                         const Elf_Sym *sym = &    
500                                                   
501                         if (sym->st_shndx == S    
502                                 continue;         
503                                                   
504                         ret = fn(data, kallsym    
505                                  kallsyms_symb    
506                         if (ret != 0)             
507                                 goto out;         
508                 }                                 
509                                                   
510                 /*                                
511                  * The given module is found,     
512                  * need to be compared.           
513                  */                               
514                 if (modname)                      
515                         break;                    
516         }                                         
517 out:                                              
518         mutex_unlock(&module_mutex);              
519         return ret;                               
520 }                                                 
521                                                   

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php