ãåç¥ã®ããã«ãçŸä»£ã®x86ïŒ_64ïŒããã³ARMã¢ãŒããã¯ãã£ã§ã¯ã幞ããªããšã«
char near*
ãš
int huge*
char near*
æéãçµéãããããããã»ã¹ã®ä»®æ³ã¡ã¢ãªã¯ç·åœ¢ã§é£ç¶çã§ãã ä»®æ³ã¡ã¢ãªã¯ããŒãžã«åå²ãããŸããéåžžã®ãµã€ãºã¯4 KiBã§ãããããã©ã«ãã§ã¯ç©çã¡ã¢ãªã«ãããã³ã°ãããªãããïŒãããã³ã°ïŒããããã®æäœã¯æ©èœããŸããã ããã»ã¹ã®çŸåšè¡šç€ºãããŠããã¢ãã¬ã¹ç¯å²ã確èªããã«ã¯ãLinux look / proc / <pid> / mapsãOS X vmmap <pid>ã§ã åã¢ãã¬ã¹ééã«ã¯ãå®è¡ãæžââã蟌ã¿ãèªã¿åãã®3çš®é¡ã®ä¿è·ããããŸãã ã芧ã®ãšãããããŒãã¢ãã¬ã¹ïŒLinuxã®ELFã®.textã»ã°ã¡ã³ããOS Xã®Mach-Oã® __TEXTã«å¯Ÿå¿ïŒã§å§ãŸãæåã®ééã¯èªã¿åãå¯èœã§å®è¡å¯èœã§ã-éåžžã«è«ççã§ãã ãŸããã¹ã¿ãã¯ã¯ä»ã®ééãšæ¬è³ªçã«å€ãããªãããšãããããŸãããŸããæçµã¢ãã¬ã¹ããéå§ã¢ãã¬ã¹ãæžç®ããããšã§ããµã€ãºããã°ããèšç®ã§ããŸãã ããŒãžã¯mmap / munmapã䜿çšããŠè¡šç€ºãã ãã»ãã¥ãªãã£ã¯mprotectã䜿çšããŠå€æŽãããŸãã ãããŒã¿ãã®åäžã®ééã®ãµã€ãºãå€æŽããçŸä»£ã®ã·ã¹ãã ã§mmapã«ãã£ãŠãšãã¥ã¬ãŒããããéå»ã®éæšå¥šã®å€ä»£ã®åæ®ã§ããbrk / sbrkããŸã ãããŸãã
mallocã®ãã¹ãŠã®POSIXå®è£ ã¯ãäžèšã®é¢æ°ã«äœããã®åœ¢ã§äŸåããŠããŸãã åçŽã«ããŒãžã匷調衚瀺ããã³è§£æŸããå¿ èŠãªãµã€ãºãåãäžããããšã«æ¯ã¹ãŠãmallocã«ã¯å€ãã®å©ç¹ããããŸãã
- ãã§ã«å²ãåœãŠãããŠããã¡ã¢ãªãæé©ã«ç®¡çããŸãã
- ã«ãŒãã«ã®åŒã³åºãåæ°ãå€§å¹ ã«åæžããŸãïŒçµå±ãmmap / sbrkã¯syscallã§ã ïŒã
- éåžžãããã°ã©ãã¯ä»®æ³ã¡ã¢ãªããæœè±¡åããããããå€ãã®äººã¯ããŒãžãå€æããŒãã«ãªã©ã®ååšãç¥ããã«mallocã䜿çšããŸãã
ååãªçè«ïŒ å®éã«mallocãæããŸãã 3ã€ã®å®éšãå®è¡ããŸãã äœæ¥ã¯POSIXäºæOSã§å¯èœã«ãªããŸããç¹ã«ãäœæ¥ã¯Linuxããã³OS Xã§ãã¹ããããŠããŸãã
mallocããNULL
ãããããããå§ããŸãããã ã³ãŒãå ã§libcïŒããã³ä»ã®ã©ã€ãã©ãªïŒããé¢æ°ãåå®çŸ©ãããšããªã³ã«ãŒã¯libcãåçã«æ¥ç¶ãããã©ãããæ°ã«ããŸããïŒããã©ã«ãã§ã¯ããã§ãïŒãäºéå®çŸ©ãèªãããšã¯ãããŸããã ããšãã°ã次ã®ãããªã³ãŒãïŒ
#include <stdio.h> #include <stdlib.h> void* malloc(size_t size) { puts("malloc"); return NULL; } int main() { return (int)malloc(100500); }
ãmallocããåºåããæ»ãã³ãŒããnullïŒ
echo $?
ïŒã«ãªããŸãã ãã ããasprintfãªã©ãmallocãåŒã³åºãããè žã§é¢æ°ãåŒã³åºããšã©ããªããã確èªããŸãããã
// program.c #include <stdio.h> #include <stddef.h> void* malloc(size_t size) { puts("malloc"); return NULL; } int main() { char *s = NULL; asprintf(&s, "%d", 0); printf("%p\n", s); return 0; }
ãããŠãããã§ã¯ãªã³ã«ã«å€§ããäŸåããŸãã ld / Linuxã®å Žåãå°å·ãããŸã
malloc (nil)
mallocãåŒã³åºãããåå®çŸ©ãããprintfã®glibcå®è£ ã§ã¯mallocã䜿çšãããªãããã glibcã®mallocã匱ãæå ïŒ__attribute __ïŒïŒweakïŒïŒïŒãšããŠå®£èšãããããã©ã«ãã®å®çŸ©ã匷ãïŒELFã«åºæïŒãããåå®çŸ©ãè¡ãããŸããã ãã ããdyld / OS Xã§ã¯ãåäœãç°ãªããŸãã
0x7fc1eb403230
å®éãã±ã·ã®mallocã¯åå®çŸ©ãããŠããŸããïŒ ããã¯ããã«ãã¬ãã«dyldåå空éã«é¢ãããã®ã§ãªããã°ãªããŸããã ããããã...
DYLD_FORCE_FLAT_NAMESPACE=1 ./program Segmentation fault: 11
äžæ©å«ãªBABAG BIGïŒ ãã®ã±ãŒã¹ã¯ãæããã«int mainïŒïŒã«ããéããŸããã§ããã ãã®çç±ã¯äœã§ããïŒ
lldb lldb ./program (lldb) target create "./program" Current executable set to './program' (x86_64). (lldb) env DYLD_FORCE_FLAT_NAMESPACE=1 (lldb) r Process 11956 launched: './program' (x86_64) Process 11956 stopped * thread #1: tid = 0x12e214, 0x00007fff9ebb9dcb libsystem_kernel.dylib`ioctl + 67, stop reason = EXC_BAD_ACCESS (code=2, address=0x7fff5f3ffff8) frame #0: 0x00007fff9ebb9dcb libsystem_kernel.dylib`ioctl + 67 libsystem_kernel.dylib`ioctl: -> 0x7fff9ebb9dcb <+67>: movq %rcx, -0xb8(%rbp) 0x7fff9ebb9dd2 <+74>: movq %rdx, -0xc0(%rbp) 0x7fff9ebb9dd9 <+81>: leaq -0xd0(%rbp), %rax 0x7fff9ebb9de0 <+88>: movq %rax, -0x10(%rbp) (lldb) bt * thread #1: tid = 0x12e214, 0x00007fff9ebb9dcb libsystem_kernel.dylib`ioctl + 67, stop reason = EXC_BAD_ACCESS (code=2, address=0x7fff5f3ffff8) * frame #0: 0x00007fff9ebb9dcb libsystem_kernel.dylib`ioctl + 67 frame #1: 0x00007fff9a20f2c8 libsystem_c.dylib`isatty + 43 frame #2: 0x00007fff9a222ac6 libsystem_c.dylib`__smakebuf + 60 frame #3: 0x00007fff9a237b4a libsystem_c.dylib`__swsetup + 155 frame #4: 0x00007fff9a221d52 libsystem_c.dylib`__sfvwrite + 73 frame #5: 0x00007fff9a2264c9 libsystem_c.dylib`puts + 144 frame #6: 0x0000000100000f0b program`malloc(size=4096) + 27 at program.c:6 frame #7: 0x00007fff9a222af6 libsystem_c.dylib`__smakebuf + 108 frame #8: 0x00007fff9a237b4a libsystem_c.dylib`__swsetup + 155 ... frame #130931: 0x0000000100000f0b program`malloc(size=4096) + 27 at program.c:6 frame #130932: 0x00007fff9a222af6 libsystem_c.dylib`__smakebuf + 108 frame #130933: 0x00007fff9a237b4a libsystem_c.dylib`__swsetup + 155 frame #130934: 0x00007fff9a221d52 libsystem_c.dylib`__sfvwrite + 73 frame #130935: 0x00007fff9a2264c9 libsystem_c.dylib`puts + 144 frame #130936: 0x0000000100000f0b program`malloc(size=8) + 27 at program.c:6 frame #130937: 0x00007fff5fc1d22e dyld`operator new(unsigned long) + 30 frame #130938: 0x00007fff5fc095a5 dyld`std::__1::vector >::insert(std::__1::__wrap_iter, char const* (* const&)(dyld_image_states, unsigned int, dyld_image_info const*)) + 343 frame #130939: 0x00007fff5fc04507 dyld`dyld::registerImageStateBatchChangeHandler(dyld_image_states, char const* (*)(dyld_image_states, unsigned int, dyld_image_info const*)) + 147 frame #130940: 0x00007fff8bb8089e libdyld.dylib`dyld_register_image_state_change_handler + 76 frame #130941: 0x00007fff8bb8065f libdyld.dylib`_dyld_initializer + 47 frame #130942: 0x00007fff982829fd libSystem.B.dylib`libSystem_initializer + 116 frame #130943: 0x00007fff5fc12feb dyld`ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) + 265 frame #130944: 0x00007fff5fc13164 dyld`ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) + 40 frame #130945: 0x00007fff5fc0f79d dyld`ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 305 frame #130946: 0x00007fff5fc0f732 dyld`ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 198 frame #130947: 0x00007fff5fc0f623 dyld`ImageLoader::processInitializers(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) + 127 frame #130948: 0x00007fff5fc0f893 dyld`ImageLoader::runInitializers(ImageLoader::LinkContext const&, ImageLoader::InitializerTimingList&) + 75 frame #130949: 0x00007fff5fc020f1 dyld`dyld::initializeMainExecutable() + 208 frame #130950: 0x00007fff5fc05e5d dyld`dyld::_main(macho_header const*, unsigned long, int, char const**, char const**, char const**, unsigned long*) + 3793 frame #130951: 0x00007fff5fc01276 dyld`dyldbootstrap::start(macho_header const*, int, char const**, long, macho_header const*, unsigned long*) + 512 frame #130952: 0x00007fff5fc01036 dyld`_dyld_start + 54
ã©ããªãã¬ãŒã ïŒ 130952ndïŒ ã¯ããå€æããŸãããStack OverflowïŒ ãŸããããã€ãã®èå³æ·±ãããšãåŠã³ãŸãããdyldã¯C ++ã§èšè¿°ãããŠãããäœããã®çç±ã§åãmallocã§ã¡ã¢ãªãå²ãåœãŠãååž°ãäœæããŸãã stdoutãããã¡ãŒã®åæåäžã«åœŒããããè¡ãã®ã¯äžåºŠã ãã ãšä¿¡ãããã ãŸããç§ãã¡ã¯ããã眮ãæããããšãäœåãªããããŠããŸã
#include <stdio.h> #include <stddef.h> #include <unistd.h> void* malloc(size_t size) { write(STDOUT_FILENO, "malloc\n", 7); return NULL; } int main() { char *s = NULL; asprintf(&s, "%d", 0); printf("%p\n", s); return 0; }
éå§ããŠç¢ºèªããŸãã
malloc malloc malloc Segmentation fault: 11
ã¹ã¿ãã¯ãã©ã°ã¡ã³ãïŒ
* thread #1: tid = 0x1309af, 0x00007fff5fc249ce dyld`_platform_bzero + 94, stop reason = EXC_BAD_ACCESS (code=1, address=0x8) * frame #0: 0x00007fff5fc249ce dyld`_platform_bzero + 94 frame #1: 0x00007fff5fc14045 dyld`calloc + 52 frame #2: 0x00007fff5fc0ce14 dyld`__cxa_get_globals + 100 frame #3: 0x00007fff5fc1ce7f dyld`__cxa_throw + 25 frame #4: 0x00007fff5fc1d267 dyld`operator new(unsigned long) + 87
ãã®ãããldãéçå²ãåœãŠã§äœæãããŠããGNU / Linuxãšã¯ç°ãªããOS Xã§ã¢ããªã±ãŒã·ã§ã³ãå®è¡ãããšãã«å€§éã®ããŒããéäžçã«äœ¿çšãããŸãã ãŸããnewæŒç®åã«ããã¡ã¢ãªã®å²ãåœãŠã®å€±æã«é¢ããäŸå€ãã¹ããŒãããšãcallocãçºçããããšãããããŸããããã¯ãmallocãšãŒãïŒbzeroïŒã®åã蟌ã¿ã®çµã¿åããã§ãã callocå®è£ ãè¿œãã€ããnullãã€ã³ã¿ãŒããã§ãã¯ããŸããã§ããã ãã®ç¥èãããã°ãOS Xãå®éã«ãæåŸã®ãã€ããŸã§ãã¡ã¢ãªã䜿ãæãããå Žåã«èµ·ããèãã¯ããã¯ãç§ã«äŒæ¯ãäžããŸããã æããã«ãæ£ããè«ççãªè§£æ±ºçã¯ãäºåã«std :: bad_allocã«ã¡ã¢ãªãå²ãåœãŠãããšã§ãã
OK GoogleãOS Xã§mallocãåå®çŸ©ããŠã¯ã©ãã·ã¥ããªãããã«ããã«ã¯ã©ãããã°ããã§ããïŒ å®è£ ã®è©³çŽ°ã«é£ã³èŸŒãå¿ èŠããããŸãã ãããŒã®Mallocã¯ããŸãŒã³ã«ã¡ã¢ãªãå²ãåœãŠãŸãã æåã¯ãããã©ã«ãã§1ã€ã®ãŸãŒã³ã®ã¿ããããvmmapã¯åºåã®æåŸã«ããã衚瀺ããŸãã åãŸãŒã³ã«ã¯ãmallocãfreeãããã³reallocãžã®ãã€ã³ã¿ãŒãæ ŒçŽãããŸããããã«ãããã¡ã¢ãªç®¡çãæè»ã«æ§æã§ããŸãã ããã©ã«ããŸãŒã³ã䜿çšããŠããã®äžã®mallocãã€ã³ã¿ãŒã眮ãæããããšãã§ããŸãã
#include <stdio.h> #include <stddef.h> #include <unistd.h> #include <malloc/malloc.h> #include <sys/mman.h> void* zone_malloc(struct _malloc_zone_t *zone, size_t size) { write(STDOUT_FILENO, "malloc\n", 7); return NULL; } int main() { malloc_zone_t* zone = malloc_default_zone(); mprotect(zone, sizeof(*zone), PROT_READ | PROT_WRITE); zone->malloc = zone_malloc; mprotect(zone, sizeof(*zone), PROT_READ); char *s = NULL; asprintf(&s, "%d", 0); printf("%p\n", s); return 0; }
mprotectã«æ³šæããŠãã ããã æåã«ãmalloc_default_zoneã¯ãæžã蟌ã¿ä¿è·ãããŠããã¡ã¢ãªé åãžã®ãã€ã³ã¿ãè¿ããŸãã ããã¯ãmprotectã䜿çšããã«ããã°ã©ã ãå®è¡ãããããã¬ãŒãšvmmapã§ã¯ã©ãã·ã¥ã調ã¹ãããšã§ç°¡åã«ç¢ºèªã§ããŸãã ãã®ãããªä¿è·ã¯éã³å¿ã®ããæããåŸãããŸã... PROT_READã«æ»ããšãå³å¯ã«èšãã°ãä¿è·ã¯å€æŽã§ããŸããã§ãããããã¯é åºã®ããã«è¿œå ãããŸããã å°å·ããããã®ïŒ
malloc malloc 0x0
printfãmallocã䜿çšããããšãããããŸãããåçã¡ã¢ãªãªãã§å®è¡ã§ãã匷床ãèŠã€ãããããã§ããã«ãã€ã³ã¿ãŒãåºåãããŸããã
ãšããã§ããŸãŒã³ã«ã€ããŠã glibcã®Mallocã¯ãobstacksãšåŒã°ããåæ§ã®ãã¬ããã³ã°ã䜿çšããŸãã äžæ¹ã§ã¯ãããããæäœããããã®å€ãã®é¢æ°ããããŸãããä»æ¹ã§ã¯ãç°ãªãobstackã§ç°ãªãã¡ã¢ãªå²ãåœãŠã¢ã«ãŽãªãºã ã䜿çšããããšã¯ã§ããŸããã
çµè«ïŒ OS XããŒãããŒããŒã§ããdyldã¯C ++ã§èšè¿°ãããŠãããint mainïŒïŒã®ããªãåã«ãã®ã·ã¹ãã äžã®ããã°ã©ã ã®æãåŠçããŸãã Linuxã®ldã§ã¯ãããã¯çºçãããããŒããžã®åŒã³åºãã¯ãããŸããã
ç¡å¹ãªmalloc
次ã«ãæ°ããç®æšãèšå®ããŸããããmallocã®ããŒãžã§ã³ãå®è£ ããåçã©ã€ãã©ãªãäœæããŸãã
// hack_malloc.c #define _GNU_SOURCE #include <stdio.h> #include <stddef.h> #include <unistd.h> #include <sys/mman.h> void* malloc(size_t size) { write(STDOUT_FILENO, "malloc... ", 10); size += sizeof(size_t); int page_size = getpagesize(); int rem = size % page_size; if (rem > 0) { size += page_size - rem; } void* addr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); if (addr == MAP_FAILED) { write(STDOUT_FILENO, "fail\n", 5); return NULL; } write(STDOUT_FILENO, "ok\n", 3); *(size_t*)addr = size; return (size_t*)addr + 1; } void free (void *ptr) { write(STDOUT_FILENO, "free... ", 8); size_t* real_ptr = (size_t*)ptr - 1; if (!munmap(real_ptr, *real_ptr)) { write(STDOUT_FILENO, "ok\n", 3); } else { write(STDOUT_FILENO, "fail\n", 5); } }
ããã§ã¯ãããŒãžã§ã¡ã¢ãªãå²ãåœãŠããšãã«æãç°¡åãªã¢ãããŒããå®è£ ãããŸãã unmapã«æž¡ããã®ãããããã«ãããŒãžã®äžéšã«ãµã€ãºãä¿åããå¿ èŠããããŸãã mmapãã©ã°ã®MAP_ANONYMOUSã¯ãå®éã®ãã¡ã€ã«ãã¡ã¢ãªã«ãããããã®ã§ã¯ãªããç©çã¡ã¢ãªããããããããšãæå³ããŸãïŒéåžžããã¡ã€ã«ã¯mmapã«ãã£ãŠã¡ã¢ãªã«ãããããŸããããã«ãããäžéšã®æäœãå éãããŸãïŒã ãã¡ã€ã«ã®å ŽåãMAP_PRIVATEã¯åå¥ã®ã³ããŒãªã³ã©ã€ãã³ããŒãäœæããŸãããå®éã«ã¯äœãããŸãããããã¥ã¡ã³ãã ãã§MAP_PRIVATEãŸãã¯MAP_SHAREDãå¿ èŠã§ãã ã¡ãªã¿ã«ãMAP_SHAREDã䜿çšãããšããã®ã³ãŒããããŸãæ©èœããŸãã
äŸã§ç¢ºèªããŸãã
// test.c #include <stdio.h> #include <stdlib.h> int main() { printf("start\n"); void* mem = malloc(100); printf("malloc() -> %p\n", mem); *(int*)mem = 0; free(mem); printf("end\n"); return 0; }
ãã®ããã«çµã¿ç«ãŠãŸãïŒ
#Linux gcc -shared -o libhackmalloc.so -fPIC -std=c99 -O2 hack_malloc.c gcc test.c -std=c99 -L. -Wl,-rpath,. -lhackmalloc -O2 -o test # Mac OS X clang -dynamiclib -undefined suppress -flat_namespace -std=c99 -fPIC -O2 hack_malloc.c -o libhackmalloc.dylib clang test.c -std=c99 -L. -lhackmalloc -O2 -o test
èµ·åæã«ã以äžã衚瀺ãããŸãã
./test start malloc... ok malloc() -> 0x10935b008 free... ok end
OS XãšLinuxã®åºåã¯åãã§ãã OS Xã®å ŽåãWindows 10ã€ã³ã¿ãŒãã§ã€ã¹ã®ããã«ãdyldåå空éãèããŠãã©ããã«ããŸãã
DYLD_FORCE_FLAT_NAMESPACE=1 ./test malloc... ok malloc... ok free... ok malloc... ok malloc... ok free... fail free... fail free... fail malloc... ok malloc... ok free... fail malloc... ok 70 free... fail 17 malloc... ok free... ok malloc... ok malloc... ok malloc... ok free... fail malloc... ok start malloc... ok malloc() -> 0x1035d9008 free... ok end
ããã°ã©ã ã¯æ©èœãããã§ã«è¯å¥œã§ããã é©ãã¹ãããšã¯ãint mainïŒïŒã®åã«mallocãšfreeãåŒã³åºãåæ°ã®æãããªççŸã§ãã ç¡æãäœåºŠã倱æããŸããã èå³ã®ããæ¹ã¯ããããã¬ã§ãã¹ããå®è¡ãããã¬ãŒã«ãŒãç¡æã§äœ¿çšããŠãdyldã®ããŒã¯ã©ã€ãã«ã€ããŠå€ããåŠã¶ããšãã§ããŸãã
çµè«ïŒ mallocã®å®è£ ã30è¡ã§ãçŽæ¥ãæžãããšã¯ããªãå¯èœã§ãã
mallocã®ã¹ãã€
DLLã€ã³ãžã§ã¯ã·ã§ã³ææ³ã䜿çšããŠãmallocãä»ã®äººã®ããã°ã©ã ã«ã€ã³ãžã§ã¯ãããŠã¿ãŸãããã Buddyãªã©ãèå³æ·±ãã¢ã«ãŽãªãºã ã¯æ°å€ããããŸãããããŒãã®å¹æçãªå®è£ ãç¬èªã«èšè¿°ããããããŸããã æ¢è£œã®å®è£ ã䜿çšããããšãå¯èœã§ãããRTLD_NEXTããªãã¯ãé©çšããŠã·ã¹ãã mallocãåç §ããŸãã 次ã®ã³ãŒããæ€èšããŠãã ããã
// trace_malloc.c #define _GNU_SOURCE #include <dlfcn.h> #include <fcntl.h> #include <stdio.h> #include <unistd.h> int fd = 0; void* (*__malloc)(size_t) = NULL; void* malloc(size_t size) { if (!__malloc) { __malloc = (void*(*)(size_t)) dlsym(RTLD_NEXT, "malloc"); } if (!fd) { fd = open("malloc.log", O_WRONLY | O_CREAT | O_TRUNC, 0666); } /* ... */ write(fd, record, sprintf(record, "%ld.%06ld\t%zu\n", sec, mcsec, size)); return __malloc(size); }
ã³ãŒãã®å®å šçãžã®ãªã³ã¯ã¯ãèšäºã®æåŸã«èšèŒãããŸãã ååã¯clock_gettimeã®ã¯ãã¹ãã©ãããã©ãŒã å®è£ ã«ãã£ãŠæ¶è²»ããã2çªç®ã¯clock_gettimeã«ã¢ã¯ã»ã¹ãããããå°ãåæžããªããã°ãªããŸããã§ããã ãã¹ãŠã®é åã1è¡ã§ïŒ
__malloc = (void*(*)(size_t)) dlsym(RTLD_NEXT, "malloc");
ãã®äžã§ãåã®ãmallocãããŒãããŸãã éåžžãdlsymã¯ããŒããããåçã©ã€ãã©ãªããé¢æ°ããã«ããããã«äœ¿çšãããŸãããããžãã¯RTLD_NEXTãã©ã€ãã©ãªèšè¿°åãšããŠäœ¿çšããŸããã å³å¯ã«èšãã°ãPOSIXã«ã¯ãããŸããããå®éã«ã¯å€ãã®ãªã³ã«ãŒã§ãµããŒããããŠããŸãã ãããã£ãŠãçã®mallocãžã®ãã€ã³ã¿ãŒãååŸããä¿åããŠããåŒã³åºããŠãçµæãè¿ããŸãã éäžã§ããã¹ãŠã®åŒã³åºããèšé²ããŸãã
hack_malloc.cãšåãæ¹æ³ã§ãã«ãããLinuxã§æ¬¡ã®ããã«äœ¿çšããŸãã
LD_PRELOAD=/path/to/libtracemalloc.so program
ãã¹ã¯çµ¶å¯Ÿãã¹ã§ãªããã°ãªããŸãããããããªããšãéæ³ã¯çºçããŸããã LD_PRELOADã¯ãããã°ã©ã ããã«ããããã¡ã€ã³ã©ã€ãã©ãªã®åã«æå®ãããã©ã€ãã©ãªã匷å¶çã«ããŒãããç¹å¥ãªç°å¢å€æ°ã§ãã ãã®æ¹æ³ã§ãä»»æã®é¢æ°ãåå®çŸ©ãããã誀ã£ãŠãªã³ã¯ãããããã°ã©ã ïŒåãlib * .soïŒnot foundã¡ãã»ãŒãžïŒã®èµ·åã«é¢ããäžæçãªåé¡ã解決ã§ããŸãã
ããšãã°ãLsã¯çŽ2 KBã®ãã°ãäœæããŸãã ãŸããwhoamiã¯ãæªå®çŸ©ã®ã·ã³ãã«ã¡ãã»ãŒãždlsymã䌎ããŸããããã¯ãdlsymãlibdl.soã§å®çŸ©ãããŠããããã§ãã ãŸããLD_PRELOADã¯æ¿å ¥ãããã©ã€ãã©ãªã®äŸåé¢ä¿ãããŒãããªãããã-ldlãæå®ããŠlibtracemallocããã«ãããããšã¯æå³ããããŸããã ãã®ãããªããšãããªããã°ãªããŸããïŒ
LD_PRELOAD=/usr/lib/.../libdl.so:/path/to/libtracemalloc.so whoami
ãŸãããã®ãããªåºæ¬ãŠãŒãã£ãªãã£ã®å Žåã§ãã1 KBã®ã¡ã¢ãªå²ãåœãŠãã°ã衚瀺ãããŸãã
OKãOS Xã¯ã©ãã§ããïŒ Dyldã¯ãåæ§ã®ããšãè¡ãDYLD_INSERT_LIBRARIESç°å¢å€æ°ããµããŒãããŠããŸãã ç§éã¯è©Šã¿ãŸãïŒ
DYLD_INSERT_LIBRARIES=/path/to/libtracemalloc.dylib ls
...æ©èœããŸãããåå空éã«ã€ããŠèŠããŠãããŠãã ããïŒ
DYLD_INSERT_LIBRARIES=/path/to/libtracemalloc.dylib DYLD_FORCE_FLAT_NAMESPACE=1 ls
...ãããŠãŸãæ®å¿µã ãã§ã«é¢çœãïŒ éèŠãªã®ã¯ã System Integrity Protectionã·ã¹ãã ããã°ã©ã ãä¿è·ããããšã§ãã æ¡åŒµãã¡ã€ã«å±æ§ã䜿çšãããã®ã¡ã«ããºã ã§ã¯ããã¡ã€ã«ã®å€æŽãã³ãŒãã®æ¿å ¥ã/ Systemã/ usrãªã©ã®ãã¹ã®ãã£ããŒã¹ã¯èš±å¯ãããŸããã幞ããªããšã«ã/ usr / localã¯èš±ãããŸããã
lldb /bin/ls (lldb) target create "/bin/ls" Current executable set to '/bin/ls' (x86_64). (lldb) r error: process exited with status -1 (cannot attach to process due to System Integrity Protection)
SIPã¯ç¡å¹ã«ã§ããŸãããç°¡åã«ã§ããŸã-èå³ã®ããããã°ã©ã ããã£ã¬ã¯ããªã«ã³ããŒããŸãã
cp $(which ls) . DYLD_INSERT_LIBRARIES=/path/to/libtracemalloc.dylib DYLD_FORCE_FLAT_NAMESPACE=1 ./ls
ãã§ã«æ©èœããŠããŸãã çµè«ãšããŠã2çš®é¡ã®ã¡ã¢ãªå²ãåœãŠã«é¢ããæåãªè«æã蚌æããŸãã mallocãã°ãåéããIPythonã®åºæ¬ã³ãŒãã䜿çšããŠãµã€ãºååžã®ãã¹ãã°ã©ã ãäœæããŸãããã
%pylab import pandas, seaborn log = pandas.DataFrame.from_csv("malloc.log", sep='\t') log[log < 100].hist() log[log < 100].count() / len(log)
å žåçãªç»åã¯ããµã€ãºãã¹ãã°ã©ã ã«è¡šç€ºãããŸãïŒY-åŒã³åºãåæ°ãX-ãµã€ãºãããã°ã©ã -clangïŒïŒ
ç§ã¯æ æã«ããŒã«ã100ãã€ãã«ã«ããããŸãããããã¯ããã倧ããªå²ãåœãŠãéåžžã«ãŸãã§ããããã¹ãã°ã©ã ã«è¡šç€ºãããªãããã§ãã ãããã£ãŠã ããŒãå ã®ãã¹ãŠã®ã¡ã¢ãªå²ãåœãŠã®98ïŒ ã¯100ãã€ãæªæºã§ããã€ãŸããåªããmallocã¯ãå°ãªããšã2ã€ã®å¥åã®ãã¡ã€ã³ïŒå€§ããªãªããžã§ã¯ãçšãšãã以å€ã®ãŠãŒã¶ãŒçšïŒã«å¯Ÿå¿ããå¿ èŠããããŸãã
ããã°ã©ã ãåæããããã«ãäžèšã®ãããªèªå·±ã¢ã»ã³ãã«ãããã©ã€ãã©ãªã䜿çšããããšã¯ã§ããŸããããæ¢è£œã®ãã®ã䜿çšããããšãã§ããŸãã ããšãã°ã tcmallocã䜿çšãããšãæã®ãããã¡ã€ã«ãäœæããããä»ã®å€ãã®äŸ¿å©ãªããšãå®è¡ãããã§ããŸã ã
ãã®èšäºã®ã³ãŒãã¯githubã§å ¥æã§ããŸãã 次åãå®éã®å€§èŠæš¡ãªããã°ã©ã ã䜿çšããŠããã®åäœäžã«ã¡ã¢ãªå²ãåœãŠã®ãã°ãåéããååž°çãã¥ãŒã©ã«ãããã¯ãŒã¯ã®LSTMã¢ãã«ã«åºã¥ããŠäºæž¬ãè©Šã¿ãŸãã