2020using Reko . Analysis ;
2121using Reko . Core ;
2222using Reko . Core . Collections ;
23+ using Reko . Core . Configuration ;
2324using Reko . Core . Graphs ;
2425using Reko . Core . Loading ;
2526using Reko . Core . Output ;
2627using Reko . Core . Scripts ;
2728using Reko . Core . Serialization ;
2829using Reko . Core . Services ;
2930using Reko . Core . Types ;
31+ using Reko . Loading ;
3032using Reko . Scanning ;
3133using Reko . Services ;
3234using Reko . Structure ;
3335using Reko . Typing ;
3436using System ;
3537using System . Collections . Generic ;
38+ using System . ComponentModel . Design ;
3639using System . IO ;
3740using System . Linq ;
3841
@@ -48,6 +51,12 @@ public class Decompiler : IDecompiler
4851 private readonly IDecompilerEventListener eventListener ;
4952 private readonly IServiceProvider services ;
5053
54+ /// <summary>
55+ /// Creates an instance of the Reko decompiler.
56+ /// </summary>
57+ /// <param name="project">Project to be analyzed.</param>
58+ /// <param name="services"><see cref="IServiceProvider"/> instance
59+ /// providing services. </param>
5160 public Decompiler ( Project project , IServiceProvider services )
5261 {
5362 this . project = project ;
@@ -57,6 +66,55 @@ public Decompiler(Project project, IServiceProvider services)
5766 BuildImageMaps ( ) ;
5867 }
5968
69+ /// <summary>
70+ /// Convenience method that creates a new instance of the decompiler, loading a binary
71+ /// file into it.
72+ /// </summary>
73+ /// <remarks>
74+ /// This method is a convenient way to create a new instance of the decompiler,
75+ /// at the cost of flexibility. To attain more flexibility, e.g. the capability
76+ /// to override default load address or loading raw binary files that lack
77+ /// any structure, you must load the binary file separately using the one of the methods on the <see cref="Loader"/> class,
78+ /// and call the constructor of this class with the resulting <see cref="Core.Project"/> instance.
79+ /// </remarks>
80+ /// <param name="filePath">File system path to the binary file or Reko project file to load.</param>
81+ /// <param name="rekoConfigFilePath">File system path to the reko.config file which contains all
82+ /// necessary Reko configuration info.
83+ /// </param>
84+ public static Decompiler Create ( string filePath , string rekoConfigFilePath )
85+ {
86+ var services = new ServiceContainer ( ) ;
87+ var pluginSvc = new PluginLoaderService ( ) ;
88+ services . AddService < IPluginLoaderService > ( pluginSvc ) ;
89+ var fsSvc = new FileSystemService ( ) ;
90+ services . AddService < IFileSystemService > ( fsSvc ) ;
91+ var eventListener = new NullDecompilerEventListener ( ) ;
92+ services . AddService < IDecompilerEventListener > ( eventListener ) ;
93+ services . AddService < IEventListener > ( eventListener ) ;
94+ var configSvc = RekoConfigurationService . Load ( services , rekoConfigFilePath ) ;
95+ services . AddService < IConfigurationService > ( configSvc ) ;
96+ var typelibSvc = new TypeLibraryLoaderServiceImpl ( services ) ;
97+ services . AddService < ITypeLibraryLoaderService > ( typelibSvc ) ;
98+ var decFileSvc = new DecompiledFileService ( services , fsSvc , eventListener ) ;
99+ services . AddService < IDecompiledFileService > ( decFileSvc ) ;
100+
101+ var loader = new Loader ( services ) ;
102+ var input = loader . Load ( ImageLocation . FromUri ( filePath ) ) ;
103+ if ( input is not Project project )
104+ {
105+ if ( input is not Program program )
106+ throw new InvalidOperationException (
107+ "The input file is not a Reko project or a recognized binary file. " +
108+ "Consider loading the file separately using one of the methods of " +
109+ "Reko.Loading.Loader." ) ;
110+ project = Project . FromSingleProgram ( program ) ;
111+ }
112+ return new Decompiler ( project , services ) ;
113+ }
114+
115+ /// <summary>
116+ /// The Reko project being analyzed.
117+ /// </summary>
60118 public Project Project { get { return project ; } set { project = value ; ProjectChanged ? . Invoke ( this , EventArgs . Empty ) ; } }
61119 public event EventHandler ? ProjectChanged ;
62120 private Project project ;
@@ -114,7 +172,7 @@ public virtual void AnalyzeDataFlow()
114172 }
115173 eventListener . Progress . ShowStatus ( "Building complex expressions." ) ;
116174 dfa . BuildExpressionTrees ( ssas ) ;
117- host . WriteIntermediateCode ( program , ( name , procs , writer ) => { EmitProgram ( program , procs , dfa , name , writer ) ; } ) ;
175+ host . WriteIntermediateCode ( program , ( name , procs , writer ) => { EmitProgram ( program , procs , dfa , writer ) ; } ) ;
118176 }
119177 catch ( Exception ex )
120178 {
@@ -128,9 +186,18 @@ public virtual void AnalyzeDataFlow()
128186 eventListener . Progress . ShowStatus ( "Interprocedural analysis complete." ) ;
129187 }
130188
189+ /// <summary>
190+ /// Writes the disassembly of the program to one or more files.
191+ /// Each segment of the binary program generates one more output files.
192+ /// </summary>
193+ /// <param name="program">Program to disassemble.</param>
194+ /// <param name="segmentItems">A dictionary mapping each <see cref="ImageSegment"/>
195+ /// to a list of <see cref="ImageMapItem"/>s discovered in that segment.
196+ /// </param>
197+ /// <param name="wr">Object responsible for formatting the output files.
198+ /// </param>
131199 public void DumpAssembler (
132200 Program program ,
133- string filename ,
134201 Dictionary < ImageSegment , List < ImageMapItem > > segmentItems ,
135202 Formatter wr )
136203 {
@@ -152,7 +219,11 @@ public void DumpAssembler(
152219 }
153220 }
154221
155- private void EmitProgram ( Program program , IEnumerable < object > objects , DataFlowAnalysis ? dfa , string filename , TextWriter output )
222+ private void EmitProgram (
223+ Program program ,
224+ IEnumerable < object > objects ,
225+ DataFlowAnalysis ? dfa ,
226+ TextWriter output )
156227 {
157228 if ( output is null )
158229 return ;
@@ -196,6 +267,9 @@ private void BuildImageMaps()
196267 }
197268 }
198269
270+ /// <summary>
271+ /// Extracts embedded resources from all programs in the project.
272+ /// </summary>
199273 public void ExtractResources ( )
200274 {
201275 if ( project is null )
@@ -209,6 +283,11 @@ public void ExtractResources()
209283 }
210284 }
211285
286+ /// <summary>
287+ /// Extracts embedded resources from the given program.
288+ /// </summary>
289+ /// <param name="program">Program file from which to extract resources.
290+ /// </param>
212291 public void ExtractResources ( Program program )
213292 {
214293 var prg = program . Resources ;
@@ -282,8 +361,6 @@ private bool WriteResource(
282361 /// <summary>
283362 /// Extracts type information from the typeless rewritten programs.
284363 /// </summary>
285- /// <param name="host"></param>
286- /// <param name="ivs"></param>
287364 public void ReconstructTypes ( )
288365 {
289366 if ( Project is null )
@@ -310,7 +387,19 @@ public void ReconstructTypes()
310387 }
311388 }
312389
313- public void WriteDecompiledObjects ( Program program , string filename , IEnumerable < IAddressable > objects , TextWriter w )
390+ /// <summary>
391+ /// Writes the high-level language decompiled objects to a file.
392+ /// </summary>
393+ /// <param name="program">Program that was decompiled.</param>
394+ /// <param name="filename">The filename of the written file.</param>
395+ /// <param name="objects">Objects that are to be written.</param>
396+ /// <param name="w">Formatter object that converts the object to text.
397+ /// </param>
398+ public void WriteDecompiledObjects (
399+ Program program ,
400+ string filename ,
401+ IEnumerable < IAddressable > objects ,
402+ TextWriter w )
314403 {
315404 WriteHeaderComment ( filename , program , w ) ;
316405 //$REFACTOR: common code -- hardwired ".h"
@@ -380,6 +469,12 @@ private static void WriteProcedureCallers(Program program, Procedure proc, TextW
380469 }
381470 }
382471
472+ /// <summary>
473+ /// Writes all detected global variables to a file.
474+ /// </summary>
475+ /// <param name="program">Program whose globals are to be written.</param>
476+ /// <param name="filename">The name of the source file receiving the written globals.</param>
477+ /// <param name="w">Formatting object that converts data globals to text.</param>
383478 public void WriteGlobals ( Program program , string filename , TextWriter w )
384479 {
385480 var headerfile = DecompiledFileService . GenerateDerivedFilename ( program , ".h" ) ;
@@ -515,8 +610,8 @@ private void ScanProgram(Program program)
515610 finally
516611 {
517612 eventListener . Progress . ShowStatus ( "Writing .asm and .dis files." ) ;
518- host . WriteDisassembly ( program , ( n , items , w ) => DumpAssembler ( program , n , items , w ) ) ;
519- host . WriteIntermediateCode ( program , ( n , procs , w ) => EmitProgram ( program , procs , null , n , w ) ) ;
613+ host . WriteDisassembly ( program , ( n , items , w ) => DumpAssembler ( program , items , w ) ) ;
614+ host . WriteIntermediateCode ( program , ( n , procs , w ) => EmitProgram ( program , procs , null , w ) ) ;
520615 // Uncomment the following for debugging.
521616 // WriteSccs(program);
522617 }
0 commit comments