in internal/r8/deobfuscator.go [93:161]
func resolveMappings(types map[string]StacktraceType, mapReader io.Reader) error {
scanner := bufio.NewScanner(mapReader)
var currentType *StacktraceType
for scanner.Scan() {
line := scanner.Text()
typeMatch := typePattern.FindStringSubmatch(line)
if typeMatch != nil {
// Found a class declaration within the map.
obfuscatedName := typeMatch[2]
stacktraceType, ok := types[obfuscatedName]
if ok {
// The class found is also in the stacktrace.
currentType = &stacktraceType
for _, frames := range stacktraceType.methods {
for _, frame := range frames {
if frame.Original == nil {
frame.Original = &modelpb.Original{}
}
// Multiple frames might point to the same class, so we need to deobfuscate the class name for them all.
frame.Original.Classname = obfuscatedName
frame.Classname = typeMatch[1]
frame.SourcemapUpdated = true
}
}
} else {
// The class found is not part of the stacktrace. We need to clear the current type to avoid looping
// through this class' methods, as R8 maps list the classes' methods right below the class definition.
currentType = nil
}
} else if currentType != nil {
// We found a class in the map that is also in the stacktrace, so we enter here to loop through its methods.
methodMatch := methodPattern.FindStringSubmatch(line)
if methodMatch != nil {
// We found a method definition.
sourceFileStart := methodMatch[1]
sourceFileEnd := methodMatch[2]
methodObfuscatedName := methodMatch[4]
methodRealName := methodMatch[3]
methodKey := methodObfuscatedName
if sourceFileStart != "" && sourceFileStart == sourceFileEnd {
// This method might be compressed, in other words, its deobfuscated form might have multiple lines.
methodKey += ":" + sourceFileStart
}
frames, ok := currentType.methods[methodKey]
if ok {
// We found this method in the stacktrace too. Since a method might be referenced multiple times
// in a single stacktrace, we must make sure to deobfuscate them all.
for _, frame := range frames {
if frame.Original.Function == "" {
frame.Original.Function = methodObfuscatedName
frame.Function = methodRealName
} else {
// If it enters here, it means that this method is compressed and its first line was set
// previously, so now we have to append extra lines to it.
frame.Function += "\n" + methodRealName
}
}
}
}
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}