1
0
Fork 0
libbluray/src/libbluray/bdj/java/org/videolan/BDJClassFileTransformer.java

125 lines
4.2 KiB
Java

/*
* This file is part of libbluray
* Copyright (C) 2015 Petri Hintukainen <phintuka@users.sourceforge.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*/
package org.videolan;
/**
* This is a class which is called by BDJClassLoader
* when ClassFormatError is thrown inside defineClass().
*
* Some discs have invalid debug info in class files (broken by
* malfunctioning obfuscater ?).
* We strip debug info from the class and try to load it again.
*
* Penguins of MAdagascar:
* java.lang.ClassFormatError: Invalid index 0 in LocalVariableTable'
* in class file com/tcs/blr/bluray/pal/fox/controller/d
*/
import java.util.Map;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.commons.SimpleRemapper;
import org.objectweb.asm.commons.RemappingClassAdapter;
public class BDJClassFileTransformer
{
public byte[] rename(byte[] b, int off, int len, Map mappings)
throws ClassFormatError
{
byte[] r = new byte[len];
for (int i = 0; i < len; i++)
r[i] = b[i+off];
return rename(r, mappings);
}
public byte[] rename(byte[] b, Map mappings)
throws ClassFormatError
{
logger.info("Trying to rename class (" + b.length + " bytes)");
try {
SimpleRemapper m = new SimpleRemapper(mappings);
ClassReader cr = new ClassReader(b);
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES/* | ClassWriter.COMPUTE_MAXS*/);
ClassVisitor cv = new RemappingClassAdapter(cw, m);
cr.accept(cv, ClassReader.SKIP_DEBUG);
return cw.toByteArray();
} catch (Exception e) {
logger.error("Failed renaming class: " + e);
}
return null;
}
public byte[] strip(byte[] b, int off, int len)
throws ClassFormatError
{
logger.info("Trying to transform broken class file (" + len + " bytes)");
byte[] r = new byte[len];
for (int i = 0; i < len; i++)
r[i] = b[i+off];
try {
ClassReader cr = new ClassReader(r);
ClassWriter cw = new ClassWriter(cr, 0/*ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS*/);
ClassVisitor cv = new MyClassVisitor(cw);
cr.accept(cv, ClassReader.SKIP_DEBUG);
return cw.toByteArray();
} catch (Exception e) {
logger.error("Failed transforming class: " + e);
}
return r;
}
private static class MyClassVisitor extends ClassVisitor {
public MyClassVisitor(ClassVisitor cv) {
super(Opcodes.ASM4, cv);
}
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
//System.err.println("visit method: " + name);
return new MyMethodVisitor(mv);
}
}
private static class MyMethodVisitor extends MethodVisitor {
public MyMethodVisitor(MethodVisitor mv) {
super(Opcodes.ASM4, mv);
}
public void visitAttribute(Attribute attr) {
//System.err.println(" attribute: " + attr.type);
super.visitAttribute(attr);
}
}
private static final Logger logger = Logger.getLogger(BDJClassFileTransformer.class.getName());
}