Search code examples
javaarraylistghidra

Java: ArrayList.clear removes elements from ArrayList passed to Map


This is my first time writing Java code in years and I'm working on a Ghidra script that Maps system call symbols to their calling functions.

private HashMap<Symbol, Reference[]> symbolRefs = new HashMap<Symbol, Reference[]>();
private HashMap<Symbol, List<Function>> callerFuncs = new HashMap<Symbol, List<Function>>();

.
.
.

private void mapSysCallToCallerFunctions(FunctionManager funcMan) throws Exception {
    List<Function> funcs = new ArrayList<Function>();
    for(HashMap.Entry<Symbol, Reference[]> entry: this.symbolRefs.entrySet()) {
        for(Reference ref : entry.getValue()) {
            Function caller = funcMan.getFunctionContaining(ref.getFromAddress());
            if(caller != null) {
                funcs.add(caller);
            }
        }
        this.callerFuncs.put(entry.getKey(), funcs);
        funcs.clear();
    }
}

My problem is that I want to clear the "funcs" list, so that I can use the empty list again for the next iteration. This causes the Function List in my HashMap to be empty, too, for some unknown reason. If I print my HashMap here:

private void printCallerSymbolMap() throws Exception {
    for(HashMap.Entry<Symbol, List<Function>> entry: this.callerFuncs.entrySet()) {
        printf("Symbol %s:\n", entry.getKey().toString());
        for(Function func : entry.getValue()) {
            printf("Called by function %s\n", func.getName());
        }
    }
}

I just get the output:

INFO  Symbol system: (GhidraScript)  
INFO  Symbol system: (GhidraScript) 

However, when I remove funcs.clear(), I get:

INFO  Symbol system: (GhidraScript)  
INFO  Called by function system (GhidraScript)  
INFO  Called by function system (GhidraScript)  
INFO  Called by function main (GhidraScript)  
INFO  Symbol system: (GhidraScript)  
INFO  Called by function system (GhidraScript)  
INFO  Called by function system (GhidraScript)  
INFO  Called by function main (GhidraScript)  

It should be like that though:

INFO  Symbol system: (GhidraScript)  
INFO  Called by function system (GhidraScript)  
INFO  Called by function system (GhidraScript)  
INFO  Symbol system: (GhidraScript) 
INFO  Called by function main (GhidraScript)  

I have two system symbols as it is thunked.


Solution

  • Insted of clearing list, initialize the list every time.

    private void mapSysCallToCallerFunctions(FunctionManager funcMan) throws Exception {
        List<Function> funcs;
        for(HashMap.Entry<Symbol, Reference[]> entry: this.symbolRefs.entrySet()) {
            funcs = new ArrayList<Function>();
            for(Reference ref : entry.getValue()) {
                Function caller = funcMan.getFunctionContaining(ref.getFromAddress());
                if(caller != null) {
                    funcs.add(caller);
                }
            }
            this.callerFuncs.put(entry.getKey(), funcs);
        }
    }