ghidra/Ghidra/Features/Base/ghidra_scripts/LinuxSystemMapImportScript....

122 lines
3.5 KiB
Java

/* ###
* 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):
// <tt>
// [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
// </tt>
// /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;
}
}
}