[Crash-utility] [PATCH] arm64: exclude mapping symbols in modules

Dave Anderson anderson at redhat.com
Thu Oct 6 20:35:42 UTC 2016


Hi Akashi,

I was playing around with this, and noted that if a module's debuginfo data is not
loaded into a crash session with the "mod" command, branch instruction targets 
that are within the module space are not translated.  For example, note the handful
of "bl" instructions with module address targets are empty:
  
  crash> dis dm_create | grep bl
  0xfffffdfffc003814 <dm_create+60>:	bl	0xfffffe0000226ce0 <kmem_cache_alloc_trace>
  0xfffffdfffc003828 <dm_create+80>:	bl	0xfffffe0000143754 <try_module_get>
  0xfffffdfffc003850 <dm_create+120>:	bl	0xfffffe00003c4f08 <idr_preload>
  0xfffffdfffc00385c <dm_create+132>:	bl	0xfffffe000078241c <_raw_spin_lock>
  0xfffffdfffc003874 <dm_create+156>:	bl	0xfffffe00003c5d90 <idr_alloc>
  0xfffffdfffc00388c <dm_create+180>:	bl	0xfffffe0000123044 <init_srcu_struct>
  0xfffffdfffc0038b0 <dm_create+216>:	bl	0xfffffe000010f9d0 <__mutex_init>
  0xfffffdfffc0038c0 <dm_create+232>:	bl	0xfffffe000010f9d0 <__mutex_init>
  0xfffffdfffc0038d4 <dm_create+252>:	bl	0xfffffe000010f9d0 <__mutex_init>
  0xfffffdfffc003918 <dm_create+320>:	bl	0xfffffe00003968c4 <blk_alloc_queue>
  0xfffffdfffc003948 <dm_create+368>:	bl	0xfffffe00003ab298 <alloc_disk>
  0xfffffdfffc003968 <dm_create+400>:	bl	0xfffffe000010a878 <__init_waitqueue_head>
  0xfffffdfffc003994 <dm_create+444>:	bl	0xfffffe000010a878 <__init_waitqueue_head>
  0xfffffdfffc0039a8 <dm_create+464>:	bl	0xfffffe000010a878 <__init_waitqueue_head>
  0xfffffdfffc0039f8 <dm_create+544>:	bl	0xfffffe00003d1224 <sprintf>
  0xfffffdfffc003a00 <dm_create+552>:	bl	0xfffffe00003aab08 <add_disk>
  0xfffffdfffc003a1c <dm_create+580>:	bl	0xfffffe00003d1224 <sprintf>
  0xfffffdfffc003a34 <dm_create+604>:	bl	0xfffffe00000e3acc <__alloc_workqueue_key>
  0xfffffdfffc003a48 <dm_create+624>:	bl	0xfffffe00003a9a8c <bdget_disk>
  0xfffffdfffc003a58 <dm_create+640>:	bl	0xfffffe000038ea84 <bio_init>
  0xfffffdfffc003a70 <dm_create+664>:	bl	0xfffffdfffc00e418
  0xfffffdfffc003a78 <dm_create+672>:	bl	0xfffffe000078241c <_raw_spin_lock>
  0xfffffdfffc003a88 <dm_create+688>:	bl	0xfffffe00003c4e54 <idr_replace>
  0xfffffdfffc003aa4 <dm_create+716>:	bl	0xfffffdfffc00d270
  0xfffffdfffc003ad8 <dm_create+768>:	bl	0xfffffe0000143860 <module_put>
  0xfffffdfffc003ae0 <dm_create+776>:	bl	0xfffffe0000228464 <kfree>
  0xfffffdfffc003b08 <dm_create+816>:	bl	0xfffffe00003c4f08 <idr_preload>
  0xfffffdfffc003b14 <dm_create+828>:	bl	0xfffffe000078241c <_raw_spin_lock>
  0xfffffdfffc003b2c <dm_create+852>:	bl	0xfffffe00003c5d90 <idr_alloc>
  0xfffffdfffc003b4c <dm_create+884>:	bl	0xfffffdfffc001220
  0xfffffdfffc003b54 <dm_create+892>:	bl	0xfffffdfffc0012e0
  0xfffffdfffc003b60 <dm_create+904>:	bl	0xfffffe00001c4828 <printk>
  crash> 
  
With this patch: 

  --- a/arm64.c
  +++ b/arm64.c
  @@ -2977,6 +2977,16 @@ arm64_dis_filter(ulong vaddr, char *inbuf, unsigned int output_radix)
                  sprintf(p1, "%s", buf1);
          }
   
  +       if (IS_MODULE_VADDR(vaddr)) {
  +               p1 = &inbuf[strlen(inbuf)-1];
  +               strcpy(buf1, inbuf);
  +               argc = parse_line(buf1, argv);
  +               if (STREQ(argv[argc-2], "bl") &&
  +                   extract_hex(argv[argc-1], &value, NULLCHAR, TRUE))
  +                       sprintf(p1, " <%s>\n",
  +                               value_to_symstr(value, buf2, output_radix));
  +       }
  +
          console("    %s", inbuf);
   
          return TRUE;

module addresses are translated without having to load the module's debuginfo:

  crash> dis dm_create | grep bl
  0xfffffdfffc003814 <dm_create+60>:	bl	0xfffffe0000226ce0 <kmem_cache_alloc_trace>
  0xfffffdfffc003828 <dm_create+80>:	bl	0xfffffe0000143754 <try_module_get>
  0xfffffdfffc003850 <dm_create+120>:	bl	0xfffffe00003c4f08 <idr_preload>
  0xfffffdfffc00385c <dm_create+132>:	bl	0xfffffe000078241c <_raw_spin_lock>
  0xfffffdfffc003874 <dm_create+156>:	bl	0xfffffe00003c5d90 <idr_alloc>
  0xfffffdfffc00388c <dm_create+180>:	bl	0xfffffe0000123044 <init_srcu_struct>
  0xfffffdfffc0038b0 <dm_create+216>:	bl	0xfffffe000010f9d0 <__mutex_init>
  0xfffffdfffc0038c0 <dm_create+232>:	bl	0xfffffe000010f9d0 <__mutex_init>
  0xfffffdfffc0038d4 <dm_create+252>:	bl	0xfffffe000010f9d0 <__mutex_init>
  0xfffffdfffc003918 <dm_create+320>:	bl	0xfffffe00003968c4 <blk_alloc_queue>
  0xfffffdfffc003948 <dm_create+368>:	bl	0xfffffe00003ab298 <alloc_disk>
  0xfffffdfffc003968 <dm_create+400>:	bl	0xfffffe000010a878 <__init_waitqueue_head>
  0xfffffdfffc003994 <dm_create+444>:	bl	0xfffffe000010a878 <__init_waitqueue_head>
  0xfffffdfffc0039a8 <dm_create+464>:	bl	0xfffffe000010a878 <__init_waitqueue_head>
  0xfffffdfffc0039f8 <dm_create+544>:	bl	0xfffffe00003d1224 <sprintf>
  0xfffffdfffc003a00 <dm_create+552>:	bl	0xfffffe00003aab08 <add_disk>
  0xfffffdfffc003a1c <dm_create+580>:	bl	0xfffffe00003d1224 <sprintf>
  0xfffffdfffc003a34 <dm_create+604>:	bl	0xfffffe00000e3acc <__alloc_workqueue_key>
  0xfffffdfffc003a48 <dm_create+624>:	bl	0xfffffe00003a9a8c <bdget_disk>
  0xfffffdfffc003a58 <dm_create+640>:	bl	0xfffffe000038ea84 <bio_init>
  0xfffffdfffc003a70 <dm_create+664>:	bl	0xfffffdfffc00e418 <dm_stats_init>
  0xfffffdfffc003a78 <dm_create+672>:	bl	0xfffffe000078241c <_raw_spin_lock>
  0xfffffdfffc003a88 <dm_create+688>:	bl	0xfffffe00003c4e54 <idr_replace>
  0xfffffdfffc003aa4 <dm_create+716>:	bl	0xfffffdfffc00d270 <dm_sysfs_init>
  0xfffffdfffc003ad8 <dm_create+768>:	bl	0xfffffe0000143860 <module_put>
  0xfffffdfffc003ae0 <dm_create+776>:	bl	0xfffffe0000228464 <kfree>
  0xfffffdfffc003b08 <dm_create+816>:	bl	0xfffffe00003c4f08 <idr_preload>
  0xfffffdfffc003b14 <dm_create+828>:	bl	0xfffffe000078241c <_raw_spin_lock>
  0xfffffdfffc003b2c <dm_create+852>:	bl	0xfffffe00003c5d90 <idr_alloc>
  0xfffffdfffc003b4c <dm_create+884>:	bl	0xfffffdfffc001220 <cleanup_mapped_device>
  0xfffffdfffc003b54 <dm_create+892>:	bl	0xfffffdfffc0012e0 <free_minor>
  0xfffffdfffc003b60 <dm_create+904>:	bl	0xfffffe00001c4828 <printk>
  crash> 

Now, this sample patch doesn't deal with branch instructions other than "bl",
so perhaps it could just check whether the last argument in the instruction
line is a translatable address.  

On the other hand, for the PLT veneer issue, it would have to:

 (1) make sure it's a "bl", and
 (2) instead of blindly doing a translation of the PLT veneer label address,
     it would first have to check whether it points to a 12-byte chunk of 
     kernel address construction, and if so, translate the reconstructed 
     address.
 
So I'm thinking something along these lines, say, where "value" may or may not be
modified by your new function:

       if (IS_MODULE_VADDR(vaddr)) {
               p1 = &inbuf[strlen(inbuf)-1];
               strcpy(buf1, inbuf);
               argc = parse_line(buf1, argv);
               if (STREQ(argv[argc-2], "bl") &&
                   extract_hex(argv[argc-1], &value, NULLCHAR, TRUE)) {
+                      value = PLT_veneer_to_kvaddr(value);
                       sprintf(p1, " <%s>\n",
                               value_to_symstr(value, buf2, output_radix));
	       }
       }

However, another thing to consider is what "dis" shows if the "mod" command
has already loaded the debuginfo data.  In that case, I'm guessing that gdb
would translate the address of the PLT veneer location?  The sample KASLR
vmcore you gave me doesn't have any modules, so I don't know. 

Dave




More information about the Crash-utility mailing list