| 539 | } |
| 540 | |
| 541 | void VMethodInterposeLinkBase::remove() |
| 542 | { |
| 543 | if (!is_applied()) |
| 544 | return; |
| 545 | |
| 546 | // Remove the link from prev to this |
| 547 | if (prev) |
| 548 | { |
| 549 | if (prev->host == host) |
| 550 | prev->next = next; |
| 551 | else |
| 552 | { |
| 553 | prev->child_next.erase(this); |
| 554 | |
| 555 | if (next) |
| 556 | prev->child_next.insert(next); |
| 557 | else |
| 558 | prev->child_hosts.insert(host); |
| 559 | } |
| 560 | } |
| 561 | |
| 562 | if (next) |
| 563 | { |
| 564 | next->set_chain(saved_chain); |
| 565 | next->prev = prev; |
| 566 | |
| 567 | assert(child_next.empty() && child_hosts.empty()); |
| 568 | } |
| 569 | else |
| 570 | { |
| 571 | MemoryPatcher patcher; |
| 572 | |
| 573 | // Remove from the list in the identity and vtable |
| 574 | host->set_interpose(vmethod_idx, prev); |
| 575 | host->set_vmethod_ptr(patcher, vmethod_idx, saved_chain); |
| 576 | |
| 577 | for (auto it = child_next.begin(); it != child_next.end(); ++it) |
| 578 | { |
| 579 | auto nlink = *it; |
| 580 | assert(nlink->saved_chain == interpose_method && nlink->prev == this); |
| 581 | nlink->set_chain(saved_chain); |
| 582 | nlink->prev = prev; |
| 583 | if (prev) |
| 584 | prev->child_next.insert(nlink); |
| 585 | } |
| 586 | |
| 587 | for (auto it = child_hosts.begin(); it != child_hosts.end(); ++it) |
| 588 | { |
| 589 | auto nhost = *it; |
| 590 | assert(nhost->get_interpose(vmethod_idx) == this); // acceptable due to assign below |
| 591 | nhost->set_interpose(vmethod_idx,prev); |
| 592 | nhost->set_vmethod_ptr(patcher, vmethod_idx, saved_chain); |
| 593 | if (prev) |
| 594 | prev->child_hosts.insert(nhost); |
| 595 | } |
| 596 | } |
| 597 | |
| 598 | applied = false; |
nothing calls this directly
no test coverage detected