[PATCH v2 2/5] Restrict use of minsym names when printing addresses in disassembled code

Pedro Alves palves@redhat.com
Fri Jul 19 17:07:00 GMT 2019


Below, more of a brain dump than an objection.  FWIW.

On 7/4/19 5:55 AM, Kevin Buettner wrote:
> 
> (gdb) x/5i foo_cold
>    0x401128 <foo_cold>:	push   %rbp
>    0x401129 <foo+35>:	mov    %rsp,%rbp
>    0x40112c <foo+38>:	callq  0x401134 <baz>
>    0x401131 <foo+43>:	nop
>    0x401132 <foo+44>:	pop    %rbp

I admit that it took me a while to reply because I'm still finding
it a bit hard to convince myself that that is the ideal output.
E.g., the first two instructions are obviously part of the same
prologue, I find it a bit odd that the disassembly shows
different function names for that instruction pair.

Maybe this won't matter in practice since IIUC your testcase is a
bit contrived, and real cold functions are just fragments of
functions jmp/ret'ed to/from, without a prologue.

BTW, I noticed (with your series applied), this divergence:

 (gdb) x /5i foo_cold
    0x40048e <foo_cold>: push   %rbp
    0x40048f <foo-18>:   mov    %rsp,%rbp
    0x400492 <foo-15>:   callq  0x400487 <baz>
    0x400497 <foo-10>:   nop
    0x400498 <foo-9>:    pop    %rbp

vs:

 (gdb) info symbol 0x40048f
 foo_cold + 1 in section .text
 (gdb) info symbol 0x400492
 foo_cold + 4 in section .text
 (gdb) info symbol 
 Argument required (address).
 (gdb) info symbol 0x400497
 foo_cold + 9 in section .text

That's of course because "info symbol" only looks at minimal symbols.

On the disassemble side, I think I'd be less confused with:

(gdb) disassemble foo
Dump of assembler code for function foo:
Address range 0x4004a1 to 0x4004bc:
   0x00000000004004a1 <foo+0>:     push   %rbp
   0x00000000004004a2 <foo+1>:     mov    %rsp,%rbp
   0x00000000004004a5 <foo+4>:     callq  0x40049a <bar>
   0x00000000004004aa <foo+9>:     mov    0x200b70(%rip),%eax        # 0x601020 <e>
   0x00000000004004b0 <foo+15>:    test   %eax,%eax
   0x00000000004004b2 <foo+17>:    je     0x4004b9 <foo+24>
   0x00000000004004b4 <foo+19>:    callq  0x40048e <foo_cold>
   0x00000000004004b9 <foo+24>:    nop
   0x00000000004004ba <foo+25>:    pop    %rbp
   0x00000000004004bb <foo+26>:    retq   
Address range 0x40048e to 0x40049a:
   0x000000000040048e <foo.cold+0>:    push   %rbp
   0x000000000040048f <foo.cold+1>:    mov    %rsp,%rbp
   0x0000000000400492 <foo.cold+4>:    callq  0x400487 <baz>
   0x0000000000400497 <foo.cold+9>:    nop
   0x0000000000400498 <foo.cold+10>:   pop    %rbp
   0x0000000000400499 <foo.cold+11>:   retq   
End of assembler dump.

Instead of:

(gdb) disassemble foo
Dump of assembler code for function foo:
Address range 0x4004a1 to 0x4004bc:
   0x00000000004004a1 <+0>:     push   %rbp
   0x00000000004004a2 <+1>:     mov    %rsp,%rbp
   0x00000000004004a5 <+4>:     callq  0x40049a <bar>
   0x00000000004004aa <+9>:     mov    0x200b70(%rip),%eax        # 0x601020 <e>
   0x00000000004004b0 <+15>:    test   %eax,%eax
   0x00000000004004b2 <+17>:    je     0x4004b9 <foo+24>
   0x00000000004004b4 <+19>:    callq  0x40048e <foo_cold>
   0x00000000004004b9 <+24>:    nop
   0x00000000004004ba <+25>:    pop    %rbp
   0x00000000004004bb <+26>:    retq   
Address range 0x40048e to 0x40049a:
   0x000000000040048e <-19>:    push   %rbp
   0x000000000040048f <-18>:    mov    %rsp,%rbp
   0x0000000000400492 <-15>:    callq  0x400487 <baz>
   0x0000000000400497 <-10>:    nop
   0x0000000000400498 <-9>:     pop    %rbp
   0x0000000000400499 <-8>:     retq   
End of assembler dump.

In your examples / testcase, the cold function is adjacent/near
the hot / main entry point of foo.  But I think that
on a real cold function, the offsets between the cold and
hot entry points can potentially be much larger (e.g., place in
different elf sections), as the point is exactly to
move cold code away from the hot path / cache.

That that would mean that we're likely to see output like:

(gdb) disassemble foo
Dump of assembler code for function foo:
Address range 0x6004a1 to 0x6004bc:
   0x00000000006004a1 <+0>:     push   %rbp
   0x00000000006004a2 <+1>:     mov    %rsp,%rbp
   0x00000000006004a5 <+4>:     callq  0x40049a <bar>
   0x00000000006004aa <+9>:     mov    0x200b70(%rip),%eax        # 0x601020 <e>
   0x00000000006004b0 <+15>:    test   %eax,%eax
   0x00000000006004b2 <+17>:    je     0x6004b9 <foo+24>
   0x00000000006004b4 <+19>:    callq  0x40048e <foo_cold>
   0x00000000006004b9 <+24>:    nop
   0x00000000006004ba <+25>:    pop    %rbp
   0x00000000006004bb <+26>:    retq   
Address range 0x40048e to 0x40049a:
   0x000000000040048e <-2097171>:    push   %rbp
   0x000000000040048f <-2097170>:    mov    %rsp,%rbp
   0x0000000000400492 <-2097167>:    callq  0x400487 <baz>
   0x0000000000400497 <-2097162>:    nop
   0x0000000000400498 <-2097161>:    pop    %rbp
   0x0000000000400499 <-2097160>:    retq   
End of assembler dump.

... and those negative offsets kind of look a bit odd.

But maybe it's just that I'm not thinking it right.  

If I think of the offset in terms of offset from the
"foo"'s entry point, which is what it really is, then I can
convince myself that I can explain why that's the right output,
pedantically.

So I guess I'll grow into it.

And with that out of the way, the series looks good to me as is.

Thanks,
Pedro Alves



More information about the Gdb-patches mailing list