/* ### * IP: GHIDRA * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // Apply the information from a System.map file or /proc/ksyms to the listing. // Symbol names are applied. If the symbol type is available, as in the // System.map file, disassembly and function creation are done for text symbols. // The System.map file has the following format (it is generated by nm): // // [address] [type] [name] // -address is a hex value, say c010000 // -type is the type of symbol: `man nm` for them all; T is a function // -name is the name of the symbol // // /proc/ksyms eliminates the middle column, and may add the name of the module // in square brackets at the end of the line. //@category CustomerSubmission.Linux import java.io.*; import ghidra.app.script.GhidraScript; import ghidra.program.model.address.*; import ghidra.program.model.symbol.SourceType; import ghidra.program.model.symbol.SymbolTable; import ghidra.util.exception.InvalidInputException; public class LinuxSystemMapImportScript extends GhidraScript { @Override public void run() throws Exception { File file = askFile("Please specify the System.Map to apply", "Apply"); BufferedReader reader = new BufferedReader(new FileReader(file)); try { readSystemMap(reader); } finally { reader.close(); } } private void readSystemMap(BufferedReader reader) throws IOException { SymbolTable st = currentProgram.getSymbolTable(); AddressSpace addrspace = currentProgram.getAddressFactory().getDefaultAddressSpace(); if (currentSelection != null && !currentSelection.isEmpty()) { addrspace = currentProgram.getAddressFactory().getDefaultAddressSpace(); } int lineno = 0; String line; while (!monitor.isCancelled() && (line = reader.readLine()) != null) { lineno++; line = line.trim(); String address, type, name; String[] tokens = line.split("\\s"); if (tokens.length == 3) { address = tokens[0]; type = tokens[1]; name = tokens[2]; // account for /proc/ksyms output of the type: c0100000 modulesym [module] if (name.matches("^\\[.*]$")) { name = tokens[1] + "__" + tokens[2]; type = ""; } } else if (tokens.length == 2) { address = tokens[0]; type = ""; name = tokens[1]; } else { println("Error parsing line " + lineno + ": \"" + line + "\"."); continue; } Address addr = getAddress(addrspace, address); if (addr == null) { println("Error parsing line " + lineno + ": \"" + line + "\": could not parse address."); continue; } try { st.createLabel(addr, name, SourceType.USER_DEFINED); } catch (InvalidInputException e) { println("Error adding label for line " + lineno + ": \"" + line + "\""); continue; } if (type.equalsIgnoreCase("t")) { // This is a function disassemble(addr); createFunction(addr, name); } } } private Address getAddress(AddressSpace addrspace, String addressString) { try { return addrspace.getAddress("0x" + addressString); } catch (AddressFormatException e) { return null; } } }