allocator

来源:互联网 发布:java cas原理 编辑:程序博客网 时间:2024/05/06 13:51

替换CRT堆处理函数

base/allocator 中有个python文件用于处理VS中libcmt.lib静态库中堆的处理函数,将其obj文件去除,这对于我来说是一个比较新颖的思路,一直以为只有hook才是一个方案,没想到这种静态链接的方法也是不错的。

import osimport shutilimport subprocessimport sysdef run(command, env_dict):  """Run |command|.  If any lines that match an error condition then      terminate.  The env_dict, will be used for the environment. None can be used to get the  default environment."""  error = 'cannot find member object'  # Need shell=True to search the path in env_dict for the executable.  popen = subprocess.Popen(      command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True,      env=env_dict)  out, _ = popen.communicate()  for line in out.splitlines():    print line    if error and line.find(error) != -1:      print 'prep_libc.py: Error stripping object from C runtime.'      sys.exit(1)def main():  bindir = 'SELF_X86'  objdir = 'INTEL'  vs_install_dir = sys.argv[1]  outdir = sys.argv[2]  if "x64" in sys.argv[3]:    bindir = 'SELF_64_amd64'    objdir = 'amd64'    vs_install_dir = os.path.join(vs_install_dir, 'amd64')  if len(sys.argv) == 5:    env_pairs = open(sys.argv[4]).read()[:-2].split('\0')    env_dict = dict([item.split('=', 1) for item in env_pairs])  else:    env_dict = None  # Use the default environment.  output_lib = os.path.join(outdir, 'libcmt.lib')  shutil.copyfile(os.path.join(vs_install_dir, 'libcmt.lib'), output_lib)  shutil.copyfile(os.path.join(vs_install_dir, 'libcmt.pdb'),                  os.path.join(outdir, 'libcmt.pdb'))  cvspath = 'f:\\binaries\\Intermediate\\vctools\\crt_bld\\' + bindir + \      '\\crt\\prebuild\\build\\' + objdir + '\\mt_obj\\nativec\\\\';  cppvspath = 'f:\\binaries\\Intermediate\\vctools\\crt_bld\\' + bindir + \      '\\crt\\prebuild\\build\\' + objdir + '\\mt_obj\\nativecpp\\\\';  cobjfiles = ['malloc', 'free', 'realloc', 'heapinit', 'calloc', 'recalloc',      'calloc_impl']  cppobjfiles = ['new', 'new2', 'delete', 'delete2', 'new_mode', 'newopnt',      'newaopnt']  for obj in cobjfiles:    cmd = ('lib /nologo /ignore:4006,4221 /remove:%s%s.obj %s' %           (cvspath, obj, output_lib))    run(cmd, env_dict)  for obj in cppobjfiles:    cmd = ('lib /nologo /ignore:4006,4221 /remove:%s%s.obj %s' %           (cppvspath, obj, output_lib))    run(cmd, env_dict)if __name__ == "__main__":  sys.exit(main())

这是python语言,核心语句是要执行下面这个命令:

cmd = ('lib /nologo /ignore:4006,4221 /remove:%s%s.obj %s' %           (cvspath, obj, output_lib))

主要的方式就是移除堆管理的obj数据。这里不深挖具体怎么处理,因为目前暂时遇不到这种情况,只是作为一个了解。

堆的管理

那么chromium接管了系统的heap处理后,他是要干什么呢,进行了那些优化呢,chromium如下这样注释,似乎表明了它的用意。

// Heap functions are stripped from libcmt.lib using the prep_libc.py// for each object file stripped, we re-implement them here to allow us to// perform additional checks:// 1. Enforcing the maximum size that can be allocated to 2Gb.// 2. Calling new_handler if malloc fails.

其实接管系统的heap处理,如果在Linux平台下是可以直接使用tcmalloc来接替内存申请,然而在window平台还是接着使用默认系统堆内存。

我们来看看它是如何接管内存处理的,先看堆的初始化

int _heap_init() {  base::allocator::g_is_win_shim_layer_initialized = true;  return win_heap_init() ? 1 : 0;}// VS2013 crt uses the process heap as its heap, so we do the same here.// See heapinit.c in VS CRT sources.bool win_heap_init() {  // Set the _crtheap global here.  THis allows us to offload most of the  // memory management to the CRT, except the functions we need to shim.  _crtheap = GetProcessHeap();  if (_crtheap == NULL)    return false;  ULONG enable_lfh = 2;  // NOTE: Setting LFH may fail.  Vista already has it enabled.  //       And under the debugger, it won't use LFH.  So we  //       ignore any errors.  HeapSetInformation(_crtheap, HeapCompatibilityInformation, &enable_lfh,                     sizeof(enable_lfh));  return true;}

这里默认设置LFH堆属性,使用进程堆,那么堆又是如何申请的呢

// Call the new handler, if one has been set.// Returns true on successfully calling the handler, false otherwise.inline bool call_new_handler(bool nothrow, size_t size) {  // Get the current new handler.  _PNH nh = _query_new_handler();#if defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS  if (!nh)    return false;  // Since exceptions are disabled, we don't really know if new_handler  // failed.  Assume it will abort if it fails.  return nh(size);#else#error "Exceptions in allocator shim are not supported!"#endif  // defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS  return false;}// Implement a C++ style allocation, which always calls the new_handler// on failure.inline void* generic_cpp_alloc(size_t size, bool nothrow) {  void* ptr;  for (;;) {    ptr = malloc(size);    if (ptr)      return ptr;    if (!call_new_handler(nothrow, size))      break;  }  return ptr;}// new.cppvoid* operator new(size_t size) {  return generic_cpp_alloc(size, false);}// delete.cppvoid operator delete(void* p) throw() {  free(p);}

这里和CRT的实现已经无什么差异了。

0 0