u/krakenlake

▲ 2 r/RISCV

Baffled by sign extension issue

OK, so my code is trying to look at a dtb in memory and to check the magic number at the beginning.

The following works fine:

27 u64 magic_le = swap32((u64)dtb->magic); 
(gdb) n 
30 log(LOG_DEBUG, "dtb magic = 0x%016lx", magic_le); 
(gdb) n 
32 if (magic_le == foo) { 
(gdb) p/x magic_le 
$1 = 0xd00dfeed 
(gdb) p/x foo 
$2 = 0xd00dfeed 
(gdb) n 
33 log(LOG_INFO, "magic number 0x%08x found @ 0x%08x", FDT_HEADER_MAGIC, (u64)dtb);

So far so good. BUT: When I comment out the log message, it breaks!

27 u64 magic_le = swap32((u64)dtb->magic);
(gdb) n
32 if (magic_le == foo) {
(gdb) p/x magic_le
$1 = 0xd00dfeed
(gdb) p/x foo
$2 = 0xd00dfeed
(gdb) n
35 log(LOG_ERR, "dtb magic number @ 0x%08x does not match, expected 0x%08x", (u64)dtb, FDT_HEADER_MAGIC);

In other words, 0xd00dfeed != 0xd00dfeed in this case, just by removing the log message!

So I tracked it down and found that foo is actually sign-extended:

0x0000000080200c14 <+52>: lui a3,0xd00e0
0x0000000080200c18 <+56>: addi a3,a3,-275 # 0xffffffffd00dfeed
0x0000000080200c1c <+60>: ld a2,0(s0)
0x0000000080200c20 <+64>: bne a0,a3,0x80200dd8 <print_dtb+504>

I know how to work around it, but there are 2 things I totally fail to understand:

  1. Why is printing a log message (which is just calling vsnprintf) making it work and
  2. why is foo initialized with the sign-extended value in the first place (it is assigned the constant 0xd00dfeed in the code) and gdb not even showing it?
reddit.com
u/krakenlake — 1 month ago