1

Wrote simple program with large buffer in .bss segment

h_vals:
    resq 99999

then tried to increment value of some array cell.

mov rcx, [h_vals+8*rax]
inc rcx
mov [h_vals+8*rax], rcx

Still in gdb see the same value(0) both before and after third instruction execution.

x/dg &h_vals &h_vals + 8 * $rax
0x6d68c0: 0

Why am I still seeing 0 when I try to inspect the address I stored to?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Bulat M.
  • 680
  • 9
  • 25

1 Answers1

2

mov obviously does move data; Your program would segfault if it failed.

The default size for symbols with no debug info is 4 bytes. You can use ptype h_vals to check what gdb thinks about it.

Remember that gdb's syntax works like C, even if you're debugging asm. In C, adding something to a pointer offsets by that many elements, not that many bytes.

&h_vals &h_vals + 8 * $rax isn't evaluating in gdb to the address you expect. (Also, I think &h_vals &h_vals is a typo, and isn't what you actually ran.)

Since gdb thinks &h_vals is an int*, &h_vals + offset will produce a byte offset of 4 * offset, just like h_vals[offset] in C. So the address you're examining in gdb is actually [h_vals + 8 * 4 * rax].

Another way to check: p /x &h_vals and p /x $rax separately. You can work out the math yourself and compare to the address you saw in the x/ output.


The safest solution here is to cast to char*:

x /dg  8 * $rax + (char*)&h_vals

Or: define your symbols in a .c so the compiler will generate debug info for them (because you don't want to do that by hand).

e.g. put unsigned long h_vals[99999]; in a .c that you compile with gcc -c -g vars.c, and link the resulting .o with the .o YASM creates from your .asm.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • ptype h_vals type = print &h_vals type = 0x6010c0 print $rax 27328 It does not agree with 27328*8=218624(0x35600), 0x35600+0x6010c0=0x6366c0(not 0x6d68c0). – Bulat M. Sep 04 '16 at 14:07
  • you can use `p /x $rax` to print in hex. Looks like the default size for symbols with no debug info is 4 bytes; that matches exactly: `(0x6d68c0 - 0x6010c0 ) / (8 * 27328)` is 4. – Peter Cordes Sep 04 '16 at 14:18
  • `rax` is 0x6aco(27328 in decimal). Calculations are the same. – Bulat M. Sep 04 '16 at 14:21
  • Up to the point, now calculations meet with gdb's showings. Is it possible to add debug info to buffer in .bss section so that gdb will think that symbol in it is of byte length, so that it would be possible not to cast to `char *`? ptype h_vals shows `` – Bulat M. Sep 04 '16 at 15:13
  • 1
    Yes, it's possible to hand-craft debug info the same way compilers generate it, but I think it's more trouble than it's worth. Have a look at `gcc -g -S` output sometime, at all the extra directives that define the debug metadata. Probably the easiest way to do it is to get the compiler to do it for you: define `unsigned long h_vals[99999];` in a .c that you compile (`gcc -c -g vars.c`), and link the resulting .o with the .o YASM creates from your .asm. – Peter Cordes Sep 04 '16 at 15:20
  • 1
    Yes, I compiled file with `unsigned long h_vals_2[99999]` and after linking with assembly it shows in gdb like `type = unsigned long [99999]`, thanks. Debug info in .s is indeed huge and not very pleasant to construct manually. – Bulat M. Sep 04 '16 at 16:07