[2/2] hexdump: add a new dump prefix DUMP_PREFIX_ADDRESS_LOW16

Message ID 20230805072116.1260-3-thunder.leizhen@huaweicloud.com
State New
Headers
Series hexdump: minimize the output width of address and offset |

Commit Message

Leizhen (ThunderTown) Aug. 5, 2023, 7:21 a.m. UTC
  From: Zhen Lei <thunder.leizhen@huawei.com>

Currently, function print_hex_dump() supports three dump prefixes:
DUMP_PREFIX_NONE, DUMP_PREFIX_ADDRESS and DUMP_PREFIX_OFFSET. But for some
usage scenarios, they don't work perfectly. For example, dump the content
of one task's stack. In order to quickly identify a stack frame,
DUMP_PREFIX_ADDRESS is preferred. But printing multiple 64-bit addresses
is a bit unwise when the 'sp' value is already printed. It is redundant
and unintuitive.

For example:
dump memory at sp=ffff800080883a90:
ffff800080883a90: 80883ac0 ffff8000 3d8e936c ffffbd5b
ffff800080883aa0: 5833f000 ffff3580 00000001 00000000
ffff800080883ab0: 40299840 ffff3580 590dfa00 ffff3580
ffff800080883ac0: 80883b30 ffff8000 3d938b28 ffffbd5b
ffff800080883ad0: 40877180 ffff3580 590dfa00 ffff3580
ffff800080883ae0: 4090f600 ffff3580 80883cb0 ffff8000
ffff800080883af0: 00000010 00000000 00000000 00000000
ffff800080883b00: 4090f700 ffff3580 00000001 00000000

Generally, we do not dump more than 64 KB memory. It is sufficient to
print only the lower 16 bits of the address.

dump memory at sp=ffff800080883a90:
3a90: 80883ac0 ffff8000 3d8e936c ffffbd5b
3aa0: 5833f000 ffff3580 00000001 00000000
3ab0: 40299840 ffff3580 590dfa00 ffff3580
3ac0: 80883b30 ffff8000 3d938b28 ffffbd5b
3ad0: 40877180 ffff3580 590dfa00 ffff3580
3ae0: 4090f600 ffff3580 80883cb0 ffff8000
3af0: 00000010 00000000 00000000 00000000
3b00: 4090f700 ffff3580 00000001 00000000

Another benefit of adding DUMP_PREFIX_ADDRESS_LOW16 is that we don't have
to worry about %p outputting address as hashed value.

Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com>
---
 include/linux/printk.h | 1 +
 lib/hexdump.c          | 4 ++++
 2 files changed, 5 insertions(+)
  

Comments

Randy Dunlap Aug. 7, 2023, 10:37 p.m. UTC | #1
On 8/5/23 00:21, thunder.leizhen@huaweicloud.com wrote:
> From: Zhen Lei <thunder.leizhen@huawei.com>
> 
> 
> Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com>


Reviewed-by: Randy Dunlap <rdunlap@infradead.org>
Thanks.

> ---
>  include/linux/printk.h | 1 +
>  lib/hexdump.c          | 4 ++++
>  2 files changed, 5 insertions(+)
> 
> diff --git a/include/linux/printk.h b/include/linux/printk.h
> index 8ef499ab3c1ed2e..ccad9e8eaaf0c31 100644
> --- a/include/linux/printk.h
> +++ b/include/linux/printk.h
> @@ -704,6 +704,7 @@ extern const struct file_operations kmsg_fops;
>  enum {
>  	DUMP_PREFIX_NONE,
>  	DUMP_PREFIX_ADDRESS,
> +	DUMP_PREFIX_ADDRESS_LOW16,
>  	DUMP_PREFIX_OFFSET
>  };
>  extern int hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
> diff --git a/lib/hexdump.c b/lib/hexdump.c
> index 86cb4cc3eec485a..eb33e477bc96df1 100644
> --- a/lib/hexdump.c
> +++ b/lib/hexdump.c
> @@ -290,6 +290,10 @@ void print_hex_dump(const char *level, const char *prefix_str, int prefix_type,
>  			printk("%s%s%p: %s\n",
>  			       level, prefix_str, ptr + i, linebuf);
>  			break;
> +		case DUMP_PREFIX_ADDRESS_LOW16:
> +			printk("%s%s%04lx: %s\n", level,
> +			       prefix_str, 0xffff & (unsigned long)(ptr + i), linebuf);
> +			break;
>  		case DUMP_PREFIX_OFFSET:
>  			printk("%s%s%0*x: %s\n", level, prefix_str, width, i, linebuf);
>  			break;
  
Steven Rostedt Aug. 8, 2023, 1:14 a.m. UTC | #2
On Sat,  5 Aug 2023 15:21:16 +0800
thunder.leizhen@huaweicloud.com wrote:

> For example:
> dump memory at sp=ffff800080883a90:
> ffff800080883a90: 80883ac0 ffff8000 3d8e936c ffffbd5b
> ffff800080883aa0: 5833f000 ffff3580 00000001 00000000
> ffff800080883ab0: 40299840 ffff3580 590dfa00 ffff3580
> ffff800080883ac0: 80883b30 ffff8000 3d938b28 ffffbd5b
> ffff800080883ad0: 40877180 ffff3580 590dfa00 ffff3580
> ffff800080883ae0: 4090f600 ffff3580 80883cb0 ffff8000
> ffff800080883af0: 00000010 00000000 00000000 00000000
> ffff800080883b00: 4090f700 ffff3580 00000001 00000000
> 
> Generally, we do not dump more than 64 KB memory. It is sufficient to
> print only the lower 16 bits of the address.
> 
> dump memory at sp=ffff800080883a90:
> 3a90: 80883ac0 ffff8000 3d8e936c ffffbd5b
> 3aa0: 5833f000 ffff3580 00000001 00000000
> 3ab0: 40299840 ffff3580 590dfa00 ffff3580
> 3ac0: 80883b30 ffff8000 3d938b28 ffffbd5b
> 3ad0: 40877180 ffff3580 590dfa00 ffff3580
> 3ae0: 4090f600 ffff3580 80883cb0 ffff8000
> 3af0: 00000010 00000000 00000000 00000000
> 3b00: 4090f700 ffff3580 00000001 00000000

I find the "before" much easier to read than the "after".


-- Steve
  
Leizhen (ThunderTown) Aug. 8, 2023, 1:51 a.m. UTC | #3
On 2023/8/8 9:14, Steven Rostedt wrote:
> On Sat,  5 Aug 2023 15:21:16 +0800
> thunder.leizhen@huaweicloud.com wrote:
> 
>> For example:
>> dump memory at sp=ffff800080883a90:
>> ffff800080883a90: 80883ac0 ffff8000 3d8e936c ffffbd5b
>> ffff800080883aa0: 5833f000 ffff3580 00000001 00000000
>> ffff800080883ab0: 40299840 ffff3580 590dfa00 ffff3580
>> ffff800080883ac0: 80883b30 ffff8000 3d938b28 ffffbd5b
>> ffff800080883ad0: 40877180 ffff3580 590dfa00 ffff3580
>> ffff800080883ae0: 4090f600 ffff3580 80883cb0 ffff8000
>> ffff800080883af0: 00000010 00000000 00000000 00000000
>> ffff800080883b00: 4090f700 ffff3580 00000001 00000000
>>
>> Generally, we do not dump more than 64 KB memory. It is sufficient to
>> print only the lower 16 bits of the address.
>>
>> dump memory at sp=ffff800080883a90:
>> 3a90: 80883ac0 ffff8000 3d8e936c ffffbd5b
>> 3aa0: 5833f000 ffff3580 00000001 00000000
>> 3ab0: 40299840 ffff3580 590dfa00 ffff3580
>> 3ac0: 80883b30 ffff8000 3d938b28 ffffbd5b
>> 3ad0: 40877180 ffff3580 590dfa00 ffff3580
>> 3ae0: 4090f600 ffff3580 80883cb0 ffff8000
>> 3af0: 00000010 00000000 00000000 00000000
>> 3b00: 4090f700 ffff3580 00000001 00000000
> 
> I find the "before" much easier to read than the "after".

That's because you're experienced and know how to look around colons
for offsets. But I can remove "and unintuitive" from the commit message.

> 
> 
> -- Steve
> 
> .
>
  
Sergey Senozhatsky Aug. 9, 2023, 4:10 a.m. UTC | #4
On (23/08/08 15:52), Leizhen (ThunderTown) wrote:
> >> I find the "before" much easier to read than the "after".
> 
> I added the boot option no_hash_pointers, so "before" can print the
> address. Otherwise, just print the 32-bit hash value, as shown below:


> [   14.872153] dump memory at sp=ffff800080903aa0:

This line is not guaranteed to be printed. If you get
"** N printk messages dropped **" instead then the
ADDRESS_LOW16 math doesn't work.

> Actually, I added DUMP_PREFIX_ADDRESS_LOW16 because of another scene:
> slab kmalloc-512 start ffff3b3c0094e800 pointer offset 168 size 512
> e888: 00400000 00000000 000f7704 00000000
> e898: 000f7704 00000000 12345678 00000000
> e8a8: 00000000 00000000 00000000 00000000
> e8b8: 9abcdef0 00000000 00507dd0 00000000
> 
> Here, the start address ffff3b3c0094e800 of slab object is printed by %px,
> the address of the error data is at p=ffff3b3c0094e8a8 = ffff3b3c0094e800 + offset 168.
> To locate the problem, dump up to 64 bytes centered on 'p'.
  
Leizhen (ThunderTown) Aug. 9, 2023, 7:05 a.m. UTC | #5
On 2023/8/9 12:10, Sergey Senozhatsky wrote:
> On (23/08/08 15:52), Leizhen (ThunderTown) wrote:
>>>> I find the "before" much easier to read than the "after".
>>
>> I added the boot option no_hash_pointers, so "before" can print the
>> address. Otherwise, just print the 32-bit hash value, as shown below:
> 
> 
>> [   14.872153] dump memory at sp=ffff800080903aa0:
> 
> This line is not guaranteed to be printed. If you get
> "** N printk messages dropped **" instead then the
> ADDRESS_LOW16 math doesn't work.

Anyone is vulnerable in the face of nature. Even DUMP_PREFIX_ADDRESS,
without the preface, no one know what's dumped. In any case,
DUMP_PREFIX_ADDRESS_LOW16 has its own unique value in this ecosystem.
The only regret is that it has a slightly longer name than others.
Maybe it could be DUMP_PREFIX_ADDRLOW or something.

By the way, would you consider changing %p to %px in case DUMP_PREFIX_ADDRESS?

> 
>> Actually, I added DUMP_PREFIX_ADDRESS_LOW16 because of another scene:
>> slab kmalloc-512 start ffff3b3c0094e800 pointer offset 168 size 512
>> e888: 00400000 00000000 000f7704 00000000
>> e898: 000f7704 00000000 12345678 00000000
>> e8a8: 00000000 00000000 00000000 00000000
>> e8b8: 9abcdef0 00000000 00507dd0 00000000
>>
>> Here, the start address ffff3b3c0094e800 of slab object is printed by %px,
>> the address of the error data is at p=ffff3b3c0094e8a8 = ffff3b3c0094e800 + offset 168.
>> To locate the problem, dump up to 64 bytes centered on 'p'.
> .
>
  
Leizhen (ThunderTown) Aug. 11, 2023, 7:31 a.m. UTC | #6
On 2023/8/9 15:05, Leizhen (ThunderTown) wrote:
> 
> 
> On 2023/8/9 12:10, Sergey Senozhatsky wrote:
>> On (23/08/08 15:52), Leizhen (ThunderTown) wrote:
>>>>> I find the "before" much easier to read than the "after".
>>>
>>> I added the boot option no_hash_pointers, so "before" can print the
>>> address. Otherwise, just print the 32-bit hash value, as shown below:
>>
>>
>>> [   14.872153] dump memory at sp=ffff800080903aa0:
>>
>> This line is not guaranteed to be printed. If you get
>> "** N printk messages dropped **" instead then the
>> ADDRESS_LOW16 math doesn't work.

I have a new idea. Replace DUMP_PREFIX_ADDRESS_LOW16 with DUMP_PREFIX_CUSTOM.
Let the user to specify the format string.

For example:
pr_info("dump memory at sp=%px:\n", sp);
print_hex_dump(KERN_INFO, "%s%16hx: %s\n", DUMP_PREFIX_CUSTOM, 16, 1, sp, 16, false);
print_hex_dump(KERN_INFO, "%s%16x: %s\n",  DUMP_PREFIX_CUSTOM, 16, 1, sp, 16, false);
print_hex_dump(KERN_INFO, "%s%px: %s\n",   DUMP_PREFIX_CUSTOM, 16, 1, sp, 16, false);

dump memory at sp=ffff80008091baa0:
            baa0: c0 ba 91 80 00 80 ff ff d4 38 16 ce fc a7 ff ff
        8091baa0: c0 ba 91 80 00 80 ff ff d4 38 16 ce fc a7 ff ff
ffff80008091baa0: c0 ba 91 80 00 80 ff ff d4 38 16 ce fc a7 ff ff

> 
> Anyone is vulnerable in the face of nature. Even DUMP_PREFIX_ADDRESS,
> without the preface, no one know what's dumped. In any case,
> DUMP_PREFIX_ADDRESS_LOW16 has its own unique value in this ecosystem.
> The only regret is that it has a slightly longer name than others.
> Maybe it could be DUMP_PREFIX_ADDRLOW or something.
> 
> By the way, would you consider changing %p to %px in case DUMP_PREFIX_ADDRESS?
> 
>>
>>> Actually, I added DUMP_PREFIX_ADDRESS_LOW16 because of another scene:
>>> slab kmalloc-512 start ffff3b3c0094e800 pointer offset 168 size 512
>>> e888: 00400000 00000000 000f7704 00000000
>>> e898: 000f7704 00000000 12345678 00000000
>>> e8a8: 00000000 00000000 00000000 00000000
>>> e8b8: 9abcdef0 00000000 00507dd0 00000000
>>>
>>> Here, the start address ffff3b3c0094e800 of slab object is printed by %px,
>>> the address of the error data is at p=ffff3b3c0094e8a8 = ffff3b3c0094e800 + offset 168.
>>> To locate the problem, dump up to 64 bytes centered on 'p'.
>> .
>>
>
  

Patch

diff --git a/include/linux/printk.h b/include/linux/printk.h
index 8ef499ab3c1ed2e..ccad9e8eaaf0c31 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -704,6 +704,7 @@  extern const struct file_operations kmsg_fops;
 enum {
 	DUMP_PREFIX_NONE,
 	DUMP_PREFIX_ADDRESS,
+	DUMP_PREFIX_ADDRESS_LOW16,
 	DUMP_PREFIX_OFFSET
 };
 extern int hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
diff --git a/lib/hexdump.c b/lib/hexdump.c
index 86cb4cc3eec485a..eb33e477bc96df1 100644
--- a/lib/hexdump.c
+++ b/lib/hexdump.c
@@ -290,6 +290,10 @@  void print_hex_dump(const char *level, const char *prefix_str, int prefix_type,
 			printk("%s%s%p: %s\n",
 			       level, prefix_str, ptr + i, linebuf);
 			break;
+		case DUMP_PREFIX_ADDRESS_LOW16:
+			printk("%s%s%04lx: %s\n", level,
+			       prefix_str, 0xffff & (unsigned long)(ptr + i), linebuf);
+			break;
 		case DUMP_PREFIX_OFFSET:
 			printk("%s%s%0*x: %s\n", level, prefix_str, width, i, linebuf);
 			break;