0

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.

Melvin
  • 407
  • 5
  • 16

1 Answers1

1

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);
    }
}
jnrdn0011
  • 417
  • 2
  • 13
  • 1
    As an alternative you can also copy the list you're putting in the map: `callerFuncs.put(entry.getKey(), new ArrayList<>(funcs))` to make `clear()` work as you expected. – Emmanuel Chebbi Jun 08 '20 at 16:09