jpcsp.test.NIDInfo.java Source code

Java tutorial

Introduction

Here is the source code for jpcsp.test.NIDInfo.java

Source

/*
This file is part of jpcsp.
    
Jpcsp is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
Jpcsp 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 General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with Jpcsp.  If not, see <http://www.gnu.org/licenses/>.
 */
package jpcsp.test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import org.jdom2.xpath.XPath;

@SuppressWarnings("deprecation")
class NIDInfo {
    public String prx;
    public String prxName;
    public String libraryName;
    public String functionName;
    public int functionNID;

    public boolean resolved;
    public String firmwareVersion;

    public NIDInfo(int nid) {
        functionNID = nid;
        resolved = false;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("prx=" + prx + " ");
        sb.append("prxName=" + prxName + " ");
        sb.append("libraryName=" + libraryName + " ");
        sb.append("functionName=" + functionName + " ");
        sb.append("functionNID=" + String.format("0x%08X", functionNID));
        return sb.toString();
    }
}

class Module {

    private final String m_name;
    private Hashtable<String, String> m_functions;

    public Module(String name) {
        m_name = new String(name);
        m_functions = new Hashtable<String, String>();
    }

    public String getName() {
        return m_name;
    }

    public String getFunctionFromModule(String nid) {
        try {
            return m_functions.get(nid);
        } catch (NullPointerException dummy) {
            return null;
        }
    }

    public int countFunctions() {
        return m_functions.size();
    }

    public void addFunction(String nid, String name) {
        //System.out.println(nid + "/" + name);
        m_functions.put(nid, name);
    }
}

class Firmware {
    private String m_version;
    private int m_moduleCount;
    private int m_functionCount;
    private Hashtable<String, Module> m_moduleTable;

    // psplibdoc parser based on hlide's FunctionLibrary.java
    @SuppressWarnings("deprecation")
    public Firmware(String version, String psplibdoc_filename) throws Exception {
        m_version = version;
        m_moduleCount = 0;
        m_functionCount = 0;
        m_moduleTable = new Hashtable<String, Module>();

        SAXBuilder builder = new SAXBuilder();
        Document doc = builder.build(new File(psplibdoc_filename));

        XPath modules = XPath.newInstance("/PSPLIBDOC/PRXFILES/PRXFILE/LIBRARIES/LIBRARY");

        List<?> LibList = modules.selectNodes(doc);
        //m_moduleList = modules.selectNodes(doc, "//NAME");

        Iterator<?> i = LibList.iterator();

        while (i.hasNext()) {
            Element curEl = (Element) i.next();
            String modName = curEl.getChild("NAME").getText();
            Module newMod = new Module(modName);
            List<?> FunctionList = curEl.getChild("FUNCTIONS").getChildren("FUNCTION");
            Iterator<?> j = FunctionList.iterator();
            while (j.hasNext()) {
                Element funcEl = (Element) j.next();
                newMod.addFunction(funcEl.getChild("NID").getText(), funcEl.getChild("NAME").getText());
                m_functionCount++;
            }
            m_moduleCount++;
            m_moduleTable.put(modName, newMod);
        }

        System.out.println("filename: " + psplibdoc_filename + " modules: " + m_moduleCount + " functions: "
                + m_functionCount);
    }

    public String getVersion() {
        return m_version;
    }

    public int getModuleCount() {
        return m_moduleCount;
    }

    public int getFunctionCount() {
        return m_functionCount;
    }

    /** @return true if resolved */
    public boolean resolveNID(NIDInfo info) {
        for (Module module : m_moduleTable.values()) {
            String functionName = module.getFunctionFromModule(String.format("0x%08X", info.functionNID));
            if (functionName != null) {
                info.functionName = functionName;
                info.libraryName = module.getName();
                if (!info.resolved) {
                    info.firmwareVersion = m_version;
                }
                info.resolved = true;
                return true;
            }
        }
        return false;
    }
}

public class ResolveUnmappedNIDs {

    public static HashMap<Integer, NIDInfo> parseLog(String filename) {
        LinkedHashMap<Integer, NIDInfo> nids = new LinkedHashMap<Integer, NIDInfo>();

        try {
            FileReader fr = new FileReader(filename);
            BufferedReader br = new BufferedReader(fr);
            String line;

            while ((line = br.readLine()) != null) {
                String[] parts = line.split(" ");
                for (int i = 10; i < parts.length; i++) {
                    if (parts[i].startsWith("[0x")) {
                        try {
                            int nid = (int) Long.parseLong(parts[i].substring(3, 11), 16);
                            NIDInfo info = new NIDInfo(nid);
                            nids.put(nid, info);
                        } catch (Exception e) {
                            //System.err.println(e.getMessage());
                            //System.err.println("error near '" + parts[i] + "'");
                        }
                        break;
                    }
                }
            }

            br.close();
            fr.close();
        } catch (FileNotFoundException e) {
            System.err.println("parseLog: File not found: " + filename);
        } catch (Exception e) {
            System.err.println("parseLog: " + filename);
            e.printStackTrace();
        }

        return nids;
    }

    public static void processNIDs(LinkedList<Firmware> firmware, HashMap<Integer, NIDInfo> nids) {
        for (NIDInfo info : nids.values()) {
            for (Firmware fw : firmware) {
                fw.resolveNID(info);
                // keep resolving in newer fw, since later libdoc have nids decoded to function names
                //if (found)
                //    break;
            }
        }
    }

    public static void printResults(HashMap<Integer, NIDInfo> nids, int syscallCode) {
        for (NIDInfo info : nids.values()) {
            //System.out.println(info);

            // sample:
            // sceUmdReplaceProhibit(0x3007, 0x87533940), // 2.00+
            String functionName = (info.functionName == null) ? String.format("unknown_%08X", info.functionNID)
                    : info.functionName;
            String firmwareVersion = (info.firmwareVersion == null) ? "" : " // " + info.firmwareVersion + "+";
            String msg = String.format("%s(0x%04x, 0x%08X),%s", functionName, syscallCode++, info.functionNID,
                    firmwareVersion);
            System.out.println(msg);
        }
    }

    public static void main(String[] args) {
        if (args.length < 1) {
            System.err.println("parameters: <logfile> [syscallCodeStart]");
            System.err.println("example: fragment.txt 0x3000");
            System.exit(1);
        }

        // Load psplibdocs
        String prefixPath = "psplibdoc/";
        LinkedList<Firmware> firmware = new LinkedList<Firmware>();

        try {
            firmware.add(new Firmware("1.00", prefixPath + "100_psplibdoc_230808.xml"));
            firmware.add(new Firmware("1.50", prefixPath + "150_psplibdoc_190808.xml"));
            firmware.add(new Firmware("2.00", prefixPath + "200_psplibdoc_260808.xml"));
            firmware.add(new Firmware("2.50", prefixPath + "250_psplibdoc_270808.xml"));
            firmware.add(new Firmware("2.71", prefixPath + "271_psplibdoc_280808.xml"));
            firmware.add(new Firmware("3.52", prefixPath + "352_psplibdoc_190808.xml"));
            firmware.add(new Firmware("3.95", prefixPath + "395_psplibdoc_020508.xml"));
            firmware.add(new Firmware("4.05", prefixPath + "405_psplibdoc_190808.xml"));
            firmware.add(new Firmware("5.00", prefixPath + "500_psplibdoc_191008.xml"));
        } catch (Exception e) {
            e.printStackTrace();
        }

        // Load log file fragment
        HashMap<Integer, NIDInfo> nids = parseLog(args[0]);

        // Resolve nids
        processNIDs(firmware, nids);

        // Output
        int syscallCode = 0x3000;
        if (args.length >= 2) {
            try {
                syscallCode = Integer.parseInt(args[1], 16);
            } catch (Exception e) {
                System.err.println("bad syscall parameter, defaulting to 0x3000");
            }
        }
        printResults(nids, syscallCode);
    }
}