mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-07-30 07:18:37 -09:00
Merge branch 'GP-7045_ryanmkurtz_swift' into patch
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# SwiftDemangler
|
||||
|
||||
This module provides support for demanling mangled [Swift](https://www.swift.org) symbols. Supported
|
||||
mangled symbols begin with `$S`, `$s`, `_$S"`, `_$s`, or `_T`.
|
||||
This module provides support for demangling mangled [Swift](https://www.swift.org) symbols.
|
||||
Supported mangled symbols begin with `$S`, `$s`, `_$S"`, `_$s`, or `_T`.
|
||||
|
||||
The demangler currently relies on making direct calls to the native Swift demangler tool, which
|
||||
comes [bundled with Swift](https://www.swift.org/download/). For example:
|
||||
@@ -21,5 +21,4 @@ protocol descriptor for SwiftUI.View
|
||||
The resulting tree is parsed by the Ghidra Swift Demangler to form and apply a demangled symbol
|
||||
name.
|
||||
|
||||
By default, the `Demangler Swift` Analyzer will search for the native Swift Demangler on the `PATH`.
|
||||
If it resides elsewhere, its path can be specified in the analyzer's options.
|
||||
The `Demangler Swift` Analyzer assumes that the native Swift Demangler is on the `PATH`.
|
||||
|
||||
@@ -55,7 +55,7 @@ public class SwiftDemanglerScript extends GhidraScript {
|
||||
return;
|
||||
}
|
||||
|
||||
SwiftNativeDemangler nativeDemangler = new SwiftNativeDemangler(options.getSwiftDir());
|
||||
SwiftNativeDemangler nativeDemangler = new SwiftNativeDemangler();
|
||||
SwiftNativeDemangledOutput demangledOutput = nativeDemangler.demangle(mangled);
|
||||
println(demangledOutput.toString());
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package ghidra.app.plugin.core.analysis;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import ghidra.app.util.demangler.*;
|
||||
@@ -36,10 +35,7 @@ public class SwiftDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
|
||||
|
||||
private static final String NAME = "Demangler Swift";
|
||||
private static final String DESCRIPTION =
|
||||
"Demangles Swift symbols and applies appropriate datatype and calling conventions where possible. Requires Swift to be installed.";
|
||||
private static final String OPTION_NAME_SWIFT_DIR = "Swift binary directory";
|
||||
private static final String OPTION_DESCRIPTION_SWIFT_DIR =
|
||||
"Path to the Swift installation binary directory, if not on PATH";
|
||||
"Demangles Swift symbols and applies appropriate datatype and calling conventions where possible. Requires Swift to be on the PATH.";
|
||||
|
||||
private static final String OPTION_NAME_INCOMPLETE_PREFIX =
|
||||
"Use incomplete demangle label prefix (%s)"
|
||||
@@ -54,7 +50,6 @@ public class SwiftDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
|
||||
"Prefix unsupported demangled labels with '%s'"
|
||||
.formatted(SwiftDemanglerOptions.UNSUPPORTED_PREFIX);
|
||||
|
||||
private File swiftDir;
|
||||
private boolean useIncompletePrefix = true;
|
||||
private boolean useUnsupportedPrefix = true;
|
||||
|
||||
@@ -94,8 +89,6 @@ public class SwiftDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
|
||||
@Override
|
||||
public void registerOptions(Options options, Program program) {
|
||||
HelpLocation help = new HelpLocation("AutoAnalysisPlugin", "Demangler_Analyzer");
|
||||
options.registerOption(OPTION_NAME_SWIFT_DIR, OptionType.FILE_TYPE, swiftDir, help,
|
||||
OPTION_DESCRIPTION_SWIFT_DIR);
|
||||
options.registerOption(OPTION_NAME_INCOMPLETE_PREFIX, OptionType.BOOLEAN_TYPE,
|
||||
useIncompletePrefix, help, OPTION_DESCRIPTION_INCOMPLETE_PREFIX);
|
||||
options.registerOption(OPTION_NAME_UNSUPPORTED_PREFIX, OptionType.BOOLEAN_TYPE,
|
||||
@@ -104,9 +97,9 @@ public class SwiftDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
|
||||
|
||||
@Override
|
||||
protected boolean validateOptions(DemanglerOptions options, MessageLog log) {
|
||||
if (options instanceof SwiftDemanglerOptions swiftDemanglerOptions) {
|
||||
if (options instanceof SwiftDemanglerOptions) {
|
||||
try {
|
||||
new SwiftNativeDemangler(swiftDemanglerOptions.getSwiftDir());
|
||||
new SwiftNativeDemangler();
|
||||
return true;
|
||||
}
|
||||
catch (IOException e) {
|
||||
@@ -120,7 +113,6 @@ public class SwiftDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
|
||||
|
||||
@Override
|
||||
public void optionsChanged(Options options, Program program) {
|
||||
swiftDir = options.getFile(OPTION_NAME_SWIFT_DIR, swiftDir);
|
||||
useIncompletePrefix =
|
||||
options.getBoolean(OPTION_NAME_INCOMPLETE_PREFIX, useIncompletePrefix);
|
||||
useUnsupportedPrefix =
|
||||
@@ -130,7 +122,6 @@ public class SwiftDemanglerAnalyzer extends AbstractDemanglerAnalyzer {
|
||||
@Override
|
||||
protected DemanglerOptions getOptions() {
|
||||
SwiftDemanglerOptions swiftDemanglerOptions = new SwiftDemanglerOptions();
|
||||
swiftDemanglerOptions.setSwiftDir(swiftDir);
|
||||
swiftDemanglerOptions.setIncompletePrefix(useIncompletePrefix);
|
||||
swiftDemanglerOptions.setUnsupportedPrefix(useUnsupportedPrefix);
|
||||
return swiftDemanglerOptions;
|
||||
|
||||
@@ -189,7 +189,7 @@ public class SwiftDemangler implements Demangler {
|
||||
private void setSwiftNativeDemangler(SwiftDemanglerOptions options) throws DemangledException {
|
||||
if (nativeDemangler == null) {
|
||||
try {
|
||||
nativeDemangler = new SwiftNativeDemangler(options.getSwiftDir());
|
||||
nativeDemangler = new SwiftNativeDemangler();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new DemangledException(e);
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package ghidra.app.util.demangler.swift;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import ghidra.app.util.demangler.DemanglerOptions;
|
||||
|
||||
/**
|
||||
@@ -27,33 +25,9 @@ public class SwiftDemanglerOptions extends DemanglerOptions {
|
||||
public static final String INCOMPLETE_PREFIX = "$";
|
||||
public static final String UNSUPPORTED_PREFIX = "$$";
|
||||
|
||||
private File swiftDir;
|
||||
private boolean useIncompletePrefix;
|
||||
private boolean useUnsupportedPrefix;
|
||||
|
||||
/**
|
||||
* Gets the Swift directory
|
||||
* <p>
|
||||
* If the Swift directory is on the PATH environment variable, this may return null
|
||||
*
|
||||
* @return The Swift directory
|
||||
*/
|
||||
public File getSwiftDir() {
|
||||
return swiftDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Swift directory
|
||||
* <p>
|
||||
* If the Swift directory is on the PATH environment variable, it is fine to set this to
|
||||
* null
|
||||
*
|
||||
* @param swiftDir The Swift directory
|
||||
*/
|
||||
public void setSwiftDir(File swiftDir) {
|
||||
this.swiftDir = swiftDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the "incomplete prefix" character to use in label names}
|
||||
*/
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* 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.
|
||||
@@ -34,7 +34,7 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
public class SwiftNativeDemangler {
|
||||
|
||||
private String nativeDemanglerPath;
|
||||
private String nativeDemanglerCmd;
|
||||
private boolean standaloneDemanglerBinary;
|
||||
|
||||
/**
|
||||
@@ -54,25 +54,20 @@ public class SwiftNativeDemangler {
|
||||
/**
|
||||
* Creates a new {@link SwiftNativeDemangler}
|
||||
*
|
||||
* @param swiftDir The Swift directory
|
||||
* @throws IOException if there was a problem finding or running the Swift native demangler
|
||||
*/
|
||||
public SwiftNativeDemangler(File swiftDir) throws IOException {
|
||||
public SwiftNativeDemangler() throws IOException {
|
||||
List<String> demanglerNames = List.of("swift-demangle", "swift");
|
||||
IOException ioe = null;
|
||||
for (String demanglerName : demanglerNames) {
|
||||
nativeDemanglerPath = demanglerName;
|
||||
if (swiftDir != null) {
|
||||
nativeDemanglerPath = swiftDir + File.separator + nativeDemanglerPath;
|
||||
}
|
||||
nativeDemanglerCmd = demanglerName; // expect swift demangler to be on the PATH
|
||||
try {
|
||||
int exitCode =
|
||||
new ProcessBuilder(List.of(nativeDemanglerPath, "--version")).start()
|
||||
.waitFor();
|
||||
new ProcessBuilder(List.of(nativeDemanglerCmd, "--version")).start().waitFor();
|
||||
if (exitCode == 0) {
|
||||
ioe = null;
|
||||
standaloneDemanglerBinary =
|
||||
new File(nativeDemanglerPath).getName().contains("-demangle");
|
||||
new File(nativeDemanglerCmd).getName().contains("-demangle");
|
||||
break;
|
||||
}
|
||||
ioe = new IOException("Native Swift demangler exited with code: " + exitCode);
|
||||
@@ -144,7 +139,7 @@ public class SwiftNativeDemangler {
|
||||
*/
|
||||
private BufferedReader demangle(String mangled, List<String> options) throws IOException {
|
||||
List<String> command = new ArrayList<>();
|
||||
command.add(nativeDemanglerPath);
|
||||
command.add(nativeDemanglerCmd);
|
||||
if (!standaloneDemanglerBinary) {
|
||||
command.add("demangle");
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ public class SwiftDemanglerTest extends AbstractGenericTest {
|
||||
// Ghidra does not ship the native Swift demangler binary, so it may not be present to run
|
||||
// these tests. In this scenario, we just want these tests skipped (as opposed to failing).
|
||||
try {
|
||||
new SwiftNativeDemangler(new SwiftDemanglerOptions().getSwiftDir());
|
||||
new SwiftNativeDemangler();
|
||||
}
|
||||
catch (IOException e) {
|
||||
assumeNoException(e); // skip test, don't fail
|
||||
|
||||
Reference in New Issue
Block a user