| 475 | }; |
| 476 | |
| 477 | bool LibcInfo::PopulateWindowsFn(const ModuleEntryCopy& module_entry) { |
| 478 | // First, store the location of the function to patch before |
| 479 | // patching it. If none of these functions are found in the module, |
| 480 | // then this module has no libc in it, and we just return false. |
| 481 | for (int i = 0; i < kNumFunctions; i++) { |
| 482 | if (!function_name_[i]) // we can turn off patching by unsetting name |
| 483 | continue; |
| 484 | // The ::GetProcAddress calls were done in the ModuleEntryCopy |
| 485 | // constructor, so we don't have to make any windows calls here. |
| 486 | const GenericFnPtr fn = module_entry.rgProcAddresses[i]; |
| 487 | if (fn) { |
| 488 | windows_fn_[i] = PreamblePatcher::ResolveTarget(fn); |
| 489 | } |
| 490 | } |
| 491 | |
| 492 | // Some modules use the same function pointer for new and new[]. If |
| 493 | // we find that, set one of the pointers to NULL so we don't double- |
| 494 | // patch. Same may happen with new and nothrow-new, or even new[] |
| 495 | // and nothrow-new. It's easiest just to check each fn-ptr against |
| 496 | // every other. |
| 497 | for (int i = 0; i < kNumFunctions; i++) { |
| 498 | for (int j = i+1; j < kNumFunctions; j++) { |
| 499 | if (windows_fn_[i] == windows_fn_[j]) { |
| 500 | // We NULL the later one (j), so as to minimize the chances we |
| 501 | // NULL kFree and kRealloc. See comments below. This is fragile! |
| 502 | windows_fn_[j] = NULL; |
| 503 | } |
| 504 | } |
| 505 | } |
| 506 | |
| 507 | // There's always a chance that our module uses the same function |
| 508 | // as another module that we've already loaded. In that case, we |
| 509 | // need to set our windows_fn to NULL, to avoid double-patching. |
| 510 | for (int ifn = 0; ifn < kNumFunctions; ifn++) { |
| 511 | for (int imod = 0; |
| 512 | imod < sizeof(g_module_libcs)/sizeof(*g_module_libcs); imod++) { |
| 513 | if (g_module_libcs[imod]->is_valid() && |
| 514 | this->windows_fn(ifn) == g_module_libcs[imod]->windows_fn(ifn)) { |
| 515 | windows_fn_[ifn] = NULL; |
| 516 | } |
| 517 | } |
| 518 | } |
| 519 | |
| 520 | bool found_non_null = false; |
| 521 | for (int i = 0; i < kNumFunctions; i++) { |
| 522 | if (windows_fn_[i]) |
| 523 | found_non_null = true; |
| 524 | } |
| 525 | if (!found_non_null) |
| 526 | return false; |
| 527 | |
| 528 | // It's important we didn't NULL out windows_fn_[kFree] or [kRealloc]. |
| 529 | // The reason is, if those are NULL-ed out, we'll never patch them |
| 530 | // and thus never get an origstub_fn_ value for them, and when we |
| 531 | // try to call origstub_fn_[kFree/kRealloc] in Perftools_free and |
| 532 | // Perftools_realloc, below, it will fail. We could work around |
| 533 | // that by adding a pointer from one patch-unit to the other, but we |
| 534 | // haven't needed to yet. |
no test coverage detected