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