Macos 如何获取“自动发布工具”地址?
我试过了Macos 如何获取“自动发布工具”地址?,macos,dlsym,dsymutil,Macos,Dlsym,Dsymutil,我试过了 extern void __NSAutoreleaseNoPool(void* obj); 但这会导致链接时出现无法解析的符号(但不确定它需要什么样的框架) 我也试过了 dlsym(RTLD_DEFAULT, "__NSAutoreleaseNoPool") 但这只会给出beNULL 我尝试了\u dyld\u lookup\u和
extern void __NSAutoreleaseNoPool(void* obj);
但这会导致链接时出现无法解析的符号(但不确定它需要什么样的框架)
我也试过了
dlsym(RTLD_DEFAULT, "__NSAutoreleaseNoPool")
但这只会给出beNULL
我尝试了\u dyld\u lookup\u和
和NSLookupSymbolInImage
,但它们也不起作用
dsymutil
和nm
都可以找到符号,不过:
$ dsymutil -s --arch=x86_64
----------------------------------------------------------------------
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
----------------------------------------------------------------------
Symbol table for: '/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation' (x86_64)
----------------------------------------------------------------------
Index n_strx n_type n_sect n_desc n_value
======== -------- ------------------ ------ ------ ----------------
[ 0] 00010795 1e (PEXT SECT ) 01 0000 0000000000000000 '__mh_dylib_header'
[ 1] 000107a7 0e ( SECT ) 01 0000 0000000000001c20 '+[NSObject(NSObject) load]'
[ 2] 000107c2 0e ( SECT ) 01 0000 0000000000002630 '___exceptionInit'
[ 3] 000107d3 0e ( SECT ) 01 0000 00000000000029e0 '___CFgetenv'
[ 4] 000107df 0e ( SECT ) 01 0000 0000000000002a50 '___CFBaseInitialize'
...
[ 1923] 0001e820 0e ( SECT ) 01 0000 000000000010ad30 '___NSAutoreleaseNoPool'
...
$ nm -arch x86_64 /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
...
000000000010ad30 t ___NSAutoreleaseNoPool
...
(这是在MacOSX 10.6上。在后来的MacOSX版本中,符号似乎确实不存在,至少我在/usr/lib
和/System/Library/Frameworks
中通过grep
找不到任何引用,LLDB也找不到它。可能是用ARC删除的。)
那么,我怎样才能在我的代码中得到那个地址呢
(有关问题:及)
(我这样做的动机是。)这样做有效:
#include <dlfcn.h>
#include <stdio.h>
#import <Foundation/Foundation.h>
#include <mach-o/dyld.h>
#include <mach-o/nlist.h>
#include <string.h>
#include <assert.h>
// Adapted from:
// https://github.com/0xced/iOS-Artwork-Extractor/blob/master/Classes/FindSymbol.c
// Adapted from MoreAddrToSym / GetFunctionName()
// http://www.opensource.apple.com/source/openmpi/openmpi-8/openmpi/opal/mca/backtrace/darwin/MoreBacktrace/MoreDebugging/MoreAddrToSym.c
void *FindSymbol(const struct mach_header *img, const char *symbol)
{
if ((img == NULL) || (symbol == NULL))
return NULL;
// only 64bit supported
#if defined (__LP64__)
if(img->magic != MH_MAGIC_64)
// we currently only support Intel 64bit
return NULL;
struct mach_header_64 *image = (struct mach_header_64*) img;
struct segment_command_64 *seg_linkedit = NULL;
struct segment_command_64 *seg_text = NULL;
struct symtab_command *symtab = NULL;
unsigned int index;
struct load_command *cmd = (struct load_command*)(image + 1);
for (index = 0; index < image->ncmds; index += 1, cmd = (struct load_command*)((char*)cmd + cmd->cmdsize))
{
switch(cmd->cmd)
{
case LC_SEGMENT_64: {
struct segment_command_64* segcmd = (struct segment_command_64*)cmd;
if (!strcmp(segcmd->segname, SEG_TEXT))
seg_text = segcmd;
else if (!strcmp(segcmd->segname, SEG_LINKEDIT))
seg_linkedit = segcmd;
break;
}
case LC_SYMTAB:
symtab = (struct symtab_command*)cmd;
break;
default:
break;
}
}
if ((seg_text == NULL) || (seg_linkedit == NULL) || (symtab == NULL))
return NULL;
unsigned long vm_slide = (unsigned long)image - (unsigned long)seg_text->vmaddr;
unsigned long file_slide = ((unsigned long)seg_linkedit->vmaddr - (unsigned long)seg_text->vmaddr) - seg_linkedit->fileoff;
struct nlist_64 *symbase = (struct nlist_64*)((unsigned long)image + (symtab->symoff + file_slide));
char *strings = (char*)((unsigned long)image + (symtab->stroff + file_slide));
struct nlist_64 *sym;
for (index = 0, sym = symbase; index < symtab->nsyms; index += 1, sym += 1)
{
if (sym->n_un.n_strx != 0 && !strcmp(symbol, strings + sym->n_un.n_strx))
{
unsigned long address = vm_slide + sym->n_value;
if (sym->n_desc & N_ARM_THUMB_DEF)
return (void*)(address | 1);
else
return (void*)(address);
}
}
#endif
return NULL;
}
typedef void (*NSAutoreleaseNoPoolFunc) (void* obj);
void getNSAutoreleaseNoPool() {
const struct mach_header* img = NSAddImage("/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation", NSADDIMAGE_OPTION_NONE);
NSAutoreleaseNoPoolFunc f = (NSAutoreleaseNoPoolFunc) FindSymbol((struct mach_header*)img, "___NSAutoreleaseNoPool");
printf("func: %p\n", f);
if(f) {
NSObject* foo = [[NSObject alloc] init];
f(foo);
}
}
发生这种情况时,标准回溯是:
(gdb) bt
#0 0x00007fff8724bd34 in __NSAutoreleaseNoPool ()
#1 0x00007fff87196e79 in _CFAutoreleasePoolAddObject ()
#2 0x00007fff87196be6 in -[NSObject(NSObject) autorelease] ()
实际的NSLog
调用是在\u CFAutoreleasePoolAddObject
中完成的
有关\uu nsautoreleasenool
的说明,来自Foundation/NSDebug.h
:
/**************** Autorelease pool debugging ****************/
// Functions used as interesting breakpoints in a debugger
// void __NSAutoreleaseNoPool(void *object);
// Called to log the "Object X of class Y autoreleased with no
// pool in place - just leaking" message. If an environment
// variable named "NSAutoreleaseHaltOnNoPool" is set with string
// value "YES", the function will automatically break in the
// debugger (or terminate the process).
// void __NSAutoreleaseFreedObject(void *freedObject);
// Called when a previously freed object would be released
// by an autorelease pool. If an environment variable named
// "NSAutoreleaseHaltOnFreedObject" is set with string value
// "YES", the function will automatically break in the debugger
// (or terminate the process).
因此,如果您想调试这种情况,可以启动GDB并发出b\u nsautoreleasenool
来设置此函数的断点。或者在shell中导出nsautoreleaseholtonopool=1
\uu nsautoreleasenool
非常简单:
(gdb) disassemble
Dump of assembler code for function __NSAutoreleaseNoPool:
0x00007fff8724bd30 <__NSAutoreleaseNoPool+0>: push %rbp
0x00007fff8724bd31 <__NSAutoreleaseNoPool+1>: mov %rsp,%rbp
0x00007fff8724bd34 <__NSAutoreleaseNoPool+4>: nop
0x00007fff8724bd35 <__NSAutoreleaseNoPool+5>: nopl 0x0(%rax)
0x00007fff8724bd39 <__NSAutoreleaseNoPool+9>: lea 0x2ced8(%rip),%rdi # 0x7fff87278c18 <__PRETTY_FUNCTION__.27904+480>
0x00007fff8724bd40 <__NSAutoreleaseNoPool+16>: callq 0x7fff871439e0 <__CFgetenv>
0x00007fff8724bd45 <__NSAutoreleaseNoPool+21>: test %rax,%rax
0x00007fff8724bd48 <__NSAutoreleaseNoPool+24>: je 0x7fff8724bd55 <__NSAutoreleaseNoPool+37>
0x00007fff8724bd4a <__NSAutoreleaseNoPool+26>: movzbl (%rax),%eax
0x00007fff8724bd4d <__NSAutoreleaseNoPool+29>: cmp $0x59,%al
0x00007fff8724bd4f <__NSAutoreleaseNoPool+31>: je 0x7fff8724bd60 <__NSAutoreleaseNoPool+48>
0x00007fff8724bd51 <__NSAutoreleaseNoPool+33>: cmp $0x79,%al
0x00007fff8724bd53 <__NSAutoreleaseNoPool+35>: je 0x7fff8724bd60 <__NSAutoreleaseNoPool+48>
0x00007fff8724bd55 <__NSAutoreleaseNoPool+37>: leaveq
0x00007fff8724bd56 <__NSAutoreleaseNoPool+38>: retq
0x00007fff8724bd57 <__NSAutoreleaseNoPool+39>: nopw 0x0(%rax,%rax,1)
0x00007fff8724bd60 <__NSAutoreleaseNoPool+48>: int3
0x00007fff8724bd61 <__NSAutoreleaseNoPool+49>: callq 0x7fff872609c2 <dyld_stub_getpid>
0x00007fff8724bd66 <__NSAutoreleaseNoPool+54>: mov %eax,%edi
0x00007fff8724bd68 <__NSAutoreleaseNoPool+56>: mov $0x9,%esi
0x00007fff8724bd6d <__NSAutoreleaseNoPool+61>: leaveq
0x00007fff8724bd6e <__NSAutoreleaseNoPool+62>: jmpq 0x7fff87260a16 <dyld_stub_kill>
0x00007fff8724bd73 <__NSAutoreleaseNoPool+67>: nopw 0x0(%rax,%rax,1)
0x00007fff8724bd79 <__NSAutoreleaseNoPool+73>: nopl 0x0(%rax)
End of assembler dump.
(gdb)反汇编
函数自动释放工具的汇编程序代码转储:
0x00007fff8724bd30:推送%rbp
0x00007fff8724bd31:mov%rsp,%rbp
0x00007fff8724bd34:否
0x00007fff8724bd35:nopl 0x0(%rax)
0x00007fff8724bd39:lea 0x2ced8(%rip),%rdi#0x7fff87278c18
0x00007fff8724bd40:调用0x7fff871439e0
0x00007fff8724bd45:测试%rax,%rax
0x00007fff8724bd48:je 0x7fff8724bd55
0x00007fff8724bd4a:movzbl(%rax),%eax
0x00007fff8724bd4d:cmp$0x59,%al
0x00007fff8724bd4f:je 0x7fff8724bd60
0x00007fff8724bd51:cmp$0x79,%al
0x00007fff8724bd53:je 0x7fff8724bd60
0x00007fff8724bd55:LEVEQ
0x00007fff8724bd56:retq
0x00007fff8724bd57:nopw 0x0(%rax,%rax,1)
0x00007fff8724bd60:int3
0x00007fff8724bd61:调用0x7fff872609c2
0x00007fff8724bd66:mov%eax,%edi
0x00007fff8724bd68:mov$0x9,%esi
0x00007fff8724bd6d:LEVEQ
0x00007fff8724bd6e:jmpq 0x7fff87260a16
0x00007fff8724bd73:nopw 0x0(%rax,%rax,1)
0x00007fff8724bd79:nopl 0x0(%rax)
汇编程序转储结束。
有关实际示例,请参见。您希望实现的目标是什么?你为什么需要这个地址?@Volker:只是想试试用mach_覆盖的黑客技术;第一个是cdecl名称混乱。@hamstergene:不起作用。另外,
\uu nsautoreleasenool
实际上有两个下划线。那么可以用三个下划线调用dlsym吗?但也有可能它根本就没有被导出,至少是名字。最后,您可以使用调试器在映像中找到它,在验证映像的md5之后,只需在预定义的偏移量处调用它。
(gdb) disassemble
Dump of assembler code for function __NSAutoreleaseNoPool:
0x00007fff8724bd30 <__NSAutoreleaseNoPool+0>: push %rbp
0x00007fff8724bd31 <__NSAutoreleaseNoPool+1>: mov %rsp,%rbp
0x00007fff8724bd34 <__NSAutoreleaseNoPool+4>: nop
0x00007fff8724bd35 <__NSAutoreleaseNoPool+5>: nopl 0x0(%rax)
0x00007fff8724bd39 <__NSAutoreleaseNoPool+9>: lea 0x2ced8(%rip),%rdi # 0x7fff87278c18 <__PRETTY_FUNCTION__.27904+480>
0x00007fff8724bd40 <__NSAutoreleaseNoPool+16>: callq 0x7fff871439e0 <__CFgetenv>
0x00007fff8724bd45 <__NSAutoreleaseNoPool+21>: test %rax,%rax
0x00007fff8724bd48 <__NSAutoreleaseNoPool+24>: je 0x7fff8724bd55 <__NSAutoreleaseNoPool+37>
0x00007fff8724bd4a <__NSAutoreleaseNoPool+26>: movzbl (%rax),%eax
0x00007fff8724bd4d <__NSAutoreleaseNoPool+29>: cmp $0x59,%al
0x00007fff8724bd4f <__NSAutoreleaseNoPool+31>: je 0x7fff8724bd60 <__NSAutoreleaseNoPool+48>
0x00007fff8724bd51 <__NSAutoreleaseNoPool+33>: cmp $0x79,%al
0x00007fff8724bd53 <__NSAutoreleaseNoPool+35>: je 0x7fff8724bd60 <__NSAutoreleaseNoPool+48>
0x00007fff8724bd55 <__NSAutoreleaseNoPool+37>: leaveq
0x00007fff8724bd56 <__NSAutoreleaseNoPool+38>: retq
0x00007fff8724bd57 <__NSAutoreleaseNoPool+39>: nopw 0x0(%rax,%rax,1)
0x00007fff8724bd60 <__NSAutoreleaseNoPool+48>: int3
0x00007fff8724bd61 <__NSAutoreleaseNoPool+49>: callq 0x7fff872609c2 <dyld_stub_getpid>
0x00007fff8724bd66 <__NSAutoreleaseNoPool+54>: mov %eax,%edi
0x00007fff8724bd68 <__NSAutoreleaseNoPool+56>: mov $0x9,%esi
0x00007fff8724bd6d <__NSAutoreleaseNoPool+61>: leaveq
0x00007fff8724bd6e <__NSAutoreleaseNoPool+62>: jmpq 0x7fff87260a16 <dyld_stub_kill>
0x00007fff8724bd73 <__NSAutoreleaseNoPool+67>: nopw 0x0(%rax,%rax,1)
0x00007fff8724bd79 <__NSAutoreleaseNoPool+73>: nopl 0x0(%rax)
End of assembler dump.