martes, 28 de enero de 2020

Memory leaks detection - Part II


In this post we will see how to relate the memory addresses with our source code to see in which line the memory leak is occurring. In the previous post, we saw some methods to detect memory leaks, of which we will take as a basis method 3 (which uses a program that fulfills the function of testnap and also leaves us a core file to analyze with mdb).

To develop this example, I used a file (fm_inv_pol_demo_leaks.c) with functions that cause memory leaks when using the macros and functions of the BRM API. This file is part of the fm_inv_pol.so library for testing purposes.

fm_inv_pol_demo_leaks.c (there is no error check so that the source code is not so long and does not take much place in the post)
#include "pcm.h"
#include "pin_cust.h"
#include "cm_fm.h"
#include "pin_errs.h"
#include "pinlog.h"
#include "pbo_decimal.h"
#include "fm_inv_pol_demo_leaks.h"

void
fm_inv_pol_demo_leaks_pin_flist_t(
 pcm_context_t *ctxp,
 pin_flist_t     *i_flistp,
 pin_errbuf_t *ebufp);
 
void
fm_inv_pol_demo_leaks_poid_t(
 pcm_context_t *ctxp,
 pin_flist_t     *i_flistp,
 pin_errbuf_t *ebufp); 
 
void
fm_inv_pol_demo_leaks_pin_decimal_t(
 pin_flist_t     *i_flistp,
 pin_errbuf_t *ebufp);
 

void
fm_inv_pol_demo_leaks_start_demo(
 pcm_context_t *ctxp,
 pin_errbuf_t    *ebufp)
{
 pin_flist_t     *demo_flistp = NULL;
 pin_flist_t     *tmp_flistp = NULL;
 
 //construyo el flist con el que hare la demostracion de como detectar los memory leaks
 demo_flistp = PIN_FLIST_CREATE(ebufp);
 PIN_FLIST_FLD_PUT(demo_flistp, PIN_FLD_POID, PIN_POID_CREATE(PCM_GET_CURRENT_DB_NO(ctxp), "/dummy", -1, ebufp), ebufp);
 PIN_FLIST_FLD_PUT(demo_flistp, PIN_FLD_ACCOUNT_OBJ, PIN_POID_CREATE(PCM_GET_CURRENT_DB_NO(ctxp), "/account", -1, ebufp), ebufp);
 PIN_FLIST_FLD_PUT(demo_flistp, PIN_FLD_AMOUNT, pbo_decimal_from_str("100", ebufp), ebufp);
 PIN_FLIST_FLD_PUT(demo_flistp, PIN_FLD_DUE, pbo_decimal_from_str("8", ebufp), ebufp);
 PIN_FLIST_FLD_PUT(demo_flistp, PIN_FLD_TOTAL_DUE, pbo_decimal_from_str("3", ebufp), ebufp);
 tmp_flistp = PIN_FLIST_ELEM_ADD(demo_flistp, PIN_FLD_BAL_IMPACTS, 0, ebufp);
 PIN_FLIST_FLD_PUT(tmp_flistp, PIN_FLD_POID, PIN_POID_CREATE(PCM_GET_CURRENT_DB_NO(ctxp), "/dummy", -1, ebufp), ebufp);
 PIN_FLIST_FLD_PUT(tmp_flistp, PIN_FLD_AMOUNT, pbo_decimal_from_str("100", ebufp), ebufp);
 tmp_flistp = PIN_FLIST_ELEM_ADD(demo_flistp, PIN_FLD_BAL_IMPACTS, 1, ebufp);
 PIN_FLIST_FLD_PUT(tmp_flistp, PIN_FLD_POID, PIN_POID_CREATE(PCM_GET_CURRENT_DB_NO(ctxp), "/dummy", -1, ebufp), ebufp);
 PIN_FLIST_FLD_PUT(tmp_flistp, PIN_FLD_AMOUNT, pbo_decimal_from_str("100", ebufp), ebufp); 
 
 fm_inv_pol_demo_leaks_pin_flist_t(ctxp, demo_flistp, ebufp);
 
 fm_inv_pol_demo_leaks_poid_t(ctxp, demo_flistp, ebufp);
 
 fm_inv_pol_demo_leaks_pin_decimal_t(demo_flistp, ebufp);
 
 PIN_FLIST_DESTROY_EX(&demo_flistp, NULL);
}

void
fm_inv_pol_demo_leaks_pin_flist_t(
 pcm_context_t *ctxp,
 pin_flist_t     *i_flistp,
 pin_errbuf_t *ebufp)
{
 pin_flist_t     *demo_create_flistp = NULL;
 pin_flist_t     *demo_take_flistp = NULL;
 pin_flist_t     *demo_copy_flistp = NULL;
 pin_flist_t     *demo_beid_flistp = NULL;
 
 demo_create_flistp = PIN_FLIST_CREATE(ebufp);
 PIN_FLIST_FLD_COPY(i_flistp, PIN_FLD_POID, demo_create_flistp, PIN_FLD_POID, ebufp);
 PIN_FLIST_FLD_COPY(i_flistp, PIN_FLD_AMOUNT, demo_create_flistp, PIN_FLD_AMOUNT, ebufp);
 
 demo_copy_flistp = PIN_FLIST_COPY(i_flistp, ebufp);
 
 demo_take_flistp = PIN_FLIST_ELEM_TAKE(i_flistp, PIN_FLD_BAL_IMPACTS, 0, 0, ebufp);
 
 demo_beid_flistp = pin_conf_beid(ctxp, ebufp);
 
}

void
fm_inv_pol_demo_leaks_poid_t(
 pcm_context_t *ctxp,
 pin_flist_t     *i_flistp,
 pin_errbuf_t *ebufp)
{
 poid_t   *poidp = NULL;
 poid_t   *demo_create_poidp = NULL;
 poid_t   *demo_copy_poidp = NULL;
 poid_t   *demo_take_poidp = NULL;
 
 demo_create_poidp = PIN_POID_CREATE(PCM_GET_CURRENT_DB_NO(ctxp), "/account", -1, ebufp);
 
 poidp = PIN_FLIST_FLD_GET(i_flistp, PIN_FLD_POID, 0, ebufp);
 demo_copy_poidp = PIN_POID_COPY(poidp, ebufp);
 
 demo_take_poidp = PIN_FLIST_FLD_TAKE(i_flistp, PIN_FLD_ACCOUNT_OBJ, 0, ebufp);
 
}

void
fm_inv_pol_demo_leaks_pin_decimal_t(
 pin_flist_t     *i_flistp,
 pin_errbuf_t *ebufp)
{
 pin_decimal_t *decimal1p = NULL;
 pin_decimal_t *decimal2p = NULL;
 pin_decimal_t *demo_create_decimalp = NULL;
 pin_decimal_t *demo_copy_decimalp = NULL;
 pin_decimal_t *demo_take_decimalp = NULL;
 pin_decimal_t *demo_add_decimalp = NULL;
 
 demo_create_decimalp = pbo_decimal_from_str("100", ebufp);
 
 decimal1p = PIN_FLIST_FLD_GET(i_flistp, PIN_FLD_AMOUNT, 0, ebufp);
 demo_copy_decimalp = pbo_decimal_copy(decimal1p, ebufp); 

 decimal1p = PIN_FLIST_FLD_GET(i_flistp, PIN_FLD_DUE, 0, ebufp);
 decimal2p = PIN_FLIST_FLD_GET(i_flistp, PIN_FLD_TOTAL_DUE, 0, ebufp);
 demo_add_decimalp = pbo_decimal_add(decimal1p, decimal2p, ebufp); 
 
 demo_take_decimalp = PIN_FLIST_FLD_TAKE(i_flistp, PIN_FLD_DUE, 0, ebufp);
 
}

After having applied method 3 to obtain the core file we begin the analysis with mdb.

pin>mdb core.29470
Loading modules: [ libumem.so.1 libc.so.1 libuutil.so.1 ld.so.1 ]
> ::findleaks
mdb: [fc000000, fc564000): couldn't read 16384 bytes at fc000000: no mapping for address
CACHE     LEAKED   BUFCTL CALLER
00062008       1 00454780 libc.so.1`strdup+0xc
00068008       1 0045a830 libcmpin.so`_alloc_result_header+0x18
00062008       1 004547e8 libcmpin.so`_pin_decimal_add_mag+0x224
000a8008       1 0040a3b0 libcmpin.so`pcmmem_malloc_flistflds+0x34
000a8008       1 0040a2e0 libcmpin.so`pcmmem_malloc_flistflds+0x34
000a8008       1 005e6220 libcmpin.so`pcmmem_malloc_flistflds+0x34
000a4008       1 004001a0 libcmpin.so`pcmmem_malloc_flisthdr+0x34
000a4008       1 0040ab68 libcmpin.so`pcmmem_malloc_flisthdr+0x34
000a4008       1 005e6970 libcmpin.so`pcmmem_malloc_flisthdr+0x34
0006c008       1 0064dd40 libcmpin.so`pcmmem_malloc_poid+0x34
0006c008       1 00635540 libcmpin.so`pcmmem_malloc_poid+0x34
0006c008       1 00635950 libcmpin.so`pcmmem_malloc_poid+0x34
0006c008       1 006355a8 libcmpin.so`pcmmem_malloc_poid+0x34
00062008       1 00454718 libcmpin.so`pin_decimal+0x358
00062008       1 00454578 libcmpin.so`pin_decimal+0x358
00068008       1 0045a5c0 libcmpin.so`pin_decimal+0x640
00068008       1 0045a760 libcmpin.so`pin_decimal+0x640
00068008       1 0045a7c8 libcmpin.so`pin_decimal_clone+0x50
----------------------------------------------------------------------
   Total      18 buffers, 2400 bytes
>

Here we see that there are 18 buffers with leaks, we will start the analysis of the first one (address bufctl: 00454780) with ::bufctl_audit

> 00454780::bufctl_audit
            ADDR          BUFADDR        TIMESTAMP           THREAD
                            CACHE          LASTLOG         CONTENTS
          454780           4528c0   9f4b67977cc06e                1
                            62008                0                0
                 libumem.so.1`umem_cache_alloc+0x13c
                 libumem.so.1`umem_alloc+0x60
                 libumem.so.1`malloc+0x28
                 libc.so.1`strdup+0xc
                 libcmpin.so`pin_decimal_clone+0x8c
                 libcmpin.so`pbo_decimal_copy+0x14
                 fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0xc0
                 fm_inv_pol.so`fm_inv_pol_demo_leaks_start_demo+0xe44
                 fm_inv_pol.so`fm_inv_pol_prep_invoice+0x11c
                 fm_inv_pol.so`op_inv_pol_prep_invoice+0xf4
                 libcmpin.so`cm_pre_pcm_op+0x14f4
                 libcmpin.so`pcm_op_ex+0x390
                 fm_inv.so`fm_inv_make_invoice_exec_opcode_prep_invoice+0xb4
                 fm_inv.so`fm_inv_make_invoice+0x1a38
                 fm_inv.so`op_inv_make_invoice+0xe4
>

Looking at the stack trace, the libumem.so.1`malloc entry in each stack is the function that is allocating the memory to the leaked buffer. What we are analyzing is our code that is used within the fm_inv_pol.so library, so the leak is on the first line in which the string fm_inv_pol.so appears (in this case it is fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0xc0) and the previous line is the function of the PIN library that is being invoked within our code (libcmpin.so`pbo_decimal_copy+0x14).

So from what was said in the previous paragraph we can see that within the function fm_inv_pol_demo_leaks_pin_decimal_t the function pbo_decimal_copy is being called and that is the memory that we are leaking.

What remains to be done now is to find where the definition of the fm_inv_pol_demo_leaks_pin_decimal_t function is among the files that make up the fm_inv_pol.so library. In this case the file is fm_inv_pol_demo_leaks.c and the function fm_inv_pol_demo_leaks_pin_decimal_t is:

void
fm_inv_pol_demo_leaks_pin_decimal_t(
 pin_flist_t     *i_flistp,
 pin_errbuf_t *ebufp)
{
 pin_decimal_t *decimal1p = NULL;
 pin_decimal_t *decimal2p = NULL;
 pin_decimal_t *demo_create_decimalp = NULL;
 pin_decimal_t *demo_copy_decimalp = NULL;
 pin_decimal_t *demo_take_decimalp = NULL;
 pin_decimal_t *demo_add_decimalp = NULL;
 
 demo_create_decimalp = pbo_decimal_from_str("100", ebufp);
 
 decimal1p = PIN_FLIST_FLD_GET(i_flistp, PIN_FLD_AMOUNT, 0, ebufp);
 demo_copy_decimalp = pbo_decimal_copy(decimal1p, ebufp); 

 decimal1p = PIN_FLIST_FLD_GET(i_flistp, PIN_FLD_DUE, 0, ebufp);
 decimal2p = PIN_FLIST_FLD_GET(i_flistp, PIN_FLD_TOTAL_DUE, 0, ebufp);
 demo_add_decimalp = pbo_decimal_add(decimal1p, decimal2p, ebufp); 
 
 demo_take_decimalp = PIN_FLIST_FLD_TAKE(i_flistp, PIN_FLD_DUE, 0, ebufp);
 
}

In this case there is only one invocation to the pbo_decimal_copy function (line 116), so it is easy to know that the memory of the demo_copy_decimalp variable must be freed. But ... what would happen if the fm_inv_pol_demo_leaks_pin_decimal_t function was not so small and that there was more than one call to the pbo_decimal_copy function and that there were many for, while with nested if and within them several times the call to pbo_decimal_copy, there the thing would not be so easy to detect. Luckily, within mdb we have more dcmd commands to find our memory leak in the source code. We will use ::dis to disassemble instructions near the current code pointer (it will give us a line close to where the leak is occurring, sometimes it gives us the exact line, later in this post I will show when we can get the exact line and when do not).

We will apply ::dis in the line where the fm_inv_pol.so library appears for the first time. Which gives us: fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0xc0::dis (it can also be fm_inv_pol_demo_leaks_pin_decimal_t+0xc0::dis is the same).
> fm_inv_pol_demo_leaks_pin_decimal_t+0xc0::dis
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x98: st        %o0, [%fp - 0x20]
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x9c: ld        [%fp - 0x20], %l0
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0xa0: ba        +0xc          <fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0xac>
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0xa4: st        %l0, [%fp - 0x1c]
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0xa8: clr       [%fp - 0x1c]
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0xac: ld        [%fp - 0x1c], %l0
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0xb0: st        %l0, [%fp - 0x4]
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0xb4: ld        [%fp - 0x4], %l0
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0xb8: ld        [%fp + 0x48], %l1
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0xbc: or        %l0, %g0, %o0
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0xc0: call      +0x274b604    <libcmpin.so`pbo_decimal_copy>
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0xc4: or        %l1, %g0, %o1
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0xc8: st        %o0, [%fp - 0x10]
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0xcc: ld        [%fp + 0x48], %l0
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0xd0: ld        [%l0 + 0x8], %l0
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0xd4: cmp       %l0, 0x0
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0xd8: bne       +0x5c         <fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x134>
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0xdc: nop
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0xe0: mov       0x76, %l1
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0xe4: ld        [%fp + 0x48], %l0
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0xe8: st        %l1, [%l0 + 0x18]
>
Seeing the result of the command will not be able to obtain the exact memory leak line (the instructions are not centered), but an approximation. Where we see the call instruction is the point where the function that produces memory leak is being invoked (in this case the <libcmpin.so`pin_poid_copy>), we look for some mov instruction and see a number in hexadecimal, that number is a line number near where the memory leak is occurring. In this case the line with the mov is mov       0x76, %l1. The number that interests us is the 0x76 that gives us the 118 decimal, so the leak will be in a call to the pbo_decimal_copy function near line 118. Since the call is before the mov we are analyzing, then the leak will be before of line 118. In our example it is on line 116.


We have already found where the leak is in our source code. Now let's analyze the second buffer that the ::findleaks gave us (address bufctl: 0045a830) with ::bufctl_audit
> 0045a830::bufctl_audit
            ADDR          BUFADDR        TIMESTAMP           THREAD
                            CACHE          LASTLOG         CONTENTS
          45a830           45c748   9f4b67977ce785                1
                            68008                0                0
                 libumem.so.1`umem_cache_alloc+0x13c
                 libumem.so.1`umem_alloc+0x60
                 libumem.so.1`malloc+0x28
                 libcmpin.so`_alloc_result_header+0x18
                 libcmpin.so`_pin_decimal_add_mag+0x4cc
                 libcmpin.so`pin_decimal_add+0x210
                 libcmpin.so`pbo_decimal_add+0xc
                 fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x1c8
                 fm_inv_pol.so`fm_inv_pol_demo_leaks_start_demo+0xe44
                 fm_inv_pol.so`fm_inv_pol_prep_invoice+0x11c
                 fm_inv_pol.so`op_inv_pol_prep_invoice+0xf4
                 libcmpin.so`cm_pre_pcm_op+0x14f4
                 libcmpin.so`pcm_op_ex+0x390
                 fm_inv.so`fm_inv_make_invoice_exec_opcode_prep_invoice+0xb4
                 fm_inv.so`fm_inv_make_invoice+0x1a38

>

Following the steps of the buffer discussed above we see that the leak is in the fm_inv_pol_demo_leaks_pin_decimal_t function when executing the pbo_decimal_add function. We apply the ::dis to fm_inv_pol_demo_leaks_pin_decimal_t+0x1c8
> fm_inv_pol_demo_leaks_pin_decimal_t+0x1c8::dis
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x1a0:ba        +0xc          <fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x1ac>
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x1a4:st        %l0, [%fp - 0x2c]
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x1a8:clr       [%fp - 0x2c]
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x1ac:ld        [%fp - 0x2c], %l0
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x1b0:st        %l0, [%fp - 0x8]
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x1b4:ld        [%fp - 0x4], %l0
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x1b8:ld        [%fp - 0x8], %l1
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x1bc:ld        [%fp + 0x48], %l2
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x1c0:or        %l0, %g0, %o0
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x1c4:or        %l1, %g0, %o1
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x1c8:call      +0x274b6d0    <libcmpin.so`pbo_decimal_add>
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x1cc:or        %l2, %g0, %o2
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x1d0:st        %o0, [%fp - 0x18]
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x1d4:ld        [%fp + 0x48], %l0
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x1d8:ld        [%l0 + 0x8], %l0
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x1dc:cmp       %l0, 0x0
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x1e0:bne       +0x5c         <fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x23c>
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x1e4:nop
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x1e8:mov       0x7a, %l1
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x1ec:ld        [%fp + 0x48], %l0
fm_inv_pol.so`fm_inv_pol_demo_leaks_pin_decimal_t+0x1f0:st        %l1, [%l0 + 0x18]
>

In this case we will not obtain the exact address (the instructions are not centered), but an approximate one, we look for the call and the mob again. The mov is after the call so the leak will be before the hexadecimal number of the mov: mov       0x7a, %l1. The 0x7a in decimal is 122, so you have to look for a function call pbo_decimal_add before line 122, in our case it is the one found on line 120.

Now let's analyze another buffer (I'm going to use one that does have the exact address) on 13 of the list thrown by the ::findleaks. (address bufctl: 006355a8) with ::bufctl_audit
> 006355a8::bufctl_audit
            ADDR          BUFADDR        TIMESTAMP           THREAD
                            CACHE          LASTLOG         CONTENTS
          6355a8           631b90   9f4b67977c50b4                1
                            6c008                0                0
                 libumem.so.1`umem_cache_alloc+0x210
                 libumem.so.1`umem_alloc+0x60
                 libumem.so.1`malloc+0x28
                 libcmpin.so`pcmmem_malloc_poid+0x34
                 libcmpin.so`pin_poid_create+0x70
                 libcmpin.so`pin_poid_copy+0x78
                 fm_inv_pol.so`fm_inv_pol_demo_leaks_poid_t+0x154
                 fm_inv_pol.so`fm_inv_pol_demo_leaks_start_demo+0xe30
                 fm_inv_pol.so`fm_inv_pol_prep_invoice+0x11c
                 fm_inv_pol.so`op_inv_pol_prep_invoice+0xf4
                 libcmpin.so`cm_pre_pcm_op+0x14f4
                 libcmpin.so`pcm_op_ex+0x390
                 fm_inv.so`fm_inv_make_invoice_exec_opcode_prep_invoice+0xb4
                 fm_inv.so`fm_inv_make_invoice+0x1a38
                 fm_inv.so`op_inv_make_invoice+0xe4
>

Here we see that the leak is in the fm_inv_pol_demo_leaks_poid_t function when invoking pin_poid_copy. The fm_inv_pol_demo_leaks_poid_t function is:
void
fm_inv_pol_demo_leaks_poid_t(
 pcm_context_t *ctxp,
 pin_flist_t     *i_flistp,
 pin_errbuf_t *ebufp)
{
 poid_t   *poidp = NULL;
 poid_t   *demo_create_poidp = NULL;
 poid_t   *demo_copy_poidp = NULL;
 poid_t   *demo_take_poidp = NULL;
 
 demo_create_poidp = PIN_POID_CREATE(PCM_GET_CURRENT_DB_NO(ctxp), "/account", -1, ebufp);
 
 poidp = PIN_FLIST_FLD_GET(i_flistp, PIN_FLD_POID, 0, ebufp);
 demo_copy_poidp = PIN_POID_COPY(poidp, ebufp);
 
 demo_take_poidp = PIN_FLIST_FLD_TAKE(i_flistp, PIN_FLD_ACCOUNT_OBJ, 0, ebufp);
 
}

We will analyze then fm_inv_pol_demo_leaks_poid_t+0x154 with ::dis
> fm_inv_pol_demo_leaks_poid_t+0x154::dis
fm_inv_pol.so`fm_inv_pol_demo_leaks_poid_t+0x12c:       mov       0x5f, %l1
fm_inv_pol.so`fm_inv_pol_demo_leaks_poid_t+0x130:       ld        [%fp + 0x4c], %l0
fm_inv_pol.so`fm_inv_pol_demo_leaks_poid_t+0x134:       st        %l1, [%l0 + 0x18]
fm_inv_pol.so`fm_inv_pol_demo_leaks_poid_t+0x138:       sethi     %hi(0xfb216c00), %l1
fm_inv_pol.so`fm_inv_pol_demo_leaks_poid_t+0x13c:       or        %l1, 0xf0, %l1
fm_inv_pol.so`fm_inv_pol_demo_leaks_poid_t+0x140:       ld        [%fp + 0x4c], %l0
fm_inv_pol.so`fm_inv_pol_demo_leaks_poid_t+0x144:       st        %l1, [%l0 + 0x1c]
fm_inv_pol.so`fm_inv_pol_demo_leaks_poid_t+0x148:       ld        [%fp - 0x4], %l0
fm_inv_pol.so`fm_inv_pol_demo_leaks_poid_t+0x14c:       ld        [%fp + 0x4c], %l1
fm_inv_pol.so`fm_inv_pol_demo_leaks_poid_t+0x150:       or        %l0, %g0, %o0
fm_inv_pol.so`fm_inv_pol_demo_leaks_poid_t+0x154:       call      +0x27445ac    <libcmpin.so`pin_poid_copy>
fm_inv_pol.so`fm_inv_pol_demo_leaks_poid_t+0x158:       or        %l1, %g0, %o1
fm_inv_pol.so`fm_inv_pol_demo_leaks_poid_t+0x15c:       st        %o0, [%fp - 0x28]
fm_inv_pol.so`fm_inv_pol_demo_leaks_poid_t+0x160:       ld        [%fp - 0x28], %l0
fm_inv_pol.so`fm_inv_pol_demo_leaks_poid_t+0x164:       ba        +0xc          <fm_inv_pol.so`fm_inv_pol_demo_leaks_poid_t+0x170>
fm_inv_pol.so`fm_inv_pol_demo_leaks_poid_t+0x168:       st        %l0, [%fp - 0x24]
fm_inv_pol.so`fm_inv_pol_demo_leaks_poid_t+0x16c:       clr       [%fp - 0x24]
fm_inv_pol.so`fm_inv_pol_demo_leaks_poid_t+0x170:       ld        [%fp - 0x24], %l0
fm_inv_pol.so`fm_inv_pol_demo_leaks_poid_t+0x174:       st        %l0, [%fp - 0xc]
fm_inv_pol.so`fm_inv_pol_demo_leaks_poid_t+0x178:       ld        [%fp + 0x4c], %l0
fm_inv_pol.so`fm_inv_pol_demo_leaks_poid_t+0x17c:       ld        [%l0 + 0x8], %l0
>

In this case ::dis is giving us the exact line where the mmory leak is located (we see that the instructions are centered), so the line is the "mov       0x5f, %l1" which in decimal is 95. Effectively seeing the code is You see that on line 95 there is the invocation of the PIN_POID_COPY and that is where the leak occurs (the memory of the demo_copy_poidp variable must be freed).

So far we have seen how with the core file using mdb we can reach the source code line where the memory allocation is taking place that is not released. The next post will address the detection of memory leaks in applications that use the framework MTA framework.

A couple of tips before finishing the post:
  1. ::findleaks -dv is like to execute ::bufctl_audit for all buffers.
  2. If we have our core file for a quick inspection of a particular library or function, we can use the following command: echo "::findleaks -d " | mdb archivo_core | grep mi_libreria.so, in the case of the example we have seen in this post: echo "::findleaks -d " | mdb core.29470 | grep fm_inv_pol.so
  3. When we are using the dcmd ::dis and we cannot find the mov instruction, execute it again but with the parameters -n quantity_instructions. Example: fm_inv_pol_demo_leaks_pin_decimal_t+0xc0::dis -n 40 (will show 40 instructions before the address and 40 after the instruction, by default the dcmd ::dis shows 10 instructions before and 10 after the address and does not always bring the mov)

Martín Falconi

No hay comentarios.:

Publicar un comentario