Skip to content

Commit

Permalink
Handle cases with multiple matching obf targets
Browse files Browse the repository at this point in the history
  • Loading branch information
Su5eD committed May 25, 2024
1 parent ebbaa8f commit d4d30fd
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 18 deletions.
45 changes: 27 additions & 18 deletions src/main/java/org/cadixdev/mercury/mixin/MixinRemapperVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,7 @@
package org.cadixdev.mercury.mixin;

import static org.cadixdev.mercury.mixin.annotation.AccessorType.FIELD_GETTER;
import static org.cadixdev.mercury.mixin.util.MixinConstants.ACCESSOR_CLASS;
import static org.cadixdev.mercury.mixin.util.MixinConstants.INJECT_CLASS;
import static org.cadixdev.mercury.mixin.util.MixinConstants.MODIFY_ARG_CLASS;
import static org.cadixdev.mercury.mixin.util.MixinConstants.MODIFY_EXPRESSION_VALUE;
import static org.cadixdev.mercury.mixin.util.MixinConstants.WRAP_OPERATION_VALUE;
import static org.cadixdev.mercury.mixin.util.MixinConstants.INVOKER_CLASS;
import static org.cadixdev.mercury.mixin.util.MixinConstants.MODIFY_CONSTANT_CLASS;
import static org.cadixdev.mercury.mixin.util.MixinConstants.MODIFY_VARIABLE_CLASS;
import static org.cadixdev.mercury.mixin.util.MixinConstants.OVERWRITE_CLASS;
import static org.cadixdev.mercury.mixin.util.MixinConstants.REDIRECT_CLASS;
import static org.cadixdev.mercury.mixin.util.MixinConstants.SHADOW_CLASS;
import static org.cadixdev.mercury.mixin.util.MixinConstants.*;
import static org.cadixdev.mercury.util.BombeBindings.convertType;

import org.cadixdev.bombe.analysis.InheritanceProvider;
Expand All @@ -39,6 +29,7 @@
import org.cadixdev.mercury.mixin.annotation.MixinClass;
import org.cadixdev.mercury.mixin.annotation.ShadowData;
import org.cadixdev.mercury.mixin.annotation.SliceData;
import org.cadixdev.mercury.mixin.util.MixinConstants;
import org.cadixdev.mercury.util.BombeBindings;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTVisitor;
Expand All @@ -64,6 +55,7 @@
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

public class MixinRemapperVisitor extends ASTVisitor {

Expand Down Expand Up @@ -323,7 +315,7 @@ public boolean visit(final MethodDeclaration node) {
final String[] injectTargets = new String[inject.getInjectTargets().length];
for (int j = 0; j < inject.getInjectTargets().length; j++) {
final InjectTarget injectTarget = inject.getInjectTargets()[j];
injectTargets[j] = remapInjectTarget(target, injectTarget);
injectTargets[j] = remapInjectTarget(target, injectTarget, binding);
}

final NormalAnnotation originalAnnotation = (NormalAnnotation) node.modifiers().get(i);
Expand Down Expand Up @@ -403,7 +395,7 @@ else if (pair.getValue() instanceof NormalAnnotation) {
return true;
}

private String remapInjectTarget(final ClassMapping<?, ?> target, final InjectTarget injectTarget) {
private String remapInjectTarget(final ClassMapping<?, ?> target, final InjectTarget injectTarget, final IMethodBinding binding) {
final String targetName = injectTarget.getTargetName();

if (injectTarget.getFieldType().isPresent()) {
Expand Down Expand Up @@ -432,12 +424,22 @@ private String remapInjectTarget(final ClassMapping<?, ?> target, final InjectTa
}
}
else {
// Handle cases where there are multiple matching obfuscated methods and only one valid deobfuscated target
MethodDescriptor methodDescriptor = injectTarget.getMethodDescriptor().orElse(null);
if (methodDescriptor == null && binding != null && shouldCalculateDescriptor(target, targetName)) {
List<ITypeBinding> parameters = List.of(binding.getParameterTypes());
int ciIndex = parameters.stream().filter(t -> CALLBACK_TYPES.contains(t.getBinaryName())).findFirst().map(parameters::indexOf).orElse(-1);
if (ciIndex != -1) {
ITypeBinding reuturnType = parameters.get(ciIndex);
String methodParams = parameters.subList(0, ciIndex).stream().map(MixinRemapperVisitor::getTypeDescriptor).collect(Collectors.joining(""));
String returnTypeDesc = reuturnType.getBinaryName().equals(CALLBACK_INFO) ? "V" : getTypeDescriptor(reuturnType.getTypeParameters()[0]);
methodDescriptor = MethodDescriptor.of("(" + methodParams + ")" + returnTypeDesc);
}
}

// this is probably targeting a method
for (final MethodMapping mapping : target.getMethodMappings()) {
if (Objects.equals(targetName, mapping.getObfuscatedName()) &&
injectTarget.getMethodDescriptor()
.map(d -> d.equals(mapping.getDescriptor()))
.orElse(true)) {
if (Objects.equals(targetName, mapping.getObfuscatedName()) && (methodDescriptor == null || methodDescriptor.equals(mapping.getDescriptor()))) {
final MethodSignature deobfuscatedSignature = mapping.getDeobfuscatedSignature();

return shouldIncludeDescriptor(target, mapping, injectTarget.getMethodDescriptor()) ?
Expand Down Expand Up @@ -470,6 +472,10 @@ private boolean shouldIncludeDescriptor(ClassMapping<?, ?> target, MethodMapping
&& target.getMethodMappings().stream().map(Mapping::getObfuscatedName).filter(mapping.getObfuscatedName()::equals).count() == 1;
}

private boolean shouldCalculateDescriptor(ClassMapping<?, ?> target, String targetName) {
return target.getMethodMappings().stream().filter(m -> Objects.equals(targetName, m.getObfuscatedName())).count() > 1;
}

private void remapSliceAnnotation(final AST ast, final ITypeBinding declaringClass, final NormalAnnotation atAnnotation,
final SliceData sliceDatum) {
for (final Object raw : atAnnotation.values()) {
Expand Down Expand Up @@ -508,7 +514,7 @@ private void remapAtAnnotation(final AST ast, final ITypeBinding declaringClass,

if (atDatum.getTarget().isPresent()) {
final InjectTarget atTarget = atDatum.getTarget().get();
final String newTarget = remapInjectTarget(atTargetMappings, atTarget);
final String newTarget = remapInjectTarget(atTargetMappings, atTarget, null);
String deobfTarget = "L" + deobfTargetClass + ";" + newTarget;
replaceExpression(ast, this.context, originalTarget, deobfTarget);
}
Expand Down Expand Up @@ -592,4 +598,7 @@ private static MethodSignature convertSignature(final String name, final IMethod
return new MethodSignature(name, new MethodDescriptor(parameters, convertType(binding.getReturnType())));
}

private static String getTypeDescriptor(ITypeBinding binding) {
return binding.isPrimitive() ? binding.getBinaryName() : "L" + binding.getBinaryName().replace('.', '/') + ";";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

package org.cadixdev.mercury.mixin.util;

import java.util.Set;

public final class MixinConstants {

public static final String MIXIN_PACKAGE = "org.spongepowered.asm.mixin";
Expand Down Expand Up @@ -36,6 +38,10 @@ public final class MixinConstants {
public static final String MODIFY_EXPRESSION_VALUE = EXTRAS_INJECTION_PACKAGE + ".ModifyExpressionValue";
public static final String WRAP_OPERATION_VALUE = EXTRAS_INJECTION_PACKAGE + ".wrapoperation.WrapOperation";

public static final String CALLBACK_INFO = INJECTION_PACKAGE + ".callback.CallbackInfo";
public static final String CALLBACK_INFO_RETURNABLE = INJECTION_PACKAGE + ".callback.CallbackInfoReturnable";
public static final Set<String> CALLBACK_TYPES = Set.of(CALLBACK_INFO, CALLBACK_INFO_RETURNABLE);

private MixinConstants() {
}

Expand Down

0 comments on commit d4d30fd

Please sign in to comment.