@ -9,11 +9,20 @@ using ICSharpCode.Decompiler.Metadata;
@@ -9,11 +9,20 @@ using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Disassembler ;
using System.Threading ;
using System.Reflection.Metadata ;
using System.Reflection.PortableExecutable ;
using ICSharpCode.Decompiler.DebugInfo ;
// ReSharper disable InconsistentNaming
namespace ICSharpCode.Decompiler.Console
{
class Program
{
// https://www.freebsd.org/cgi/man.cgi?query=sysexits&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html
private const int EX_USAGE = 6 4 ;
private const int EX_DATAERR = 6 5 ;
private const int EX_NOINPUT = 6 6 ;
private const int EX_SOFTWARE = 7 0 ;
static int Main ( string [ ] args )
{
// https://github.com/natemcmaster/CommandLineUtils/
@ -28,6 +37,7 @@ namespace ICSharpCode.Decompiler.Console
@@ -28,6 +37,7 @@ namespace ICSharpCode.Decompiler.Console
var typeOption = app . Option ( "-t|--type <type-name>" , "The fully qualified name of the type to decompile." , CommandOptionType . SingleValue ) ;
var listOption = app . Option ( "-l|--list <entity-type(s)>" , "Lists all entities of the specified type(s). Valid types: c(lass), i(interface), s(truct), d(elegate), e(num)" , CommandOptionType . MultipleValue ) ;
var ilViewerOption = app . Option ( "-il|--ilcode" , "Show IL code." , CommandOptionType . NoValue ) ;
var pdbGeneration = app . Option ( "-d|--debuginfo" , "Generate PDB." , CommandOptionType . NoValue ) ;
app . ExtendedHelpText = Environment . NewLine + "-o is valid with every option and required when using -p." ;
app . ThrowOnUnexpectedArgument = false ; // Ignore invalid arguments / options
@ -42,15 +52,15 @@ namespace ICSharpCode.Decompiler.Console
@@ -42,15 +52,15 @@ namespace ICSharpCode.Decompiler.Console
}
if ( ! File . Exists ( inputAssemblyFileName . Value ) ) {
app . Error . WriteLine ( $"ERROR: Input file not found." ) ;
return - 1 ;
return EX_NOINPUT ;
}
if ( ! outputOption . HasValue ( ) & & projectOption . HasValue ( ) ) {
app . Error . WriteLine ( $"ERROR: Output directory not speciified." ) ;
return - 1 ;
return EX_USAGE ;
}
if ( outputOption . HasValue ( ) & & ! Directory . Exists ( outputOption . Value ( ) ) ) {
app . Error . WriteLine ( $"ERROR: Output directory '{outputOption.Value()}' does not exist." ) ;
return - 1 ;
return EX_NOINPUT ;
}
TextWriter output = System . Console . Out ;
try {
@ -72,6 +82,16 @@ namespace ICSharpCode.Decompiler.Console
@@ -72,6 +82,16 @@ namespace ICSharpCode.Decompiler.Console
output = File . CreateText ( Path . Combine ( directory , outputName ) + ".il" ) ;
}
ShowIL ( inputAssemblyFileName . Value , output ) ;
} else if ( pdbGeneration . HasValue ( ) ) {
string pdbFileName = null ;
if ( outputOption . HasValue ( ) ) {
string directory = outputOption . Value ( ) ;
string outputName = Path . GetFileNameWithoutExtension ( inputAssemblyFileName . Value ) ;
pdbFileName = Path . Combine ( directory , outputName ) + ".pdb" ;
} else {
pdbFileName = Path . ChangeExtension ( inputAssemblyFileName . Value , ".pdb" ) ;
}
return GeneratePdbForAssembly ( inputAssemblyFileName . Value , pdbFileName , app ) ;
} else {
if ( outputOption . HasValue ( ) ) {
string directory = outputOption . Value ( ) ;
@ -139,5 +159,31 @@ namespace ICSharpCode.Decompiler.Console
@@ -139,5 +159,31 @@ namespace ICSharpCode.Decompiler.Console
output . Write ( decompiler . DecompileTypeAsString ( name ) ) ;
}
}
static int GeneratePdbForAssembly ( string assemblyFileName , string pdbFileName , CommandLineApplication app )
{
var module = new PEFile ( assemblyFileName ,
new FileStream ( assemblyFileName , FileMode . Open , FileAccess . Read ) ,
PEStreamOptions . PrefetchEntireImage ,
metadataOptions : MetadataReaderOptions . None ) ;
if ( ! PortablePdbWriter . HasCodeViewDebugDirectoryEntry ( module ) ) {
app . Error . WriteLine ( $"Cannot create PDB file for {assemblyFileName}, because it does not contain a PE Debug Directory Entry of type 'CodeView'." ) ;
return EX_DATAERR ;
}
using ( FileStream stream = new FileStream ( pdbFileName , FileMode . OpenOrCreate , FileAccess . Write ) ) {
try {
var decompiler = GetDecompiler ( assemblyFileName ) ;
PortablePdbWriter . WritePdb ( module , decompiler , new DecompilerSettings ( ) { ThrowOnAssemblyResolveErrors = false } , stream ) ;
} catch ( Exception ex ) {
app . Error . WriteLine ( $"Cannot create PDB file for {assemblyFileName}" ) ;
app . Error . WriteLine ( ex . ToString ( ) ) ;
return EX_SOFTWARE ;
}
}
return 0 ;
}
}
}