mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-28 17:11:11 -09:00
Candidate release of source code.
This commit is contained in:
1
Ghidra/Features/GnuDemangler/Module.manifest
Normal file
1
Ghidra/Features/GnuDemangler/Module.manifest
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
7
Ghidra/Features/GnuDemangler/build.gradle
Normal file
7
Ghidra/Features/GnuDemangler/build.gradle
Normal file
@@ -0,0 +1,7 @@
|
||||
apply plugin: 'eclipse'
|
||||
eclipse.project.name = 'Features GnuDemangler'
|
||||
apply from: "$rootProject.projectDir/gradleScripts/ghidraScripts.gradle"
|
||||
|
||||
dependencies {
|
||||
compile project(":Base")
|
||||
}
|
||||
9
Ghidra/Features/GnuDemangler/certification.manifest
Normal file
9
Ghidra/Features/GnuDemangler/certification.manifest
Normal file
@@ -0,0 +1,9 @@
|
||||
##VERSION: 2.0
|
||||
##MODULE IP: BSD
|
||||
.classpath||GHIDRA||||END|
|
||||
.project||GHIDRA||||END|
|
||||
Module.manifest||GHIDRA||||END|
|
||||
build.gradle||GHIDRA||||END|
|
||||
src/test/resources/ghidra/app/util/demangler/gnu_mangled_names.txt||GHIDRA||reviewed||END|
|
||||
src/test/resources/ghidra/app/util/demangler/gnu_mangled_names_macho.txt||GHIDRA||reviewed||END|
|
||||
src/test/resources/ghidra/app/util/demangler/libMagick.symbols.txt||GHIDRA||reviewed||END|
|
||||
@@ -0,0 +1,128 @@
|
||||
/* ###
|
||||
* 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.
|
||||
*/
|
||||
// An exemplar script that allows the user to pass options to the Gnu Demangler. One such
|
||||
// option is the '-s arm' option which is hard coded into the script to show how it is done.
|
||||
// See binutils' c++filt for more information on supported options.
|
||||
|
||||
//
|
||||
//@category Examples.Demangler
|
||||
import java.io.*;
|
||||
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.app.util.demangler.DemangledObject;
|
||||
import ghidra.app.util.demangler.DemanglerOptions;
|
||||
import ghidra.app.util.demangler.gnu.GnuDemanglerParser;
|
||||
import ghidra.app.util.opinion.ElfLoader;
|
||||
import ghidra.app.util.opinion.MachoLoader;
|
||||
import ghidra.framework.*;
|
||||
import ghidra.program.model.lang.CompilerSpec;
|
||||
import ghidra.program.model.symbol.Symbol;
|
||||
|
||||
public class DemangleElfWithOptionScript extends GhidraScript {
|
||||
|
||||
@Override
|
||||
protected void run() throws Exception {
|
||||
|
||||
String executableFormat = currentProgram.getExecutableFormat();
|
||||
if (!canDemangle(executableFormat)) {
|
||||
println("Cannot use the elf demangling options for executable format: " +
|
||||
executableFormat);
|
||||
return;
|
||||
}
|
||||
|
||||
Symbol symbol = null;
|
||||
if (currentAddress != null && (currentSelection == null || currentSelection.isEmpty())) {
|
||||
symbol = getSymbolAt(currentAddress);
|
||||
}
|
||||
if (symbol == null) {
|
||||
println("No symbol at the current address (selections are not supported)");
|
||||
return;
|
||||
}
|
||||
|
||||
String mangled = symbol.getName();
|
||||
|
||||
Process process = createProcess(executableFormat);
|
||||
|
||||
InputStream in = process.getInputStream();
|
||||
OutputStream out = process.getOutputStream();
|
||||
|
||||
BufferedReader input = new BufferedReader(new InputStreamReader(in));
|
||||
PrintWriter output = new PrintWriter(out);
|
||||
|
||||
output.println(mangled);
|
||||
output.flush();
|
||||
String demangled = input.readLine();
|
||||
println("demangled: " + demangled);
|
||||
|
||||
GnuDemanglerParser parser = new GnuDemanglerParser(null);
|
||||
DemangledObject demangledObject = parser.parse(mangled, demangled);
|
||||
if (demangledObject == null) {
|
||||
println("Could not demangle: " + mangled);
|
||||
return;
|
||||
}
|
||||
|
||||
DemanglerOptions options = new DemanglerOptions();
|
||||
options.setDoDisassembly(false);
|
||||
options.setApplySignature(true);
|
||||
options.setDemangleOnlyKnownPatterns(true);
|
||||
|
||||
if (!demangledObject.applyTo(currentProgram, currentAddress, options, monitor)) {
|
||||
println("Failed to apply demangled data for " + mangled);
|
||||
}
|
||||
println("Succesfully demangled " + mangled + " to " + demangled);
|
||||
}
|
||||
|
||||
private boolean canDemangle(String executableFormat) {
|
||||
|
||||
//check if language is GCC - this is not altogether correct !
|
||||
// Objective-C and other non-GCC based symbols may be handled improperly
|
||||
|
||||
if (isELF(executableFormat) || isMacho(executableFormat)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
CompilerSpec compilerSpec = currentProgram.getCompilerSpec();
|
||||
if (compilerSpec.getCompilerSpecID().getIdAsString().toLowerCase().indexOf("windows") == -1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isELF(String executableFormat) {
|
||||
return executableFormat != null && executableFormat.indexOf(ElfLoader.ELF_NAME) != -1;
|
||||
}
|
||||
|
||||
private boolean isMacho(String executableFormat) {
|
||||
return executableFormat != null && executableFormat.indexOf(MachoLoader.MACH_O_NAME) != -1;
|
||||
}
|
||||
|
||||
private Process createProcess(String executableName) throws Exception {
|
||||
|
||||
OperatingSystem OS = Platform.CURRENT_PLATFORM.getOperatingSystem();
|
||||
String demanglerExe =
|
||||
(OS == OperatingSystem.WINDOWS) ? "demangler_gnu.exe" : "demangler_gnu";
|
||||
File commandPath = Application.getOSFile("GnuDemangler", demanglerExe);
|
||||
|
||||
//
|
||||
// This is where special options are to be passed. Put your own here as necessary.
|
||||
//
|
||||
String[] command = new String[] { commandPath.getAbsolutePath(), "-s", "arm" };
|
||||
|
||||
Process process = Runtime.getRuntime().exec(command);
|
||||
|
||||
return process;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
/* ###
|
||||
* 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.
|
||||
*/
|
||||
// VxWorksSymTab_5_4 is a copy of VxWorksSymTab_6_1 with a different value for SYM_ENTRY_SIZE
|
||||
// It was replaced at the request of a customer who tested that it worked with the slight modification
|
||||
// VxWorksSymTab_6_1 is an adaptation of the vxWorksSymTab script. It was modified by a customer
|
||||
// to use a single loop, instead of two. It also added demangling of C++ symbol names - at least
|
||||
// those that Ghidra knows how to demangle.
|
||||
//
|
||||
// Extracts all symbols in a VxWorks symbol table and disassembles
|
||||
// the global functions. Any existing symbols in the Ghidra symbol table
|
||||
// that collide with symbols defined in the VxWorks symbol table are deleted.
|
||||
//
|
||||
// The VxWorks symbol table is an array of symbol table entries [0..n-1]
|
||||
// followed by a 32-bit value that is equal to n (number of sym tbl entries).
|
||||
// Each entry in the array has the following structure:
|
||||
//
|
||||
// // Total size: 0x18 (24) bytes
|
||||
// 0x00 int NULL
|
||||
// 0x04 char *symNameAddr // symbol name
|
||||
// 0x08 void *symLocAddr // location of object named by symbol
|
||||
// 0x0c int NULL
|
||||
// 0x10 int NULL
|
||||
// 0x14 uchar symType // see switch statement below
|
||||
// 0x15 uchar fill[3]
|
||||
//
|
||||
// The script requests:
|
||||
// - Output file name: Each symbol name and address is recorded here.
|
||||
// (Errors are also logged to this file.)
|
||||
// - Address of "number of symbols" value: At the end of the symbol table,
|
||||
// its length is recorded as a 32-bit integer. The
|
||||
// script needs the address of that value to calculate
|
||||
// the symbol table's start address.
|
||||
//
|
||||
// @category CustomerSubmission.vxWorks
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import ghidra.app.cmd.label.DemanglerCmd;
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.app.util.demangler.DemangledException;
|
||||
import ghidra.app.util.demangler.gnu.GnuDemangler;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.symbol.*;
|
||||
|
||||
public class VxWorksSymTab_5_4 extends GhidraScript {
|
||||
|
||||
static final int SYM_ENTRY_SIZE = 16;
|
||||
static final int SYM_NAME_OFF = 4;
|
||||
static final int SYM_LOC_OFF = 8;
|
||||
static final int SYM_TYPE_OFF = 0x14;
|
||||
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
|
||||
// Get Memory and SymbolTable objects (used later)
|
||||
Memory mem = currentProgram.getMemory();
|
||||
SymbolTable ghidraSymTbl = currentProgram.getSymbolTable();
|
||||
|
||||
// Open output file
|
||||
// All symbols found (address and name) will be logged to this file
|
||||
try (PrintWriter output =
|
||||
new PrintWriter(new FileOutputStream(askFile("vxWorks Symbol Table Parser",
|
||||
"Output file name?")))) {
|
||||
|
||||
// Get address of "total number of sym tbl entries" value
|
||||
Address vxNumSymEntriesAddr =
|
||||
askAddress("vxWorks Symbol Table Parser",
|
||||
"Address of \"total number of symbol table entries\" value?");
|
||||
int vxNumSymEntries = mem.getInt(vxNumSymEntriesAddr);
|
||||
println("VxWorks symbol table has " + vxNumSymEntries + " entries");
|
||||
|
||||
// Create a GNU demangler instance
|
||||
GnuDemangler demangler = new GnuDemangler();
|
||||
if (!demangler.canDemangle(currentProgram)) {
|
||||
println("Unable to create demangler.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Process entries in VxWorks symbol table
|
||||
Address vxSymTbl = vxNumSymEntriesAddr.subtract(vxNumSymEntries * SYM_ENTRY_SIZE);
|
||||
for (int i = 0; i < vxNumSymEntries; i++) {
|
||||
|
||||
if (monitor.isCancelled())
|
||||
return; // check for cancel button
|
||||
println("i=" + i); // visual counter
|
||||
|
||||
// Extract symbol table entry values
|
||||
Address symEntry = vxSymTbl.add(i * SYM_ENTRY_SIZE);
|
||||
Address symNameAddr = toAddr(mem.getInt(symEntry.add(SYM_NAME_OFF)));
|
||||
Address symLocAddr = toAddr(mem.getInt(symEntry.add(SYM_LOC_OFF)));
|
||||
byte symType = mem.getByte(symEntry.add(SYM_TYPE_OFF));
|
||||
println("symNameAddr: 0x" + symNameAddr.toString() + ", symLocAddr: 0x" +
|
||||
symLocAddr.toString() + ", symType: " + symType);
|
||||
|
||||
// Remove any data or instructions that overlap this symName
|
||||
// (May happen if disassembly creates invalid references)
|
||||
Address a;
|
||||
String symName;
|
||||
for (a = symNameAddr; mem.getByte(a) != 0; a = a.add(1)) {
|
||||
if (getDataAt(a) != null)
|
||||
removeDataAt(a);
|
||||
if (getInstructionAt(a) != null)
|
||||
removeInstructionAt(a);
|
||||
}
|
||||
if (getDataAt(a) != null)
|
||||
removeDataAt(a);
|
||||
if (getInstructionAt(a) != null)
|
||||
removeInstructionAt(a);
|
||||
|
||||
// Turn *symNameAddr into a string and store it in symName
|
||||
try {
|
||||
symName = (String) createAsciiString(symNameAddr).getValue();
|
||||
}
|
||||
catch (Exception e) {
|
||||
println("createAsciiString: caught exception...");
|
||||
println(e.getMessage());
|
||||
return;
|
||||
}
|
||||
println("symName: " + symName);
|
||||
|
||||
// Demangle symName
|
||||
String symDemangledName = null;
|
||||
try {
|
||||
// if successful, symDemangledName will be non-NULL
|
||||
symDemangledName = demangler.demangle(symName, true).getSignature(false);
|
||||
}
|
||||
catch (DemangledException e) {
|
||||
// if symName wasn't a mangled name, silently continue
|
||||
if (!e.isInvalidMangledName()) {
|
||||
println("demangle: Demangling error");
|
||||
output.println("demangle: Demangling error");
|
||||
}
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
println("demangle: Caught runtime exception");
|
||||
output.println("demangle: Caught runtime exception");
|
||||
}
|
||||
if (symDemangledName != null) {
|
||||
println("symDemangledName: " + symDemangledName);
|
||||
}
|
||||
|
||||
// Delete any symbol in the Ghidra symbol table with the same name
|
||||
SymbolIterator syms = ghidraSymTbl.getSymbols(symName);
|
||||
Symbol sym;
|
||||
while (syms.hasNext()) {
|
||||
sym = syms.next();
|
||||
println("Deleting matching Ghidra symbol: " + sym.getName());
|
||||
ghidraSymTbl.removeSymbolSpecial(sym);
|
||||
}
|
||||
|
||||
// Delete any symbol in the Ghidra symbol table at the same address
|
||||
if ((sym = getSymbolAt(symLocAddr)) != null) {
|
||||
println("Deleting symbol at target address: " + sym.getName());
|
||||
ghidraSymTbl.removeSymbolSpecial(sym);
|
||||
}
|
||||
|
||||
switch (symType) {
|
||||
case 0: // Undefined Symbol
|
||||
println("NULL symType!");
|
||||
break;
|
||||
case 2: // Local Absolute
|
||||
case 3: // Global Absolute
|
||||
case 6: // Local Data
|
||||
case 7: // Global Data
|
||||
case 8: // Local BSS
|
||||
case 9: // Global BSS
|
||||
// Data: log the symbol & create a Ghidra symbol at symLocAddr
|
||||
output.println(symLocAddr.toString() + "\t" + symName);
|
||||
createLabel(symLocAddr, symName, true);
|
||||
if (symDemangledName != null) {
|
||||
new DemanglerCmd(symLocAddr, symName).applyTo(currentProgram, monitor);
|
||||
ghidraSymTbl.removeSymbolSpecial(getSymbol(symName,
|
||||
currentProgram.getGlobalNamespace()));
|
||||
}
|
||||
break;
|
||||
case 4: // Local .text
|
||||
case 5: // Global .text
|
||||
// Code: log the symbol, disassemble, & create/name function
|
||||
output.println(symLocAddr.toString() + "\t" + symName);
|
||||
goTo(symLocAddr);
|
||||
disassemble(symLocAddr);
|
||||
createFunction(symLocAddr, symName);
|
||||
if (getFunctionAt(symLocAddr) != null) {
|
||||
getFunctionAt(symLocAddr).setName(symName, SourceType.USER_DEFINED);
|
||||
if (symDemangledName != null) {
|
||||
new DemanglerCmd(symLocAddr, symName).applyTo(currentProgram,
|
||||
monitor);
|
||||
ghidraSymTbl.removeSymbolSpecial(getSymbol(symName,
|
||||
currentProgram.getGlobalNamespace()));
|
||||
}
|
||||
}
|
||||
else {
|
||||
println("createFunction: Failed to create function");
|
||||
output.println("createFunction: Failed to create function");
|
||||
createLabel(symLocAddr, symName, true);
|
||||
if (symDemangledName != null) {
|
||||
new DemanglerCmd(symLocAddr, symName).applyTo(currentProgram,
|
||||
monitor);
|
||||
ghidraSymTbl.removeSymbolSpecial(getSymbol(symName,
|
||||
currentProgram.getGlobalNamespace()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
println("Invalid symType!");
|
||||
break;
|
||||
}
|
||||
|
||||
symEntry = symEntry.add(SYM_ENTRY_SIZE); // goto next entry
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
/* ###
|
||||
* 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.
|
||||
*/
|
||||
// VxWorksSymTab_6_1 is an adaptation of the vxWorksSymTab script. It was modified by a customer
|
||||
// to use a single loop, instead of two. It also added demangling of C++ symbol names - at least
|
||||
// those that Ghidra knows how to demangle.
|
||||
//
|
||||
// Extracts all symbols in a VxWorks symbol table and disassembles
|
||||
// the global functions. Any existing symbols in the Ghidra symbol table
|
||||
// that collide with symbols defined in the VxWorks symbol table are deleted.
|
||||
//
|
||||
// The VxWorks symbol table is an array of symbol table entries [0..n-1]
|
||||
// followed by a 32-bit value that is equal to n (number of sym tbl entries).
|
||||
// Each entry in the array has the following structure:
|
||||
//
|
||||
// // Total size: 0x18 (24) bytes
|
||||
// 0x00 int NULL
|
||||
// 0x04 char *symNameAddr // symbol name
|
||||
// 0x08 void *symLocAddr // location of object named by symbol
|
||||
// 0x0c int NULL
|
||||
// 0x10 int NULL
|
||||
// 0x14 uchar symType // see switch statement below
|
||||
// 0x15 uchar fill[3]
|
||||
//
|
||||
// The script requests:
|
||||
// - Output file name: Each symbol name and address is recorded here.
|
||||
// (Errors are also logged to this file.)
|
||||
// - Address of "number of symbols" value: At the end of the symbol table,
|
||||
// its length is recorded as a 32-bit integer. The
|
||||
// script needs the address of that value to calculate
|
||||
// the symbol table's start address.
|
||||
//
|
||||
// @category CustomerSubmission.vxWorks
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import ghidra.app.cmd.label.DemanglerCmd;
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.app.util.demangler.DemangledException;
|
||||
import ghidra.app.util.demangler.gnu.GnuDemangler;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.mem.Memory;
|
||||
import ghidra.program.model.symbol.*;
|
||||
|
||||
public class VxWorksSymTab_6_1 extends GhidraScript {
|
||||
|
||||
static final int SYM_ENTRY_SIZE = 24;
|
||||
static final int SYM_NAME_OFF = 4;
|
||||
static final int SYM_LOC_OFF = 8;
|
||||
static final int SYM_TYPE_OFF = 0x14;
|
||||
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
|
||||
// Get Memory and SymbolTable objects (used later)
|
||||
Memory mem = currentProgram.getMemory();
|
||||
SymbolTable ghidraSymTbl = currentProgram.getSymbolTable();
|
||||
|
||||
// Open output file
|
||||
// All symbols found (address and name) will be logged to this file
|
||||
try (PrintWriter output = new PrintWriter(
|
||||
new FileOutputStream(askFile("vxWorks Symbol Table Parser", "Output file name?")))) {
|
||||
|
||||
// Get address of "total number of sym tbl entries" value
|
||||
Address vxNumSymEntriesAddr = askAddress("vxWorks Symbol Table Parser",
|
||||
"Address of \"total number of symbol table entries\" value?");
|
||||
int vxNumSymEntries = mem.getInt(vxNumSymEntriesAddr);
|
||||
println("VxWorks symbol table has " + vxNumSymEntries + " entries");
|
||||
|
||||
// Create a GNU demangler instance
|
||||
GnuDemangler demangler = new GnuDemangler();
|
||||
if (!demangler.canDemangle(currentProgram)) {
|
||||
println("Unable to create demangler.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Process entries in VxWorks symbol table
|
||||
Address vxSymTbl = vxNumSymEntriesAddr.subtract(vxNumSymEntries * SYM_ENTRY_SIZE);
|
||||
for (int i = 0; i < vxNumSymEntries; i++) {
|
||||
|
||||
if (monitor.isCancelled()) {
|
||||
return; // check for cancel button
|
||||
}
|
||||
println("i=" + i); // visual counter
|
||||
|
||||
// Extract symbol table entry values
|
||||
Address symEntry = vxSymTbl.add(i * SYM_ENTRY_SIZE);
|
||||
Address symNameAddr = toAddr(mem.getInt(symEntry.add(SYM_NAME_OFF)));
|
||||
Address symLocAddr = toAddr(mem.getInt(symEntry.add(SYM_LOC_OFF)));
|
||||
byte symType = mem.getByte(symEntry.add(SYM_TYPE_OFF));
|
||||
println("symNameAddr: 0x" + symNameAddr.toString() + ", symLocAddr: 0x" +
|
||||
symLocAddr.toString() + ", symType: " + symType);
|
||||
|
||||
// Remove any data or instructions that overlap this symName
|
||||
// (May happen if disassembly creates invalid references)
|
||||
Address a;
|
||||
String symName;
|
||||
for (a = symNameAddr; mem.getByte(a) != 0; a = a.add(1)) {
|
||||
if (getDataAt(a) != null) {
|
||||
removeDataAt(a);
|
||||
}
|
||||
if (getInstructionAt(a) != null) {
|
||||
removeInstructionAt(a);
|
||||
}
|
||||
}
|
||||
if (getDataAt(a) != null) {
|
||||
removeDataAt(a);
|
||||
}
|
||||
if (getInstructionAt(a) != null) {
|
||||
removeInstructionAt(a);
|
||||
}
|
||||
|
||||
// Turn *symNameAddr into a string and store it in symName
|
||||
try {
|
||||
symName = (String) createAsciiString(symNameAddr).getValue();
|
||||
}
|
||||
catch (Exception e) {
|
||||
println("createAsciiString: caught exception...");
|
||||
println(e.getMessage());
|
||||
return;
|
||||
}
|
||||
println("symName: " + symName);
|
||||
|
||||
// Demangle symName
|
||||
String symDemangledName = null;
|
||||
try {
|
||||
// if successful, symDemangledName will be non-NULL
|
||||
symDemangledName = demangler.demangle(symName, true).getSignature(false);
|
||||
}
|
||||
catch (DemangledException e) {
|
||||
// if symName wasn't a mangled name, silently continue
|
||||
if (!e.isInvalidMangledName()) {
|
||||
println("demangle: Demangling error");
|
||||
output.println("demangle: Demangling error");
|
||||
}
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
println("demangle: Caught runtime exception");
|
||||
output.println("demangle: Caught runtime exception");
|
||||
}
|
||||
if (symDemangledName != null) {
|
||||
println("symDemangledName: " + symDemangledName);
|
||||
}
|
||||
|
||||
// Delete any symbol in the Ghidra symbol table with the same name
|
||||
SymbolIterator syms = ghidraSymTbl.getSymbols(symName);
|
||||
Symbol sym;
|
||||
while (syms.hasNext()) {
|
||||
sym = syms.next();
|
||||
println("Deleting matching Ghidra symbol: " + sym.getName());
|
||||
ghidraSymTbl.removeSymbolSpecial(sym);
|
||||
}
|
||||
|
||||
// Delete any symbol in the Ghidra symbol table at the same address
|
||||
if ((sym = getSymbolAt(symLocAddr)) != null) {
|
||||
println("Deleting symbol at target address: " + sym.getName());
|
||||
ghidraSymTbl.removeSymbolSpecial(sym);
|
||||
}
|
||||
|
||||
switch (symType) {
|
||||
case 0: // Undefined Symbol
|
||||
println("NULL symType!");
|
||||
break;
|
||||
case 2: // Local Absolute
|
||||
case 3: // Global Absolute
|
||||
case 6: // Local Data
|
||||
case 7: // Global Data
|
||||
case 8: // Local BSS
|
||||
case 9: // Global BSS
|
||||
// Data: log the symbol & create a Ghidra symbol at symLocAddr
|
||||
output.println(symLocAddr.toString() + "\t" + symName);
|
||||
createLabel(symLocAddr, symName, true);
|
||||
if (symDemangledName != null) {
|
||||
new DemanglerCmd(symLocAddr, symName).applyTo(currentProgram, monitor);
|
||||
ghidraSymTbl.removeSymbolSpecial(
|
||||
getSymbol(symName, currentProgram.getGlobalNamespace()));
|
||||
}
|
||||
break;
|
||||
case 4: // Local .text
|
||||
case 5: // Global .text
|
||||
// Code: log the symbol, disassemble, & create/name function
|
||||
output.println(symLocAddr.toString() + "\t" + symName);
|
||||
goTo(symLocAddr);
|
||||
disassemble(symLocAddr);
|
||||
createFunction(symLocAddr, symName);
|
||||
if (getFunctionAt(symLocAddr) != null) {
|
||||
getFunctionAt(symLocAddr).setName(symName, SourceType.USER_DEFINED);
|
||||
if (symDemangledName != null) {
|
||||
new DemanglerCmd(symLocAddr, symName).applyTo(currentProgram,
|
||||
monitor);
|
||||
ghidraSymTbl.removeSymbolSpecial(
|
||||
getSymbol(symName, currentProgram.getGlobalNamespace()));
|
||||
}
|
||||
}
|
||||
else {
|
||||
println("createFunction: Failed to create function");
|
||||
output.println("createFunction: Failed to create function");
|
||||
createLabel(symLocAddr, symName, true);
|
||||
if (symDemangledName != null) {
|
||||
new DemanglerCmd(symLocAddr, symName).applyTo(currentProgram,
|
||||
monitor);
|
||||
ghidraSymTbl.removeSymbolSpecial(
|
||||
getSymbol(symName, currentProgram.getGlobalNamespace()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
println("Invalid symType!");
|
||||
break;
|
||||
}
|
||||
|
||||
symEntry = symEntry.add(SYM_ENTRY_SIZE); // goto next entry
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,840 @@
|
||||
/* ###
|
||||
* 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.
|
||||
*/
|
||||
// Locates and parses the VxWorks symbol table. Names the table "vxSymTbl"
|
||||
// and names the table length variable "vxSymTblLen" (if the length variable
|
||||
// appears either directly before or after the symbol table). Defines the
|
||||
// symbol table as SYMBOL[vxSymTblLen].
|
||||
//
|
||||
// Extracts symbol name, location, and type from each entry. Disassembles,
|
||||
// creates, and names functions. Names global variables.
|
||||
//
|
||||
// Any existing Ghidra symbol table entries that collide with VxWorks symbol
|
||||
// table entries are deleted. Mangled C++ symbol names are demangled.
|
||||
//
|
||||
// The VxWorks symbol table is an array [0..n-1] of (struct SYMBOL) entries.
|
||||
// The table may be immediately followed or preceeded by an (int) vxSymTblLen
|
||||
// value.
|
||||
//
|
||||
// Prerequisites:
|
||||
//
|
||||
// - Program memory block(s) is(are) aligned with actual load addresses
|
||||
// (run something like MemAlignARM_LE.java)
|
||||
//
|
||||
// - Symbol table cannot be in a memory block with a name that contains
|
||||
// the string "text" or "bss"
|
||||
//
|
||||
// - Modify getVxSymbolClass() to recognize your program's VxWorks
|
||||
// symbol table entry structure, if necessary
|
||||
//
|
||||
// @category VxWorks
|
||||
|
||||
import ghidra.app.cmd.disassemble.DisassembleCommand;
|
||||
import ghidra.app.cmd.label.DemanglerCmd;
|
||||
import ghidra.app.plugin.core.analysis.AutoAnalysisManager;
|
||||
import ghidra.app.script.GhidraScript;
|
||||
import ghidra.app.services.DataTypeManagerService;
|
||||
import ghidra.app.util.demangler.DemangledException;
|
||||
import ghidra.app.util.demangler.gnu.GnuDemangler;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSet;
|
||||
import ghidra.program.model.data.ArrayDataType;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.DataTypeComponent;
|
||||
import ghidra.program.model.data.DataTypeConflictHandler;
|
||||
import ghidra.program.model.data.DataTypeManager;
|
||||
import ghidra.program.model.data.PointerDataType;
|
||||
import ghidra.program.model.data.StructureDataType;
|
||||
import ghidra.program.model.listing.Data;
|
||||
import ghidra.program.model.listing.Instruction;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.program.model.symbol.SourceType;
|
||||
import ghidra.program.model.symbol.Symbol;
|
||||
|
||||
public class VxWorksSymTab_Finder extends GhidraScript {
|
||||
|
||||
boolean debug = false;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// getDataTypeManagerByName
|
||||
//
|
||||
// Retrieves data type manager by name.
|
||||
//
|
||||
// Returns:
|
||||
// Success: DataTypeManager
|
||||
// Failure: null
|
||||
//------------------------------------------------------------------------
|
||||
private DataTypeManager getDataTypeManagerByName(String name) {
|
||||
|
||||
DataTypeManagerService service = state.getTool().getService(DataTypeManagerService.class);
|
||||
|
||||
// Loop through all managers in the data type manager service
|
||||
for (DataTypeManager manager : service.getDataTypeManagers()) {
|
||||
if (manager.getName().equals(name)) {
|
||||
return manager;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// VxSymbol
|
||||
//
|
||||
// Contains a SYMBOL data type representing a VxWorks symbol table entry
|
||||
// and several associated methods.
|
||||
//------------------------------------------------------------------------
|
||||
private class VxSymbol {
|
||||
|
||||
StructureDataType dt = null;
|
||||
int nameOffset = 0;
|
||||
int locOffset = 0;
|
||||
int typeOffset = 0;
|
||||
int length = 0;
|
||||
|
||||
public VxSymbol(StructureDataType struct) {
|
||||
dt = struct;
|
||||
nameOffset = getFieldOffset(dt, "symNameOff");
|
||||
locOffset = getFieldOffset(dt, "symLocOff");
|
||||
typeOffset = getFieldOffset(dt, "symType");
|
||||
length = dt.getLength();
|
||||
}
|
||||
|
||||
private int getFieldOffset(StructureDataType dataType, String name) {
|
||||
for (DataTypeComponent comp : dataType.getComponents()) {
|
||||
if (comp.getFieldName().equals(name)) {
|
||||
return comp.getOffset();
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public DataType dataType() {
|
||||
return dt;
|
||||
}
|
||||
|
||||
public int length() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public int nameOffset() {
|
||||
return nameOffset;
|
||||
}
|
||||
|
||||
public int locOffset() {
|
||||
return locOffset;
|
||||
}
|
||||
|
||||
public int typeOffset() {
|
||||
return typeOffset;
|
||||
}
|
||||
|
||||
// Add SYMBOL data type to Program DataTypeManager
|
||||
// (if data type already exists, replace it)
|
||||
public void createGhidraType() {
|
||||
currentProgram.getDataTypeManager().addDataType(dt,
|
||||
DataTypeConflictHandler.REPLACE_HANDLER);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// getVxSymbolClass
|
||||
//
|
||||
// Creates a SYMBOL structure data type and uses it to create a new
|
||||
// VxSymbol class instance.
|
||||
//
|
||||
// Returns:
|
||||
// Success: VxSymbol
|
||||
// Failure: null
|
||||
//------------------------------------------------------------------------
|
||||
private VxSymbol getVxSymbolClass(int type) {
|
||||
|
||||
// Pre-define base data types used to define symbol table entry data type
|
||||
DataTypeManager builtin = getDataTypeManagerByName("BuiltInTypes");
|
||||
DataType charType = builtin.getDataType("/char");
|
||||
DataType charPtrType = PointerDataType.getPointer(charType, 4);
|
||||
DataType byteType = builtin.getDataType("/byte");
|
||||
DataType ushortType = builtin.getDataType("/ushort");
|
||||
DataType intType = builtin.getDataType("/int");
|
||||
DataType uintType = builtin.getDataType("/uint");
|
||||
DataType voidType = builtin.getDataType("/void");
|
||||
DataType voidPtrType = PointerDataType.getPointer(voidType, 4);
|
||||
|
||||
// Define a SYMBOL data type (try to put most common first).
|
||||
// Each SYMBOL data type must include at least 3 fields named
|
||||
// symNameOff, symLocOff, and symType.
|
||||
StructureDataType dt = null;
|
||||
switch (type) {
|
||||
case 0:
|
||||
|
||||
// Version 5.4, 6.4 and 6.8
|
||||
//
|
||||
// Total length: 0x14 bytes
|
||||
// 0x00 uint symHashNode // NULL
|
||||
// 0x04 char *symNameOff
|
||||
// 0x08 void *symLocOff
|
||||
// 0x0c int NULL
|
||||
// 0x10 ushort symGroup
|
||||
// 0x12 uchar symType
|
||||
// 0x13 uchar undef
|
||||
dt = new StructureDataType("SYMBOL", 0x14);
|
||||
dt.replaceAtOffset(0, uintType, 4, "symHashNode", "");
|
||||
dt.replaceAtOffset(4, charPtrType, 4, "symNameOff", "");
|
||||
dt.replaceAtOffset(8, voidPtrType, 4, "symLocOff", "");
|
||||
dt.replaceAtOffset(0x0c, intType, 4, "", "");
|
||||
dt.replaceAtOffset(0x10, ushortType, 2, "symGroup", "");
|
||||
dt.replaceAtOffset(0x12, byteType, 1, "symType", "");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
||||
// Version 6.1
|
||||
//
|
||||
// Total length: 0x18 bytes
|
||||
// 0x00 uint symHashNode // NULL
|
||||
// 0x04 char *symNameOff
|
||||
// 0x08 void *symLocOff
|
||||
// 0x0c int NULL
|
||||
// 0x10 int NULL
|
||||
// 0x14 uchar symType
|
||||
// 0x15 uchar undef[3]
|
||||
dt = new StructureDataType("SYMBOL", 0x18);
|
||||
dt.replaceAtOffset(0, uintType, 4, "symHashNode", "");
|
||||
dt.replaceAtOffset(4, charPtrType, 4, "symNameOff", "");
|
||||
dt.replaceAtOffset(8, voidPtrType, 4, "symLocOff", "");
|
||||
dt.replaceAtOffset(0x0c, intType, 4, "", "");
|
||||
dt.replaceAtOffset(0x10, intType, 4, "", "");
|
||||
dt.replaceAtOffset(0x14, byteType, 1, "symType", "");
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
||||
// Unknown VxWorks version(s)
|
||||
//
|
||||
// Total length: 0x1c bytes
|
||||
// 0x00 uint symHashNode // NULL
|
||||
// 0x04 char *symNameOff
|
||||
// 0x08 void *symLocOff
|
||||
// 0x0c int unk; // no clear pattern to values
|
||||
// 0x10 int NULL
|
||||
// 0x14 int NULL
|
||||
// 0x18 uchar symType
|
||||
// 0x19 uchar undef[3]
|
||||
dt = new StructureDataType("SYMBOL", 0x1c);
|
||||
dt.replaceAtOffset(0, uintType, 4, "symHashNode", "");
|
||||
dt.replaceAtOffset(4, charPtrType, 4, "symNameOff", "");
|
||||
dt.replaceAtOffset(8, voidPtrType, 4, "symLocOff", "");
|
||||
dt.replaceAtOffset(0x0c, intType, 4, "", "");
|
||||
dt.replaceAtOffset(0x10, intType, 4, "", "");
|
||||
dt.replaceAtOffset(0x14, intType, 4, "", "");
|
||||
dt.replaceAtOffset(0x18, byteType, 1, "symType", "");
|
||||
break;
|
||||
|
||||
case 3:
|
||||
|
||||
// Version 5.5
|
||||
//
|
||||
// Total length: 0x10 bytes
|
||||
// 0x00 uint symHashNode // NULL
|
||||
// 0x04 char *symNameOff
|
||||
// 0x08 void *symLocOff
|
||||
// 0x0c ushort symGroup // NULL
|
||||
// 0x0e uchar symType
|
||||
// 0x0f uchar undef
|
||||
dt = new StructureDataType("SYMBOL", 0x10);
|
||||
dt.replaceAtOffset(0, uintType, 4, "symHashNode", "");
|
||||
dt.replaceAtOffset(4, charPtrType, 4, "symNameOff", "");
|
||||
dt.replaceAtOffset(8, voidPtrType, 4, "symLocOff", "");
|
||||
dt.replaceAtOffset(0x0c, ushortType, 2, "symGroup", "");
|
||||
dt.replaceAtOffset(0x0e, byteType, 1, "symType", "");
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Return a VxSymbol class for this SYMBOL data type
|
||||
return new VxSymbol(dt);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// isExecute
|
||||
//
|
||||
// Is address in an executable memory block?
|
||||
//------------------------------------------------------------------------
|
||||
private boolean isExecute(Address addr) {
|
||||
|
||||
// Search all program memory blocks
|
||||
for (MemoryBlock block : getMemoryBlocks()) {
|
||||
if (block.contains(addr)) {
|
||||
return block.isExecute();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// isAddress
|
||||
//
|
||||
// Is offset in an existing memory block?
|
||||
//------------------------------------------------------------------------
|
||||
private boolean isAddress(long offset) {
|
||||
|
||||
// Search all program memory blocks
|
||||
for (MemoryBlock block : getMemoryBlocks()) {
|
||||
|
||||
if (block.getStart().getOffset() <= offset && block.getEnd().getOffset() >= offset) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false; // no match
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// isAddress
|
||||
//
|
||||
// Is offset in the specified memory block?
|
||||
//------------------------------------------------------------------------
|
||||
private boolean isAddress(long offset, MemoryBlock block) {
|
||||
|
||||
if (block.getStart().getOffset() <= offset && block.getEnd().getOffset() >= offset) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// isString
|
||||
//
|
||||
// Are the bytes starting at addr a C string?
|
||||
//
|
||||
// Algorithm: Scan bytes until finding either an invalid char or null.
|
||||
// If scan stops at null, return true -- else false.
|
||||
//------------------------------------------------------------------------
|
||||
private boolean isString(Address addr) {
|
||||
byte _byte;
|
||||
|
||||
try {
|
||||
_byte = getByte(addr);
|
||||
}
|
||||
catch (Exception except) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while ( // May need to add valid character examples here.
|
||||
(_byte == 0x09 || _byte == 0x0a || _byte == 0x0d || (_byte > 0x19 && _byte < 0x80)) &&
|
||||
_byte != 0x00) {
|
||||
|
||||
if (monitor.isCancelled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
addr = addr.add(1);
|
||||
try {
|
||||
_byte = getByte(addr);
|
||||
}
|
||||
catch (Exception except) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (_byte == 0x00)
|
||||
{
|
||||
return true; // Scan stopped at null.
|
||||
}
|
||||
return false; // Scan stopped at invalid char.
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// clearString
|
||||
//
|
||||
// Remove data or instructions that overlap the null-terminated
|
||||
// string at addr (may happen if disassembly creates invalid references
|
||||
// or compiler optimization creates shared strings).
|
||||
//
|
||||
// Use get*Containing() in case a string that ends with the string
|
||||
// at addr has already been defined (e.g., the string at addr is
|
||||
// "CoolFunc" and the string "g_pfCoolFunc" overlaps it).
|
||||
//------------------------------------------------------------------------
|
||||
private void clearString(Address addr) throws Exception {
|
||||
Data data;
|
||||
Instruction inst;
|
||||
|
||||
// Clear the string, breaking on the terminating null character
|
||||
while (getByte(addr) != 0) {
|
||||
data = getDataContaining(addr);
|
||||
if (data != null) {
|
||||
removeDataAt(data.getAddress());
|
||||
}
|
||||
inst = getInstructionContaining(addr);
|
||||
if (inst != null) {
|
||||
removeInstructionAt(inst.getAddress());
|
||||
}
|
||||
|
||||
addr = addr.add(1);
|
||||
}
|
||||
|
||||
// Now clear at string's terminating null character
|
||||
data = getDataContaining(addr);
|
||||
if (data != null) {
|
||||
removeDataAt(data.getAddress());
|
||||
}
|
||||
inst = getInstructionContaining(addr);
|
||||
if (inst != null) {
|
||||
removeInstructionAt(inst.getAddress());
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// isSymTblEntry
|
||||
//
|
||||
// Does data pointed to by entry look like a VxWorks symbol table entry?
|
||||
// Test is weak.
|
||||
//------------------------------------------------------------------------
|
||||
private boolean isSymTblEntry(Address entry, VxSymbol vxSymbol) throws Exception {
|
||||
|
||||
// First dword must be null or a valid ptr (typically into the sym table)
|
||||
long value = getInt(entry) & 0xffffffffL;
|
||||
if ((value != 0) && !isAddress(value)) {
|
||||
if (debug) {
|
||||
println("1: " + entry + " --> " + Long.toHexString(value));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// symNameOff field must point to a non-null C string
|
||||
value = getInt(entry.add(vxSymbol.nameOffset())) & 0xffffffffL;
|
||||
if (!isAddress(value)) {
|
||||
if (debug) {
|
||||
println("2: " + entry + " --> " + Long.toHexString(value));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Address symNameAddr = toAddr(value);
|
||||
if (!isString(symNameAddr)) {
|
||||
if (debug) {
|
||||
println("3: " + entry + " --> " + Long.toHexString(value));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (getByte(symNameAddr) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// symLocOff field can be almost anything (e.g., external mem ref)
|
||||
//value = (long)getInt(entry.add(vxSymbol.locOffset())) & 0xffffffffL;
|
||||
//if (value == 0) {
|
||||
// if (debug) println("4: " + entry);
|
||||
// return false;
|
||||
//}
|
||||
|
||||
// symType field must be recognized type code (this test is weak)
|
||||
byte symType = getByte(entry.add(vxSymbol.typeOffset()));
|
||||
if (!isValidSymType(symType)) {
|
||||
if (debug) {
|
||||
println("5: " + entry + " --> " + symType);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isValidSymType(byte symType) {
|
||||
switch (symType) {
|
||||
case 0: // Undefined Symbol
|
||||
return false;
|
||||
case 2: // Local Absolute
|
||||
case 3: // Global Absolute
|
||||
case 6: // Local Data
|
||||
case 7: // Global Data
|
||||
case 8: // Local BSS
|
||||
case 9: // Global BSS
|
||||
case 4: // Local .text
|
||||
case 5: // Global .text
|
||||
case 0x11: // External ref -- ignore
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// findSymTbl
|
||||
//
|
||||
// Searches all memory blocks for data that looks like a run of testLen
|
||||
// VxWorks symbol table entries.
|
||||
//
|
||||
// Returns:
|
||||
// Success: table address
|
||||
// Failure: null
|
||||
//------------------------------------------------------------------------
|
||||
private Address findSymTbl(VxSymbol vxSymbol) throws Exception {
|
||||
|
||||
int testLen = 100; // number of symbol tbl entries to look for
|
||||
|
||||
boolean hasNonExecute = checkNonExecute();
|
||||
|
||||
// Iterate through all memory blocks
|
||||
for (MemoryBlock block : currentProgram.getMemory().getBlocks()) {
|
||||
|
||||
// Skip code/execute blocks if there are non-execute blocks,
|
||||
// otherwise search everything.
|
||||
if (hasNonExecute && block.isExecute()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip uninit
|
||||
if (!block.isInitialized()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Search current block for run of testLen symbol table entries
|
||||
int testBlkSize = vxSymbol.length * testLen;
|
||||
printf(" block: " + block.getName() + " (" + block.getStart() + ", " +
|
||||
block.getEnd() + ") ");
|
||||
printf("testBlkSize = " + Integer.toHexString(testBlkSize) + " ");
|
||||
System.out.flush();
|
||||
long prevOffset = 0;
|
||||
Address cursor = block.getStart();
|
||||
while ((cursor != null) && isAddress(cursor.getOffset() + testBlkSize, block)) {
|
||||
|
||||
// Script cancel check and visual feedback
|
||||
if (monitor.isCancelled()) {
|
||||
return null;
|
||||
}
|
||||
if ((cursor.getOffset() - prevOffset) >= 0x100000) {
|
||||
printf(".");
|
||||
System.out.flush();
|
||||
prevOffset = cursor.getOffset();
|
||||
}
|
||||
|
||||
// Determine whether cursor now points to a symbol table
|
||||
int i = 0;
|
||||
for (Address entry = cursor; isSymTblEntry(entry, vxSymbol) &&
|
||||
(i < testLen); entry = entry.add(vxSymbol.length()), i++) {
|
||||
}
|
||||
if (i == testLen) {
|
||||
// May have symbol table -- verify length
|
||||
if (getSymTblLen(cursor, vxSymbol) != 0) {
|
||||
printf("\n");
|
||||
System.out.flush();
|
||||
return cursor; // found table -- stop searching
|
||||
}
|
||||
if (debug) {
|
||||
printf("Possible symbol table at " + cursor + " has length error\n");
|
||||
}
|
||||
}
|
||||
|
||||
cursor = cursor.add(4);
|
||||
}
|
||||
printf("\n");
|
||||
printf(" search terminated at: " + cursor + "\n");
|
||||
System.out.flush();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean checkNonExecute() {
|
||||
for (MemoryBlock block : currentProgram.getMemory().getBlocks()) {
|
||||
if (!block.isExecute()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// getSymTblLen
|
||||
//
|
||||
// Counts number of entries in VxWorks table at address symTbl.
|
||||
//
|
||||
// Returns:
|
||||
// Success: number of table entries (> 0)
|
||||
// Failure: 0
|
||||
//------------------------------------------------------------------------
|
||||
private int getSymTblLen(Address symTbl, VxSymbol vxSymbol) throws Exception {
|
||||
|
||||
Address entry = symTbl;
|
||||
int j = 0;
|
||||
while (isSymTblEntry(entry, vxSymbol)) {
|
||||
entry = entry.add(vxSymbol.length());
|
||||
j++;
|
||||
}
|
||||
|
||||
return j;
|
||||
|
||||
// NOTE: Found an example of a VxWorks symbol table that was not
|
||||
// directly adjacent to the symbol table length variable...
|
||||
// so removed the following constraint.
|
||||
|
||||
/*
|
||||
// Symbol table length entry may be at beginning or end of the symbol
|
||||
// table...so compare computed length with both values. If either
|
||||
// matches, table length is verified.
|
||||
if ((j == getInt(entry)) || (j == getInt(symTbl.subtract(4)))) {
|
||||
return j;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Look before/after the table to see if there is a size value there and mark it if it agrees with TableLen
|
||||
*
|
||||
* @param symTbl
|
||||
* @param vxSymbol
|
||||
* @param tableLen
|
||||
* @throws Exception
|
||||
*/
|
||||
private void markSymbolTableLen(Address symTbl, VxSymbol vxSymbol, int symTblLen)
|
||||
throws Exception {
|
||||
// NOTE: Found an example of a VxWorks symbol table that was not
|
||||
// directly adjacent to the symbol table length variable...
|
||||
|
||||
// Name the VxWorks symbol length variable
|
||||
// (if it appears either directly before or after the symbol table)
|
||||
Address symTblLenPtr = null;
|
||||
long foreOff = symTbl.getOffset() - 4;
|
||||
long aftOff = symTbl.getOffset() + symTblLen * vxSymbol.length();
|
||||
if (isAddress(foreOff) && getInt(toAddr(foreOff)) == symTblLen) {
|
||||
symTblLenPtr = toAddr(foreOff);
|
||||
}
|
||||
else if (isAddress(aftOff) && getInt(toAddr(aftOff)) == symTblLen) {
|
||||
symTblLenPtr = toAddr(aftOff);
|
||||
}
|
||||
if (symTblLenPtr != null) {
|
||||
removeConflictingSymbols("vxSymTblLen", symTblLenPtr);
|
||||
createLabel(symTblLenPtr, "vxSymTblLen", true);
|
||||
createDWord(symTblLenPtr);
|
||||
}
|
||||
else {
|
||||
println("Warning: Symbol Table Size not found before of after table");
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// removeConflictingSymbols
|
||||
//
|
||||
// Deletes all symbols with the same name and the primary symbol at addr.
|
||||
//------------------------------------------------------------------------
|
||||
private void removeConflictingSymbols(String name, Address addr) {
|
||||
|
||||
// Delete any existing symbols with the same name
|
||||
for (Symbol sym : currentProgram.getSymbolTable().getSymbols(name)) {
|
||||
sym.delete();
|
||||
}
|
||||
|
||||
// Delete primary Ghidra symbol at the same address
|
||||
Symbol sym = getSymbolAt(addr);
|
||||
if (sym != null) {
|
||||
sym.delete();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// applyDemangled
|
||||
//
|
||||
// Apply demangled symbol name to symbol.
|
||||
//------------------------------------------------------------------------
|
||||
private void applyDemangled(Address addr, String mangled, String demangled) {
|
||||
|
||||
if (demangled != null) {
|
||||
new DemanglerCmd(addr, mangled).applyTo(currentProgram, monitor);
|
||||
currentProgram.getSymbolTable().removeSymbolSpecial(
|
||||
getSymbol(mangled, currentProgram.getGlobalNamespace()));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// doLocalDisassemble
|
||||
//
|
||||
// Do our own disassembly, and don't let auto-analysis start until after
|
||||
// this script finishes. This speeds up the script substantially and
|
||||
// allows auto-analysis to operate with more information (and code/data
|
||||
// that isn't rapidly changing).
|
||||
//------------------------------------------------------------------------
|
||||
private void doLocalDisassemble(Address addr) {
|
||||
|
||||
// Only disassemble in memory blocks marked executable
|
||||
if (!isExecute(addr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
DisassembleCommand cmd = new DisassembleCommand(addr, null, true);
|
||||
cmd.enableCodeAnalysis(false); // Queues changes up for later analysis
|
||||
cmd.applyTo(currentProgram, monitor);
|
||||
|
||||
AddressSet set = cmd.getDisassembledAddressSet();
|
||||
AutoAnalysisManager.getAnalysisManager(currentProgram).codeDefined(set);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// getScriptAnalysisMode
|
||||
//
|
||||
// Force auto-analysis to wait until script completes.
|
||||
//------------------------------------------------------------------------
|
||||
@Override
|
||||
public AnalysisMode getScriptAnalysisMode() {
|
||||
return AnalysisMode.SUSPENDED;
|
||||
}
|
||||
|
||||
//========================================================================
|
||||
// Main
|
||||
//========================================================================
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
|
||||
// Find VxWorks symbol table
|
||||
Address symTbl = null;
|
||||
VxSymbol vxSymbol = getVxSymbolClass(0);
|
||||
for (int i = 0; ((vxSymbol != null) && !monitor.isCancelled()); i++, vxSymbol =
|
||||
getVxSymbolClass(i)) {
|
||||
|
||||
println("Searching for symbol table variant " + i);
|
||||
if ((symTbl = findSymTbl(vxSymbol)) != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (vxSymbol == null) {
|
||||
return;
|
||||
}
|
||||
int symTblLen = getSymTblLen(symTbl, vxSymbol);
|
||||
println("Symbol table at " + symTbl + " (" + symTblLen + " entries)");
|
||||
|
||||
// Name the VxWorks symbol table
|
||||
removeConflictingSymbols("vxSymTbl", symTbl);
|
||||
createLabel(symTbl, "vxSymTbl", true);
|
||||
markSymbolTableLen(symTbl, vxSymbol, symTblLen);
|
||||
|
||||
// Create symbol data type and symbol table structure
|
||||
println("Creating SYMBOL data type and symbol table structure...");
|
||||
vxSymbol.createGhidraType();
|
||||
clearListing(symTbl, symTbl.add(symTblLen * vxSymbol.length() - 1));
|
||||
createData(symTbl, new ArrayDataType(vxSymbol.dataType(), symTblLen, vxSymbol.length()));
|
||||
|
||||
// Create a GNU demangler instance
|
||||
GnuDemangler demangler = new GnuDemangler();
|
||||
if (!demangler.canDemangle(currentProgram)) {
|
||||
println("Unable to create demangler.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Process VxWorks symbol table entries
|
||||
println("Processing symbol table entries.");
|
||||
Address symEntry = symTbl;
|
||||
for (int i = 0; (i < symTblLen) && !monitor.isCancelled(); i++, symEntry =
|
||||
symEntry.add(vxSymbol.length())) {
|
||||
|
||||
// Extract symbol table entry values
|
||||
Address symNameAddr = toAddr(getInt(symEntry.add(vxSymbol.nameOffset())) & 0xffffffffL);
|
||||
Address symLoc = toAddr(getInt(symEntry.add(vxSymbol.locOffset())) & 0xffffffffL);
|
||||
byte symType = getByte(symEntry.add(vxSymbol.typeOffset()));
|
||||
|
||||
// Remove any data or instructions that overlap string at *symNameAddr
|
||||
clearString(symNameAddr);
|
||||
|
||||
// Turn *symNameAddr into a string and store it in symName
|
||||
String symName;
|
||||
try {
|
||||
symName = (String) createAsciiString(symNameAddr).getValue();
|
||||
}
|
||||
catch (Exception e) {
|
||||
println("createAsciiString: caught exception...");
|
||||
println(e.getMessage());
|
||||
println(e.toString());
|
||||
return;
|
||||
}
|
||||
if (symName.length() > 2000) {
|
||||
symName = symName.substring(0, 2000);
|
||||
}
|
||||
|
||||
// Demangle symName
|
||||
String symDemangledName = null;
|
||||
try {
|
||||
symDemangledName = demangler.demangle(symName, true).getSignature(false);
|
||||
}
|
||||
catch (DemangledException e) { // report demangling error
|
||||
if (!e.isInvalidMangledName()) {
|
||||
println("demangle: Demangling error");
|
||||
}
|
||||
}
|
||||
catch (RuntimeException e) { // ignore unmangled symNames
|
||||
}
|
||||
|
||||
// Status update
|
||||
if (symDemangledName != null) {
|
||||
println("i=" + i + ", nameAddr: " + symNameAddr + ", loc: " + symLoc + ", type: " +
|
||||
symType + ", name: " + symName + ", demangled: " + symDemangledName);
|
||||
}
|
||||
else {
|
||||
println("i=" + i + ", nameAddr: " + symNameAddr + ", loc: " + symLoc + ", type: " +
|
||||
symType + ", name: " + symName);
|
||||
}
|
||||
|
||||
// Clear any conflicting symbols from the Ghidra symbol table
|
||||
removeConflictingSymbols(symName, symLoc);
|
||||
|
||||
// If entry type is data, simply create a Ghidra symbol for it.
|
||||
// If entry type is code, disassemble it and create function.
|
||||
switch (symType) {
|
||||
|
||||
case 0: // Undefined Symbol
|
||||
println("NULL symType!");
|
||||
break;
|
||||
|
||||
case 2: // Local Absolute
|
||||
case 3: // Global Absolute
|
||||
case 6: // Local Data
|
||||
case 7: // Global Data
|
||||
case 8: // Local BSS
|
||||
case 9: // Global BSS
|
||||
createLabel(symLoc, symName, true);
|
||||
applyDemangled(symLoc, symName, symDemangledName);
|
||||
break;
|
||||
|
||||
case 4: // Local .text
|
||||
case 5: // Global .text
|
||||
doLocalDisassemble(symLoc);
|
||||
createFunction(symLoc, symName);
|
||||
if (getFunctionAt(symLoc) != null) {
|
||||
getFunctionAt(symLoc).setName(symName, SourceType.USER_DEFINED);
|
||||
applyDemangled(symLoc, symName, symDemangledName);
|
||||
}
|
||||
else {
|
||||
println("createFunction: Failed to create function");
|
||||
createLabel(symLoc, symName, true);
|
||||
applyDemangled(symLoc, symName, symDemangledName);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x11: // External ref -- ignore
|
||||
break;
|
||||
|
||||
default:
|
||||
println("Invalid symType!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
/* ###
|
||||
* 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.
|
||||
*/
|
||||
package ghidra.app.util.demangler.gnu;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import generic.jar.ResourceFile;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.app.util.opinion.ElfLoader;
|
||||
import ghidra.app.util.opinion.MachoLoader;
|
||||
import ghidra.framework.Application;
|
||||
import ghidra.program.model.lang.CompilerSpec;
|
||||
import ghidra.program.model.listing.Program;
|
||||
|
||||
/**
|
||||
* A class for demangling debug symbols created using GNU GCC.
|
||||
*/
|
||||
public class GnuDemangler implements Demangler {
|
||||
|
||||
private static final String DWARF_REF = "DW.ref."; //dwarf debug reference
|
||||
private static final String GLOBAL_PREFIX = "_GLOBAL_";
|
||||
|
||||
public GnuDemangler() {
|
||||
// needed to instantiate dynamically
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDemangle(Program program) {
|
||||
String executableFormat = program.getExecutableFormat();
|
||||
if (isELF(executableFormat) || isMacho(executableFormat)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//check if language is GCC
|
||||
CompilerSpec compilerSpec = program.getCompilerSpec();
|
||||
if (compilerSpec.getCompilerSpecID().getIdAsString().toLowerCase().indexOf(
|
||||
"windows") == -1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DemangledObject demangle(String mangled, boolean demangleOnlyKnownPatterns)
|
||||
throws DemangledException {
|
||||
|
||||
if (skip(mangled, demangleOnlyKnownPatterns)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String originalMangled = mangled;
|
||||
|
||||
String globalPrefix = null;
|
||||
if (mangled.startsWith(GLOBAL_PREFIX)) {
|
||||
int index = mangled.indexOf("_Z");
|
||||
if (index > 0) {
|
||||
globalPrefix = mangled.substring(0, index);
|
||||
mangled = mangled.substring(index);
|
||||
}
|
||||
}
|
||||
else if (mangled.startsWith("__Z")) {
|
||||
mangled = mangled.substring(1);//removed first underscore....
|
||||
}
|
||||
|
||||
boolean isDwarf = false;
|
||||
if (mangled.startsWith(DWARF_REF)) {
|
||||
int len = DWARF_REF.length();
|
||||
mangled = mangled.substring(len);
|
||||
isDwarf = true;
|
||||
}
|
||||
|
||||
try {
|
||||
GnuDemanglerNativeProcess process = GnuDemanglerNativeProcess.getDemanglerNativeProcess();
|
||||
String demangled = process.demangle(mangled).trim();
|
||||
|
||||
if (mangled.equals(demangled) || demangled.length() == 0) {
|
||||
throw new DemangledException(true);
|
||||
}
|
||||
|
||||
DemangledObject demangledObject =
|
||||
parse(mangled, process, demangled, demangleOnlyKnownPatterns);
|
||||
if (demangledObject == null) {
|
||||
return demangledObject;
|
||||
}
|
||||
|
||||
if (globalPrefix != null) {
|
||||
// TODO: may need better naming convention for demangled function
|
||||
DemangledFunction dfunc =
|
||||
new DemangledFunction(globalPrefix + demangledObject.getName());
|
||||
dfunc.setNamespace(demangledObject.getNamespace());
|
||||
demangledObject = dfunc;
|
||||
}
|
||||
else {
|
||||
demangledObject.setSignature(demangled);
|
||||
}
|
||||
demangledObject.setOriginalMangled(originalMangled);
|
||||
|
||||
if (isDwarf) {
|
||||
DemangledAddressTable dat = new DemangledAddressTable((String) null, 1);
|
||||
dat.setSpecialPrefix("DWARF Debug ");
|
||||
dat.setName(demangledObject.getName());
|
||||
dat.setNamespace(demangledObject.getNamespace());
|
||||
dat.setOriginalMangled(originalMangled);
|
||||
return dat;
|
||||
}
|
||||
|
||||
return demangledObject;
|
||||
}
|
||||
catch (IOException e) {
|
||||
if (e.getMessage().endsWith("14001")) {//missing runtime dlls, prolly
|
||||
ResourceFile installationDir = Application.getInstallationDirectory();
|
||||
throw new DemangledException("Missing runtime libraries. " + "Please install " +
|
||||
installationDir + File.separatorChar + "support" + File.separatorChar +
|
||||
"install_windows_runtime_libraries.exe.");
|
||||
}
|
||||
throw new DemangledException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean skip(String mangled, boolean demangleOnlyKnownPatterns) {
|
||||
|
||||
// Ignore versioned symbols which are generally duplicated at the same address
|
||||
if (mangled.indexOf("@") > 0) { // do not demangle versioned symbols
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mangled.startsWith("___")) {
|
||||
// not a mangled symbol, but the demangler will try anyway, so don't let it
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!demangleOnlyKnownPatterns) {
|
||||
return false; // let it go through
|
||||
}
|
||||
|
||||
// add to this list if we find any other known GNU start patterns
|
||||
if (mangled.startsWith("_Z")) {
|
||||
return false;
|
||||
}
|
||||
else if (mangled.startsWith("__Z")) {
|
||||
return false;
|
||||
}
|
||||
else if (mangled.startsWith("h__")) {
|
||||
return false; // not sure about this one
|
||||
}
|
||||
else if (mangled.startsWith("?")) {
|
||||
return false; // not sure about this one
|
||||
}
|
||||
else if (isGnu2Or3Pattern(mangled)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private DemangledObject parse(String mangled, GnuDemanglerNativeProcess process, String demangled,
|
||||
boolean demangleOnlyKnownPatterns) {
|
||||
|
||||
if (demangleOnlyKnownPatterns && !isMangledString(mangled, demangled)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
GnuDemanglerParser parser = new GnuDemanglerParser(process);
|
||||
DemangledObject demangledObject = parser.parse(mangled, demangled);
|
||||
return demangledObject;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isMangledString(String mangled, String demangled) {
|
||||
//
|
||||
// We get requests to demangle strings that are not mangled. For newer mangled strings
|
||||
// we know how to avoid that. However, older mangled strings can be of many forms. To
|
||||
// detect whether a string is mangled, we have to resort to examining the output of
|
||||
// the demangler.
|
||||
//
|
||||
|
||||
// check for the case where good strings have '__' in them (which is valid GNU2 mangling)
|
||||
if (isInvalidDoubleUnderscoreString(mangled, demangled)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isInvalidDoubleUnderscoreString(String mangled, String demangled) {
|
||||
|
||||
int index = mangled.indexOf("__");
|
||||
if (index == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Bad string form: text__moretext
|
||||
//
|
||||
// The demangler will output something like text(..)(...)(...) or e::text(...)(...)
|
||||
String leadingText = mangled.substring(0, index);
|
||||
return demangled.contains(leadingText);
|
||||
}
|
||||
|
||||
private boolean isGnu2Or3Pattern(String mangled) {
|
||||
|
||||
//@formatter:off
|
||||
return // Gnu2/3 constructs--not sure if we still need these
|
||||
mangled.startsWith("_GLOBAL_.I.") ||
|
||||
mangled.startsWith("_GLOBAL_.D.") ||
|
||||
mangled.startsWith("_GLOBAL__I__Z") ||
|
||||
mangled.startsWith("_GLOBAL__D__Z");
|
||||
//@formatter:on
|
||||
}
|
||||
|
||||
private boolean isELF(String executableFormat) {
|
||||
return executableFormat != null && executableFormat.indexOf(ElfLoader.ELF_NAME) != -1;
|
||||
}
|
||||
|
||||
private boolean isMacho(String executableFormat) {
|
||||
return executableFormat != null && executableFormat.indexOf(MachoLoader.MACH_O_NAME) != -1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/* ###
|
||||
* 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.
|
||||
*/
|
||||
package ghidra.app.util.demangler.gnu;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import ghidra.framework.Application;
|
||||
import ghidra.framework.Platform;
|
||||
|
||||
public class GnuDemanglerNativeProcess {
|
||||
private static final String DEMANGLER_GNU = "demangler_gnu";
|
||||
|
||||
private static GnuDemanglerNativeProcess demanglerNativeProcess;
|
||||
|
||||
private boolean isDisposed;
|
||||
private Process process;
|
||||
private BufferedReader reader;
|
||||
private PrintWriter writer;
|
||||
|
||||
public static synchronized GnuDemanglerNativeProcess getDemanglerNativeProcess()
|
||||
throws IOException {
|
||||
if (demanglerNativeProcess == null) {
|
||||
demanglerNativeProcess = new GnuDemanglerNativeProcess();
|
||||
}
|
||||
return demanglerNativeProcess;
|
||||
}
|
||||
|
||||
private GnuDemanglerNativeProcess() throws IOException {
|
||||
createProcess();
|
||||
}
|
||||
|
||||
public synchronized String demangle(String mangled) throws IOException {
|
||||
if (isDisposed) {
|
||||
throw new IOException("Demangled process has been terminated.");
|
||||
}
|
||||
return demangle(mangled, true);
|
||||
}
|
||||
|
||||
private String demangle(String mangled, boolean restart) throws IOException {
|
||||
try {
|
||||
writer.println(mangled);
|
||||
writer.flush();
|
||||
|
||||
return reader.readLine();
|
||||
}
|
||||
catch (IOException e) {
|
||||
dispose();
|
||||
if (!restart) {
|
||||
demanglerNativeProcess = null;
|
||||
throw new IOException("Demangler process is not running.");
|
||||
}
|
||||
createProcess();
|
||||
return demangle(mangled, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void dispose() {
|
||||
try {
|
||||
if (process != null) {
|
||||
process.destroy();
|
||||
}
|
||||
process = null;
|
||||
reader = null;
|
||||
writer = null;
|
||||
}
|
||||
catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
finally {
|
||||
isDisposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void createProcess() throws IOException {
|
||||
|
||||
String executableName = DEMANGLER_GNU + Platform.CURRENT_PLATFORM.getExecutableExtension();
|
||||
File commandPath = Application.getOSFile(executableName);
|
||||
|
||||
String[] command = new String[] { commandPath.getAbsolutePath() };
|
||||
|
||||
process = Runtime.getRuntime().exec(command);
|
||||
|
||||
InputStream in = process.getInputStream();
|
||||
OutputStream out = process.getOutputStream();
|
||||
|
||||
reader = new BufferedReader(new InputStreamReader(in));
|
||||
writer = new PrintWriter(out);
|
||||
|
||||
isDisposed = false;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,195 @@
|
||||
/* ###
|
||||
* 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.
|
||||
*/
|
||||
package ghidra.app.util.demangler.gnu;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import generic.test.AbstractGenericTest;
|
||||
import ghidra.app.cmd.label.DemanglerCmd;
|
||||
import ghidra.app.util.demangler.*;
|
||||
import ghidra.program.database.ProgramDB;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.data.TerminatedStringDataType;
|
||||
import ghidra.program.model.listing.CodeUnit;
|
||||
import ghidra.program.model.listing.Data;
|
||||
import ghidra.program.model.symbol.*;
|
||||
import ghidra.test.ToyProgramBuilder;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
public class GnuDemanglerTest extends AbstractGenericTest {
|
||||
|
||||
private ProgramDB program;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
ToyProgramBuilder builder = new ToyProgramBuilder("test", true);
|
||||
builder.createMemory(".text", "0x01001000", 0x100);
|
||||
program = builder.getProgram();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonMangledSymbol() throws Exception {
|
||||
|
||||
String mangled = "Java_org_sqlite_NativeDB__1exec";
|
||||
|
||||
GnuDemangler demangler = new GnuDemangler();
|
||||
demangler.canDemangle(program);// this perform initialization
|
||||
|
||||
// this throws an exception with the bug in place
|
||||
demangler.demangle(mangled, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDemangleOnlyKnownPatterns_False() throws Exception {
|
||||
|
||||
String mangled = "abracadabra_hocus_pocus";
|
||||
|
||||
GnuDemangler demangler = new GnuDemangler();
|
||||
demangler.canDemangle(program);// this perform initialization
|
||||
|
||||
try {
|
||||
demangler.demangle(mangled, false);
|
||||
fail("Demangle should have failed attempting to demangle a non-mangled string");
|
||||
}
|
||||
catch (DemangledException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDemangleOnlyKnownPatterns_True() throws Exception {
|
||||
|
||||
String mangled = "abracadabra_hocus_pocus";
|
||||
|
||||
GnuDemangler demangler = new GnuDemangler();
|
||||
demangler.canDemangle(program);// this perform initialization
|
||||
|
||||
DemangledObject result = demangler.demangle(mangled, true);
|
||||
assertNull("Demangle did not skip a name that does not match a known mangled pattern",
|
||||
result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDemangleTypeInfo() throws Exception {
|
||||
|
||||
String mangled = "_ZTIN6AP_HAL3HAL9CallbacksE";
|
||||
|
||||
program.startTransaction("markup...");
|
||||
program.getMemory().setInt(addr("01001000"), 0x1001010);
|
||||
|
||||
SymbolTable symbolTable = program.getSymbolTable();
|
||||
symbolTable.createLabel(addr("01001000"), mangled, SourceType.IMPORTED);
|
||||
|
||||
GnuDemangler demangler = new GnuDemangler();
|
||||
DemangledObject obj = demangler.demangle(mangled, true);
|
||||
assertNotNull(obj);
|
||||
|
||||
//assertEquals("typeinfo for AP_HAL::HAL::Callbacks", obj.getSignature(false));
|
||||
|
||||
assertTrue(
|
||||
obj.applyTo(program, addr("01001000"), new DemanglerOptions(), TaskMonitor.DUMMY));
|
||||
|
||||
Symbol s = symbolTable.getPrimarySymbol(addr("01001000"));
|
||||
assertNotNull(s);
|
||||
assertEquals("typeinfo", s.getName());
|
||||
assertEquals("AP_HAL::HAL::Callbacks", s.getParentNamespace().getName(true));
|
||||
|
||||
assertEquals("typeinfo for AP_HAL::HAL::Callbacks",
|
||||
program.getListing().getComment(CodeUnit.PLATE_COMMENT, addr("01001000")));
|
||||
|
||||
Data d = program.getListing().getDefinedDataAt(addr("01001000"));
|
||||
assertNotNull(d);
|
||||
assertTrue(d.isPointer());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDemangleTypeInfoName() throws Exception {
|
||||
|
||||
String mangled = "_ZTSN6AP_HAL3HAL9CallbacksE";
|
||||
|
||||
program.startTransaction("markup...");
|
||||
program.getMemory().setBytes(addr("01001000"), "ABC\0".getBytes());
|
||||
|
||||
SymbolTable symbolTable = program.getSymbolTable();
|
||||
symbolTable.createLabel(addr("01001000"), mangled, SourceType.IMPORTED);
|
||||
|
||||
GnuDemangler demangler = new GnuDemangler();
|
||||
DemangledObject obj = demangler.demangle(mangled, true);
|
||||
assertNotNull(obj);
|
||||
|
||||
assertEquals("typeinfo name for AP_HAL::HAL::Callbacks", obj.getSignature(false));
|
||||
|
||||
assertTrue(
|
||||
obj.applyTo(program, addr("01001000"), new DemanglerOptions(), TaskMonitor.DUMMY));
|
||||
|
||||
Symbol s = symbolTable.getPrimarySymbol(addr("01001000"));
|
||||
assertNotNull(s);
|
||||
assertEquals("typeinfo_name", s.getName());
|
||||
assertEquals("AP_HAL::HAL::Callbacks", s.getParentNamespace().getName(true));
|
||||
|
||||
assertEquals("typeinfo name for AP_HAL::HAL::Callbacks",
|
||||
program.getListing().getComment(CodeUnit.PLATE_COMMENT, addr("01001000")));
|
||||
|
||||
Data d = program.getListing().getDefinedDataAt(addr("01001000"));
|
||||
assertNotNull(d);
|
||||
assertTrue(d.getDataType() instanceof TerminatedStringDataType);
|
||||
assertEquals("ABC", d.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDemangler_Format_EDG_DemangleOnlyKnownPatterns_False()
|
||||
throws DemangledException {
|
||||
|
||||
String mangled = "_$_10MyFunction";
|
||||
|
||||
GnuDemangler demangler = new GnuDemangler();
|
||||
demangler.canDemangle(program);// this perform initialization
|
||||
|
||||
DemangledObject result = demangler.demangle(mangled, false);
|
||||
assertNotNull(result);
|
||||
assertEquals("undefined MyFunction::~MyFunction(void)", result.getSignature(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDemangler_Format_EDG_DemangleOnlyKnownPatterns_True()
|
||||
throws DemangledException {
|
||||
|
||||
/*
|
||||
Note:
|
||||
This test is less of a requirement and more of an observation. This symbol was
|
||||
seen in the wild and is claimed to be of the Edison Design Group (EDG) format.
|
||||
It fails our parsing due to its resemblance to non-mangled text (see
|
||||
the test testNonMangledSymbol()). If we update the code that checks for this
|
||||
noise, then this test and it's parter should be consolidated.
|
||||
*/
|
||||
|
||||
String mangled = "_$_10MyFunction";
|
||||
|
||||
GnuDemangler demangler = new GnuDemangler();
|
||||
demangler.canDemangle(program);// this perform initialization
|
||||
|
||||
DemangledObject result = demangler.demangle(mangled, true);
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
private Address addr(String address) {
|
||||
return program.getAddressFactory().getAddress(address);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,336 @@
|
||||
###############################################################################################
|
||||
#
|
||||
# GNU V3 MANGLED NAMES
|
||||
#
|
||||
###############################################################################################
|
||||
_Z10enumToEnumP6MYENUM # enumToEnum(MYENUM *)
|
||||
_Z12unionToUnion2_U # unionToUnion(_U)
|
||||
_Z6toChari # toChar(int)
|
||||
_Z6toEnumv # toEnum(void)
|
||||
_Z6toLongi # toLong(int)
|
||||
_Z7toFloati # toFloat(int)
|
||||
_Z7toFloatidcls # toFloat(int,double,char,long,short)
|
||||
_Z7toFloatPiPdPcPlPs # toFloat(int *,double *,char *,long *,short *)
|
||||
_Z7toFloatPPiPPdPPcPPlPPs # toFloat(int * *,double * *,char * *,long * *,short * *)
|
||||
_Z8toDoublei # toDouble(int)
|
||||
_Z9toIntegerf # toInteger(float)
|
||||
_Z9intToEnum6MYENUM # intToEnum(MYENUM)
|
||||
###############################################################################################
|
||||
_Znaj # operator new[](unsigned)
|
||||
###############################################################################################
|
||||
_ZN3FooC1Ei # Foo::Foo[in-charge](int)
|
||||
_ZN3BarC1Ei # Bar::Bar[in-charge](int)
|
||||
_ZN3Bar4FredC1Ei # Bar::Fred::Fred[in-charge](int)
|
||||
###############################################################################################
|
||||
_ZN3Bar4Fred4getXEv # Bar::Fred::getX(void)
|
||||
_ZN3Foo4getEEl # Foo::getE(long)
|
||||
_ZN3Foo4getXEi # Foo::getX(int)
|
||||
_ZN3Foo4getXEv # Foo::getX(void)
|
||||
_ZN3Foo6getBarEv # Foo::getBar(void)
|
||||
_ZN3Foo6getFooEv # Foo::getFoo(void)
|
||||
_ZN3Foo7getBoolEf # Foo::getBool(float)
|
||||
_ZN3Foo7getBoolEv # Foo::getBool(void)
|
||||
###############################################################################################
|
||||
_ZN3FooaSEi # Foo::operator=(int)
|
||||
_ZN3FoolsEi # Foo::operator<<(int)
|
||||
_ZN3FoolsES_ # Foo::operator<<(Foo)
|
||||
_ZN3FoorsEi # Foo::operator>>(int)
|
||||
###############################################################################################
|
||||
_GLOBAL__I__ZN6Magick21borderGeometryDefaultE # global constructors keyed to Magick::borderGeometryDefault
|
||||
###############################################################################################
|
||||
_ZNK6Magick8ColorYUV1yEv # Magick::ColorYUV::y(void) const
|
||||
_ZNK6Magick5ColorcvSsEv # Magick::Color::operator<cast>(std::string)(void) const
|
||||
_ZN6Magick12DrawablePathC1ERKS0_ # Magick::DrawablePath::DrawablePath[in-charge](const Magick::DrawablePath &)
|
||||
_ZNK6Magick9pageImageclERNS_5ImageE # Magick::pageImage::operator()(Magick::Image &) const
|
||||
_ZNK6Magick9pageImageclERNS0_5ImageE # Magick::pageImage::operator()(Magick::pageImage::Image &) const
|
||||
_ZNK6Magick9pageImageclERNS0_5Image3abcE # Magick::pageImage::operator()(Magick::pageImage::Image::abc &) const
|
||||
_ZN6MagickltERKNS_10CoordinateES2_ # Magick::operator<(const Magick::Coordinate &,const Magick::Coordinate &)
|
||||
_ZN6MagickneERKNS_10CoordinateES2_ # Magick::operator!=(const Magick::Coordinate &,const Magick::Coordinate &)
|
||||
_ZN6MagickgtERKNS_5ColorES2_ # Magick::operator>(const Magick::Color &,const Magick::Color &)
|
||||
_ZN6Magick14PathCurvetoAbsC1ERKS0_ # Magick::PathCurvetoAbs::PathCurvetoAbs[in-charge](const Magick::PathCurvetoAbs &)
|
||||
_ZN6Magick4Blob12updateNoCopyEPvjNS0_9AllocatorE # Magick::Blob::updateNoCopy(void *,unsigned int,Magick::Blob::Allocator)
|
||||
###############################################################################################
|
||||
_ZN6Magick18magickCleanUpGuardE # Magick::magickCleanUpGuard
|
||||
_ZN6Magick18magickCleanUpGuardEv # Magick::magickCleanUpGuard(void)
|
||||
_ZN6Magick18magickCleanUpGuardEi # Magick::magickCleanUpGuard(int)
|
||||
_ZN6Magick21borderGeometryDefaultE # Magick::borderGeometryDefault
|
||||
###############################################################################################
|
||||
_ZNK6Magick18DrawablePopPatternclEPN9MagickLib12_DrawContextE # Magick::DrawablePopPattern::operator()(MagickLib::_DrawContext *) const
|
||||
_ZNK6Magick9CoderInfo4nameEv # Magick::CoderInfo::name(void) const
|
||||
###############################################################################################
|
||||
_ZN6Magick5ImageC2EjjRKSsN9MagickLib11StorageTypeEPKv # Magick::Image::Image[not-in-charge](unsigned, unsigned, const std::basic_string<char, std::char_traits<char>, std::allocator<char>> &, MagickLib::StorageType, const void *)
|
||||
###############################################################################################
|
||||
_ZNSsC1ERKSs # std::string::std::string[in-charge](const std::string &)
|
||||
_ZNSsC1EPKcRKSaIcE # std::string::std::string[in-charge](const char *,const std::allocator<char> &)
|
||||
_ZNSsC1EPKcjRKSaIcE # std::string::std::string[in-charge](const char *,unsigned int,const std::allocator<char> &)
|
||||
###############################################################################################
|
||||
_ZN6Magick14DrawableBezierC1ERKSt4listINS_10CoordinateESaIS2_EE
|
||||
_ZN6Magick12DrawablePathC2ERKSt4listINS_5VPathESaIS2_EE
|
||||
###############################################################################################
|
||||
_ZNSt10_List_baseIN6Magick11PathArcArgsESaIS1_EED2Ev # std::_List_base<Magick::PathArcArgs,std::allocator<Magick::PathArcArgs>>::~_List_base[not-in-charge](void)
|
||||
_ZNSt24__default_alloc_templateILb1ELi0EE8allocateEj
|
||||
_ZNSt10_List_baseIN6Magick5VPathESaIS1_EE5clearEv
|
||||
_ZNSt10_List_baseIN6Magick8DrawableESaIS1_EE5clearEv
|
||||
_ZNSt10_List_baseIN6Magick8DrawableESaIS1_EED2Ev
|
||||
_ZNSt4listIN6Magick8DrawableESaIS1_EE14_M_create_nodeERKS1_
|
||||
_ZNSt10_List_baseIN6Magick10CoordinateESaIS1_EE5clearEv
|
||||
_ZNSt10_List_baseIN6Magick5VPathESaIS1_EE5clearEv
|
||||
_ZNSt10_List_baseIN6Magick11PathArcArgsESaIS1_EE5clearEv
|
||||
_ZNSt10_List_baseIN6Magick15PathCurvetoArgsESaIS1_EE5clearEv
|
||||
_ZNSt10_List_baseIN6Magick24PathQuadraticCurvetoArgsESaIS1_EE5clearEv
|
||||
_ZNSt10_List_baseIN6Magick10CoordinateESaIS1_EED2Ev
|
||||
_ZNSt10_List_baseIN6Magick5VPathESaIS1_EED2Ev
|
||||
_ZNSt10_List_baseIN6Magick15PathCurvetoArgsESaIS1_EED2Ev
|
||||
_ZNSt10_List_baseIN6Magick24PathQuadraticCurvetoArgsESaIS1_EED2Ev
|
||||
_ZNSt4listIN6Magick10CoordinateESaIS1_EE14_M_create_nodeERKS1_
|
||||
_ZNSt4listIN6Magick11PathArcArgsESaIS1_EE14_M_create_nodeERKS1_
|
||||
_ZNSt4listIN6Magick15PathCurvetoArgsESaIS1_EE14_M_create_nodeERKS1_
|
||||
_ZNSt4listIN6Magick24PathQuadraticCurvetoArgsESaIS1_EE14_M_create_nodeERKS1_
|
||||
_ZNKSt8_Rb_treeI8LocationS0_St9_IdentityIS0_ESt4lessIS0_ESaIS0_EE4findERKS0_ # std::_Rb_tree<Location,Location,std::_Identity<Location>,std::less<Location>,std::allocator<Location>>::find(const Location &) const
|
||||
_ZNSt4listIN6Magick8DrawableESaIS1_EE14_M_create_nodeERKS1_ # std::list<Magick::Drawable,std::allocator<Magick::Drawable>>::_M_create_node(const Magick::Drawable &)
|
||||
_ZNSt4listIN6Magick8DrawableESaIS0_EE14_M_create_nodeERKS1_ # std::list<Magick::Drawable,std::allocator<Magick>>::_M_create_node(const Magick::Drawable &)
|
||||
_ZNSt4listIN6Magick8DrawableESaIS_EE14_M_create_nodeERKS1_ # std::list<Magick::Drawable,std::allocator<std::list>>::_M_create_node(const Magick::Drawable &)
|
||||
|
||||
|
||||
|
||||
# TEMPLATED CONSTRUCTORS
|
||||
_ZN6Magick14PathCurvetoAbsC2ERKSt4listINS_15PathCurvetoArgsESaIS2_EE
|
||||
_ZN6Magick14PathCurvetoAbsC1ERKSt4listINS_15PathCurvetoArgsESaIS2_EE
|
||||
_ZN6Magick13PathLinetoRelC2ERKSt4listINS_10CoordinateESaIS2_EE
|
||||
|
||||
_ZNSt4listIN6Magick24PathQuadraticCurvetoArgsESaIS1_EE14_M_fill_insertESt14_List_iteratorIS1_RS1_PS1_EjRKS1_
|
||||
_ZNSt4listIN6Magick24PathQuadraticCurvetoArgsESaIS1_EE18_M_insert_dispatchISt14_List_iteratorIS1_RKS1_PS6_EEEdS5_IS1_RS1_PS1_ET_SD_12__false_type
|
||||
|
||||
_ZNSt14__simple_allocISt10_List_nodeIN6Magick5VPathEESt24__default_alloc_templateILb1ELi0EEE10deallocateEPS3_j
|
||||
|
||||
_ZSt10__distanceISt14_List_iteratorIN6Magick10CoordinateERKS2_PS3_EENSt15iterator_traitsIT_E15difference_typeES8_S8_St18input_iterator_tag
|
||||
|
||||
|
||||
#note: this mangled named contridicts.
|
||||
#the "S1_" is supposed to refer to bbnode, but ends up referring
|
||||
#to "std::less"
|
||||
#_ZNSt3setIP6bbnodeSt4lessIS1_ESaIS1_EE6insertERKS1_ # std::set<bbnode *,std::less<bbnode *>,std::allocator<bbnode *>>::insert(const bbnode * &)
|
||||
|
||||
###############################################################################################
|
||||
|
||||
_ZNSt24__default_alloc_templateILb1ELi0EE8allocateEj # std::__default_alloc_template<(bool)1, (int)0>::allocate(unsigned)
|
||||
|
||||
###############################################################################################
|
||||
_ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_EPKS3_RKS6_ #
|
||||
###############################################################################################
|
||||
_ZTch0_h40_NK8KHotKeys14Window_trigger4copyEPNS_11Action_dataE # covariant_return_thunk[0,40] KHotKeys::Window_trigger::copy(KHotKeys::Action_data *) const
|
||||
_ZTch0_h40_NK8KHotKeys23Active_window_condition4copyEPNS_19Condition_list_baseE # covariant_return_thunk[0,40] KHotKeys::Active_window_condition::copy(KHotKeys::Condition_list_base *) const
|
||||
###############################################################################################
|
||||
_ZThn72_N8KHotKeys11KHotKeysAppD0Ev # nonvirtual_thunk[-72] KHotKeys::KHotKeysApp::~KHotKeysApp[in-charge deleting](void)
|
||||
_ZThn40_N8KHotKeys14Window_triggerD1Ev # nonvirtual_thunk[-40] KHotKeys::Window_trigger::~Window_trigger[in-charge](void)
|
||||
_ZThn204_N8KHotKeys11KHotKeysApp9functionsEv # nonvirtual_thunk[-204] KHotKeys::KHotKeysApp::functions(void)
|
||||
_ZThn8_NSdD0Ev # nonvirtual_thunk[-8] std::iostream::~std::iostream[in-charge deleting](void)
|
||||
_ZThn8_NSdD1Ev # nonvirtual_thunk[-8] std::iostream::~std::iostream[in-charge](void)
|
||||
_ZThn8_NSdD1Ev # nonvirtual_thunk[-8] std::iostream::~std::iostream[in-charge](void)
|
||||
###############################################################################################
|
||||
_ZThn8_NSt13basic_fstreamIcSt11char_traitsIcEED0Ev # nonvirtual_thunk[-8] std::basic_fstream<char,std::char_traits<char>>::~basic_fstream[in-charge deleting](void)
|
||||
_ZThn8_NSt18basic_stringstreamIwSt11char_traitsIwESaIwEED0Ev # nonvirtual_thunk[-8] std::basic_stringstream<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t>>::~basic_stringstream[in-charge deleting](void)
|
||||
###############################################################################################
|
||||
_ZTv0_n44_N4Arts20FileInputStream_skel14_interfaceNameEv # virtual_thunk[0,-44] Arts::FileInputStream_skel::_interfaceName(void)
|
||||
_ZTv0_n48_N4Arts20FileInputStream_impl9streamEndEv # virtual_thunk[0,-48] Arts::FileInputStream_impl::streamEnd(void)
|
||||
_ZTv0_n52_N4Arts16InputStream_baseD0Ev # virtual_thunk[0,-52] Arts::InputStream_base::~InputStream_base[in-charge deleting](void)
|
||||
_ZTv0_n96_N4Arts20FileInputStream_skel17_isCompatibleWithERKSs # virtual_thunk[0,-96] Arts::FileInputStream_skel::_isCompatibleWith(const std::string &)
|
||||
#_ZTv0_n88_N4Arts20FileInputStream_impl15request_outdataEPNS_10DataPacketIhEE # virtual_thunk[0,-88] Arts::FileInputStream_impl::request_outdata(Arts::DataPacket<unsigned char>*)
|
||||
###############################################################################################
|
||||
_ZTVN4Arts16InputStream_skelE # Arts::InputStream_skel::vtable
|
||||
_ZTVN4Arts16SynthModule_skelE # Arts::SynthModule_skel::vtable
|
||||
_ZTVN4Arts17StdoutWriter_implE # Arts::StdoutWriter_impl::vtable
|
||||
_ZTVN4Arts25StdoutWriter_impl_FactoryE # Arts::StdoutWriter_impl_Factory::vtable
|
||||
_ZTVN4Arts28FileInputStream_impl_FactoryE # Arts::FileInputStream_impl_Factory::vtable
|
||||
_ZTVN10__cxxabiv121__vmi_class_type_infoE # __cxxabiv1::__vmi_class_type_info::vtable
|
||||
###############################################################################################
|
||||
_ZTTN4Arts14StdSynthModuleE # Arts::StdSynthModule::VTT
|
||||
_ZTTN4Arts16SynthModule_skelE # Arts::SynthModule_skel::VTT
|
||||
_ZTT13Observer_stub # Observer_stub::VTT
|
||||
_ZTT8UIServer # UIServer::VTT
|
||||
###############################################################################################
|
||||
_ZTIN4Arts28FileInputStream_impl_FactoryE # Arts::FileInputStream_impl_Factory::typeinfo
|
||||
_ZTIN4Arts20FileInputStream_baseE # Arts::FileInputStream_base::typeinfo
|
||||
_ZTIN4Arts16InputStream_skelE # Arts::InputStream_skel::typeinfo
|
||||
_ZTI13Observer_stub # Observer_stub::typeinfo
|
||||
_ZTI18UIServerSystemTray # UIServerSystemTray::typeinfo
|
||||
_ZTI8QPtrListI15KSSLCertificateE # QPtrList::typeinfo
|
||||
###############################################################################################
|
||||
#_ZTF
|
||||
###############################################################################################
|
||||
_ZTSN6Magick15DrawableViewboxE # typeinfo name for N6Magick15DrawableViewboxE
|
||||
_ZTSN6Magick22DrawableRoundRectangleE # typeinfo name for N6Magick22DrawableRoundRectangleE
|
||||
_ZTSN10__cxxabiv116__enum_type_infoE # typeinfo name for N10__cxxabiv116__enum_type_infoE
|
||||
_ZTSNSt8ios_base7failureE # typeinfo name for NSt8ios_base7failureE
|
||||
#_ZTSSt14unary_functionIPN9MagickLib12_DrawContextEvE # typeinfo name for std::unary_function<MagickLib::_DrawContext*,void>
|
||||
#_ZTSSt5ctypeIcE # typeinfo name for std::ctype<char>
|
||||
#_ZTSSt14basic_ifstreamIwSt11char_traitsIwEE # typeinfo name for std::basic_ifstream<wchar_t, std::char_traits<wchar_t>>
|
||||
#_ZTSSt12out_of_range # typeinfo name for std::out_of_range
|
||||
#_ZTSSd # typeinfo name for std::basic_iostream<char, std::char_traits<char>>
|
||||
#_ZTSSi # typeinfo name for std::basic_istream<char, std::char_traits<char>>
|
||||
#_ZTSSo # typeinfo name for std::basic_ostream<char, std::char_traits<char>>
|
||||
#_ZTSSt10__num_base # typeinfo name for std::__num_base
|
||||
###############################################################################################
|
||||
#_ZTJ
|
||||
###############################################################################################
|
||||
_ZTCN4Arts17StdoutWriter_implE68_NS_11Object_skelE # Arts::StdoutWriter_impl::construction_vtable[68]
|
||||
_ZTCN4Arts20FileInputStream_implE0_NS_16SynthModule_baseE # Arts::FileInputStream_impl::construction_vtable[0]
|
||||
_ZTCN4Arts20FileInputStream_implE112_NS_16InputStream_skelE # Arts::FileInputStream_impl::construction_vtable[112]
|
||||
_ZTCN4Arts20FileInputStream_implE132_NS_16SynthModule_skelE # Arts::FileInputStream_impl::construction_vtable[132]
|
||||
###############################################################################################
|
||||
_ZGVZN10KDirLister11emitChangesEvE3dot # guard variable for KDirLister::emitChanges(void)::dot
|
||||
_ZGVZN11KFileDialog16pathComboChangedERK7QStringE9localRoot # guard variable for KFileDialog::pathComboChanged(const_QString_&)::localRoot
|
||||
_ZGVZNK17KSimpleFileFilter12passesFilterEPK9KFileItemE6dotdot # guard variable for KSimpleFileFilter::passesFilter(const_KFileItem_*)::dotdot
|
||||
#_ZGVZN15KDirListerCache11slotEntriesEPN3KIO3JobERK10QValueListIS3_INS0_7UDSAtomEEEE3dot # guard variable for KDirListerCache::slotEntries(KIO::Job*,const QValueList<QValueList<KIO::USDAtom>> &)::dot
|
||||
#_ZGVZN9__gnu_cxx20__common_pool_policyINS_6__poolELb1EE11_S_get_poolEvE7_S_pool # guard variable for __gnu_cxx::__common_pool_policy<__gnu_cxx::__pool, true>::_S_get_pool()::_S_pool
|
||||
_ZGRZNK17KSimpleFileFilter12passesFilterEPK9KFileItemE6dotdot # reference temporary for KSimpleFileFilter::passesFilter(const_KFileItem_*)::dotdot
|
||||
#_ZGRZN15KDirListerCache11slotEntriesEPN3KIO3JobERK10QValueListIS3_INS0_7UDSAtomEEEE3dot # reference temporary for KDirListerCache::slotEntries(KIO::Job*,const QValueList<QValueList<KIO::USDAtom>> &)::dot
|
||||
###############################################################################################
|
||||
_ZZN11KFileDialog16staticMetaObjectEvE12param_slot_0 # KFileDialog::staticMetaObject(void)::param_slot_0
|
||||
_ZZN11KFileDialog16staticMetaObjectEijE12param_slot_0 # KFileDialog::staticMetaObject(int,unsigned_int)::param_slot_0
|
||||
_ZZN11KFileDialog16staticMetaObjectEvE12param_slot_1 # KFileDialog::staticMetaObject(void)::param_slot_1
|
||||
_ZZNK9KFileItem6pixmapEiiE17defaultFolderIcon # KFileItem::pixmap(int,int)::defaultFolderIcon
|
||||
_ZZNK10KDirLister13matchesFilterEPK9KFileItemE6dotdot # KDirLister::matchesFilter(const_KFileItem_*)::dotdot
|
||||
_ZZN8Observer16staticMetaObjectEvE7slot_10 # Observer::staticMetaObject(void)::slot_10
|
||||
_ZZN9KMimeType9findByURLERK4KURLjbbE9dotkdelnk # KMimeType::findByURL(const_KURL_&,unsigned_int,bool,bool)::dotkdelnk
|
||||
_ZZN3KIO9http_postERK4KURLRK9QMemArrayIcEbE9bad_ports # KIO::http_post(const_KURL_&,const_QMemArray<char>_&,bool)::bad_ports
|
||||
#_ZZN9__gnu_cxx20__common_pool_policyINS_6__poolELb1EE11_S_get_poolEvE7_S_pool # __gnu_cxx::__common_pool_policy<__gnu_cxx::__pool, true>::_S_get_pool()::_S_pool
|
||||
###############################################################################################
|
||||
_Znaj # operator<new>[](unsigned int)
|
||||
_ZeqRK7QStringPKc # operator==(const QString &,const char *)
|
||||
_ZdlPv # operator<delete>(void *)
|
||||
_ZlsR11QDataStreamRK9QMemArrayIcE # operator<<(QDataStream &,const QMemArray<char> &)
|
||||
_ZltRK7QStringS1_ # operator<(const QString &,const QString &)
|
||||
#_ZlsI8QCStringER11QDataStreamS2_RK10QValueListIT_E # QDataStream&& operator<< <QCString>(QDataStream&, QValueList<QCString> const&)
|
||||
_ZlsR16OutputCharStreamR11GroveString # operator<<(OutputCharStream &,GroveString &)
|
||||
_ZeqRK6StringItEPKc # operator==(const String<unsigned short> &,const char *)
|
||||
###############################################################################################
|
||||
#
|
||||
# OLD STYLE GNU GCC MANGLED NAMES
|
||||
#
|
||||
# These can be created using /usr/bin/gcc296.
|
||||
#
|
||||
###############################################################################################
|
||||
|
||||
###############################################################################################
|
||||
# Functions...
|
||||
###############################################################################################
|
||||
__default_terminate__Fv # __default_terminate(void)
|
||||
__fast_compare__FPCcT0 # __fast_compare(const char *,const char *)
|
||||
pipeName__Fi # pipeName(int)
|
||||
cocaConnect__FPCc # cocaConnect(const char *)
|
||||
cocaConnectAction__FPvP6tTsTmr # cocaConnectAction(void *,tTsTmr *)
|
||||
cocaMulticast__FP11msgGenStruc # cocaMulticast(msgGenStruc *)
|
||||
mfgDataFill__FsP10tManufDataUiPc # mfgDataFill(short,tManufData *,unsigned int,char *)
|
||||
printSem__FPP9semaphore # printSem(semaphore * *)
|
||||
###############################################################################################
|
||||
# Constructors...
|
||||
###############################################################################################
|
||||
__8ofstreamicii # ofstream::ofstream(int,char,int,int)
|
||||
__8ofstreamiPcii # ofstream::ofstream(int,char *,int,int)
|
||||
__8ofstreamiPCcii # ofstream::ofstream(int,const char *,int,int)
|
||||
__8ofstreamiPCVcii # ofstream::ofstream(int,const volatile char *,int,int)
|
||||
__11_ios_fields # _ios_fields::_ios_fields()
|
||||
__11RtrvFsteCmdiPcT2 # RtrvFsteCmd::RtrvFsteCmd(int,char *,char *)
|
||||
__17RtrvPmschedDsnCmdiPcT29MOD2_ENUM # RtrvPmschedDsnCmd::RtrvPmschedDsnCmd(int,char *,char *,MOD2_ENUM)
|
||||
###############################################################################################
|
||||
# Destructors...
|
||||
###############################################################################################
|
||||
_._8Document # Document::~Document()
|
||||
_._8Documentfi # Document::~Document(float,int)
|
||||
_._C8Documentcb # Document::~Document(char,bool) const
|
||||
###############################################################################################
|
||||
# C++ Methods...
|
||||
###############################################################################################
|
||||
__fb_init__11istreambase # istreambase::__fb_init()
|
||||
flags__3iosUI # ios::flags(unsigned int0_t)
|
||||
clear__8LogArrayUi # LogArray::clear(unsigned int)
|
||||
isValid__8LogArrayUi # LogArray::isValid(unsigned int)
|
||||
getDefaultValue__C12OpticsParKeyRlN21 # OpticsParKey::getDefaultValue(long &,long &,long &) const
|
||||
getDefaultValue__C12OpticsParKeyRbN10_1 # OpticsParKey::getDefaultValue(bool &,bool &,bool &,bool &,bool &,bool &,bool &,bool &,bool &,bool &,bool &) const
|
||||
getSsmRefStrip__8SyncImplRUcRScT1 # SyncImpl::getSsmRefStrip(unsigned char &,short &,char,unsigned char &)
|
||||
###############################################################################################
|
||||
__eq__C9type_infoRC9type_info # type_info::operator==(const type_info &) const
|
||||
__ls__7ostreamP9streambuf # ostream::operator<<(streambuf *)
|
||||
__opPc__C8MyString # MyString::operator char *() const
|
||||
__opPb__C8MyString # MyString::operator bool *() const
|
||||
__opl__C8MyStringi # MyString::operator long(int) const
|
||||
###############################################################################################
|
||||
setObjectId__14LmpGeneralImplPt9XpsUFLSeq2ZUcZUc # LmpGeneralImpl::setObjectId(XpsUFLSeq<unsigned char,unsigned char> *)
|
||||
setObjectId__14LmpGeneralImplPt9XpsUFLSeq3ZUcZUcZUi # LmpGeneralImpl::setObjectId(XpsUFLSeq<unsigned char,unsigned char,unsigned int> *)
|
||||
setObjectId__14LmpGeneralImplPt9XpsUFLSeq3ZUcZUcZUii # LmpGeneralImpl::setObjectId(XpsUFLSeq<unsigned char,unsigned char,unsigned int> *,int)
|
||||
setObjectId__14LmpGeneralImplbPt9XpsUFLSeq3ZUcZUcZUii # LmpGeneralImpl::setObjectId(bool,XpsUFLSeq<unsigned char,unsigned char,unsigned int> *,int)
|
||||
setObjectId__14LmpGeneralImplbPt9XpsUFLSeq10_ZbZbZbZbZbZbZbZbZbZbi # LmpGeneralImpl::setObjectId(bool,XpsUFLSeq<bool,bool,bool,bool,bool,bool,bool,bool,bool,bool> *,int)
|
||||
###############################################################################################
|
||||
# Function Pointers...
|
||||
###############################################################################################
|
||||
fPtr1__FPFi_fi # fPtr1(float (*)(int),int)
|
||||
fPtr1__FPPFi_fi # fPtr1(float (**)(int),int)
|
||||
fPtr1__FPFi_ci # fPtr1(char (*)(int),int)
|
||||
fPtr1__FPFi_fiP9_MYSTRUCT # fPtr1(float (*)(int),int,_MYSTRUCT *)
|
||||
fPtr1__FPFi_ciP9_MYSTRUCT # fPtr1(char (*)(int),int,_MYSTRUCT *)
|
||||
fPtr2__FPFiPfc_fPFidPb_cidc # fPtr2(float (*)(int,float *,char),char (*)(int,double,bool *),int,double,char)
|
||||
###############################################################################################
|
||||
# Type Info...
|
||||
###############################################################################################
|
||||
__tf14ContentHandler # ContentHandler::type_info_function()
|
||||
__tf11TreeHandler # TreeHandler::type_info_function()
|
||||
__ti14ContentHandler # ContentHandler::type_info_node()
|
||||
__ti9xml_error # xml_error::type_info_node()
|
||||
###############################################################################################
|
||||
_repository_id__C14CORBA_INV_FLAG # CORBA_INV_FLAG::_repository_id() const
|
||||
_repository_id__Q210Ds123Media7General # Ds123Media::General::_repository_id()
|
||||
_set_stub_factory__12CORBA_ObjectPFP7IOP_IOR_P12CORBA_Object # CORBA_Object::_set_stub_factory(CORBA_Object * (*)(IOP_IOR *))
|
||||
_set_stub_factory__Q23Lmp7GeneralPFP7IOP_IOR_PQ23Lmp7General # Lmp::General::_set_stub_factory(Lmp::General * (*)(IOP_IOR *))
|
||||
_factory__Q27FCTrunk12General_stubP7IOP_IOR # FCTrunk::General_stub::_factory(IOP_IOR *)
|
||||
###############################################################################################
|
||||
_4Node.FTAM_ERR_SEND_LOC_FILE # Node::FTAM_ERR_SEND_LOC_FILE
|
||||
_4Node.SysErr # Node::SysErr
|
||||
_4Rmon._tc__a_Rmon___CORBA__Char_21_32 # Rmon::_tc__a_Rmon___CORBA__Char_21_32
|
||||
_6Optics._tc_General # Optics::_tc_General
|
||||
_6XpsCDR.m_lut4 # XpsCDR::m_lut4
|
||||
_7FCMedia._tc__a_FC___CORBA__Char_31_32 # FCMedia::_tc__a_FC___CORBA__Char_31_32
|
||||
###############################################################################################
|
||||
_GLOBAL_.D.chipSet # global destructors keyed to chipSet
|
||||
_GLOBAL_.D.acHelp__Fv # global destructors keyed to acHelp(void)
|
||||
_GLOBAL_.D.__7XcVtTblss # global destructors keyed to XcVtTbl::XcVtTbl(short,short)
|
||||
_GLOBAL_.D._10ClientInfo.list # global destructors keyed to ClientInfo::list
|
||||
_GLOBAL_.D.testCreateStsMonitor__FUiUiUiUiUiUiUi # global destructors keyed to testCreateStsMonitor(unsigned int,unsigned int,unsigned int,unsigned int,unsigned int,unsigned int,unsigned int)
|
||||
_GLOBAL_.D._._10opticalArc # global destructors keyed to opticalArc::~opticalArc()
|
||||
_GLOBAL_.D.__10RollClientiPcPFPv_v # global destructors keyed to RollClient::RollClient(int,char *,void (*)(void *))
|
||||
_GLOBAL_.D.__ls__FR7ostreamQ214OpticsTopology15eConnectionType # global destructors keyed to operator<<(ostream &,OpticsTopology::eConnectionType)
|
||||
_GLOBAL_.D.__ls__FR7ostreamRC15CORBA_Exception # global destructors keyed to operator<<(ostream &,const CORBA_Exception &)
|
||||
_GLOBAL_.D._release__4_var # global destructors keyed to _var::_release()
|
||||
_GLOBAL_.D._type_id__12CORBA_Policy # global destructors keyed to CORBA_Policy::_type_id()
|
||||
_GLOBAL_.D._type_id__Q22If15xAlsConfigError # global destructors keyed to If::xAlsConfigError::_type_id()
|
||||
_GLOBAL_.D.__as__25tRmonAlarmPersistenceInfoRC28tRmonAlarmPersistenceInfo_V1 # global destructors keyed to tRmonAlarmPersistenceInfo::operator=(const tRmonAlarmPersistenceInfo_V1 &)
|
||||
_GLOBAL_.D.__17RtrvRollClientStsiPcT29MOD2_ENUM # global destructors keyed to RtrvRollClientSts::RtrvRollClientSts(int,char *,char *,MOD2_ENUM)
|
||||
###############################################################################################
|
||||
_GLOBAL_.I.esiTable # global constructors keyed to esiTable
|
||||
_GLOBAL_.I.corbaRmonAlarmAdminInfoGet__FUlPQ24Rmon15sAlarmAdminInfo # global constructors keyed to corbaRmonAlarmAdminInfoGet(unsigned long,Rmon::sAlarmAdminInfo *)
|
||||
_GLOBAL_.I.convertVc4ToSts__12MetaRangeVc4i # global constructors keyed to MetaRangeVc4::convertVc4ToSts(int)
|
||||
_GLOBAL_.I.acHelp__Fv # global constructors keyed to acHelp(void)
|
||||
_GLOBAL_.I._10ClientInfo.list # global constructors keyed to ClientInfo::list
|
||||
_GLOBAL_.I.__12PvmPluggable # global constructors keyed to PvmPluggable::PvmPluggable()
|
||||
_GLOBAL_.I.__11FtpIoUploadPCcN41iUiRCQ25FtpIo12FttdConnInfo # global constructors keyed to FtpIoUpload::FtpIoUpload(const char *,const char *,const char *,const char *,const char *,int,unsigned int,const FtpIo::FttdConnInfo &)
|
||||
_GLOBAL_.I.__17SetBulkRollClientiPcN429MOD2_ENUMPFPv_v # global constructors keyed to SetBulkRollClient::SetBulkRollClient(int,char *,char *,char *,char *,char *,MOD2_ENUM,void (*)(void *))
|
||||
###############################################################################################
|
||||
__t9allocator1ZP7Element # allocator<Element *>::allocator()
|
||||
__t14XpsMapIterator2ZlZP14CORBA_TypeCode # XpsMapIterator<long,CORBA_TypeCode *>::XpsMapIterator()
|
||||
__t6XpsMap2ZlZP14CORBA_TypeCodePFRCl_UlUlUlf # XpsMap<long,CORBA_TypeCode *>::XpsMap(unsigned long (*)(const long &),unsigned long,unsigned long,float)
|
||||
_._t6XpsMap2ZlZP14CORBA_TypeCode # XpsMap<long,CORBA_TypeCode *>::~XpsMap()
|
||||
_._t14XpsPolicy_impl1Zs # XpsPolicy_impl<short>::~XpsPolicy_impl()
|
||||
_cast__Ct14XpsPolicy_impl1Zsl # XpsPolicy_impl<short>::_cast(long) const
|
||||
erase__t6XpsMap2ZlZP14CORBA_TypeCode # XpsMap<long,CORBA_TypeCode *>::erase()
|
||||
__vc__t6XpsMap2ZlZP14CORBA_TypeCodeRCl # XpsMap<long,CORBA_TypeCode *>::operator[](const long &)
|
||||
###############################################################################################
|
||||
_Q214LmpGeneralImpl13ProductConfig.dbVer # LmpGeneralImpl::ProductConfig::dbVer
|
||||
###############################################################################################
|
||||
invoke_request_wrapper__42PortableInterceptor_ClientRequestInfo_implUlP15IOP_ClientCodecR12CORBA_ObjectRt9XpsUFLSeq2ZUcZUcPcUlQ25CORBA13OperationModeUcP18CORBA_ReplyHandlerP9IOP_ParamUlT10_UlRt9XpsUVLSeq1ZQ23IOP14ServiceContextT14_RUcUxR17CORBA_Environment # PortableInterceptor_ClientRequestInfo_impl::invoke_request_wrapper(unsigned long,IOP_ClientCodec *,CORBA_Object &,XpsUFLSeq<unsigned char,unsigned char> &,char *,unsigned long,CORBA::OperationMode,unsigned char,CORBA_ReplyHandler *,IOP_Param *,unsigned long,IOP_Param *,unsigned long,XpsUVLSeq<IOP::ServiceContext> &,XpsUVLSeq<IOP::ServiceContext> &,unsigned char &,unsigned long long,CORBA_Environment &)
|
||||
###############################################################################################
|
||||
#get_codec_factory__8__ssliop # __ssliop::get_codec_factory()
|
||||
#get_codec_factory__16__ssliop__ssliop # __ssliop__ssliop::get_codec_factory()
|
||||
#get_codec_factory__8__ssliop # __ssliop::get_codec_factory()
|
||||
#__get__codec__factory__16__ssliop__ssliop # __ssliop__ssliop::__get__codec__factory()
|
||||
#__get__codec__4__factory__16__ssliop__ssliopi # __ssliop__ssliop::__get__codec__4__factory(int)
|
||||
###############################################################################################
|
||||
@@ -0,0 +1,16 @@
|
||||
__ZTV15_IOConfigThread #
|
||||
__ZN8IOSyncer9metaClassE #
|
||||
__ZN8IOSyncer10superClassE #
|
||||
|
||||
__ZN12KLDBootstrapD1Ev #
|
||||
__ZN12KLDBootstrapD2Ev #
|
||||
__ZN12KLDBootstrapC1Ev #
|
||||
__ZN12KLDBootstrapC2Ev #
|
||||
|
||||
__ZL26kCharsetNameISOLatinHebrew
|
||||
__ZN9__gnu_cxxL16__stl_prime_listE
|
||||
__ZNSs6appendERKSs
|
||||
__ZTV21MmsMessageClassHeader
|
||||
|
||||
__ZL30addRecipientsFromMmsWithHeaderPKcP10MmsMessageP9CTMessage # addRecipientsFromMmsWithHeader(char const*, MmsMessage*, CTMessage*)
|
||||
__ZZN13MmsPduDecoder21_decodeMessageHeadersEP10MmsMessageE15requiredHeaders
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user