PK F9O BenLincoln.DebugSymbols/PK
j$O~f
6 BenLincoln.DebugSymbols/BenLincoln.DebugSymbols.csproj
Debug
AnyCPU
{F72110A0-4359-41CF-A7BD-ADA41A8C3A84}
Library
Properties
BenLincoln.DebugSymbols
BenLincoln.DebugSymbols
v4.6.1
512
true
full
false
bin\Debug\
DEBUG;TRACE
prompt
4
pdbonly
true
bin\Release\
TRACE
prompt
4
lib\Newtonsoft.Json.dll
PK
jA7O8 0 BenLincoln.DebugSymbols/CodeElementFileMapper.csusing System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BenLincoln.DebugSymbols.SymDump;
namespace BenLincoln.DebugSymbols
{
public class ObjectFileToSourceFileMap
{
public string ObjectFile;
public Dictionary SourceFilesWithCounts;
public ObjectFileToSourceFileMap()
{
ObjectFile = "";
SourceFilesWithCounts = new Dictionary();
}
}
public class CodeElementFileMapper
{
public Dictionary ObjectFileToSourceFileMapEntries;
// TKTK: also build a map of memory offsets based on functions and SLD information, and use that as a secondary map
// for anything that's not categorized by the object file method
// maybe use it as the primary method, since it should be more accurate WRT conflicts
public CodeElementFileMapper()
{
ObjectFileToSourceFileMapEntries = new Dictionary();
}
public void GetDataFromCElement(BenLincoln.DebugSymbols.SymDump.CElement e)
{
if ((e.source_file != null) && (e.source_file != ""))
{
for (int i = 0; i < e.object_files.Count; i++)
{
string objectFile = e.object_files[i];
ObjectFileToSourceFileMap oMap = new ObjectFileToSourceFileMap();
if (ObjectFileToSourceFileMapEntries.ContainsKey(objectFile))
{
oMap = ObjectFileToSourceFileMapEntries[objectFile];
}
else
{
oMap.ObjectFile = objectFile;
}
if (oMap.SourceFilesWithCounts.ContainsKey(e.source_file))
{
oMap.SourceFilesWithCounts[e.source_file]++;
}
else
{
oMap.SourceFilesWithCounts.Add(e.source_file, 1);
}
if (ObjectFileToSourceFileMapEntries.ContainsKey(objectFile))
{
ObjectFileToSourceFileMapEntries[objectFile] = oMap;
}
else
{
ObjectFileToSourceFileMapEntries.Add(objectFile, oMap);
}
}
}
}
public void GetAllDataFromSymbolCollection(BenLincoln.DebugSymbols.SymDump.SymDumpSymbolCollection syms)
{
foreach (CFunction func in syms.functions)
{
GetDataFromCElement(func);
}
foreach (CLabel l in syms.labels)
{
GetDataFromCElement(l);
}
foreach (CEnum e in syms.enums)
{
GetDataFromCElement(e);
}
foreach (CStruct s in syms.structs)
{
GetDataFromCElement(s);
}
foreach (CUnion u in syms.unions)
{
GetDataFromCElement(u);
}
foreach (CTypeDef t in syms.typedefs)
{
GetDataFromCElement(t);
}
foreach (CExternalDeclaration x in syms.external_declarations)
{
GetDataFromCElement(x);
}
}
public void GetAllDataFromOverlay(BenLincoln.DebugSymbols.SymDump.PsyQOverlayDescription ol)
{
foreach (CFunction func in ol.functions)
{
GetDataFromCElement(func);
}
foreach (CLabel l in ol.labels)
{
GetDataFromCElement(l);
}
foreach (CEnum e in ol.enums)
{
GetDataFromCElement(e);
}
foreach (CStruct s in ol.structs)
{
GetDataFromCElement(s);
}
foreach (CUnion u in ol.unions)
{
GetDataFromCElement(u);
}
foreach (CTypeDef t in ol.typedefs)
{
GetDataFromCElement(t);
}
foreach (CExternalDeclaration x in ol.external_declarations)
{
GetDataFromCElement(x);
}
}
public void SetBestSourceFileMatch(BenLincoln.DebugSymbols.SymDump.CElement e, string elementName, string defaultSourceFileName, StringBuilder manualChangesBuilder)
{
if ((e.source_file != null) && (e.source_file != ""))
{
return;
}
string result = defaultSourceFileName;
int highestCount = 0;
List sourceFileNames = new List();
Dictionary sourceFileRefCounts = new Dictionary();
foreach (string objectFile in e.object_files)
{
if (ObjectFileToSourceFileMapEntries.ContainsKey(objectFile))
{
ObjectFileToSourceFileMap oMap = ObjectFileToSourceFileMapEntries[objectFile];
foreach (string sourceFileName in oMap.SourceFilesWithCounts.Keys)
{
if (!sourceFileNames.Contains(sourceFileName))
{
sourceFileNames.Add(sourceFileName);
}
int count = oMap.SourceFilesWithCounts[sourceFileName];
if (!sourceFileRefCounts.Keys.Contains(sourceFileName))
{
sourceFileRefCounts.Add(sourceFileName, oMap.SourceFilesWithCounts[sourceFileName]);
}
else
{
count = sourceFileRefCounts[sourceFileName] + oMap.SourceFilesWithCounts[sourceFileName];
sourceFileRefCounts[sourceFileName] = count;
}
if (count > highestCount)
{
highestCount = count;
}
}
}
sourceFileNames.Sort();
for (int i = 0; i < sourceFileNames.Count; i++)
{
if (sourceFileRefCounts[sourceFileNames[i]] == highestCount)
{
result = sourceFileNames[i];
break;
}
}
if (sourceFileNames.Count > 1)
{
string objectFiles = BenLincoln.DebugSymbols.Utilities.GetListAsString(e.object_files);
manualChangesBuilder.Append(string.Format("The code element '{0}' was mapped to the source file '{1}' based on its association with object file(s) '{2}'. However, multiple source files mapped to that object file, with the following counts of elements:", elementName, result, objectFiles));
manualChangesBuilder.Append(Environment.NewLine);
foreach (string sfn in sourceFileNames)
{
manualChangesBuilder.Append("\t");
manualChangesBuilder.Append(string.Format("{0}: {1}", sfn, sourceFileRefCounts[sfn]));
manualChangesBuilder.Append(Environment.NewLine);
}
manualChangesBuilder.Append("If you would rather use one of the other destinations, update the JSON file manually before passing it to PopulateSkeleton.");
manualChangesBuilder.Append(Environment.NewLine);
}
}
e.source_file = result;
}
}
}
PK
9O6Z 0 BenLincoln.DebugSymbols/DebugSymbolDefinition.cs// This file is part of BenLincoln.DebugSymbols.
// BenLincoln.DebugSymbols is free software: you can redistribute it and/or modify
// it under the terms of version 3 of the GNU General Public License as published by
// the Free Software Foundation.
// BenLincoln.DebugSymbols is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with BenLincoln.DebugSymbols (in the file LICENSE.txt).
// If not, see .
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BenLincoln.DebugSymbols
{
public class DebugSymbolDefinition
{
}
}
PK
Т#O#0u u 0 BenLincoln.DebugSymbols/GhidraScriptGenerator.csusing System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using BenLincoln.DebugSymbols.SymDump;
namespace BenLincoln.DebugSymbols
{
public struct AddDataTypeByNameResult
{
public string GhidraCodeSubroutines;
public string GhidraCodeSubroutineCalls;
public List AddedNames;
public int NextSubroutineNumber;
}
public struct RenameJSONEntriesForGhidraResult
{
public string JSONText;
public StringBuilder ManualChangesBuilder;
}
public class GhidraScriptGenerator
{
public static AddDataTypeByNameResult GetAddDataTypesScriptCode(string ghidraImportDataTypeSubroutineTemplate, IEnumerable elements, string projectName, string elementTypeName, int maxElementsPerSubroutine, int currentSubroutineNumber)
{
StringBuilder subCollectionBuilder = new StringBuilder();
StringBuilder subBuilder = new StringBuilder();
StringBuilder subCallBuilder = new StringBuilder();
AddDataTypeByNameResult result = new AddDataTypeByNameResult();
result.NextSubroutineNumber = currentSubroutineNumber;
int dtNum = 0;
int elemNum = 0;
result.AddedNames = new List();
foreach (CElement e in elements)
{
if (!result.AddedNames.Contains(e.name))
{
subBuilder.Append(String.Format("\t\tdataTypeMap = addDataTypeByName(dataTypeMap, \"/{0}.H/{1}\", \"{1}\", \"{2}\");", projectName, BenLincoln.DebugSymbols.InputValidator.GetReasonablySafeJavaString(e.name), BenLincoln.DebugSymbols.InputValidator.GetReasonablySafeJavaString(elementTypeName)));
subBuilder.Append(Environment.NewLine);
result.AddedNames.Add(e.name);
dtNum++;
}
elemNum++;
if ((dtNum > maxElementsPerSubroutine) || (elemNum >= elements.Count()))
{
string subRoutineDefinition = ghidraImportDataTypeSubroutineTemplate.Replace("%IMPORT_DATATYPES_SUB_CONTENT%", subBuilder.ToString());
subRoutineDefinition = subRoutineDefinition.Replace("%IMPORT_DATATYPES_SUBROUTINE_NUMBER%", String.Format("{0}", result.NextSubroutineNumber));
subCollectionBuilder.Append(subRoutineDefinition);
subCallBuilder.Append(String.Format("\t\tdataTypeMap = ImportDataTypesSub{0}(dataTypeMap);", result.NextSubroutineNumber));
subCallBuilder.Append(Environment.NewLine);
subBuilder.Clear();
dtNum = 0;
result.NextSubroutineNumber++;
}
}
result.GhidraCodeSubroutines = subCollectionBuilder.ToString();
result.GhidraCodeSubroutineCalls = subCallBuilder.ToString();
return result;
}
public static RenameJSONEntriesForGhidraResult RenameJSONEntriesForGhidra(string jsonText, StringBuilder manualChangesBuilder)
{
// fix names that don't work in Ghidra
RenameJSONEntriesForGhidraResult result = new RenameJSONEntriesForGhidraResult();
result.JSONText = jsonText;
Regex dotRenameRex = new Regex("(?(union|struct|enum)( | [^ ]+ \\*)\\.[^ ;\"$]+)[ ;\"$]");
MatchCollection drMatches = dotRenameRex.Matches(result.JSONText);
Dictionary dotNames = new Dictionary();
foreach (Match m in drMatches)
{
if (m.Groups["itemName"] != null)
{
string matchText = m.Groups["itemName"].Value;
if (!dotNames.ContainsKey(matchText))
{
dotNames.Add(matchText, 1);
}
else
{
dotNames[matchText]++;
}
}
}
if (dotNames.Count > 0)
{
manualChangesBuilder.Append("The input JSON file contains at least one C element with a name that starts with a '.'. This naming convention is incompatible with Ghidra, so it will be replaced by a leading underscore. You should consider renaming these elements in the source JSON file, and will need to do so if any of them have name conflicts listed later in this file.");
manualChangesBuilder.Append(Environment.NewLine);
List keyNames = dotNames.Keys.ToList();
keyNames.Sort();
manualChangesBuilder.Append("Elements which will be renamed:");
manualChangesBuilder.Append(Environment.NewLine);
foreach (string dotName in keyNames)
{
if (dotNames[dotName] > 1)
{
manualChangesBuilder.Append(string.Format("\t{0} ({1} occurrences)", dotName, dotNames[dotName]));
}
else
{
manualChangesBuilder.Append(string.Format("\t{0}", dotName));
}
manualChangesBuilder.Append(Environment.NewLine);
}
manualChangesBuilder.Append(Environment.NewLine);
}
result.JSONText = result.JSONText.Replace("union .", "union _");
result.JSONText = result.JSONText.Replace("struct .", "struct _");
result.JSONText = result.JSONText.Replace("enum .", "enum _");
result.JSONText = result.JSONText.Replace("\"name\": \".", "\"name\": \"_");
foreach (string matchText in dotNames.Keys)
{
string replaceText = matchText.Replace(".", "_");
Console.WriteLine(string.Format("Debug: replacing '{0}' with '{1}', {2} occurrences in JSON file", matchText, replaceText, dotNames[matchText]));
result.JSONText = result.JSONText.Replace(matchText, replaceText);
}
result.ManualChangesBuilder = manualChangesBuilder;
return result;
}
}
}
PK
K$O,tO O ) BenLincoln.DebugSymbols/InputValidator.csusing System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace BenLincoln.DebugSymbols
{
public class InputValidator
{
public const string DefaultReplacementForInvalidChars = "";
public enum EscapingMode
{
Hex,
Octal
}
public static string EscapeNonPrintableCharactersInASCIICString(string text, EscapingMode escapeMode)
{
string result = text;
if ((escapeMode != EscapingMode.Hex) && (escapeMode != EscapingMode.Octal))
{
throw new Exception(string.Format("Unsupported escape mode: {0}", escapeMode));
}
result = result.Replace("\n", "\\n");
result = result.Replace("\r", "\\r");
result = result.Replace("\t", "\\t");
StringBuilder builder = new StringBuilder();
byte[] charBytes = ASCIIEncoding.ASCII.GetBytes(result);
for (int i = 0; i < charBytes.Length; i++)
{
bool handled = false;
if ((charBytes[i] < 32) || (charBytes[i] > 126))
{
if (escapeMode == EscapingMode.Hex)
{
builder.Append(string.Format("\\x{0:X2}", charBytes[i]));
}
if (escapeMode == EscapingMode.Octal)
{
builder.Append(string.Format("\\0{0}", Convert.ToString(charBytes[i], 8)));
}
handled = true;
}
if (!handled)
{
builder.Append((char)charBytes[i]);
}
}
return builder.ToString();
}
// formats the content of a C string so that it shouldn't be able to escape out of quotes
// when placed inside double quotes
public static string GetReasonablySafeCString(string text)
{
string result = text;
Regex quoteRex = new Regex("([^\\])\"");
MatchCollection quoteMatches = quoteRex.Matches(result);
foreach (Match m in quoteMatches)
{
string replacementText = string.Format("{0}\\\"", m.Value.Substring(0, 1));
result = result.Replace(m.Value, replacementText);
}
result = EscapeNonPrintableCharactersInASCIICString(result, EscapingMode.Hex);
return result;
}
// formats the content of a Java string so that it shouldn't be able to escape out of quotes
// when placed inside double quotes
public static string GetReasonablySafeJavaString(string text)
{
string result = text;
Regex quoteRex = new Regex("([^\\\\])\"");
MatchCollection quoteMatches = quoteRex.Matches(result);
foreach (Match m in quoteMatches)
{
string replacementText = string.Format("{0}\\\"", m.Value.Substring(0, 1));
result = result.Replace(m.Value, replacementText);
}
result = EscapeNonPrintableCharactersInASCIICString(result, EscapingMode.Octal);
return result;
}
// replaces characters which are not valid in the name of a C item
public static string GetReasonablySafeCName(string name, string replacement)
{
string result = name;
StringBuilder builder = new StringBuilder();
byte[] charBytes = ASCIIEncoding.ASCII.GetBytes(result);
byte[] invalidCharNums = ASCIIEncoding.ASCII.GetBytes("!\"#$%&'()*+,/:;<=>?@[\\]^`{|}~");
for (int i = 0; i < charBytes.Length; i++)
{
bool handled = false;
if (charBytes[i] < 32)
{
builder.Append(replacement);
handled = true;
}
if (!handled && (charBytes[i] > 126))
{
builder.Append(replacement);
handled = true;
}
if (!handled && (invalidCharNums.Contains(charBytes[i])))
{
builder.Append(replacement);
handled = true;
}
if (!handled)
{
builder.Append((char)charBytes[i]);
}
}
return builder.ToString();
}
public static string GetReasonablySafeCNameWithDefaultReplacement(string name)
{
return GetReasonablySafeCName(name, DefaultReplacementForInvalidChars);
}
}
}
PK N BenLincoln.DebugSymbols/lib/PK
g}NtM
M
/ BenLincoln.DebugSymbols/lib/Newtonsoft.Json.dllMZ @ !L!This program cannot be run in DOS mode.
$ PE L 謫 " 0 $
@
`
D
` ?
O `
.
>
T H .text "
$
`.rsrc `
&
@ @.reloc
,
@ B ?
H y t d>
(
*(
*.(
*} ( { X } * 0 -~
*~ X
baX
XX
+b aX
X
2cY
cY
cY
{ _{ +,{U 3{T ( ,{T *{V -* 0 -r ps
zo
-~
*~ X+bo
aXXo
2cYcYcY{ { _
+% {U 3 {T o
, {T * {V
-( *0 H { _
{ s
{ { X} { 3( {T *0 l {
{ ZXX
+8 +){U _{V }V - X
i2} } *0 . o
.*
+o
X.*X
o
2*{# *"}# *(- *:(- }# *"(. *(
*{$ *"}$ *{% *"}% *{&