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

TOMOYO Linux Cross Reference
Linux/arch/arm/kernel/module.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 /arch/arm/kernel/module.c (Architecture mips) and /arch/i386/kernel/module.c (Architecture i386)


  1 // SPDX-License-Identifier: GPL-2.0-only            1 
  2 /*                                                
  3  *  linux/arch/arm/kernel/module.c                
  4  *                                                
  5  *  Copyright (C) 2002 Russell King.              
  6  *  Modified for nommu by Hyok S. Choi            
  7  *                                                
  8  * Module allocation method suggested by Andi     
  9  */                                               
 10 #include <linux/module.h>                         
 11 #include <linux/moduleloader.h>                   
 12 #include <linux/kernel.h>                         
 13 #include <linux/mm.h>                             
 14 #include <linux/elf.h>                            
 15 #include <linux/fs.h>                             
 16 #include <linux/string.h>                         
 17                                                   
 18 #include <asm/sections.h>                         
 19 #include <asm/smp_plat.h>                         
 20 #include <asm/unwind.h>                           
 21 #include <asm/opcodes.h>                          
 22                                                   
 23 bool module_init_section(const char *name)        
 24 {                                                 
 25         return strstarts(name, ".init") ||        
 26                 strstarts(name, ".ARM.extab.in    
 27                 strstarts(name, ".ARM.exidx.in    
 28 }                                                 
 29                                                   
 30 bool module_exit_section(const char *name)        
 31 {                                                 
 32         return strstarts(name, ".exit") ||        
 33                 strstarts(name, ".ARM.extab.ex    
 34                 strstarts(name, ".ARM.exidx.ex    
 35 }                                                 
 36                                                   
 37 #ifdef CONFIG_ARM_HAS_GROUP_RELOCS                
 38 /*                                                
 39  * This implements the partitioning algorithm     
 40  * documented in the ARM AArch32 ELF psABI (IH    
 41  *                                                
 42  * A single PC-relative symbol reference is di    
 43  * operations, where the final one could be in    
 44  * instruction with immediate offset. E.g.,       
 45  *                                                
 46  *   ADD        Rd, PC, #...            or        
 47  *   ADD        Rd, Rd, #...                      
 48  *   LDR        Rd, [Rd, #...]                    
 49  *                                                
 50  * The latter has a guaranteed range of only 1    
 51  * of limited use in the kernel. However, the     
 52  * -/+ 256 MiB, (2x8 + 12 == 28 bits), which m    
 53  * any in-kernel symbol reference (unless modu    
 54  *                                                
 55  * The main advantage of this approach over th    
 56  * load is that literal loads may miss in the     
 57  * lower cache efficiency for variables that a    
 58  * different places in the code.                  
 59  */                                               
 60 static u32 get_group_rem(u32 group, u32 *offse    
 61 {                                                 
 62         u32 val = *offset;                        
 63         u32 shift;                                
 64         do {                                      
 65                 shift = val ? (31 - __fls(val)    
 66                 *offset = val;                    
 67                 if (!val)                         
 68                         break;                    
 69                 val &= 0xffffff >> shift;         
 70         } while (group--);                        
 71         return shift;                             
 72 }                                                 
 73 #endif                                            
 74                                                   
 75 int                                               
 76 apply_relocate(Elf32_Shdr *sechdrs, const char    
 77                unsigned int relindex, struct m    
 78 {                                                 
 79         Elf32_Shdr *symsec = sechdrs + syminde    
 80         Elf32_Shdr *relsec = sechdrs + relinde    
 81         Elf32_Shdr *dstsec = sechdrs + relsec-    
 82         Elf32_Rel *rel = (void *)relsec->sh_ad    
 83         unsigned int i;                           
 84                                                   
 85         for (i = 0; i < relsec->sh_size / size    
 86                 unsigned long loc;                
 87                 Elf32_Sym *sym;                   
 88                 const char *symname;              
 89 #ifdef CONFIG_ARM_HAS_GROUP_RELOCS                
 90                 u32 shift, group = 1;             
 91 #endif                                            
 92                 s32 offset;                       
 93                 u32 tmp;                          
 94 #ifdef CONFIG_THUMB2_KERNEL                       
 95                 u32 upper, lower, sign, j1, j2    
 96 #endif                                            
 97                                                   
 98                 offset = ELF32_R_SYM(rel->r_in    
 99                 if (offset < 0 || offset > (sy    
100                         pr_err("%s: section %u    
101                                 module->name,     
102                         return -ENOEXEC;          
103                 }                                 
104                                                   
105                 sym = ((Elf32_Sym *)symsec->sh    
106                 symname = strtab + sym->st_nam    
107                                                   
108                 if (rel->r_offset < 0 || rel->    
109                         pr_err("%s: section %u    
110                                module->name, r    
111                                rel->r_offset,     
112                         return -ENOEXEC;          
113                 }                                 
114                                                   
115                 loc = dstsec->sh_addr + rel->r    
116                                                   
117                 switch (ELF32_R_TYPE(rel->r_in    
118                 case R_ARM_NONE:                  
119                         /* ignore */              
120                         break;                    
121                                                   
122                 case R_ARM_ABS32:                 
123                 case R_ARM_TARGET1:               
124                         *(u32 *)loc += sym->st    
125                         break;                    
126                                                   
127                 case R_ARM_PC24:                  
128                 case R_ARM_CALL:                  
129                 case R_ARM_JUMP24:                
130                         if (sym->st_value & 3)    
131                                 pr_err("%s: se    
132                                        module-    
133                                 return -ENOEXE    
134                         }                         
135                                                   
136                         offset = __mem_to_opco    
137                         offset = (offset & 0x0    
138                         offset = sign_extend32    
139                                                   
140                         offset += sym->st_valu    
141                                                   
142                         /*                        
143                          * Route through a PLT    
144                          * supported range. No    
145                          * contains the absolu    
146                          * @sym + addend, corr    
147                          */                       
148                         if (IS_ENABLED(CONFIG_    
149                             (offset <= (s32)0x    
150                              offset >= (s32)0x    
151                                 offset = get_m    
152                                                   
153                                          - loc    
154                                                   
155                         if (offset <= (s32)0xf    
156                             offset >= (s32)0x0    
157                                 pr_err("%s: se    
158                                        module-    
159                                        ELF32_R    
160                                        sym->st    
161                                 return -ENOEXE    
162                         }                         
163                                                   
164                         offset >>= 2;             
165                         offset &= 0x00ffffff;     
166                                                   
167                         *(u32 *)loc &= __opcod    
168                         *(u32 *)loc |= __opcod    
169                         break;                    
170                                                   
171                case R_ARM_V4BX:                   
172                        /* Preserve Rm and the     
173                         * other bits to re-cod    
174                         * MOV PC,Rm.              
175                         */                        
176                        *(u32 *)loc &= __opcode    
177                        *(u32 *)loc |= __opcode    
178                        break;                     
179                                                   
180                 case R_ARM_PREL31:                
181                         offset = (*(s32 *)loc     
182                         offset += sym->st_valu    
183                         if (offset >= 0x400000    
184                                 pr_err("%s: se    
185                                        module-    
186                                        ELF32_R    
187                                        sym->st    
188                                 return -ENOEXE    
189                         }                         
190                         *(u32 *)loc &= 0x80000    
191                         *(u32 *)loc |= offset     
192                         break;                    
193                                                   
194                 case R_ARM_REL32:                 
195                         *(u32 *)loc += sym->st    
196                         break;                    
197                                                   
198                 case R_ARM_MOVW_ABS_NC:           
199                 case R_ARM_MOVT_ABS:              
200                 case R_ARM_MOVW_PREL_NC:          
201                 case R_ARM_MOVT_PREL:             
202                         offset = tmp = __mem_t    
203                         offset = ((offset & 0x    
204                         offset = sign_extend32    
205                                                   
206                         offset += sym->st_valu    
207                         if (ELF32_R_TYPE(rel->    
208                             ELF32_R_TYPE(rel->    
209                                 offset -= loc;    
210                         if (ELF32_R_TYPE(rel->    
211                             ELF32_R_TYPE(rel->    
212                                 offset >>= 16;    
213                                                   
214                         tmp &= 0xfff0f000;        
215                         tmp |= ((offset & 0xf0    
216                                 (offset & 0x0f    
217                                                   
218                         *(u32 *)loc = __opcode    
219                         break;                    
220                                                   
221 #ifdef CONFIG_ARM_HAS_GROUP_RELOCS                
222                 case R_ARM_ALU_PC_G0_NC:          
223                         group = 0;                
224                         fallthrough;              
225                 case R_ARM_ALU_PC_G1_NC:          
226                         tmp = __mem_to_opcode_    
227                         offset = ror32(tmp & 0    
228                         if (tmp & BIT(22))        
229                                 offset = -offs    
230                         offset += sym->st_valu    
231                         if (offset < 0) {         
232                                 offset = -offs    
233                                 tmp = (tmp & ~    
234                         } else {                  
235                                 tmp = (tmp & ~    
236                         }                         
237                                                   
238                         shift = get_group_rem(    
239                         if (shift < 24) {         
240                                 offset >>= 24     
241                                 offset |= (shi    
242                         }                         
243                         *(u32 *)loc = __opcode    
244                         break;                    
245                                                   
246                 case R_ARM_LDR_PC_G2:             
247                         tmp = __mem_to_opcode_    
248                         offset = tmp & 0xfff;     
249                         if (~tmp & BIT(23))       
250                                 offset = -offs    
251                         offset += sym->st_valu    
252                         if (offset < 0) {         
253                                 offset = -offs    
254                                 tmp &= ~BIT(23    
255                         } else {                  
256                                 tmp |= BIT(23)    
257                         }                         
258                         get_group_rem(2, &offs    
259                                                   
260                         if (offset > 0xfff) {     
261                                 pr_err("%s: se    
262                                        module-    
263                                        ELF32_R    
264                                        sym->st    
265                                 return -ENOEXE    
266                         }                         
267                         *(u32 *)loc = __opcode    
268                         break;                    
269 #endif                                            
270 #ifdef CONFIG_THUMB2_KERNEL                       
271                 case R_ARM_THM_CALL:              
272                 case R_ARM_THM_JUMP24:            
273                         /*                        
274                          * For function symbol    
275                          * allowed (no interwo    
276                          *                        
277                          * For non-function sy    
278                          * has no specific ARM    
279                          * the branch is resol    
280                          * that interworking i    
281                          */                       
282                         if (ELF32_ST_TYPE(sym-    
283                             !(sym->st_value &     
284                                 pr_err("%s: se    
285                                        module-    
286                                 return -ENOEXE    
287                         }                         
288                                                   
289                         upper = __mem_to_opcod    
290                         lower = __mem_to_opcod    
291                                                   
292                         /*                        
293                          * 25 bit signed addre    
294                          * instructions):         
295                          *   S:I1:I2:imm10:imm    
296                          * where:                 
297                          *   S     = upper[10]    
298                          *   I1    = ~(J1 ^ S)    
299                          *   I2    = ~(J2 ^ S)    
300                          *   imm10 = upper[9:0    
301                          *   imm11 = lower[10:    
302                          *   J1    = lower[13]    
303                          *   J2    = lower[11]    
304                          */                       
305                         sign = (upper >> 10) &    
306                         j1 = (lower >> 13) & 1    
307                         j2 = (lower >> 11) & 1    
308                         offset = (sign << 24)     
309                                 ((~(j2 ^ sign)    
310                                 ((upper & 0x03    
311                                 ((lower & 0x07    
312                         offset = sign_extend32    
313                         offset += sym->st_valu    
314                                                   
315                         /*                        
316                          * Route through a PLT    
317                          * supported range.       
318                          */                       
319                         if (IS_ENABLED(CONFIG_    
320                             (offset <= (s32)0x    
321                              offset >= (s32)0x    
322                                 offset = get_m    
323                                                   
324                                          - loc    
325                                                   
326                         if (offset <= (s32)0xf    
327                             offset >= (s32)0x0    
328                                 pr_err("%s: se    
329                                        module-    
330                                        ELF32_R    
331                                        sym->st    
332                                 return -ENOEXE    
333                         }                         
334                                                   
335                         sign = (offset >> 24)     
336                         j1 = sign ^ (~(offset     
337                         j2 = sign ^ (~(offset     
338                         upper = (u16)((upper &    
339                                             ((    
340                         lower = (u16)((lower &    
341                                       (j1 << 1    
342                                       ((offset    
343                                                   
344                         *(u16 *)loc = __opcode    
345                         *(u16 *)(loc + 2) = __    
346                         break;                    
347                                                   
348                 case R_ARM_THM_MOVW_ABS_NC:       
349                 case R_ARM_THM_MOVT_ABS:          
350                 case R_ARM_THM_MOVW_PREL_NC:      
351                 case R_ARM_THM_MOVT_PREL:         
352                         upper = __mem_to_opcod    
353                         lower = __mem_to_opcod    
354                                                   
355                         /*                        
356                          * MOVT/MOVW instructi    
357                          *                        
358                          * i    = upper[10]       
359                          * imm4 = upper[3:0]      
360                          * imm3 = lower[14:12]    
361                          * imm8 = lower[7:0]      
362                          *                        
363                          * imm16 = imm4:i:imm3    
364                          */                       
365                         offset = ((upper & 0x0    
366                                 ((upper & 0x04    
367                                 ((lower & 0x70    
368                         offset = sign_extend32    
369                         offset += sym->st_valu    
370                                                   
371                         if (ELF32_R_TYPE(rel->    
372                             ELF32_R_TYPE(rel->    
373                                 offset -= loc;    
374                         if (ELF32_R_TYPE(rel->    
375                             ELF32_R_TYPE(rel->    
376                                 offset >>= 16;    
377                                                   
378                         upper = (u16)((upper &    
379                                       ((offset    
380                                       ((offset    
381                         lower = (u16)((lower &    
382                                       ((offset    
383                                       (offset     
384                         *(u16 *)loc = __opcode    
385                         *(u16 *)(loc + 2) = __    
386                         break;                    
387 #endif                                            
388                                                   
389                 default:                          
390                         pr_err("%s: unknown re    
391                                module->name, E    
392                         return -ENOEXEC;          
393                 }                                 
394         }                                         
395         return 0;                                 
396 }                                                 
397                                                   
398 static const Elf_Shdr *find_mod_section(const     
399         const Elf_Shdr *sechdrs, const char *n    
400 {                                                 
401         const Elf_Shdr *s, *se;                   
402         const char *secstrs = (void *)hdr + se    
403                                                   
404         for (s = sechdrs, se = sechdrs + hdr->    
405                 if (strcmp(name, secstrs + s->    
406                         return s;                 
407                                                   
408         return NULL;                              
409 }                                                 
410                                                   
411 extern void fixup_pv_table(const void *, unsig    
412 extern void fixup_smp(const void *, unsigned l    
413                                                   
414 int module_finalize(const Elf32_Ehdr *hdr, con    
415                     struct module *mod)           
416 {                                                 
417         const Elf_Shdr *s = NULL;                 
418 #ifdef CONFIG_ARM_UNWIND                          
419         const char *secstrs = (void *)hdr + se    
420         const Elf_Shdr *sechdrs_end = sechdrs     
421         struct list_head *unwind_list = &mod->    
422                                                   
423         INIT_LIST_HEAD(unwind_list);              
424         mod->arch.init_table = NULL;              
425                                                   
426         for (s = sechdrs; s < sechdrs_end; s++    
427                 const char *secname = secstrs     
428                 const char *txtname;              
429                 const Elf_Shdr *txt_sec;          
430                                                   
431                 if (!(s->sh_flags & SHF_ALLOC)    
432                     s->sh_type != ELF_SECTION_    
433                         continue;                 
434                                                   
435                 if (!strcmp(".ARM.exidx", secn    
436                         txtname = ".text";        
437                 else                              
438                         txtname = secname + st    
439                 txt_sec = find_mod_section(hdr    
440                                                   
441                 if (txt_sec) {                    
442                         struct unwind_table *t    
443                                 unwind_table_a    
444                                                   
445                                                   
446                                                   
447                                                   
448                         list_add(&table->mod_l    
449                                                   
450                         /* save init table for    
451                         if (strcmp(".ARM.exidx    
452                                 mod->arch.init    
453                 }                                 
454         }                                         
455 #endif                                            
456 #ifdef CONFIG_ARM_PATCH_PHYS_VIRT                 
457         s = find_mod_section(hdr, sechdrs, ".p    
458         if (s)                                    
459                 fixup_pv_table((void *)s->sh_a    
460 #endif                                            
461         s = find_mod_section(hdr, sechdrs, ".a    
462         if (s && !is_smp())                       
463 #ifdef CONFIG_SMP_ON_UP                           
464                 fixup_smp((void *)s->sh_addr,     
465 #else                                             
466                 return -EINVAL;                   
467 #endif                                            
468         return 0;                                 
469 }                                                 
470                                                   
471 void                                              
472 module_arch_cleanup(struct module *mod)           
473 {                                                 
474 #ifdef CONFIG_ARM_UNWIND                          
475         struct unwind_table *tmp;                 
476         struct unwind_table *n;                   
477                                                   
478         list_for_each_entry_safe(tmp, n,          
479                         &mod->arch.unwind_list    
480                 list_del(&tmp->mod_list);         
481                 unwind_table_del(tmp);            
482         }                                         
483         mod->arch.init_table = NULL;              
484 #endif                                            
485 }                                                 
486                                                   
487 void __weak module_arch_freeing_init(struct mo    
488 {                                                 
489 #ifdef CONFIG_ARM_UNWIND                          
490         struct unwind_table *init = mod->arch.    
491                                                   
492         if (init) {                               
493                 mod->arch.init_table = NULL;      
494                 list_del(&init->mod_list);        
495                 unwind_table_del(init);           
496         }                                         
497 #endif                                            
498 }                                                 
499                                                   

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