mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
273 lines
9.6 KiB
Java
273 lines
9.6 KiB
Java
/* ###
|
|
* IP: GHIDRA
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
package mdemangler.object;
|
|
|
|
import mdemangler.*;
|
|
import mdemangler.MDMang.ProcessingMode;
|
|
import mdemangler.datatype.MDDataTypeParser;
|
|
import mdemangler.template.MDTemplateNameAndArguments;
|
|
|
|
/**
|
|
* This class parses the mangled string at the current offset to determine and
|
|
* create the appropriate type of <b><code>MDObject</code></b>.
|
|
*/
|
|
public class MDMangObjectParser {
|
|
|
|
public static MDParsableItem determineItemAndParse(MDMang dmang) throws MDException {
|
|
boolean retry = false;
|
|
MDException firstException = null;
|
|
MDParsableItem myItem = null;
|
|
int index = dmang.getIndex();
|
|
try {
|
|
myItem = parseDefaultStandard(dmang);
|
|
if (myItem != null) {
|
|
myItem.parse();
|
|
}
|
|
else {
|
|
retry = true;
|
|
}
|
|
}
|
|
catch (MDException e) {
|
|
retry = true;
|
|
myItem = null;
|
|
firstException = e;
|
|
}
|
|
if (!retry) {
|
|
return myItem;
|
|
}
|
|
try {
|
|
dmang.setIndex(index);
|
|
myItem = parseLlvm(dmang);
|
|
if (myItem != null) {
|
|
myItem.parse();
|
|
}
|
|
}
|
|
catch (MDException e) {
|
|
if (firstException != null) {
|
|
throw firstException;
|
|
}
|
|
throw e;
|
|
}
|
|
if (myItem == null && firstException != null) {
|
|
throw firstException;
|
|
}
|
|
return myItem;
|
|
}
|
|
|
|
public static MDParsableItem parseDefaultStandard(MDMang dmang) throws MDException {
|
|
MDParsableItem item;
|
|
dmang.setProcessingMode(ProcessingMode.DEFAULT_STANDARD);
|
|
if (dmang.peek() == '?') {
|
|
if (dmang.peek(1) == '@') {
|
|
item = new MDObjectCodeView(dmang);
|
|
}
|
|
else if (dmang.peek(1) == '$') {
|
|
item = new MDTemplateNameAndArguments(dmang);
|
|
}
|
|
else {
|
|
item = new MDObjectCPP(dmang);
|
|
}
|
|
}
|
|
else if ((dmang.peek() == '_') &&
|
|
((dmang.peek(1) == '_') || ((dmang.peek(1) >= 'A') && (dmang.peek(1) <= 'Z')))) {
|
|
item = parseObjectReserved(dmang);
|
|
}
|
|
else if (dmang.peek() == '.') {
|
|
dmang.increment();
|
|
item = MDDataTypeParser.parseDataType(dmang, false);
|
|
}
|
|
else {
|
|
item = new MDObjectC(dmang);
|
|
}
|
|
return item;
|
|
}
|
|
|
|
public static MDParsableItem parseLlvm(MDMang dmang) {
|
|
// Might eliminate next test if we create other "non-standard" processing
|
|
// that does not begin with "?$".
|
|
if (dmang.peek() != '?' && dmang.peek(1) != '$') {
|
|
return null;
|
|
}
|
|
dmang.setProcessingMode(ProcessingMode.LLVM);
|
|
MDObjectCPP item = new MDObjectCPP(dmang);
|
|
return item;
|
|
}
|
|
|
|
// Thus far, we have seen (created from forward code example):
|
|
// __mep => [MEP], which is presumably "Managed Entry Point"
|
|
// __t2m => [T2M], which is presumably "Transition to Managed (code)"
|
|
// Other double underscore values, seen internal to symbols (which we are not sure about
|
|
// whether comes back to this code):
|
|
// ____abi
|
|
// __mpnHeap
|
|
// __pParameter_m
|
|
// We have seen other examples (in our compiled jan_gray code) that show up in the
|
|
// symbols, but dumpbin does not give a demangled output for them. In both of these,
|
|
// we currently let the first '$' be part of the bracketed string (our fragment reader
|
|
// allows this character in a fragment at this time, but this could change and the '$'
|
|
// might need to be a flag of some sort. One of these symbols has another '$' prior to
|
|
// a number (which seems to show overloading of the method--we have actually seen "$0"
|
|
// and "$1" suffixes:
|
|
// mangled = "__ehhandler$?test_except_f@@YAXH@Z";
|
|
// msTruth = "[EHHANDLER$] void __cdecl test_except_f(int)";
|
|
// mangled = "__undwindfunclet$?test_except_f@@YAXH@Z$1";
|
|
// msTruth = "[UNDWINDFUNCLET$][1] void __cdecl test_except_f(int)";
|
|
// We crafted a representation for these symbols that have no real truth to compare to.
|
|
//Following are some that are not reported by dumpbin, so no msTruth. Again, we are
|
|
// making up our own answers.
|
|
//Interestingly, the 64-bit version of gray.exe
|
|
// only has one underscore in the beginning. How do we reconcile this. Perhaps these
|
|
// are much different than the __MEP and __T2M prefixes that we see from dumpbin.
|
|
// mangled = "__TI1?AUX@@";
|
|
// mdTruth = "[TI1] AUX";
|
|
// mangled = "__CTA1?AUX@@";
|
|
// mdTruth = "[CT] AUX";
|
|
// mangled = "__CT??_R0?AUX@@@81"; //We can get the next line if we ignore that last character '1'
|
|
// mdTruth = "[CT] struct X `RTTI Type Descriptor'";
|
|
/**
|
|
* Parses the input data for "Compiler-Reserved" symbols. The C++/C-specification says that
|
|
* symbols that begin with two underscores or with a single underscore followed by a
|
|
* capital letter are reserved for compiler use. These are generally symbols that the
|
|
* compiler has generated for code that it generates to fulfill certain needs such as code
|
|
* for C++ internals or exception-handling internals. This method creates our idea of what
|
|
* the underlying object is that is named by this compiler-reserved symbol.
|
|
* @param dmang The <b><code>MDMang</code></b> worker for demangling.
|
|
* @return MDParsableItem object representing the underlying object that is named
|
|
* by the compiler-reserved symbol.
|
|
* @throws MDException Upon <b><code>MDMang</code></b> parsing issues that cause us to fail
|
|
* processing.
|
|
*/
|
|
public static MDParsableItem parseObjectReserved(MDMang dmang) {
|
|
MDParsableItem item;
|
|
if (dmang.positionStartsWith("__TI")) {
|
|
dmang.increment("__TI".length());
|
|
item = new MDObjectThrowInfo(dmang);
|
|
}
|
|
//Single underscore version is seen in 64-bit binaries
|
|
else if (dmang.positionStartsWith("_TI")) {
|
|
dmang.increment("_TI".length());
|
|
item = new MDObjectThrowInfo(dmang);
|
|
}
|
|
//__CTA must come before __CT prefix case
|
|
else if (dmang.positionStartsWith("__CTA")) {
|
|
dmang.increment("__CTA".length());
|
|
item = new MDObjectCatchableTypeArray(dmang);
|
|
}
|
|
else if (dmang.positionStartsWith("__CT")) {
|
|
dmang.increment("__CT".length());
|
|
item = new MDObjectCatchableType(dmang);
|
|
}
|
|
//_CTA must come before _CT prefix case
|
|
//Single underscore version is seen in 64-bit binaries
|
|
else if (dmang.positionStartsWith("_CTA")) {
|
|
dmang.increment("_CTA".length());
|
|
item = new MDObjectCatchableTypeArray(dmang);
|
|
}
|
|
//Single underscore version is seen in 64-bit binaries
|
|
else if (dmang.positionStartsWith("_CT")) {
|
|
dmang.increment("_CT".length());
|
|
item = new MDObjectCatchableType(dmang);
|
|
}
|
|
else if (dmang.positionStartsWith("__catch$")) {
|
|
dmang.increment("__catch$".length());
|
|
item = new MDObjectCatch(dmang);
|
|
}
|
|
else if (dmang.positionStartsWith("__catchsym$")) {
|
|
dmang.increment("__catchsym$".length());
|
|
item = new MDObjectCatchSym(dmang);
|
|
}
|
|
else if (dmang.positionStartsWith("__unwindfunclet$")) {
|
|
dmang.increment("__unwindfunclet$".length());
|
|
item = new MDObjectUnwindFunclet(dmang);
|
|
}
|
|
else if (dmang.positionStartsWith("__tryblocktable$")) {
|
|
dmang.increment("__tryblocktable$".length());
|
|
item = new MDObjectTryBlockTable(dmang);
|
|
}
|
|
else if (dmang.positionStartsWith("__unwindtable$")) {
|
|
dmang.increment("__unwindtable$".length());
|
|
item = new MDObjectUnwindTable(dmang);
|
|
}
|
|
else if (dmang.positionStartsWith("__ehhandler$")) {
|
|
dmang.increment("__ehhandler$".length());
|
|
item = new MDObjectEHHandler(dmang);
|
|
}
|
|
else if (dmang.positionStartsWith("__m2mep@")) {
|
|
//dmang.increment("__m2mep@".length());
|
|
//See source8P
|
|
item = new MDObjectBracket(dmang);
|
|
}
|
|
else if (dmang.positionStartsWith("__mep@")) {
|
|
//dmang.increment("__mep@".length());
|
|
//Managed Entry Point
|
|
item = new MDObjectBracket(dmang);
|
|
}
|
|
else if (dmang.positionStartsWith("__t2m@")) {
|
|
//dmang.increment("__t2m@".length());
|
|
//Transition-to-Managed
|
|
item = new MDObjectBracket(dmang);
|
|
}
|
|
else if (dmang.positionStartsWith("__unep@")) {
|
|
//dmang.increment("__unep@".length());
|
|
//See source8P
|
|
item = new MDObjectBracket(dmang);
|
|
}
|
|
else {
|
|
//What else?
|
|
/*See cn3:
|
|
___iob_func
|
|
@__security_check_cookie@4
|
|
__CxxThrowException@8
|
|
___CxxFrameHandler3
|
|
__imp__InitOnceExecuteOnce@16
|
|
__real@00000000
|
|
__real@0000000000000000
|
|
__real@3f1a36e2eb1c432d
|
|
*/
|
|
item = new MDObjectReserved(dmang);
|
|
}
|
|
return item;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
/******************************************************************************/
|
|
// DO NOT DELETE THE CODE BELOW!!!
|
|
// It is work in progress, trying to find the right hierarchical structures
|
|
// and output mechanisms that will make everything better.
|
|
// ...especially for the '???' nesting.
|
|
/******************************************************************************/
|
|
/******************************************************************************/
|
|
|
|
// private void parseOptionalContexts(MDMang dmang) throws MDException {
|
|
// while (dmang.peek() == '?' && dmang.peek(1) == '?') {
|
|
// dmang.getAndIncrement();
|
|
// //TODO: removed to clean up dmang, but would need an appropriate substitute we
|
|
// // we intend to use parseOptionalContexts(): dmang.pushContext();
|
|
// parseOptionalContexts(dmang);
|
|
// dmang.popContext();
|
|
// }
|
|
// //qualifiedName = new MDQualifiedName(dmang);
|
|
// qualifiedName = new MDQualifiedName();
|
|
// qualifiedName.parse1(dmang);
|
|
// //typeInfo = new MDTypeInfo(dmang);
|
|
// typeInfo = new MDTypeInfo();
|
|
// typeInfo.parse1(dmang);
|
|
// }
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/******************************************************************************/
|