Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
macOS自定义malloc/free使用DYLD_INSERT_库,加载时间不够早_C_Macos_Debugging_Memory_Malloc - Fatal编程技术网

macOS自定义malloc/free使用DYLD_INSERT_库,加载时间不够早

macOS自定义malloc/free使用DYLD_INSERT_库,加载时间不够早,c,macos,debugging,memory,malloc,C,Macos,Debugging,Memory,Malloc,我正试图编写自己的malloc/free包装来捕获缓冲区溢出。原因:Guard Malloc不够激进,因为它无法捕获溢出,除非它们接近页面边界。我不介意稍后(当内存被释放时)检测溢出,但我不介意检测它 我使用了插入和DYLD\u INSERT\u库来注入malloc和free的实现。问题是,在加载动态库之前,似乎有对malloc的调用。当这些对象被释放时,我的free()认为它们已损坏,因为我要添加的序言和尾声不存在 我的代码如下所示: #define DYLD_INTERPOSE(_repla

我正试图编写自己的malloc/free包装来捕获缓冲区溢出。原因:Guard Malloc不够激进,因为它无法捕获溢出,除非它们接近页面边界。我不介意稍后(当内存被释放时)检测溢出,但我不介意检测它

我使用了插入和
DYLD\u INSERT\u库
来注入malloc和free的实现。问题是,在加载动态库之前,似乎有对malloc的调用。当这些对象被释放时,我的
free()
认为它们已损坏,因为我要添加的序言和尾声不存在

我的代码如下所示:

#define DYLD_INTERPOSE(_replacment,_replacee) \
__attribute__((used)) static struct{ const void* replacment; const void* replacee; } _interpose_##_replacee \
__attribute__ ((section ("__DATA,__interpose"))) = { (const void*)(unsigned long)&_replacment, (const void*)(unsigned long)&_replacee };

static const char *premagic = "abcdefgh";
static const char *postmagic = "zyxwvuts";
static const size_t prologueLength = 16;
static const size_t sizeOffset = 8;
static const size_t preMagicOffset = 0;
static const size_t epilogueLength = 8;
static const size_t totalOverhead = prologueLength + epilogueLength;

static void WriteMetadata(void *p, size_t size) {
    memmove(p + preMagicOffset, premagic, 8);
    memmove(p + sizeOffset, &size, sizeof(size));
    memmove(p + prologueLength + size, postmagic, 8);
}

static void CheckMemory(void *ptr) {
    void *realP = ptr - prologueLength;

    // Get size
    size_t size;
    memmove(&size, realP + sizeOffset, sizeof(size_t));

    // Check premagic
    if (memcmp(realP + preMagicOffset, premagic, 8)) {
        while (1);
    }

    // Check postmagic
    void *post = ptr + size;
    if (memcmp(post, postmagic, 8)) {
        while (1);
    }
}

void *ITMalloc(size_t size) {
    void *p = malloc(size + totalOverhead);
    if (p == 0) {
        return p;
    }
    WriteMetadata(p, size);
    return p + prologueLength;
}
DYLD_INTERPOSE(ITMalloc, malloc);

void ITFree(void *ptr) {
    CheckMemory(ptr);

    void *realP = ptr - prologueLength;
    free(realP);
}
DYLD_INTERPOSE(ITFree, free);

... and more for calloc, realloc, etc. ...
下面是我如何运行它的:

DYLD_INSERT_LIBRARIES=libitmalloc.dylib ./helloworld
问题是,我的
ITFree
函数被调用时使用的
ptr
从未由
ITMalloc
分配。使用
MallocStackLogging
我可以看到,它是在boostapping期间由动态加载程序的一部分分配的。以下是第一次此类分配的堆栈跟踪:

 0x10261d036 (dyld) _dyld_start 
 0x10261d503 (dyld) dyldbootstrap::start(macho_header const*, int, char const**, long, macho_header const*, unsigned long*) 
 0x102623709 (dyld) dyld::_main(macho_header const*, unsigned long, int, char const**, char const**, char const**, unsigned long*) 
 0x10261e71f (dyld) dyld::initializeMainExecutable() 
 0x10262ee05 (dyld) ImageLoader::runInitializers(ImageLoader::LinkContext const&, ImageLoader::InitializerTimingList&) 
 0x10262ed73 (dyld) ImageLoader::processInitializers(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) 
 0x10262fb80 (dyld) ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) 
 0x10262fb80 (dyld) ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) 
 0x10262fb80 (dyld) ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&)
 0x10262fb80 (dyld) ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) 
 0x10262fb80 (dyld) ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) 
 0x10262fbea (dyld) ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) 
 0x102634798 (dyld) ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) 
 0x102634592 (dyld) ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) 
 0x7fff76ad49c5 (libSystem.B.dylib) libSystem_initializer 
 0x7fff79cccad2 (libdispatch.dylib) libdispatch_init 
 0x7fff79cc0e36 (libdispatch.dylib) _os_object_init 
 0x7fff784ce234 (libobjc.A.dylib) _objc_init 
 0x7fff79cf9a27 (libdyld.dylib) _dyld_objc_notify_register 
 0x10262162e (dyld) dyld::registerObjCNotifiers(void (*)(unsigned int, char const* const*, mach_header const* const*), void (*)(char const*, mach_header const*), void (*)(char const*, mach_header const*)) 
 0x10262147b (dyld) dyld::notifyBatchPartial(dyld_image_states, bool, char const* (*)(dyld_image_states, unsigned int, dyld_image_info const*), bool, bool) 
 0x7fff784e1560 (libobjc.A.dylib) map_images 
 0x7fff784cea50 (libobjc.A.dylib) map_images_nolock 
 0x7fff784cfa92 (libobjc.A.dylib) _read_images 
 0x7fff784d0847 (libobjc.A.dylib) NXCreateMapTable 
 0x7fff784d089d (libobjc.A.dylib) NXCreateMapTableFromZone 
 0x7fff784d09c0 (libobjc.A.dylib) NXCreateHashTable 
 0x7fff784d0aff (libobjc.A.dylib) NXCreateHashTableFromZone 
 0x7fff784d0de4 (libobjc.A.dylib) NXHashInsert 
 0x7fff79ebb1b0 (libsystem_malloc.dylib) malloc_zone_calloc 

我是否得出结论,唯一的解决方案是维护一个“已知指针”的副表,我知道它有我的开场白/尾声,并且不依赖于在任何其他用户之前挂钩
malloc
?或者,有没有一种方法可以让我的代码更早地加载到我还没有找到的地方?

dyld需要在dyld_INSERT_库插入的库之前运行初始化器libSystem,这是有道理的,因为它不能告诉这些初始化器通常会做什么。正如回溯所示,初始化libSystem确实需要分配。因此,您可能会被这样一个事实所困扰,即您的库无法看到某些分配。dyld需要在dyld_INSERT_库插入库的分配之前运行初始值设定项libSystem,这是有道理的,因为它无法告诉这些初始值设定项通常会做什么。正如回溯所示,初始化libSystem确实需要分配。因此,您可能会被这样一个事实所困扰,即您的库无法看到分配。