SlideShare a Scribd company logo
1 of 51
Download to read offline
Tips of
malloc & free
 Making your own malloc
library for troubleshooting
  2013.2.22 Embedded Linux Conference


   Tetsuyuki Kobayashi
                                        1
   The latest version of this slide will
    be available from here
   http://www.slideshare.net/tetsu.koba/presentations




                                                   2
Who am I?
   20+ years involved in embedded systems
       10 years in real time OS, such as iTRON
       10 years in embedded Java Virtual Machine
       Now GCC, Linux, QEMU, Android, …
   Blogs
       http://d.hatena.ne.jp/embedded/ (Personal)
       http://blog.kmckk.com/ (Corporate)
       http://kobablog.wordpress.com/(English)
   Twitter
       @tetsu_koba                                  3
Today's topics
   Prologue: Making your own malloc
    library for troubleshooting
   System calls to allocate memory in
    user space
   Tips of glibc's malloc
   How to hook and replace malloc (and
    pitfalls I fell)
   dlmalloc
                                          4
Prologue:
  Making your own malloc
library for troubleshooting


                          5
Typical troubles of heap memory
   Corruption
      crashed by SEGV at malloc or free.

       looks malloc bug, but NOT
      Who actually destroy heap?


   Leaking
      malloc'ed but not free'ed


      damages silently


   You want additional checking and
    logging in malloc/free                  6
Wrapping macro/fuction

   #define malloc(x) debug_malloc(x)
   Useful. But you can't cover all
    malloc calling because ...




                                        7
Explicit call for malloc

   many standard library functions
    use malloc internally
      example) sprintf


   C++ new operator uses malloc
    internelly


                                      8
Modify glibc(libc.so) directly?

   libc source package is quite large
   If you replace libc.so, it affects
    whole system
      not only for the debugee process




                                      9
So I did was

   making my own malloc library
     easy to modify


     use this only for the debugee

      process



                                      10
System calls
to allocate memory in
      user space

                        11
System calls to allocate
       memory in user space
   You need system call to allocate in
    user space when you make your own
    malloc library
   There are 2 types of them
      brk/sbrk


      mmap/munmap/mremap




                                          12
brk/sbrk
   exists from ancient Unix
      before virtual memory system


   extends data segment
   standard malloc library use these
    system calls
   You should not use these system calls
    if your own malloc library co-exist with
    standard malloc library                13
brk/sbrk extends data segment
         Memory map of user process on old simple UNIX

                                 Text                   Read Only
                                              etext

                                 Data
                                             edata

                  Zero cleared   Bss                     Read Write
                                              end

                                 Heap
    At modern OS
start address of heap                    Extends by brk(2)/sbrk(2)
    is randomized
                                        Grows down automatically
                                 Stack
                                                                      14
cat /proc/self/maps
You see memory map of 'cat /proc/self/maps' itself
$ cat /proc/self/maps
00400000-0040d000 r-xp 00000000 08:01 1048675             /bin/cat
                                                                                  This is heap area
0060d000-0060e000 r--p 0000d000 08:01 1048675             /bin/cat
0060e000-0060f000 rw-p 0000e000 08:01 1048675             /bin/cat
01a7a000-01a9b000 rw-p 00000000 00:00 0                   [heap]
7f10f05d0000-7f10f074d000 r-xp 00000000 08:01 316763      /lib/libc-2.11.1.so
7f10f074d000-7f10f094c000 ---p 0017d000 08:01 316763      /lib/libc-2.11.1.so
7f10f094c000-7f10f0950000 r--p 0017c000 08:01 316763      /lib/libc-2.11.1.so
7f10f0950000-7f10f0951000 rw-p 00180000 08:01 316763      /lib/libc-2.11.1.so
7f10f0951000-7f10f0956000 rw-p 00000000 00:00 0
7f10f0956000-7f10f0976000 r-xp 00000000 08:01 272407      /lib/ld-2.11.1.so
7f10f09fa000-7f10f0a39000 r--p 00000000 08:01 1580725     /usr/lib/locale/en_US.utf8/LC_CTYPE
7f10f0a39000-7f10f0b57000 r--p 00000000 08:01 1580503     /usr/lib/locale/en_US.utf8/LC_COLLATE
7f10f0b57000-7f10f0b5a000 rw-p 00000000 00:00 0
7f10f0b62000-7f10f0b63000 r--p 00000000 08:01 1580587     /usr/lib/locale/en_US.utf8/LC_NUMERIC
7f10f0b63000-7f10f0b64000 r--p 00000000 08:01 1583228     /usr/lib/locale/en_US.utf8/LC_TIME
7f10f0b64000-7f10f0b65000 r--p 00000000 08:01 1583229     /usr/lib/locale/en_US.utf8/LC_MONETARY
7f10f0b65000-7f10f0b66000 r--p 00000000 08:01 1583230     /usr/lib/locale/en_US.utf8/LC_MESSAGES/SYS_LC_MESSAGES
7f10f0b66000-7f10f0b67000 r--p 00000000 08:01 1580575     /usr/lib/locale/en_US.utf8/LC_PAPER
7f10f0b67000-7f10f0b68000 r--p 00000000 08:01 1580573     /usr/lib/locale/en_US.utf8/LC_NAME
7f10f0b68000-7f10f0b69000 r--p 00000000 08:01 1583231     /usr/lib/locale/en_US.utf8/LC_ADDRESS
7f10f0b69000-7f10f0b6a000 r--p 00000000 08:01 1583232     /usr/lib/locale/en_US.utf8/LC_TELEPHONE
7f10f0b6a000-7f10f0b6b000 r--p 00000000 08:01 1580571     /usr/lib/locale/en_US.utf8/LC_MEASUREMENT
7f10f0b6b000-7f10f0b72000 r--s 00000000 08:01 1623537     /usr/lib/gconv/gconv-modules.cache
7f10f0b72000-7f10f0b73000 r--p 00000000 08:01 1583233     /usr/lib/locale/en_US.utf8/LC_IDENTIFICATION
7f10f0b73000-7f10f0b75000 rw-p 00000000 00:00 0
7f10f0b75000-7f10f0b76000 r--p 0001f000 08:01 272407      /lib/ld-2.11.1.so
7f10f0b76000-7f10f0b77000 rw-p 00020000 08:01 272407      /lib/ld-2.11.1.so
7f10f0b77000-7f10f0b78000 rw-p 00000000 00:00 0
7fff80929000-7fff8093e000 rw-p 00000000 00:00 0           [stack]
7fff809ff000-7fff80a00000 r-xp 00000000 00:00 0           [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0   [vsyscall]
                                                                                                            15
mmap/munmap/mremap

   newer system calls than brk/sbrk
      integrate memory and file mapping


   Glibc's malloc also use these when
    large chunk (>= 128KB: default)
    required
   Use these when you implement your
    own malloc library
                                           16
Usage of mmap(2)

      addr = mmap(NULL, size, PROT_READ|PROT_WRITE,
                  MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
      if (MAP_FAILED == addr) {
              perror("mmap");
              abort();
      }




You don't have to specify address. (set NULL)
Then kernel allocate memory from free space.


                                                      17
alloca(3)
    By the way,

    allocates memory in caller's stack
     frame
    frees automatically when the function
     that called alloca() returns
       same as local variables


       machine and compiler dependent


       be careful when stack size is small


               especially multi-thread
                                              18
Tips of glibc's malloc


                         19
mallopt

   int mallopt(int param, int value)
   configures glibc malloc such as
      M_CHECK_ACTION


      M_MMAP_THRESHOLD


      M_TOP_PAD


      M_TRIM_THRESHOLD


   see man 3 mallopt
                                        20
malloc_stats

   void malloc_stats(void)
   prints (on standard error) statistics
    about heap like this
        Arena 0:
        system bytes     =    135168
        in use bytes     =       128
        Total (incl. mmap):
        system bytes     =    139264
        in use bytes     =      4224
        max mmap regions =         1
        max mmap bytes   =    569344
                                            21
malloc_usable_size
   size_t malloc_usable_size(void *__ptr)
      reports the number of usable allocated bytes
       associated with allocated chunk __ptr
      This size may be a bit bigger than the size

       specified at malloc()
               because of alignment of next data


   This is useful when counting allocated total
    size
       increment size in hooked malloc
       decrement size in hooked free           22
MALLOC_CHECK_

   easy way to enable additional
    checking in glibc malloc
      with some overhead


   environment variable
    MALLOC_CHECK_
      0: no check at all (no overhead)


      1: check and print message if error


      2: check and abort if error
                                             23
__malloc_hook
   glibc's malloc has its own hook
    mechanism
   global variables of function pointers
      __malloc_hook


      __realloc_hook


      __memalign_hook


      __free_hook


      __malloc_initialize_hook


   man malloc_hook for detail              24
mtrace

   easy way to enable logging in glibc
    malloc
      see man 3 mtrace


   There is tool to check log and find
    leaking memory
      see man 1 mtrace


   implemented using __malloc_hook
      This seems not thread safe
                                          25
How to hook and
 replace malloc

                  26
Hook and replace malloc

   2 methods to hook malloc
     LD_PRELOAD & dlsym


     __malloc_hook


   These do not require to recompile
    other program and libraries


                                        27
Using LD_PRELOAD & dlsym to
             hook malloc
   Use dynamic link mechanism
     can not use when static linking
   Make your own malloc dynamic link library
    and set it to environment variable
    LD_PRELOAD
   Then your malloc is used prior to glibc's
    malloc
   You can get glibc's malloc address by
    dlsym(3)                                    28
Usual call for malloc




                       glibc

executable
 executable            malloc
                       malloc
 /libraries
  /libraries




                                29
Hooking malloc by LD_PRELOAD

preload by LD_PRELOAD

                        your own library
                                               get address by
                                               dlsym(RTLD_NEXT, “malloc”)
                            malloc
                            malloc

                                                     glibc

      executable
       executable                                    malloc
                                                     malloc
       /libraries
        /libraries            output log or
                             record size ...




                                                                       30
minimum sample code

static void __attribute__((constructor)) init(void)
{
      callocp = (void *(*) (size_t, size_t)) dlsym (RTLD_NEXT, "calloc");
      mallocp = (void *(*) (size_t)) dlsym (RTLD_NEXT, "malloc");
      reallocp = (void *(*) (void *, size_t)) dlsym (RTLD_NEXT, "realloc");
      memalignp = (void *(*)(size_t, size_t)) dlsym (RTLD_NEXT, "memalign");
      freep = (void (*) (void *)) dlsym (RTLD_NEXT, "free");



                     void *malloc (size_t len)
                    {
                         void *ret;

                         ret = (*mallocp)(len);
                         return ret;
                    }

                                                                               31
Pitfall #1

   If you use printf to output logs, it
    causes recursive call of malloc.
    Because printf uses malloc
    internally.




                                           32
Avoid infinite recursive call
   static __thread int no_hook;

   void *malloc (size_t len)                   TLS (Thread Local Storage)
   {
        void *ret;
        void *caller;

        if (no_hook) {
              return (*mallocp)(len);
        }

        no_hook = 1;
        caller = RETURN_ADDRESS(0);
        fprintf(logfp, "%p malloc(%zu", caller, len);
        ret = (*mallocp)(len);
        fprintf(logfp, ") -> %pn", ret);
        no_hook = 0;
        return ret;
   }                                                                   33
Pitfall #2

   When compile with -pthread, it
    crashes at the beginning. Why?
   In multi-thread mode, dlsym() uses
    calloc() at the first time.
      calloc() requires dlsym()

       dlsym() requires calloc() … !!
      prepare special calloc() for the first

       call of calloc().
                                                34
st
Call special calloc at the 1 time

    void *calloc (size_t n, size_t len)
    {
         void *ret;
         void *caller;                    Just returns some static
                                             allocated memory
         if (no_hook) {
               if (callocp == NULL) {
                     ret = my_calloc(n, len);
                     return ret;
               }
               return (*callocp)(n, len);
         }
         ...

                                                               35
Using __malloc_hook variable to
         hook malloc
   function pointer variables for hooking
       void *(*__malloc_hook)(size_t, const void*)
       void*(*__realloc_hook)(void*, size_t, const void*)
       void*(*__memalign_hook)(size_t, size_t, const void*)
       void (*__free_hook)(void)
       void (*__malloc_initialize_hook)(void)




                                                             36
Usual call for malloc


                       glibc

executable
 executable            malloc
                       malloc
 /libraries
  /libraries




                                37
Hooking malloc by
                    __malloc_hook

                                                               glibc

           executable
            executable                                         malloc
                                                               malloc
            /libraries
             /libraries                                     __malloc_hook



void_t *malloc(size_t bytes)
{
  __malloc_ptr_t (*hook) (size_t, __const __malloc_ptr_t)
    =__malloc_hook;                                          my_malloc
                                                             my_malloc
  if (hook != NULL)
    return (*hook)(bytes, RETURN_ADDRESS (0));
                                                            Your own library
                                                                               38
Thread unsafe example
static void *
my_malloc_hook(size_t size, const void *caller)               __malloc_hook is not
{
      void *result;
                                                                 locked at all

     /* Restore all old hooks */
     __malloc_hook = old_malloc_hook;

     /* Call recursively */
     result = malloc(size);

     /* Save underlying hooks */                                      In this moment
     old_malloc_hook = __malloc_hook;                                 malloc from other
                                                                      thread does not
     /* printf() might call malloc(), so protect it too. */           hook.
     printf("malloc(%u) called from %p returns %pn",
           (unsigned int) size, caller, result);

     /* Restore our own hooks */
     __malloc_hook = my_malloc_hook;
     return result;                                                                  39
}
Workaround

   Changing __malloc_hook variable is
    not thread safe. (Actually these
    variables are marked as 'deprecated')
   Set once these hook variables at
    initial time and don't touch after that.
      You can not call back glibc's malloc.


      link and replace to other malloc.


               dlmalloc is good for this.
                                           40
Which ?

   If you replace malloc
      You can use __malloc_hook with

       care
   Otherwise
      use LD_PRELOAD & dlsym




                                    41
Another pitfall

   Almost program works fine with my
    own malloc library. But some game
    app. causes SEGV accessing null
    pointer.
   At first I doubt that malloc returns
    NULL because heap runs out …


                                           42
Behavior of malloc(size=0)

   I thought malloc(0) returns NULL.
   man malloc says:
      “If size is 0, then malloc() returns

       either NULL, or a unique pointer
       value that can later be successfully
       passed to free().”
   glibc's malloc does the latter.
   The game app. calls malloc(0) and
    use the pointer without check!
      so it causes null pointer access


   I modified my malloc returns a unique
    pointer even if size == 0
   Then the game app. works fine with
    my malloc library.
dlmalloc


           45
dlmalloc

   by Doug Lea
   http://g.oswego.edu/dl/html/malloc.html
   easy to compile and use
       can add prefix to all function names to
        avoid conflict to standard malloc
        functions (-DUSE_DL_PREFIX)
       add -DUSE_LOCKS=1 for thread safe
   Actually glibc's malloc is based on this      46
mspace of dlmalloc

   can have multiple separate memory
    spaces for heap
      per thread, per functional module, ...


   Good for troubleshooting
       isolate heap of module in question
Usual single heap


   (UI)
    (UI)      malloc()   The single heap


(graphics)
 (graphics)




(database)
 (database)

                             In the same process
                                                   48
Using mspaces

                          Their own mspaces

   (UI)
    (UI)
              mspace_malloc()


(graphics)
 (graphics)




(database)
 (database)

                                In the same process
                                                      49
Summary

   Make your own malloc library rather
    than modify glibc (libc.so).
   Use mmap(2) to get memory.
   __malloc_hook is not thread safe and
    deprecated.
   Use LD_PRELOAD & dlsym(3) to
    hook glibc's malloc.
                                           50
Q&A




              Thank you for listening!


@tetsu_koba
                                         51

More Related Content

What's hot

Linux Kernel Booting Process (1) - For NLKB
Linux Kernel Booting Process (1) - For NLKBLinux Kernel Booting Process (1) - For NLKB
Linux Kernel Booting Process (1) - For NLKBshimosawa
 
qemu + gdb: The efficient way to understand/debug Linux kernel code/data stru...
qemu + gdb: The efficient way to understand/debug Linux kernel code/data stru...qemu + gdb: The efficient way to understand/debug Linux kernel code/data stru...
qemu + gdb: The efficient way to understand/debug Linux kernel code/data stru...Adrian Huang
 
BPF Internals (eBPF)
BPF Internals (eBPF)BPF Internals (eBPF)
BPF Internals (eBPF)Brendan Gregg
 
AARCH64 VMSA Under Linux Kernel
AARCH64 VMSA Under Linux KernelAARCH64 VMSA Under Linux Kernel
AARCH64 VMSA Under Linux KernelHaifeng Li
 
Vmlinux: anatomy of bzimage and how x86 64 processor is booted
Vmlinux: anatomy of bzimage and how x86 64 processor is bootedVmlinux: anatomy of bzimage and how x86 64 processor is booted
Vmlinux: anatomy of bzimage and how x86 64 processor is bootedAdrian Huang
 
The Linux Block Layer - Built for Fast Storage
The Linux Block Layer - Built for Fast StorageThe Linux Block Layer - Built for Fast Storage
The Linux Block Layer - Built for Fast StorageKernel TLV
 
The e820 trap of Linux kernel hibernation
The e820 trap of Linux kernel hibernationThe e820 trap of Linux kernel hibernation
The e820 trap of Linux kernel hibernationjoeylikernel
 
Linux Memory Management
Linux Memory ManagementLinux Memory Management
Linux Memory ManagementNi Zo-Ma
 
COSCUP 2020 RISC-V 32 bit linux highmem porting
COSCUP 2020 RISC-V 32 bit linux highmem portingCOSCUP 2020 RISC-V 32 bit linux highmem porting
COSCUP 2020 RISC-V 32 bit linux highmem portingEric Lin
 
netfilter and iptables
netfilter and iptablesnetfilter and iptables
netfilter and iptablesKernel TLV
 
Reverse Mapping (rmap) in Linux Kernel
Reverse Mapping (rmap) in Linux KernelReverse Mapping (rmap) in Linux Kernel
Reverse Mapping (rmap) in Linux KernelAdrian Huang
 
Performance Wins with BPF: Getting Started
Performance Wins with BPF: Getting StartedPerformance Wins with BPF: Getting Started
Performance Wins with BPF: Getting StartedBrendan Gregg
 
Linux Kernel Booting Process (2) - For NLKB
Linux Kernel Booting Process (2) - For NLKBLinux Kernel Booting Process (2) - For NLKB
Linux Kernel Booting Process (2) - For NLKBshimosawa
 
Page cache in Linux kernel
Page cache in Linux kernelPage cache in Linux kernel
Page cache in Linux kernelAdrian Huang
 
Linux kernel memory allocators
Linux kernel memory allocatorsLinux kernel memory allocators
Linux kernel memory allocatorsHao-Ran Liu
 
Understanding eBPF in a Hurry!
Understanding eBPF in a Hurry!Understanding eBPF in a Hurry!
Understanding eBPF in a Hurry!Ray Jenkins
 
U-Boot Porting on New Hardware
U-Boot Porting on New HardwareU-Boot Porting on New Hardware
U-Boot Porting on New HardwareRuggedBoardGroup
 

What's hot (20)

Linux Kernel Booting Process (1) - For NLKB
Linux Kernel Booting Process (1) - For NLKBLinux Kernel Booting Process (1) - For NLKB
Linux Kernel Booting Process (1) - For NLKB
 
qemu + gdb: The efficient way to understand/debug Linux kernel code/data stru...
qemu + gdb: The efficient way to understand/debug Linux kernel code/data stru...qemu + gdb: The efficient way to understand/debug Linux kernel code/data stru...
qemu + gdb: The efficient way to understand/debug Linux kernel code/data stru...
 
BPF Internals (eBPF)
BPF Internals (eBPF)BPF Internals (eBPF)
BPF Internals (eBPF)
 
AARCH64 VMSA Under Linux Kernel
AARCH64 VMSA Under Linux KernelAARCH64 VMSA Under Linux Kernel
AARCH64 VMSA Under Linux Kernel
 
Linux Network Stack
Linux Network StackLinux Network Stack
Linux Network Stack
 
Vmlinux: anatomy of bzimage and how x86 64 processor is booted
Vmlinux: anatomy of bzimage and how x86 64 processor is bootedVmlinux: anatomy of bzimage and how x86 64 processor is booted
Vmlinux: anatomy of bzimage and how x86 64 processor is booted
 
The Linux Block Layer - Built for Fast Storage
The Linux Block Layer - Built for Fast StorageThe Linux Block Layer - Built for Fast Storage
The Linux Block Layer - Built for Fast Storage
 
Qemu JIT Code Generator and System Emulation
Qemu JIT Code Generator and System EmulationQemu JIT Code Generator and System Emulation
Qemu JIT Code Generator and System Emulation
 
The e820 trap of Linux kernel hibernation
The e820 trap of Linux kernel hibernationThe e820 trap of Linux kernel hibernation
The e820 trap of Linux kernel hibernation
 
Linux Memory Management
Linux Memory ManagementLinux Memory Management
Linux Memory Management
 
COSCUP 2020 RISC-V 32 bit linux highmem porting
COSCUP 2020 RISC-V 32 bit linux highmem portingCOSCUP 2020 RISC-V 32 bit linux highmem porting
COSCUP 2020 RISC-V 32 bit linux highmem porting
 
netfilter and iptables
netfilter and iptablesnetfilter and iptables
netfilter and iptables
 
Reverse Mapping (rmap) in Linux Kernel
Reverse Mapping (rmap) in Linux KernelReverse Mapping (rmap) in Linux Kernel
Reverse Mapping (rmap) in Linux Kernel
 
Virtual Machine Constructions for Dummies
Virtual Machine Constructions for DummiesVirtual Machine Constructions for Dummies
Virtual Machine Constructions for Dummies
 
Performance Wins with BPF: Getting Started
Performance Wins with BPF: Getting StartedPerformance Wins with BPF: Getting Started
Performance Wins with BPF: Getting Started
 
Linux Kernel Booting Process (2) - For NLKB
Linux Kernel Booting Process (2) - For NLKBLinux Kernel Booting Process (2) - For NLKB
Linux Kernel Booting Process (2) - For NLKB
 
Page cache in Linux kernel
Page cache in Linux kernelPage cache in Linux kernel
Page cache in Linux kernel
 
Linux kernel memory allocators
Linux kernel memory allocatorsLinux kernel memory allocators
Linux kernel memory allocators
 
Understanding eBPF in a Hurry!
Understanding eBPF in a Hurry!Understanding eBPF in a Hurry!
Understanding eBPF in a Hurry!
 
U-Boot Porting on New Hardware
U-Boot Porting on New HardwareU-Boot Porting on New Hardware
U-Boot Porting on New Hardware
 

Similar to Tips of Malloc & Free

Valgrind debugger Tutorial
Valgrind debugger TutorialValgrind debugger Tutorial
Valgrind debugger TutorialAnurag Tomar
 
TLPI - 7 Memory Allocation
TLPI - 7 Memory AllocationTLPI - 7 Memory Allocation
TLPI - 7 Memory AllocationShu-Yu Fu
 
Check the version with fixes. Link in description
Check the version with fixes. Link in descriptionCheck the version with fixes. Link in description
Check the version with fixes. Link in descriptionPrzemyslaw Koltermann
 
The true story_of_hello_world
The true story_of_hello_worldThe true story_of_hello_world
The true story_of_hello_worldfantasy zheng
 
Understanding SLAB in Linux Kernel
Understanding SLAB in Linux KernelUnderstanding SLAB in Linux Kernel
Understanding SLAB in Linux KernelHaifeng Li
 
May2010 hex-core-opt
May2010 hex-core-optMay2010 hex-core-opt
May2010 hex-core-optJeff Larkin
 
Perl Memory Use 201207 (OUTDATED, see 201209 )
Perl Memory Use 201207 (OUTDATED, see 201209 )Perl Memory Use 201207 (OUTDATED, see 201209 )
Perl Memory Use 201207 (OUTDATED, see 201209 )Tim Bunce
 
Buffer overflow tutorial
Buffer overflow tutorialBuffer overflow tutorial
Buffer overflow tutorialhughpearse
 
Mastering java in containers - MadridJUG
Mastering java in containers - MadridJUGMastering java in containers - MadridJUG
Mastering java in containers - MadridJUGJorge Morales
 
Java on Linux for devs and ops
Java on Linux for devs and opsJava on Linux for devs and ops
Java on Linux for devs and opsaragozin
 
Dynamic memory Allocation in c language
Dynamic memory Allocation in c languageDynamic memory Allocation in c language
Dynamic memory Allocation in c languagekiran Patel
 
Why you’re going to fail running java on docker!
Why you’re going to fail running java on docker!Why you’re going to fail running java on docker!
Why you’re going to fail running java on docker!Red Hat Developers
 
exploit-writing-tutorial-part-5-how-debugger-modules-plugins-can-speed-up-bas...
exploit-writing-tutorial-part-5-how-debugger-modules-plugins-can-speed-up-bas...exploit-writing-tutorial-part-5-how-debugger-modules-plugins-can-speed-up-bas...
exploit-writing-tutorial-part-5-how-debugger-modules-plugins-can-speed-up-bas...tutorialsruby
 

Similar to Tips of Malloc & Free (20)

Valgrind debugger Tutorial
Valgrind debugger TutorialValgrind debugger Tutorial
Valgrind debugger Tutorial
 
Metasploit Basics
Metasploit BasicsMetasploit Basics
Metasploit Basics
 
TLPI - 7 Memory Allocation
TLPI - 7 Memory AllocationTLPI - 7 Memory Allocation
TLPI - 7 Memory Allocation
 
Securefile LOBs
Securefile LOBsSecurefile LOBs
Securefile LOBs
 
Check the version with fixes. Link in description
Check the version with fixes. Link in descriptionCheck the version with fixes. Link in description
Check the version with fixes. Link in description
 
The true story_of_hello_world
The true story_of_hello_worldThe true story_of_hello_world
The true story_of_hello_world
 
Understanding SLAB in Linux Kernel
Understanding SLAB in Linux KernelUnderstanding SLAB in Linux Kernel
Understanding SLAB in Linux Kernel
 
May2010 hex-core-opt
May2010 hex-core-optMay2010 hex-core-opt
May2010 hex-core-opt
 
Valgrind
ValgrindValgrind
Valgrind
 
Docker as an every day work tool
Docker as an every day work toolDocker as an every day work tool
Docker as an every day work tool
 
Virtual memory 20070222-en
Virtual memory 20070222-enVirtual memory 20070222-en
Virtual memory 20070222-en
 
Perl Memory Use 201207 (OUTDATED, see 201209 )
Perl Memory Use 201207 (OUTDATED, see 201209 )Perl Memory Use 201207 (OUTDATED, see 201209 )
Perl Memory Use 201207 (OUTDATED, see 201209 )
 
Buffer overflow tutorial
Buffer overflow tutorialBuffer overflow tutorial
Buffer overflow tutorial
 
Mastering java in containers - MadridJUG
Mastering java in containers - MadridJUGMastering java in containers - MadridJUG
Mastering java in containers - MadridJUG
 
Java on Linux for devs and ops
Java on Linux for devs and opsJava on Linux for devs and ops
Java on Linux for devs and ops
 
Lev
LevLev
Lev
 
Dynamic memory Allocation in c language
Dynamic memory Allocation in c languageDynamic memory Allocation in c language
Dynamic memory Allocation in c language
 
Introduction to c part -3
Introduction to c   part -3Introduction to c   part -3
Introduction to c part -3
 
Why you’re going to fail running java on docker!
Why you’re going to fail running java on docker!Why you’re going to fail running java on docker!
Why you’re going to fail running java on docker!
 
exploit-writing-tutorial-part-5-how-debugger-modules-plugins-can-speed-up-bas...
exploit-writing-tutorial-part-5-how-debugger-modules-plugins-can-speed-up-bas...exploit-writing-tutorial-part-5-how-debugger-modules-plugins-can-speed-up-bas...
exploit-writing-tutorial-part-5-how-debugger-modules-plugins-can-speed-up-bas...
 

More from Tetsuyuki Kobayashi

Try new transport protocol SRT (ver. 2)
Try new transport protocol SRT  (ver. 2)Try new transport protocol SRT  (ver. 2)
Try new transport protocol SRT (ver. 2)Tetsuyuki Kobayashi
 
Raspberry Pi Zero とカメラモジュールで作るライブ配信実験機
Raspberry Pi Zero とカメラモジュールで作るライブ配信実験機Raspberry Pi Zero とカメラモジュールで作るライブ配信実験機
Raspberry Pi Zero とカメラモジュールで作るライブ配信実験機Tetsuyuki Kobayashi
 
WebOS Open Source Edition を試してみた
WebOS Open Source Edition を試してみたWebOS Open Source Edition を試してみた
WebOS Open Source Edition を試してみたTetsuyuki Kobayashi
 
Linuxのユーザーランドをinitから全てまるごとgolangで書く
Linuxのユーザーランドをinitから全てまるごとgolangで書くLinuxのユーザーランドをinitから全てまるごとgolangで書く
Linuxのユーザーランドをinitから全てまるごとgolangで書くTetsuyuki Kobayashi
 
組み込みLinuxでのGolangのススメ(Go con版)
組み込みLinuxでのGolangのススメ(Go con版)組み込みLinuxでのGolangのススメ(Go con版)
組み込みLinuxでのGolangのススメ(Go con版)Tetsuyuki Kobayashi
 
組み込みLinuxでのGolangのススメ
組み込みLinuxでのGolangのススメ組み込みLinuxでのGolangのススメ
組み込みLinuxでのGolangのススメTetsuyuki Kobayashi
 
Tricky implementation of Go ARM soft float
Tricky implementation of Go ARM soft floatTricky implementation of Go ARM soft float
Tricky implementation of Go ARM soft floatTetsuyuki Kobayashi
 
Simple and efficient way to get the last log using MMAP
Simple and efficient way to get the last log using MMAPSimple and efficient way to get the last log using MMAP
Simple and efficient way to get the last log using MMAPTetsuyuki Kobayashi
 
Basic of virtual memory of Linux
Basic of virtual memory of LinuxBasic of virtual memory of Linux
Basic of virtual memory of LinuxTetsuyuki Kobayashi
 
ADB(Android Debug Bridge): How it works?
ADB(Android Debug Bridge): How it works?ADB(Android Debug Bridge): How it works?
ADB(Android Debug Bridge): How it works?Tetsuyuki Kobayashi
 
Inter-process communication of Android
Inter-process communication of AndroidInter-process communication of Android
Inter-process communication of AndroidTetsuyuki Kobayashi
 
Android is NOT just 'Java on Linux'
Android is NOT just 'Java on Linux'Android is NOT just 'Java on Linux'
Android is NOT just 'Java on Linux'Tetsuyuki Kobayashi
 

More from Tetsuyuki Kobayashi (20)

some topic of ffmpeg
some topic of ffmpeg some topic of ffmpeg
some topic of ffmpeg
 
New VIdeo CODEC AV1
New VIdeo CODEC AV1 New VIdeo CODEC AV1
New VIdeo CODEC AV1
 
Try new transport protocol SRT (ver. 2)
Try new transport protocol SRT  (ver. 2)Try new transport protocol SRT  (ver. 2)
Try new transport protocol SRT (ver. 2)
 
Try new transport protocol SRT
Try new transport protocol SRTTry new transport protocol SRT
Try new transport protocol SRT
 
Raspberry Pi Zero とカメラモジュールで作るライブ配信実験機
Raspberry Pi Zero とカメラモジュールで作るライブ配信実験機Raspberry Pi Zero とカメラモジュールで作るライブ配信実験機
Raspberry Pi Zero とカメラモジュールで作るライブ配信実験機
 
WebOS Open Source Edition を試してみた
WebOS Open Source Edition を試してみたWebOS Open Source Edition を試してみた
WebOS Open Source Edition を試してみた
 
Linuxのユーザーランドをinitから全てまるごとgolangで書く
Linuxのユーザーランドをinitから全てまるごとgolangで書くLinuxのユーザーランドをinitから全てまるごとgolangで書く
Linuxのユーザーランドをinitから全てまるごとgolangで書く
 
組み込みLinuxでのGolangのススメ(Go con版)
組み込みLinuxでのGolangのススメ(Go con版)組み込みLinuxでのGolangのススメ(Go con版)
組み込みLinuxでのGolangのススメ(Go con版)
 
組み込みLinuxでのGolangのススメ
組み込みLinuxでのGolangのススメ組み込みLinuxでのGolangのススメ
組み込みLinuxでのGolangのススメ
 
Tricky implementation of Go ARM soft float
Tricky implementation of Go ARM soft floatTricky implementation of Go ARM soft float
Tricky implementation of Go ARM soft float
 
ARM 64bit has come!
ARM 64bit has come!ARM 64bit has come!
ARM 64bit has come!
 
Simple and efficient way to get the last log using MMAP
Simple and efficient way to get the last log using MMAPSimple and efficient way to get the last log using MMAP
Simple and efficient way to get the last log using MMAP
 
Basic of virtual memory of Linux
Basic of virtual memory of LinuxBasic of virtual memory of Linux
Basic of virtual memory of Linux
 
Patch101
Patch101Patch101
Patch101
 
ADB(Android Debug Bridge): How it works?
ADB(Android Debug Bridge): How it works?ADB(Android Debug Bridge): How it works?
ADB(Android Debug Bridge): How it works?
 
Tweaking Google TV emulator
Tweaking Google TV emulatorTweaking Google TV emulator
Tweaking Google TV emulator
 
Inter-process communication of Android
Inter-process communication of AndroidInter-process communication of Android
Inter-process communication of Android
 
Android is NOT just 'Java on Linux'
Android is NOT just 'Java on Linux'Android is NOT just 'Java on Linux'
Android is NOT just 'Java on Linux'
 
Android ipm 20110409
Android ipm 20110409Android ipm 20110409
Android ipm 20110409
 
Init of Android
Init of AndroidInit of Android
Init of Android
 

Tips of Malloc & Free

  • 1. Tips of malloc & free Making your own malloc library for troubleshooting 2013.2.22 Embedded Linux Conference Tetsuyuki Kobayashi 1
  • 2. The latest version of this slide will be available from here  http://www.slideshare.net/tetsu.koba/presentations 2
  • 3. Who am I?  20+ years involved in embedded systems  10 years in real time OS, such as iTRON  10 years in embedded Java Virtual Machine  Now GCC, Linux, QEMU, Android, …  Blogs  http://d.hatena.ne.jp/embedded/ (Personal)  http://blog.kmckk.com/ (Corporate)  http://kobablog.wordpress.com/(English)  Twitter  @tetsu_koba 3
  • 4. Today's topics  Prologue: Making your own malloc library for troubleshooting  System calls to allocate memory in user space  Tips of glibc's malloc  How to hook and replace malloc (and pitfalls I fell)  dlmalloc 4
  • 5. Prologue: Making your own malloc library for troubleshooting 5
  • 6. Typical troubles of heap memory  Corruption  crashed by SEGV at malloc or free. looks malloc bug, but NOT  Who actually destroy heap?  Leaking  malloc'ed but not free'ed  damages silently  You want additional checking and logging in malloc/free 6
  • 7. Wrapping macro/fuction  #define malloc(x) debug_malloc(x)  Useful. But you can't cover all malloc calling because ... 7
  • 8. Explicit call for malloc  many standard library functions use malloc internally  example) sprintf  C++ new operator uses malloc internelly 8
  • 9. Modify glibc(libc.so) directly?  libc source package is quite large  If you replace libc.so, it affects whole system  not only for the debugee process 9
  • 10. So I did was  making my own malloc library  easy to modify  use this only for the debugee process 10
  • 11. System calls to allocate memory in user space 11
  • 12. System calls to allocate memory in user space  You need system call to allocate in user space when you make your own malloc library  There are 2 types of them  brk/sbrk  mmap/munmap/mremap 12
  • 13. brk/sbrk  exists from ancient Unix  before virtual memory system  extends data segment  standard malloc library use these system calls  You should not use these system calls if your own malloc library co-exist with standard malloc library 13
  • 14. brk/sbrk extends data segment Memory map of user process on old simple UNIX Text Read Only etext Data edata Zero cleared Bss Read Write end Heap At modern OS start address of heap Extends by brk(2)/sbrk(2) is randomized Grows down automatically Stack 14
  • 15. cat /proc/self/maps You see memory map of 'cat /proc/self/maps' itself $ cat /proc/self/maps 00400000-0040d000 r-xp 00000000 08:01 1048675 /bin/cat This is heap area 0060d000-0060e000 r--p 0000d000 08:01 1048675 /bin/cat 0060e000-0060f000 rw-p 0000e000 08:01 1048675 /bin/cat 01a7a000-01a9b000 rw-p 00000000 00:00 0 [heap] 7f10f05d0000-7f10f074d000 r-xp 00000000 08:01 316763 /lib/libc-2.11.1.so 7f10f074d000-7f10f094c000 ---p 0017d000 08:01 316763 /lib/libc-2.11.1.so 7f10f094c000-7f10f0950000 r--p 0017c000 08:01 316763 /lib/libc-2.11.1.so 7f10f0950000-7f10f0951000 rw-p 00180000 08:01 316763 /lib/libc-2.11.1.so 7f10f0951000-7f10f0956000 rw-p 00000000 00:00 0 7f10f0956000-7f10f0976000 r-xp 00000000 08:01 272407 /lib/ld-2.11.1.so 7f10f09fa000-7f10f0a39000 r--p 00000000 08:01 1580725 /usr/lib/locale/en_US.utf8/LC_CTYPE 7f10f0a39000-7f10f0b57000 r--p 00000000 08:01 1580503 /usr/lib/locale/en_US.utf8/LC_COLLATE 7f10f0b57000-7f10f0b5a000 rw-p 00000000 00:00 0 7f10f0b62000-7f10f0b63000 r--p 00000000 08:01 1580587 /usr/lib/locale/en_US.utf8/LC_NUMERIC 7f10f0b63000-7f10f0b64000 r--p 00000000 08:01 1583228 /usr/lib/locale/en_US.utf8/LC_TIME 7f10f0b64000-7f10f0b65000 r--p 00000000 08:01 1583229 /usr/lib/locale/en_US.utf8/LC_MONETARY 7f10f0b65000-7f10f0b66000 r--p 00000000 08:01 1583230 /usr/lib/locale/en_US.utf8/LC_MESSAGES/SYS_LC_MESSAGES 7f10f0b66000-7f10f0b67000 r--p 00000000 08:01 1580575 /usr/lib/locale/en_US.utf8/LC_PAPER 7f10f0b67000-7f10f0b68000 r--p 00000000 08:01 1580573 /usr/lib/locale/en_US.utf8/LC_NAME 7f10f0b68000-7f10f0b69000 r--p 00000000 08:01 1583231 /usr/lib/locale/en_US.utf8/LC_ADDRESS 7f10f0b69000-7f10f0b6a000 r--p 00000000 08:01 1583232 /usr/lib/locale/en_US.utf8/LC_TELEPHONE 7f10f0b6a000-7f10f0b6b000 r--p 00000000 08:01 1580571 /usr/lib/locale/en_US.utf8/LC_MEASUREMENT 7f10f0b6b000-7f10f0b72000 r--s 00000000 08:01 1623537 /usr/lib/gconv/gconv-modules.cache 7f10f0b72000-7f10f0b73000 r--p 00000000 08:01 1583233 /usr/lib/locale/en_US.utf8/LC_IDENTIFICATION 7f10f0b73000-7f10f0b75000 rw-p 00000000 00:00 0 7f10f0b75000-7f10f0b76000 r--p 0001f000 08:01 272407 /lib/ld-2.11.1.so 7f10f0b76000-7f10f0b77000 rw-p 00020000 08:01 272407 /lib/ld-2.11.1.so 7f10f0b77000-7f10f0b78000 rw-p 00000000 00:00 0 7fff80929000-7fff8093e000 rw-p 00000000 00:00 0 [stack] 7fff809ff000-7fff80a00000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] 15
  • 16. mmap/munmap/mremap  newer system calls than brk/sbrk  integrate memory and file mapping  Glibc's malloc also use these when large chunk (>= 128KB: default) required  Use these when you implement your own malloc library 16
  • 17. Usage of mmap(2) addr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); if (MAP_FAILED == addr) { perror("mmap"); abort(); } You don't have to specify address. (set NULL) Then kernel allocate memory from free space. 17
  • 18. alloca(3) By the way,  allocates memory in caller's stack frame  frees automatically when the function that called alloca() returns  same as local variables  machine and compiler dependent  be careful when stack size is small  especially multi-thread 18
  • 19. Tips of glibc's malloc 19
  • 20. mallopt  int mallopt(int param, int value)  configures glibc malloc such as  M_CHECK_ACTION  M_MMAP_THRESHOLD  M_TOP_PAD  M_TRIM_THRESHOLD  see man 3 mallopt 20
  • 21. malloc_stats  void malloc_stats(void)  prints (on standard error) statistics about heap like this Arena 0: system bytes = 135168 in use bytes = 128 Total (incl. mmap): system bytes = 139264 in use bytes = 4224 max mmap regions = 1 max mmap bytes = 569344 21
  • 22. malloc_usable_size  size_t malloc_usable_size(void *__ptr)  reports the number of usable allocated bytes associated with allocated chunk __ptr  This size may be a bit bigger than the size specified at malloc()  because of alignment of next data  This is useful when counting allocated total size  increment size in hooked malloc  decrement size in hooked free 22
  • 23. MALLOC_CHECK_  easy way to enable additional checking in glibc malloc  with some overhead  environment variable MALLOC_CHECK_  0: no check at all (no overhead)  1: check and print message if error  2: check and abort if error 23
  • 24. __malloc_hook  glibc's malloc has its own hook mechanism  global variables of function pointers  __malloc_hook  __realloc_hook  __memalign_hook  __free_hook  __malloc_initialize_hook  man malloc_hook for detail 24
  • 25. mtrace  easy way to enable logging in glibc malloc  see man 3 mtrace  There is tool to check log and find leaking memory  see man 1 mtrace  implemented using __malloc_hook  This seems not thread safe 25
  • 26. How to hook and replace malloc 26
  • 27. Hook and replace malloc  2 methods to hook malloc  LD_PRELOAD & dlsym  __malloc_hook  These do not require to recompile other program and libraries 27
  • 28. Using LD_PRELOAD & dlsym to hook malloc  Use dynamic link mechanism can not use when static linking  Make your own malloc dynamic link library and set it to environment variable LD_PRELOAD  Then your malloc is used prior to glibc's malloc  You can get glibc's malloc address by dlsym(3) 28
  • 29. Usual call for malloc glibc executable executable malloc malloc /libraries /libraries 29
  • 30. Hooking malloc by LD_PRELOAD preload by LD_PRELOAD your own library get address by dlsym(RTLD_NEXT, “malloc”) malloc malloc glibc executable executable malloc malloc /libraries /libraries output log or record size ... 30
  • 31. minimum sample code static void __attribute__((constructor)) init(void) { callocp = (void *(*) (size_t, size_t)) dlsym (RTLD_NEXT, "calloc"); mallocp = (void *(*) (size_t)) dlsym (RTLD_NEXT, "malloc"); reallocp = (void *(*) (void *, size_t)) dlsym (RTLD_NEXT, "realloc"); memalignp = (void *(*)(size_t, size_t)) dlsym (RTLD_NEXT, "memalign"); freep = (void (*) (void *)) dlsym (RTLD_NEXT, "free"); void *malloc (size_t len) { void *ret; ret = (*mallocp)(len); return ret; } 31
  • 32. Pitfall #1  If you use printf to output logs, it causes recursive call of malloc. Because printf uses malloc internally. 32
  • 33. Avoid infinite recursive call static __thread int no_hook; void *malloc (size_t len) TLS (Thread Local Storage) { void *ret; void *caller; if (no_hook) { return (*mallocp)(len); } no_hook = 1; caller = RETURN_ADDRESS(0); fprintf(logfp, "%p malloc(%zu", caller, len); ret = (*mallocp)(len); fprintf(logfp, ") -> %pn", ret); no_hook = 0; return ret; } 33
  • 34. Pitfall #2  When compile with -pthread, it crashes at the beginning. Why?  In multi-thread mode, dlsym() uses calloc() at the first time.  calloc() requires dlsym() dlsym() requires calloc() … !!  prepare special calloc() for the first call of calloc(). 34
  • 35. st Call special calloc at the 1 time void *calloc (size_t n, size_t len) { void *ret; void *caller; Just returns some static allocated memory if (no_hook) { if (callocp == NULL) { ret = my_calloc(n, len); return ret; } return (*callocp)(n, len); } ... 35
  • 36. Using __malloc_hook variable to hook malloc  function pointer variables for hooking  void *(*__malloc_hook)(size_t, const void*)  void*(*__realloc_hook)(void*, size_t, const void*)  void*(*__memalign_hook)(size_t, size_t, const void*)  void (*__free_hook)(void)  void (*__malloc_initialize_hook)(void) 36
  • 37. Usual call for malloc glibc executable executable malloc malloc /libraries /libraries 37
  • 38. Hooking malloc by __malloc_hook glibc executable executable malloc malloc /libraries /libraries __malloc_hook void_t *malloc(size_t bytes) { __malloc_ptr_t (*hook) (size_t, __const __malloc_ptr_t) =__malloc_hook; my_malloc my_malloc if (hook != NULL) return (*hook)(bytes, RETURN_ADDRESS (0)); Your own library 38
  • 39. Thread unsafe example static void * my_malloc_hook(size_t size, const void *caller) __malloc_hook is not { void *result; locked at all /* Restore all old hooks */ __malloc_hook = old_malloc_hook; /* Call recursively */ result = malloc(size); /* Save underlying hooks */ In this moment old_malloc_hook = __malloc_hook; malloc from other thread does not /* printf() might call malloc(), so protect it too. */ hook. printf("malloc(%u) called from %p returns %pn", (unsigned int) size, caller, result); /* Restore our own hooks */ __malloc_hook = my_malloc_hook; return result; 39 }
  • 40. Workaround  Changing __malloc_hook variable is not thread safe. (Actually these variables are marked as 'deprecated')  Set once these hook variables at initial time and don't touch after that.  You can not call back glibc's malloc.  link and replace to other malloc.  dlmalloc is good for this. 40
  • 41. Which ?  If you replace malloc  You can use __malloc_hook with care  Otherwise  use LD_PRELOAD & dlsym 41
  • 42. Another pitfall  Almost program works fine with my own malloc library. But some game app. causes SEGV accessing null pointer.  At first I doubt that malloc returns NULL because heap runs out … 42
  • 43. Behavior of malloc(size=0)  I thought malloc(0) returns NULL.  man malloc says:  “If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().”  glibc's malloc does the latter.
  • 44. The game app. calls malloc(0) and use the pointer without check!  so it causes null pointer access  I modified my malloc returns a unique pointer even if size == 0  Then the game app. works fine with my malloc library.
  • 45. dlmalloc 45
  • 46. dlmalloc  by Doug Lea  http://g.oswego.edu/dl/html/malloc.html  easy to compile and use  can add prefix to all function names to avoid conflict to standard malloc functions (-DUSE_DL_PREFIX)  add -DUSE_LOCKS=1 for thread safe  Actually glibc's malloc is based on this 46
  • 47. mspace of dlmalloc  can have multiple separate memory spaces for heap  per thread, per functional module, ...  Good for troubleshooting  isolate heap of module in question
  • 48. Usual single heap (UI) (UI) malloc() The single heap (graphics) (graphics) (database) (database) In the same process 48
  • 49. Using mspaces Their own mspaces (UI) (UI) mspace_malloc() (graphics) (graphics) (database) (database) In the same process 49
  • 50. Summary  Make your own malloc library rather than modify glibc (libc.so).  Use mmap(2) to get memory.  __malloc_hook is not thread safe and deprecated.  Use LD_PRELOAD & dlsym(3) to hook glibc's malloc. 50
  • 51. Q&A Thank you for listening! @tetsu_koba 51