MCPcopy Create free account
hub / github.com/beefytech/Beef / PatchAllModules

Function PatchAllModules

BeefRT/gperftools/src/windows/patch_functions.cc:679–773  ·  view source on GitHub ↗

Iterates over all the modules currently loaded by the executable, according to windows, and makes sure they're all patched. Most modules will already be in loaded_modules, meaning we have already loaded and either patched them or determined they did not need to be patched. Others will not, which means we need to patch them (if necessary). Finally, we have to go through the existing g_module_lib

Source from the content-addressed store, hash-verified

677// false if we were a noop. May update loaded_modules as well.
678// NOTE: you must hold the patch_all_modules_lock to access loaded_modules.
679bool PatchAllModules() {
680 std::vector<ModuleEntryCopy> modules;
681 bool made_changes = false;
682
683 const HANDLE hCurrentProcess = GetCurrentProcess();
684 DWORD num_modules = 0;
685 HMODULE hModules[kMaxModules]; // max # of modules we support in one process
686 if (!::EnumProcessModules(hCurrentProcess, hModules, sizeof(hModules),
687 &num_modules)) {
688 num_modules = 0;
689 }
690 // EnumProcessModules actually set the bytes written into hModules,
691 // so we need to divide to make num_modules actually be a module-count.
692 num_modules /= sizeof(*hModules);
693 if (num_modules >= kMaxModules) {
694 printf("PERFTOOLS ERROR: Too many modules in this executable to try"
695 " to patch them all (if you need to, raise kMaxModules in"
696 " patch_functions.cc).\n");
697 num_modules = kMaxModules;
698 }
699
700 // Now we handle the unpatching of modules we have in g_module_libcs
701 // but that were not found in EnumProcessModules. We need to
702 // invalidate them. To speed that up, we store the EnumProcessModules
703 // output in a set.
704 // At the same time, we prepare for the adding of new modules, by
705 // removing from hModules all the modules we know we've already
706 // patched (or decided don't need to be patched). At the end,
707 // hModules will hold only the modules that we need to consider patching.
708 std::set<HMODULE> currently_loaded_modules;
709 {
710 SpinLockHolder h(&patch_all_modules_lock);
711 if (!g_last_loaded) g_last_loaded = new std::set<HMODULE>;
712 // At the end of this loop, currently_loaded_modules contains the
713 // full list of EnumProcessModules, and hModules just the ones we
714 // haven't handled yet.
715 for (int i = 0; i < num_modules; ) {
716 currently_loaded_modules.insert(hModules[i]);
717 if (g_last_loaded->count(hModules[i]) > 0) {
718 hModules[i] = hModules[--num_modules]; // replace element i with tail
719 } else {
720 i++; // keep element i
721 }
722 }
723 // Now we do the unpatching/invalidation.
724 for (int i = 0; i < sizeof(g_module_libcs)/sizeof(*g_module_libcs); i++) {
725 if (g_module_libcs[i]->patched() &&
726 currently_loaded_modules.count(g_module_libcs[i]->hmodule()) == 0) {
727 // Means g_module_libcs[i] is no longer loaded (no me32 matched).
728 // We could call Unpatch() here, but why bother? The module
729 // has gone away, so nobody is going to call into it anyway.
730 g_module_libcs[i]->set_is_valid(false);
731 made_changes = true;
732 }
733 }
734 // Update the loaded module cache.
735 g_last_loaded->swap(currently_loaded_modules);
736 }

Callers 3

Perftools_FreeLibraryMethod · 0.70
PatchWindowsFunctionsFunction · 0.70

Calls 10

ModuleEntryCopyClass · 0.70
PatchOneModuleLockedFunction · 0.70
patchedMethod · 0.45
hmoduleMethod · 0.45
set_is_validMethod · 0.45
push_backMethod · 0.45
beginMethod · 0.45
endMethod · 0.45
PopulateWindowsFnMethod · 0.45

Tested by

no test coverage detected