Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ private void printMessage(MessageType type, CharSequence msg, SuppressedBy suppr
private void addSoftTarget(TypeHandle type, String reference) {
ObfuscationData<String> obfClassData = this.obf.getDataProvider().getObfClass(type);
if (!obfClassData.isEmpty()) {
this.obf.getReferenceManager().addClassMapping(this.classRef, reference, obfClassData);
this.obf.getReferenceManager().addMapping(this.classRef, reference, obfClassData);
}

this.addTarget(type);
Expand Down Expand Up @@ -498,6 +498,11 @@ public int getPriority() {
throw new UnsupportedOperationException("Priority not available at compile time");
}

@Override
public boolean isCompileTime() {
return true;
}

@Override
public IAnnotationHandle getAnnotation(Class<? extends Annotation> annotationClass) {
return AnnotationHandle.of(this.mixin, annotationClass);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ private void registerFactoryForTarget(AnnotatedElementInvoker elem, TypeHandle t
}

ObfuscationData<String> obfData = this.obf.getDataProvider().getObfClass(elem.getAnnotationValue().replace('.', '/'));
this.obf.getReferenceManager().addClassMapping(this.mixin.getClassRef(), elem.getAnnotationValue(), obfData);
this.obf.getReferenceManager().addMapping(this.mixin.getClassRef(), elem.getAnnotationValue(), obfData);
}

private String getAccessorTargetName(AnnotatedElementAccessor elem) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@
package org.spongepowered.tools.obfuscation;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
Expand All @@ -41,9 +44,11 @@
import org.spongepowered.asm.mixin.injection.selectors.InvalidSelectorException;
import org.spongepowered.asm.mixin.injection.selectors.TargetSelector;
import org.spongepowered.asm.mixin.injection.struct.InjectionPointData;
import org.spongepowered.asm.mixin.injection.struct.MemberInfo;
import org.spongepowered.asm.mixin.refmap.IMixinContext;
import org.spongepowered.asm.obfuscation.mapping.common.MappingField;
import org.spongepowered.asm.obfuscation.mapping.common.MappingMethod;
import org.spongepowered.asm.util.NameAndDesc;
import org.spongepowered.asm.util.asm.IAnnotationHandle;
import org.spongepowered.tools.obfuscation.ReferenceManager.ReferenceConflictException;
import org.spongepowered.tools.obfuscation.ext.SpecialPackages;
Expand Down Expand Up @@ -195,6 +200,7 @@ public void registerInjector(AnnotatedElementInjector elem) {
private void registerInjectorTarget(AnnotatedElementInjector elem, String reference, ITargetSelector targetSelector, String subject) {
try {
targetSelector.validate();
targetSelector.validateNext();
} catch (InvalidSelectorException ex) {
elem.printMessage(this.ap, MessageType.TARGET_SELECTOR_VALIDATION, ex.getMessage());
}
Expand All @@ -204,88 +210,159 @@ private void registerInjectorTarget(AnnotatedElementInjector elem, String refere
}

ITargetSelectorByName targetMember = (ITargetSelectorByName)targetSelector;
if (targetMember.getName() == null) {
return;
}

if (targetMember.getDesc() != null) {

if (targetMember.getName() != null && targetMember.getDesc() != null) {
this.validateReferencedTarget(elem, reference, targetMember, subject);
}

if (targetSelector instanceof ITargetSelectorRemappable && elem.shouldRemap()) {
for (TypeHandle target : this.mixin.getTargets()) {
if (!this.registerInjector(elem, reference, (ITargetSelectorRemappable)targetMember, target)) {
break;
}
}

if (targetSelector instanceof ITargetSelectorRemappable) {
this.registerInjector(elem, reference, (ITargetSelectorRemappable) targetMember);
}
}

private boolean registerInjector(AnnotatedElementInjector elem, String reference, ITargetSelectorRemappable targetMember, TypeHandle target) {
String desc = target.findDescriptor(targetMember);
if (desc == null) {
MessageType messageType = this.mixin.isMultiTarget() ? MessageType.MISSING_INJECTOR_DESC_MULTITARGET
: MessageType.MISSING_INJECTOR_DESC_SINGLETARGET;
if (target.isSimulated()) {
elem.printMessage(this.ap, MessageType.MISSING_INJECTOR_DESC_SIMULATED, elem + " target '" + reference
+ "' in @Pseudo mixin will not be obfuscated");
} else if (target.isImaginary()) {
elem.printMessage(this.ap, messageType, elem + " target requires method signature because enclosing type information for "
+ target + " is unavailable");
} else if (!targetMember.isInitialiser()) {
elem.printMessage(this.ap, messageType, "Unable to determine descriptor for " + elem + " target method");
}
return true;
}

private void registerInjector(AnnotatedElementInjector elem, String reference, ITargetSelectorRemappable targetMember) {
String targetName = elem + " target " + targetMember.getName();
MappingMethod targetMethod = target.getMappingMethod(targetMember.getName(), desc);
ObfuscationData<MappingMethod> obfData = this.obf.getDataProvider().getObfMethod(targetMethod);
if (obfData.isEmpty()) {
if (target.isSimulated()) {
obfData = this.obf.getDataProvider().getRemappedMethod(targetMethod);
} else if (targetMember.isClassInitialiser()) {
return true;
} else {
elem.addMessage(targetMember.isConstructor() ? MessageType.NO_OBFDATA_FOR_CTOR : MessageType.NO_OBFDATA_FOR_TARGET,
"Unable to locate obfuscation mapping for " + targetName, elem.getElement(), elem.getAnnotation());
return false;
ObfuscationData<String> remapped;
if (elem.shouldRemap() && targetMember.getName() != null) {
remapped = this.remapTarget(elem, reference, targetMember, targetName);
if (remapped == null) {
return;
}
} else {
remapped = new ObfuscationData<>();
}


if (targetMember instanceof MemberInfo) {
// Need to try remapping the nested selectors, even if remap is false
remapped = this.remapMemberInfo((MemberInfo) targetMember, remapped);
} else if (!elem.shouldRemap()) {
return;
}

IReferenceManager refMaps = this.obf.getReferenceManager();
try {
// If the original owner is unspecified, and the mixin is multi-target, we strip the owner from the obf mappings
if ((targetMember.getOwner() == null && this.mixin.isMultiTarget()) || target.isSimulated()) {
obfData = AnnotatedMixinElementHandler.<MappingMethod>stripOwnerData(obfData);
}
refMaps.addMethodMapping(this.classRef, reference, obfData);
refMaps.addMapping(this.classRef, reference, remapped);
} catch (ReferenceConflictException ex) {
String conflictType = this.mixin.isMultiTarget() ? "Multi-target" : "Target";


elem.printMessage(this.ap, MessageType.INJECTOR_MAPPING_CONFLICT, conflictType + " reference conflict for " + targetName + ": "
+ reference + " -> " + ex.getNew() + " previously defined as " + ex.getOld());
}
}

private ObfuscationData<String> remapTarget(AnnotatedElementInjector elem, String reference, ITargetSelectorRemappable targetMember, String targetName) {
ObfuscationData<Set<NameAndDesc>> remapped = new ObfuscationData<>();
for (ObfuscationEnvironment env : this.obf.getEnvironments()) {
remapped.put(env.getType(), new HashSet<>());
}

for (TypeHandle target : this.mixin.getTargets()) {
String desc = target.findDescriptor(targetMember);
if (desc == null) {
MessageType messageType = this.mixin.isMultiTarget() ? MessageType.MISSING_INJECTOR_DESC_MULTITARGET
: MessageType.MISSING_INJECTOR_DESC_SINGLETARGET;
if (target.isSimulated()) {
elem.printMessage(this.ap, MessageType.MISSING_INJECTOR_DESC_SIMULATED, elem + " target '" + reference
+ "' in @Pseudo mixin will not be obfuscated");
} else if (target.isImaginary()) {
elem.printMessage(this.ap, messageType, elem + " target requires method signature because enclosing type information for "
+ target + " is unavailable");
} else if (!targetMember.isInitialiser()) {
elem.printMessage(this.ap, messageType, "Unable to determine descriptor for " + elem + " target method");
}
continue;
}

MappingMethod targetMethod = target.getMappingMethod(targetMember.getName(), desc);
ObfuscationData<MappingMethod> obfData = this.obf.getDataProvider().getObfMethod(targetMethod);
if (obfData.isEmpty()) {
if (target.isSimulated()) {
obfData = this.obf.getDataProvider().getRemappedMethod(targetMethod);
} else if (targetMember.isClassInitialiser()) {
continue;
} else {
elem.addMessage(targetMember.isConstructor() ? MessageType.NO_OBFDATA_FOR_CTOR : MessageType.NO_OBFDATA_FOR_TARGET,
"Unable to locate obfuscation mapping for " + targetName, elem.getElement(), elem.getAnnotation());
return null;
}
}

if ((targetMember.getOwner() == null && this.mixin.isMultiTarget()) || target.isSimulated()) {
obfData = AnnotatedMixinElementHandler.stripOwnerData(obfData);
}

for (ObfuscationEnvironment env : this.obf.getEnvironments()) {
MappingMethod mapping = obfData.get(env.getType());
String name = mapping.getSimpleName();
if (mapping.getOwner() != null) {
name = 'L' + mapping.getOwner() + ';' + name;
}
remapped.get(env.getType()).add(new NameAndDesc(name, mapping.getDesc()));
}
}

ObfuscationData<String> result = new ObfuscationData<>();
for (ObfuscationEnvironment env : this.obf.getEnvironments()) {
Set<NameAndDesc> members = remapped.get(env.getType());
if (members.size() == 1) {
NameAndDesc member = members.iterator().next();
result.put(env.getType(), member.name + member.desc);
continue;
}

if (elem.hasCoerceArgument() && targetMember.getOwner() == null && targetMember.getDesc() == null) {
ITargetSelector oldMember = TargetSelector.parse(ex.getOld(), elem);
ITargetSelector newMember = TargetSelector.parse(ex.getNew(), elem);
String oldName = oldMember instanceof ITargetSelectorByName ? ((ITargetSelectorByName)oldMember).getName() : oldMember.toString();
String newName = newMember instanceof ITargetSelectorByName ? ((ITargetSelectorByName)newMember).getName() : newMember.toString();
if (oldName != null && oldName.equals(newName)) {
obfData = AnnotatedMixinElementHandler.<MappingMethod>stripDescriptors(obfData);
refMaps.setAllowConflicts(true);
refMaps.addMethodMapping(this.classRef, reference, obfData);
refMaps.setAllowConflicts(false);
Set<String> names = members.stream().map(it -> it.name).collect(Collectors.toSet());
if (names.size() == 1) {
String name = names.iterator().next();
result.put(env.getType(), name);

// This is bad because in notch mappings, using the bare target name might cause everything to explode
elem.printMessage(this.ap, MessageType.BARE_REFERENCE, "Coerced " + conflictType + " reference has conflicting descriptors for "
+ targetName + ": Storing bare references " + obfData.values() + " in refMap");
return true;
elem.printMessage(this.ap, MessageType.BARE_REFERENCE, "Coerced Multi-target reference has conflicting descriptors for "
+ targetName + ": Storing bare reference " + name + " in refMap");
}
continue;
}

elem.printMessage(this.ap, MessageType.INJECTOR_MAPPING_CONFLICT, conflictType + " reference conflict for " + targetName + ": "
+ reference + " -> " + ex.getNew() + " previously defined as " + ex.getOld());

elem.printMessage(
this.ap, MessageType.INJECTOR_MAPPING_CONFLICT,
"Multi-target reference conflict for " + targetName + ": " + members
);
}

return true;

return result;
}

private ObfuscationData<String> remapMemberInfo(MemberInfo targetMember, ObfuscationData<String> rootNames) {
MemberInfo next = (MemberInfo) targetMember.next();
if (next == null) {
return rootNames;
}

ObfuscationData<String> result = new ObfuscationData<>();
for (ObfuscationEnvironment env : this.obf.getEnvironments()) {
boolean needsMapping = false;
String rootName = rootNames.get(env.getType());
if (rootName == null) {
rootName = targetMember.headToString();
} else {
needsMapping = true;
}

MemberInfo remappedNext = next.remapNestedUsing(new ObfuscationEnvironmentRemapper(env, this.obf.getDataProvider()));
if (remappedNext == null) {
// No change
remappedNext = next;
} else {
needsMapping = true;
}

if (needsMapping) {
String remapped = rootName + " ->" + targetMember.recurseDepthToString() + ' ' + remappedNext;
result.put(env.getType(), remapped);
}
}

return result;
}

/**
Expand Down Expand Up @@ -357,7 +434,7 @@ protected final void remapNewTarget(String subject, String reference, ITargetSel
}
}

this.obf.getReferenceManager().addClassMapping(this.classRef, reference, mappings);
this.obf.getReferenceManager().addMapping(this.classRef, reference, mappings);
}

elem.notifyRemapped();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,10 @@ public MappingMethod getObfMethod(MappingMethod method, boolean lazyRemap) {
*/
@Override
public ITargetSelectorRemappable remapDescriptor(ITargetSelectorRemappable method) {
if (!this.initMappings()) {
return null;
}

boolean transformed = false;

String owner = method.getOwner();
Expand Down Expand Up @@ -289,6 +293,10 @@ public ITargetSelectorRemappable remapDescriptor(ITargetSelectorRemappable metho
*/
@Override
public String remapDescriptor(String desc) {
if (!this.initMappings()) {
return desc;
}

String newDesc = ObfuscationUtil.mapDescriptor(desc, this.remapper);
return newDesc != null ? newDesc : desc;
}
Expand Down
Loading
Loading