Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

possible bug in src/windows/patch_functions.cc #664

Open
GoogleCodeExporter opened this issue Jul 4, 2015 · 3 comments
Open

possible bug in src/windows/patch_functions.cc #664

GoogleCodeExporter opened this issue Jul 4, 2015 · 3 comments

Comments

@GoogleCodeExporter
Copy link

LibcInfo::PopulateWindowsFn() in src/windows/patch_functions.cc
has this code to deal with multiple modules using the same symbol:

  // There's always a chance that our module uses the same function
  // as another module that we've already loaded.  In that case, we
  // need to set our windows_fn to NULL, to avoid double-patching.
  for (int ifn = 0; ifn < kNumFunctions; ifn++) {
    for (int imod = 0;
         imod < sizeof(g_module_libcs)/sizeof(*g_module_libcs);  imod++) {
      if (g_module_libcs[imod]->is_valid() &&
          this->windows_fn(ifn) == g_module_libcs[imod]->windows_fn(ifn)) {
        windows_fn_[ifn] = NULL;
      }
    }
  }

I am not sure this works.  An earlier line sets windows_fn_:

      windows_fn_[i] = PreamblePatcher::ResolveTarget(fn);

The problem is that ResolveTarget() chases JMP instructions.  If the
function appeared in an earlier module, it has been patched, and its
first instruction is now a jump to the corresponding
LibcInfoWithPatchFunctions<T>::Perftools_XXX().  So windows_fn_[i]
in the current module gets set to the address of that, but in the
loop you are comparing it with the address of the original Windows
function.

This seems to be the cause of a crash in a program linked with with
libtcmalloc_minimal.  PopulateWindowsFn() gets called thrice during
initialization: for MSVCRT, then MSVCR100, and finally the main
executable.  In the ModuleEntryCopy argument for the last call, the
addresses of malloc(), free(), realloc(), calloc(), _msize(), and
_expand() are the same as for MSVCR100.  The last entry in the
address array, for k_CallocCrt, is calloc() again.  But the eight
new/delete function addresses are different and seem to be in the
executable rather than the DLL.

For the functions that are repeated,
PreamblePatcher::RawPatchWithStub() patches
LibcInfoWithPatchFunctions<2>::Perftools_XXX().  It aborts because
Perftools__expand() is too short to patch.

This is a 32-bit executable running on 64-bit Windows 7.  The
compiler is VS 2010 SP1.  Only the 32-bit debug build of the program
fails.  The 32-bit release build works, as do the 64-bit debug and
release builds.  All builds are statically linked with the release
build of libtcmalloc_minimal, which is compiled with /MD.  I am
using gperftools 2.2.1, but even in 2.3.90 the code in src/windows/
is not significantly different.

Original issue reported on code.google.com by [email protected] on 7 Jan 2015 at 3:38

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant