4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
6
6
* You may obtain a copy of the License at
7
- *
7
+ *
8
8
* http://www.apache.org/licenses/LICENSE-2.0
9
- *
9
+ *
10
10
* Unless required by applicable law or agreed to in writing, software
11
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -47,6 +47,7 @@ public class CppExporter extends Exporter {
47
47
public static final String CREATE_HEADER_FILE = "Create Header File (.h)" ;
48
48
public static final String USE_CPP_STYLE_COMMENTS = "Use C++ Style Comments (//)" ;
49
49
public static final String EMIT_TYPE_DEFINITONS = "Emit Data-type Definitions" ;
50
+ public static final String EMIT_REFERENCED_GLOBALS = "Emit Referenced Globals" ;
50
51
public static final String FUNCTION_TAG_FILTERS = "Function Tags to Filter" ;
51
52
public static final String FUNCTION_TAG_EXCLUDE = "Function Tags Excluded" ;
52
53
@@ -56,6 +57,7 @@ public class CppExporter extends Exporter {
56
57
private boolean isCreateCFile = true ;
57
58
private boolean isUseCppStyleComments = true ;
58
59
private boolean emitDataTypeDefinitions = true ;
60
+ private boolean emitReferencedGlobals = true ;
59
61
private String tagOptions = "" ;
60
62
61
63
private Set <FunctionTag > functionTagSet = new HashSet <>();
@@ -69,7 +71,7 @@ public CppExporter() {
69
71
}
70
72
71
73
public CppExporter (DecompileOptions options , boolean createHeader , boolean createFile ,
72
- boolean emitTypes , boolean excludeTags , String tags ) {
74
+ boolean emitTypes , boolean emitGlobals , boolean excludeTags , String tags ) {
73
75
this ();
74
76
this .options = options ;
75
77
if (options != null ) {
@@ -78,6 +80,7 @@ public CppExporter(DecompileOptions options, boolean createHeader, boolean creat
78
80
isCreateHeaderFile = createHeader ;
79
81
isCreateCFile = createFile ;
80
82
emitDataTypeDefinitions = emitTypes ;
83
+ emitReferencedGlobals = emitGlobals ;
81
84
excludeMatchingTags = excludeTags ;
82
85
if (tags != null ) {
83
86
tagOptions = tags ;
@@ -164,13 +167,14 @@ private void decompileAndExport(AddressSetView addrSet, Program program,
164
167
Listing listing = program .getListing ();
165
168
FunctionIterator iterator = listing .getFunctions (addrSet , true );
166
169
List <Function > functions = new ArrayList <>();
170
+ Set <String > processedGlobals = new HashSet <>();
167
171
for (int i = 0 ; iterator .hasNext (); i ++) {
168
172
//
169
173
// Write results every so many items so that we don't blow out memory
170
174
//
171
175
if (i % 10000 == 0 ) {
172
176
List <CPPResult > results = parallelDecompiler .decompileFunctions (functions );
173
- writeResults (results , headerWriter , cFileWriter , chunkingMonitor );
177
+ writeResults (results , processedGlobals , headerWriter , cFileWriter , chunkingMonitor );
174
178
functions .clear ();
175
179
}
176
180
@@ -184,7 +188,7 @@ private void decompileAndExport(AddressSetView addrSet, Program program,
184
188
185
189
// handle any remaining functions
186
190
List <CPPResult > results = parallelDecompiler .decompileFunctions (functions );
187
- writeResults (results , headerWriter , cFileWriter , chunkingMonitor );
191
+ writeResults (results , processedGlobals , headerWriter , cFileWriter , chunkingMonitor );
188
192
}
189
193
190
194
private boolean excludeFunction (Function currentFunction ) {
@@ -205,26 +209,37 @@ private boolean excludeFunction(Function currentFunction) {
205
209
return excludeMatchingTags == hasTag ;
206
210
}
207
211
208
- private void writeResults (List <CPPResult > results , PrintWriter headerWriter ,
209
- PrintWriter cFileWriter , TaskMonitor monitor ) throws CancelledException {
212
+ private void writeResults (List <CPPResult > results , Set <String > processedGlobals ,
213
+ PrintWriter headerWriter , PrintWriter cFileWriter , TaskMonitor monitor )
214
+ throws CancelledException {
210
215
monitor .checkCancelled ();
211
216
212
217
Collections .sort (results );
213
218
219
+ StringBuilder globalDecls = new StringBuilder ();
214
220
StringBuilder headers = new StringBuilder ();
215
221
StringBuilder bodies = new StringBuilder ();
222
+
216
223
for (CPPResult result : results ) {
217
224
monitor .checkCancelled ();
218
225
if (result == null ) {
219
226
continue ;
220
227
}
221
- String headerCode = result .getHeaderCode ();
228
+ if (emitReferencedGlobals ) {
229
+ for (String global : result .globals ()) {
230
+ if (processedGlobals .add (global )) {
231
+ globalDecls .append (global );
232
+ globalDecls .append (EOL );
233
+ }
234
+ }
235
+ }
236
+ String headerCode = result .headerCode ();
222
237
if (headerCode != null ) {
223
238
headers .append (headerCode );
224
239
headers .append (EOL );
225
240
}
226
241
227
- String bodyCode = result .getBodyCode ();
242
+ String bodyCode = result .bodyCode ();
228
243
if (bodyCode != null ) {
229
244
bodies .append (bodyCode );
230
245
bodies .append (EOL );
@@ -237,6 +252,7 @@ private void writeResults(List<CPPResult> results, PrintWriter headerWriter,
237
252
headerWriter .println (headers .toString ());
238
253
}
239
254
if (cFileWriter != null ) {
255
+ cFileWriter .print (globalDecls .toString ());
240
256
cFileWriter .print (bodies .toString ());
241
257
}
242
258
}
@@ -343,6 +359,7 @@ public List<Option> getOptions(DomainObjectService domainObjectService) {
343
359
list .add (new Option (CREATE_C_FILE , Boolean .valueOf (isCreateCFile )));
344
360
list .add (new Option (USE_CPP_STYLE_COMMENTS , Boolean .valueOf (isUseCppStyleComments )));
345
361
list .add (new Option (EMIT_TYPE_DEFINITONS , Boolean .valueOf (emitDataTypeDefinitions )));
362
+ list .add (new Option (EMIT_REFERENCED_GLOBALS , Boolean .valueOf (emitReferencedGlobals )));
346
363
list .add (new Option (FUNCTION_TAG_FILTERS , tagOptions ));
347
364
list .add (new Option (FUNCTION_TAG_EXCLUDE , Boolean .valueOf (excludeMatchingTags )));
348
365
return list ;
@@ -365,6 +382,9 @@ else if (optName.equals(USE_CPP_STYLE_COMMENTS)) {
365
382
else if (optName .equals (EMIT_TYPE_DEFINITONS )) {
366
383
emitDataTypeDefinitions = ((Boolean ) option .getValue ()).booleanValue ();
367
384
}
385
+ else if (optName .equals (EMIT_REFERENCED_GLOBALS )) {
386
+ emitReferencedGlobals = ((Boolean ) option .getValue ()).booleanValue ();
387
+ }
368
388
else if (optName .equals (FUNCTION_TAG_FILTERS )) {
369
389
tagOptions = (String ) option .getValue ();
370
390
}
@@ -452,31 +472,12 @@ private static String getFakeCTypeDefinitions(DataOrganization dataOrganization)
452
472
// Inner Classes
453
473
//==================================================================================================
454
474
455
- private class CPPResult implements Comparable <CPPResult > {
456
-
457
- private Address address ;
458
- private String bodyCode ;
459
- private String headerCode ;
460
-
461
- CPPResult (Address address , String headerCode , String bodyCode ) {
462
- this .address = address ;
463
- this .headerCode = headerCode ;
464
- this .bodyCode = bodyCode ;
465
- }
466
-
467
- String getHeaderCode () {
468
- return headerCode ;
469
- }
470
-
471
- String getBodyCode () {
472
- return bodyCode ;
473
- }
474
-
475
+ private record CPPResult (Address address , String headerCode , String bodyCode ,
476
+ List <String > globals ) implements Comparable <CPPResult > {
475
477
@ Override
476
478
public int compareTo (CPPResult other ) {
477
479
return address .compareTo (other .address );
478
480
}
479
-
480
481
}
481
482
482
483
private class DecompilerFactory extends CountingBasicFactory <DecompInterface > {
@@ -492,7 +493,7 @@ public DecompInterface doCreate(int itemNumber) throws IOException {
492
493
DecompInterface decompiler = new DecompInterface ();
493
494
decompiler .setOptions (options );
494
495
decompiler .openProgram (program );
495
- decompiler .toggleSyntaxTree (false ); // Don't need syntax tree
496
+ decompiler .toggleSyntaxTree (true );
496
497
return decompiler ;
497
498
}
498
499
@@ -532,7 +533,7 @@ private CPPResult doWork(Function function, DecompInterface decompiler,
532
533
CodeUnit codeUnitAt = function .getProgram ().getListing ().getCodeUnitAt (entryPoint );
533
534
if (codeUnitAt == null || !(codeUnitAt instanceof Instruction )) {
534
535
return new CPPResult (entryPoint , function .getPrototypeString (false , false ) + ';' ,
535
- null );
536
+ null , List . of () );
536
537
}
537
538
538
539
monitor .setMessage ("Decompiling " + function .getName ());
@@ -546,14 +547,24 @@ private CPPResult doWork(Function function, DecompInterface decompiler,
546
547
monitor .incrementProgress (1 );
547
548
return new CPPResult (entryPoint , null ,
548
549
"/*" + EOL + "Unable to decompile '" + function .getName () + "'" + EOL +
549
- "Cause: " + errorMessage + EOL + "*/" + EOL );
550
+ "Cause: " + errorMessage + EOL + "*/" + EOL ,
551
+ List .of ());
550
552
}
551
553
return null ;
552
554
}
553
555
554
556
DecompiledFunction decompiledFunction = dr .getDecompiledFunction ();
557
+ List <String > globals =
558
+ CollectionUtils .asStream (dr .getHighFunction ().getGlobalSymbolMap ().getSymbols ())
559
+ .map (hsym -> {
560
+ String dt = hsym .getDataType ().getDisplayName ();
561
+ String name = hsym .getName ();
562
+ String space = dt .endsWith ("*" ) ? "" : " " ;
563
+ return "%s%s%s;" .formatted (dt , space , name );
564
+ })
565
+ .toList ();
555
566
return new CPPResult (entryPoint , decompiledFunction .getSignature (),
556
- decompiledFunction .getC ());
567
+ decompiledFunction .getC (), globals );
557
568
}
558
569
}
559
570
0 commit comments