6

I am trying to debug a tricky core dump (from an -O2 optimized binary).

// Caller Function 
void caller(Container* c)
{
  std::list < Message*> msgs;
  if(!decoder.called(c->buf_, msgs))
  {
   ....
   .....
  }
// Called Function
bool
Decoder::called(Buffer* buf, list < Message*>& msgs)
{
   add_data(buf); // Inlined code to append buf to decoders buf chain
   while(m_data_in && m_data_in->length() > 0)
   {
     .....
   }
}

In both caller and the callee, the first argument is optimized out, that means it must be somewhere in the register.

Caller Disassembly:

push   %r15
mov    %rdi,%r15
push   %r14
push   %r13
push   %r12
push   %rbp
push   %rbx
sub    $0x68,%rsp
test   %rsi,%rsi
je     0x8ccd62 
cmpq   $0x0,(%rsi)
je     0x8ccd62 
lea    0x40(%rsp),%rax
lea    0x1b8(%rdi),%rdi
mov    %rax,(%rsp)
mov    %rax,0x40(%rsp)
mov    %rax,%rdx
mov    %rax,0x48(%rsp)
mov    (%rsi),%rsi
callq  0x8cc820 

Caller Register Info:

rax            0x7fbfffc7e0 548682057696
rbx            0x2a97905ba0 182931446688
rcx            0x0  0
rdx            0x2  2
rsi            0x1  1
rdi            0x7fbfffc7e2 548682057698
rbp            0x4f 0x4f
rsp            0x7fbfffc870 0x7fbfffc870
r8             0x40 64
r9             0x20 32
r10            0x7fbfffc7e0 548682057696
r11            0x2abe466600 183580911104
r12            0x7fbfffd910 548682062096 // THIS IS HOLDING buf_
r13            0x7fbfffdec0 548682063552
r14            0x5dc    1500
r15            0x2a97905ba0 182931446688
rip            0x8cca89 0x8cca89 
eflags         0x206    [ PF IF ]
cs             0x33 51
ss             0x2b 43
ds             0x0  0
es             0x0  0
fs             0x0  0
gs             0x0  0



Called function Disassembly:

push   %r14
push   %r13
mov    %rdx,%r13
push   %r12
mov    %rdi,%r12
push   %rbp
push   %rbx
sub    $0x10,%rsp
mov    0x8(%rdi),%rdx
test   %rdx,%rdx
jne    0x8cc843 
jmpq   0x8cc9cb 
mov    %rax,%rdx
mov    0x8(%rdx),%rax
test   %rax,%rax
mov    %rsi,0x8(%rdx)
mov    0x8(%r12),%rax
test   %rax,%rax
xor    %edx,%edx
add    0x4(%rax),%edx
mov    0x8(%rax),%rax
lea    0x8(%rsp),%rsi
mov    %r12,%rdi
movq   $0x0,0x8(%rsp)

Called function Register Info
:

rax            0x7fbfffc7e0     548682057696
rbx            0x2abc49f9c0     183547591104
rcx            0x0      0
rdx            0x2      2
rsi            0x1      1
rdi            0x7fbfffc7e2     548682057698
rbp            0xffffffff       0xffffffff
rsp            0x7fbfffc830     0x7fbfffc830
r8             0x40     64
r9             0x20     32
r10            0x7fbfffc7e0     548682057696
r11            0x2abe466600     183580911104
r12            0x2a97905d58     182931447128
r13            0x7fbfffc8b0     548682057904
r14            0x5dc    1500
r15            0x2a97905ba0     182931446688
rip            0x8cc88a 0x8cc88a 
eflags         0x206    [ PF IF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0


The issue is, in the called function, it appears that "add_data" function achieved nothing. So, wanted to know whether in disassembly of called function, do we see the "buf_" pointer being used anywhere (Register r12 in callee function).

I do understand assembly to some level, but all those code inlining has left me confused.
Would appreciate some help in demistifying called function disassembly.

UPDATE:
add_data does below:


if (m_data_in) {
    m_data_in->next = data;
} else {
    m_data_in = data;
}

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Arunmu
  • 6,837
  • 1
  • 24
  • 46
  • First, show the source of `add_data()` as well. Then, make sure that you are compiling the right source and not some older one where `add_data()` is not complete yet. – wilx Apr 15 '14 at 13:10
  • Very hard to say without knowing what `add_data` and `buf` actually looks like (and not having the addresses on the disassembly doesn't help much either) – Mats Petersson Apr 15 '14 at 13:12
  • @VáclavZeman: Thanks for responding. This code is been in production for around 1.5 years now. Dead sure that add_data is completed. – Arunmu Apr 15 '14 at 13:17
  • @MatsPetersson: Thanks for responding. At this time I just want to know, if the address of buf_ passed is being used anywhere in called function. – Arunmu Apr 15 '14 at 13:20
  • Like I said, we need to see what `add_data` does. – Mats Petersson Apr 15 '14 at 13:26
  • Sorry for nitpicking, but "callee" and "called" mean the same thing in English. – QuestionC Apr 15 '14 at 13:35
  • What if both `m_data_in` and `m_data_in->next` are not null? You'd leak whatever `m_data_in->next` was pointing to. – Mike DeSimone Apr 15 '14 at 13:35
  • Also, `bool Decoder::called(Buffer* buf, list msgs)` should probably be `bool Decoder::called(Buffer* buf, list & msgs)` unless you *really* want a duplicate, temporary list created for the function when called. Add `const` in there if `called` doesn't change the list. – Mike DeSimone Apr 15 '14 at 13:39
  • @MikeDeSimone: Regarding pass by reference, I have corrected it in the post. I had missed it. Regarding m_data_in->next, can we assume, it wont matter for now ? Actually I have removed one step, which iterates till the sentinel. So, your case actually never happens – Arunmu Apr 15 '14 at 13:44
  • It's certainly no easy task. From your register dump, `%rsp = 0x7fbfffc830`, so I would start looking at the memory at that address and higher (anything below that is just garbage data from earlier function calls.) Then look for anything close to the value of `%rip` – puppydrum64 Nov 23 '22 at 16:08

1 Answers1

4

This looks like if (m_data_in)

mov    0x8(%rdi),%rdx
test   %rdx,%rdx
test   %rdx,%rdx
jne    0x8cc843 
jmpq   0x8cc9cb 

Now, I don't quite know where 0x8cc843 and 0x8cc9cb are located in your code, so can't really follow the code further. There is still not enough code & information to say exactly what is going on in the original question. I'm happy to fill in more of this answer if more information is provided.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • Really appreciate your help on this. I will have a look again on the assembly to check what you have said. Will get back to you :) – Arunmu Apr 15 '14 at 13:58
  • I had a detailed look on the assembly with a peaceful mind and could see the instructions for the add_data function completely. But, couldnt understand the purpose of the last instruction that I have posted in the called disassembly "movq $0x0,0x8(%rsp)". – Arunmu Apr 15 '14 at 19:23
  • "mov %rsi,0x8(%rdx)" is basically the instruction that is assigning my second argument to the called function to the next_ field. After this I dont see any instruction changing the value of "rdx". Still in the register info it shows a seemingly incorrect value of 0x2. Any possible reasons ? – Arunmu Apr 15 '14 at 19:29
  • Also, I havent posted the entire assembly, coz its very big, but you can trust me on the above comment :). I have gone through it fully – Arunmu Apr 15 '14 at 19:31
  • Understood the assembly code. It looks alright, but I think i cannot trace on what had happened. – Arunmu Apr 16 '14 at 16:39
  • So, understanding compiled code is often pretty hard. Compiling with debug info (even in optimized code) and using `objdump -S myprog` can give better disassembly than what you have posted here, with the source code sprinkled in based on the debug info. It's not perfect, but you should be able to follow the code. It also REALLY helps to know the data structure's layout in memory - something you also haven't provided in your original question, making it really hard to know what is what. – Mats Petersson Apr 16 '14 at 21:19
  • I really understand. I just cant provide more details on the code etc :(. By the way, the issue I found out seems to be more and more because of corrupt data received from corrupted DB source. – Arunmu Apr 17 '14 at 07:09
  • Yeah, that'll do it... ;) – Mats Petersson Apr 17 '14 at 07:12