~ [ 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-6.1.116)


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

~ [ 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