|
13 | 13 | //===----------------------------------------------------------------------===//
|
14 | 14 |
|
15 | 15 | #include "xray_interface_internal.h"
|
| 16 | +#include "llvm/Support/ErrorHandling.h" |
16 | 17 |
|
17 | 18 | #include <cinttypes>
|
18 | 19 | #include <cstdio>
|
@@ -289,24 +290,9 @@ XRayPatchingStatus patchFunction(int32_t FuncId, int32_t ObjId,
|
289 | 290 | // controlPatching implements the common internals of the patching/unpatching
|
290 | 291 | // implementation. |Enable| defines whether we're enabling or disabling the
|
291 | 292 | // runtime XRay instrumentation.
|
292 |
| -XRayPatchingStatus controlPatching(bool Enable, |
293 |
| - int32_t ObjId) XRAY_NEVER_INSTRUMENT { |
294 |
| - |
295 |
| - if (!atomic_load(&XRayInitialized, memory_order_acquire)) |
296 |
| - return XRayPatchingStatus::NOT_INITIALIZED; // Not initialized. |
297 |
| - |
298 |
| - uint8_t NotPatching = false; |
299 |
| - if (!atomic_compare_exchange_strong( |
300 |
| - &XRayPatching, &NotPatching, true, memory_order_acq_rel)) |
301 |
| - return XRayPatchingStatus::ONGOING; // Already patching. |
302 |
| - |
303 |
| - uint8_t PatchingSuccess = false; |
304 |
| - auto XRayPatchingStatusResetter = |
305 |
| - at_scope_exit([&PatchingSuccess] { |
306 |
| - if (!PatchingSuccess) |
307 |
| - atomic_store(&XRayPatching, false, memory_order_release); |
308 |
| - }); |
309 |
| - |
| 293 | +// This function should only be called after ensuring that XRay is initialized |
| 294 | +// and no other thread is currently patching. |
| 295 | +XRayPatchingStatus controlPatchingObjectUnchecked(bool Enable, int32_t ObjId) { |
310 | 296 | XRaySledMap InstrMap;
|
311 | 297 | {
|
312 | 298 | SpinMutexLock Guard(&XRayInstrMapMutex);
|
@@ -382,10 +368,80 @@ XRayPatchingStatus controlPatching(bool Enable,
|
382 | 368 | patchSled(Sled, Enable, PackedId, InstrMap.Trampolines);
|
383 | 369 | }
|
384 | 370 | atomic_store(&XRayPatching, false, memory_order_release);
|
385 |
| - PatchingSuccess = true; |
386 | 371 | return XRayPatchingStatus::SUCCESS;
|
387 | 372 | }
|
388 | 373 |
|
| 374 | + |
| 375 | +// Controls patching for all registered objects. |
| 376 | +// Returns: SUCCESS, if patching succeeds for all objects. |
| 377 | +// NOT_INITIALIZED, if one or more objects returned NOT_INITIALIZED |
| 378 | +// but none failed. |
| 379 | +// FAILED, if patching of one or more objects failed. |
| 380 | +XRayPatchingStatus controlPatching(bool Enable) XRAY_NEVER_INSTRUMENT { |
| 381 | + if (!atomic_load(&XRayInitialized, memory_order_acquire)) |
| 382 | + return XRayPatchingStatus::NOT_INITIALIZED; // Not initialized. |
| 383 | + |
| 384 | + uint8_t NotPatching = false; |
| 385 | + if (!atomic_compare_exchange_strong( |
| 386 | + &XRayPatching, &NotPatching, true, memory_order_acq_rel)) |
| 387 | + return XRayPatchingStatus::ONGOING; // Already patching. |
| 388 | + |
| 389 | + auto XRayPatchingStatusResetter = |
| 390 | + at_scope_exit([] { |
| 391 | + atomic_store(&XRayPatching, false, memory_order_release); |
| 392 | + }); |
| 393 | + |
| 394 | + unsigned NumObjects = __xray_num_objects(); |
| 395 | + |
| 396 | + XRayPatchingStatus CombinedStatus{NOT_INITIALIZED}; |
| 397 | + for (unsigned I = 0; I < NumObjects; ++I) { |
| 398 | + if (!isObjectLoaded(I)) |
| 399 | + continue; |
| 400 | + auto LastStatus = controlPatchingObjectUnchecked(Enable, I); |
| 401 | + switch (LastStatus) { |
| 402 | + case SUCCESS: |
| 403 | + if (CombinedStatus == NOT_INITIALIZED) |
| 404 | + CombinedStatus = SUCCESS; |
| 405 | + break; |
| 406 | + case FAILED: |
| 407 | + // Report failure, but try to patch the remaining objects |
| 408 | + CombinedStatus = FAILED; |
| 409 | + break; |
| 410 | + case NOT_INITIALIZED: |
| 411 | + // XRay has been initialized but there are no sleds available for this |
| 412 | + // object. Try to patch remaining objects. |
| 413 | + if (CombinedStatus != FAILED) |
| 414 | + CombinedStatus = NOT_INITIALIZED; |
| 415 | + break; |
| 416 | + case ONGOING: |
| 417 | + llvm_unreachable("Status ONGOING should not appear at this point"); |
| 418 | + default: |
| 419 | + llvm_unreachable("Unhandled patching status"); |
| 420 | + } |
| 421 | + } |
| 422 | + return CombinedStatus; |
| 423 | +} |
| 424 | + |
| 425 | +// Controls patching for one object. |
| 426 | +XRayPatchingStatus controlPatching(bool Enable, |
| 427 | + int32_t ObjId) XRAY_NEVER_INSTRUMENT { |
| 428 | + |
| 429 | + if (!atomic_load(&XRayInitialized, memory_order_acquire)) |
| 430 | + return XRayPatchingStatus::NOT_INITIALIZED; // Not initialized. |
| 431 | + |
| 432 | + uint8_t NotPatching = false; |
| 433 | + if (!atomic_compare_exchange_strong( |
| 434 | + &XRayPatching, &NotPatching, true, memory_order_acq_rel)) |
| 435 | + return XRayPatchingStatus::ONGOING; // Already patching. |
| 436 | + |
| 437 | + auto XRayPatchingStatusResetter = |
| 438 | + at_scope_exit([] { |
| 439 | + atomic_store(&XRayPatching, false, memory_order_release); |
| 440 | + }); |
| 441 | + |
| 442 | + return controlPatchingObjectUnchecked(Enable, ObjId); |
| 443 | +} |
| 444 | + |
389 | 445 | XRayPatchingStatus mprotectAndPatchFunction(int32_t FuncId, int32_t ObjId,
|
390 | 446 | bool Enable) XRAY_NEVER_INSTRUMENT {
|
391 | 447 | XRaySledMap InstrMap;
|
@@ -420,7 +476,7 @@ XRayPatchingStatus mprotectAndPatchFunction(int32_t FuncId, int32_t ObjId,
|
420 | 476 | return XRayPatchingStatus::FAILED;
|
421 | 477 | }
|
422 | 478 |
|
423 |
| - // Here we compute the minumum sled and maximum sled associated with a |
| 479 | + // Here we compute the minimum sled and maximum sled associated with a |
424 | 480 | // particular function ID.
|
425 | 481 | XRayFunctionSledIndex SledRange;
|
426 | 482 | if (InstrMap.SledsIndex) {
|
@@ -518,57 +574,15 @@ uint16_t __xray_register_event_type(
|
518 | 574 | }
|
519 | 575 |
|
520 | 576 | XRayPatchingStatus __xray_patch() XRAY_NEVER_INSTRUMENT {
|
521 |
| - XRayPatchingStatus CombinedStatus{SUCCESS}; |
522 |
| - for (size_t I = 0; I < __xray_num_objects(); ++I) { |
523 |
| - if (!isObjectLoaded(I)) |
524 |
| - continue; |
525 |
| - auto LastStatus = controlPatching(true, I); |
526 |
| - switch (LastStatus) { |
527 |
| - case FAILED: |
528 |
| - CombinedStatus = FAILED; |
529 |
| - break; |
530 |
| - case NOT_INITIALIZED: |
531 |
| - if (CombinedStatus != FAILED) |
532 |
| - CombinedStatus = NOT_INITIALIZED; |
533 |
| - break; |
534 |
| - case ONGOING: |
535 |
| - if (CombinedStatus != FAILED && CombinedStatus != NOT_INITIALIZED) |
536 |
| - CombinedStatus = ONGOING; |
537 |
| - break; |
538 |
| - default: |
539 |
| - break; |
540 |
| - } |
541 |
| - } |
542 |
| - return CombinedStatus; |
| 577 | + return controlPatching(true); |
543 | 578 | }
|
544 | 579 |
|
545 | 580 | XRayPatchingStatus __xray_patch_object(int32_t ObjId) XRAY_NEVER_INSTRUMENT {
|
546 | 581 | return controlPatching(true, ObjId);
|
547 | 582 | }
|
548 | 583 |
|
549 | 584 | XRayPatchingStatus __xray_unpatch() XRAY_NEVER_INSTRUMENT {
|
550 |
| - XRayPatchingStatus CombinedStatus{SUCCESS}; |
551 |
| - for (size_t I = 0; I < __xray_num_objects(); ++I) { |
552 |
| - if (!isObjectLoaded(I)) |
553 |
| - continue; |
554 |
| - auto LastStatus = controlPatching(false, I); |
555 |
| - switch (LastStatus) { |
556 |
| - case FAILED: |
557 |
| - CombinedStatus = FAILED; |
558 |
| - break; |
559 |
| - case NOT_INITIALIZED: |
560 |
| - if (CombinedStatus != FAILED) |
561 |
| - CombinedStatus = NOT_INITIALIZED; |
562 |
| - break; |
563 |
| - case ONGOING: |
564 |
| - if (CombinedStatus != FAILED && CombinedStatus != NOT_INITIALIZED) |
565 |
| - CombinedStatus = ONGOING; |
566 |
| - break; |
567 |
| - default: |
568 |
| - break; |
569 |
| - } |
570 |
| - } |
571 |
| - return CombinedStatus; |
| 585 | + return controlPatching(false); |
572 | 586 | }
|
573 | 587 |
|
574 | 588 | XRayPatchingStatus __xray_unpatch_object(int32_t ObjId) XRAY_NEVER_INSTRUMENT {
|
|
0 commit comments