mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-09-19 16:40:38 -09:00
Merge remote-tracking branch 'origin/ghidra1_Emulator'
Conflicts: gradle/root/eclipse.gradle
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
##VERSION: 2.0
|
||||
ghidra.xtext.sleigh.feature/build.gradle||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.feature/build.properties||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.feature/category.xml||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.feature/feature.xml||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.ide/META-INF/MANIFEST.MF||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.ide/build.gradle||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.ide/build.properties||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.ide/src/ghidra/xtext/sleigh/ide/SleighIdeModule.xtend||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.ide/src/ghidra/xtext/sleigh/ide/SleighIdeSetup.xtend||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.tests/META-INF/MANIFEST.MF||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.tests/build.gradle||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.tests/build.properties||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.tests/src/ghidra/xtext/sleigh/tests/CrossReferenceTest.xtend||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.tests/src/ghidra/xtext/sleigh/tests/SleighMacroTest.xtend||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.tests/src/ghidra/xtext/sleigh/tests/SleighParsingTest.xtend||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.tests/src/ghidra/xtext/sleigh/tests/SleighScopeTest.xtend||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.ui.tests/META-INF/MANIFEST.MF||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.ui.tests/build.gradle||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.ui.tests/build.properties||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.ui/META-INF/MANIFEST.MF||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.ui/build.gradle||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.ui/build.properties||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.ui/plugin.xml||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/SleighEObjectHoverProvider.xtend||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/SleighTextEditComposer.xtend||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/SleighUiModule.xtend||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/console/ConsoleHyperlinking.xtend||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/contentassist/SleighProposalProvider.xtend||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/labeling/SleighDescriptionLabelProvider.xtend||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/labeling/SleighLabelProvider.xtend||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/outline/SleighOutlineTreeProvider.xtend||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh.ui/src/ghidra/xtext/sleigh/ui/quickfix/SleighQuickfixProvider.xtend||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh/.launch/Generate Sleigh (sleigh) Language Infrastructure.launch||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh/.launch/Launch Runtime Eclipse.launch||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh/GhidraSleighEditor_README.html||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh/META-INF/MANIFEST.MF||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh/build.gradle||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh/build.properties||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh/build_README.txt||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh/plugin.xml||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/GenerateSleigh.mwe2||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/Sleigh.xtext||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/SleighRuntimeModule.xtend||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/SleighStandaloneSetup.xtend||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/formatting2/SleighFormatter.xtend||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/generator/SleighGenerator.xtend||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/scoping/SleighScopeProvider.xtend||GHIDRA||||END|
|
||||
ghidra.xtext.sleigh/src/ghidra/xtext/sleigh/validation/SleighValidator.xtend||GHIDRA||||END|
|
||||
@@ -0,0 +1,12 @@
|
||||
// This project requires the Eclipse DSL plugin. To create Eclipse files for this project, run
|
||||
// "gradle eclipse -PeclipseDSL"
|
||||
if (hasProperty("eclipseDSL")) {
|
||||
apply plugin: 'eclipse'
|
||||
eclipse {
|
||||
project {
|
||||
name = 'Eclipse SleighEditor Feature'
|
||||
buildCommand 'org.eclipse.pde.FeatureBuilder'
|
||||
natures 'org.eclipse.pde.FeatureNature'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
bin.includes = feature.xml,\
|
||||
category.xml
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<site>
|
||||
<feature url="features/ghidra.xtext.sleigh.feature_1.0.0.qualifier.jar" id="ghidra.xtext.sleigh.feature" version="1.0.0.qualifier">
|
||||
<category name="ghidra.xtext.sleigh.editor"/>
|
||||
</feature>
|
||||
<category-def name="ghidra.xtext.sleigh.editor" label="Ghidra"/>
|
||||
</site>
|
||||
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<feature
|
||||
id="ghidra.xtext.sleigh.feature"
|
||||
label="Ghidra Sleigh Editor"
|
||||
version="1.0.0.qualifier"
|
||||
provider-name="Ghidra">
|
||||
|
||||
<copyright>
|
||||
None
|
||||
</copyright>
|
||||
|
||||
<license url="">
|
||||
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.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
</license>
|
||||
|
||||
<requires>
|
||||
<import plugin="org.eclipse.xtext"/>
|
||||
<import plugin="org.eclipse.xtext.xbase"/>
|
||||
<import plugin="org.eclipse.xtext.ide"/>
|
||||
<import plugin="org.eclipse.xtext.xbase.ide"/>
|
||||
<import plugin="org.eclipse.xtext.ui"/>
|
||||
<import plugin="org.eclipse.xtext.builder"/>
|
||||
</requires>
|
||||
|
||||
<plugin
|
||||
id="ghidra.xtext.sleigh"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="ghidra.xtext.sleigh.ide"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
<plugin
|
||||
id="ghidra.xtext.sleigh.ui"
|
||||
download-size="0"
|
||||
install-size="0"
|
||||
version="0.0.0"
|
||||
unpack="false"/>
|
||||
|
||||
</feature>
|
||||
@@ -0,0 +1,15 @@
|
||||
Manifest-Version: 1.0
|
||||
Automatic-Module-Name: ghidra.xtext.sleigh.ide
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: ghidra.xtext.sleigh.ide
|
||||
Bundle-Vendor: Ghidra
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-SymbolicName: ghidra.xtext.sleigh.ide; singleton:=true
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: ghidra.xtext.sleigh,
|
||||
org.eclipse.xtext.ide,
|
||||
org.eclipse.xtext.xbase.ide,
|
||||
org.antlr.runtime;bundle-version="[3.2.0,3.2.1)"
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Export-Package: ghidra.xtext.sleigh.ide.contentassist.antlr,
|
||||
ghidra.xtext.sleigh.ide.contentassist.antlr.internal
|
||||
@@ -0,0 +1,40 @@
|
||||
apply plugin: 'java'
|
||||
|
||||
// This project requires the Eclipse DSL plugin. To create Eclipse files for this project, run
|
||||
// "gradle eclipse -PeclipseDSL"
|
||||
if (hasProperty("eclipseDSL")) {
|
||||
apply plugin: 'eclipse'
|
||||
eclipse {
|
||||
project {
|
||||
name = 'Eclipse SleighEditor IDE'
|
||||
buildCommand 'org.eclipse.pde.ManifestBuilder'
|
||||
buildCommand 'org.eclipse.pde.SchemaBuilder'
|
||||
buildCommand 'org.eclipse.xtext.ui.shared.xtextBuilder'
|
||||
natures 'org.eclipse.pde.PluginNature'
|
||||
natures 'org.eclipse.xtext.ui.shared.xtextNature'
|
||||
classpath.file {
|
||||
def requiredPlugins = 'org.eclipse.pde.core.requiredPlugins'
|
||||
beforeMerged { classpath ->
|
||||
classpath.entries.removeAll { entry ->
|
||||
entry.path == requiredPlugins
|
||||
}
|
||||
}
|
||||
whenMerged { classpath ->
|
||||
withXml {
|
||||
def node = it.asNode()
|
||||
node.appendNode('classpathentry', [kind: 'con', path: requiredPlugins])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
srcDir 'src'
|
||||
srcDir 'src-gen'
|
||||
srcDir 'xtend-gen'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
source.. = src/,\
|
||||
src-gen/,\
|
||||
xtend-gen/
|
||||
bin.includes = .,\
|
||||
META-INF/
|
||||
bin.excludes = **/*.xtend
|
||||
@@ -0,0 +1,23 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.xtext.sleigh.ide
|
||||
|
||||
|
||||
/**
|
||||
* Use this class to register ide components.
|
||||
*/
|
||||
class SleighIdeModule extends AbstractSleighIdeModule {
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.xtext.sleigh.ide
|
||||
|
||||
import com.google.inject.Guice
|
||||
import ghidra.xtext.sleigh.SleighRuntimeModule
|
||||
import ghidra.xtext.sleigh.SleighStandaloneSetup
|
||||
import org.eclipse.xtext.util.Modules2
|
||||
|
||||
/**
|
||||
* Initialization support for running Xtext languages as language servers.
|
||||
*/
|
||||
class SleighIdeSetup extends SleighStandaloneSetup {
|
||||
|
||||
override createInjector() {
|
||||
Guice.createInjector(Modules2.mixin(new SleighRuntimeModule, new SleighIdeModule))
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
Manifest-Version: 1.0
|
||||
Automatic-Module-Name: ghidra.xtext.sleigh.tests
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: ghidra.xtext.sleigh.tests
|
||||
Bundle-Vendor: Ghidra
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-SymbolicName: ghidra.xtext.sleigh.tests; singleton:=true
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: ghidra.xtext.sleigh,
|
||||
org.junit.jupiter.api;bundle-version="[5.0.0,6.0.0)",
|
||||
org.eclipse.xtext.testing,
|
||||
org.eclipse.xtext.xbase.testing,
|
||||
org.eclipse.xtext.xbase.lib;bundle-version="2.14.0"
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Export-Package: ghidra.xtext.sleigh.tests;x-internal=true
|
||||
@@ -0,0 +1,40 @@
|
||||
apply plugin: 'java'
|
||||
|
||||
// This project requires the Eclipse DSL plugin. To create Eclipse files for this project, run
|
||||
// "gradle eclipse -PeclipseDSL"
|
||||
if (hasProperty("eclipseDSL")) {
|
||||
apply plugin: 'eclipse'
|
||||
eclipse {
|
||||
project {
|
||||
name = 'Eclipse SleighEditor Tests'
|
||||
buildCommand 'org.eclipse.pde.ManifestBuilder'
|
||||
buildCommand 'org.eclipse.pde.SchemaBuilder'
|
||||
buildCommand 'org.eclipse.xtext.ui.shared.xtextBuilder'
|
||||
natures 'org.eclipse.pde.PluginNature'
|
||||
natures 'org.eclipse.xtext.ui.shared.xtextNature'
|
||||
classpath.file {
|
||||
def requiredPlugins = 'org.eclipse.pde.core.requiredPlugins'
|
||||
beforeMerged { classpath ->
|
||||
classpath.entries.removeAll { entry ->
|
||||
entry.path == requiredPlugins
|
||||
}
|
||||
}
|
||||
whenMerged { classpath ->
|
||||
withXml {
|
||||
def node = it.asNode()
|
||||
node.appendNode('classpathentry', [kind: 'con', path: requiredPlugins])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
srcDir 'src'
|
||||
srcDir 'src-gen'
|
||||
srcDir 'xtend-gen'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
source.. = src/,\
|
||||
src-gen/,\
|
||||
xtend-gen/
|
||||
bin.includes = .,\
|
||||
META-INF/
|
||||
bin.excludes = **/*.xtend
|
||||
@@ -0,0 +1,171 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.xtext.sleigh.tests
|
||||
|
||||
import com.google.inject.Inject
|
||||
import org.eclipse.xtext.diagnostics.Diagnostic
|
||||
import org.eclipse.xtext.testing.InjectWith
|
||||
import org.eclipse.xtext.testing.extensions.InjectionExtension
|
||||
import org.eclipse.xtext.testing.util.ParseHelper
|
||||
import org.eclipse.xtext.testing.validation.ValidationTestHelper
|
||||
import ghidra.xtext.sleigh.sleigh.Model
|
||||
import ghidra.xtext.sleigh.sleigh.SleighPackage
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.^extension.ExtendWith
|
||||
|
||||
@ExtendWith(InjectionExtension)
|
||||
@InjectWith(SleighInjectorProvider)
|
||||
class CrossReferenceTest {
|
||||
|
||||
@Inject extension ParseHelper<Model>
|
||||
@Inject extension ValidationTestHelper
|
||||
|
||||
@Test def void testReferences() {
|
||||
// Macro should have access to registers (globals)
|
||||
var model = '''
|
||||
define space register size=2 type=register_space wordsize=1 default;
|
||||
define register offset=0 size=1 [ Z C N V ];
|
||||
|
||||
define token instr(16)
|
||||
op = (0,15)
|
||||
reg = (0,1)
|
||||
cc = (2,3)
|
||||
;
|
||||
|
||||
attach variables [ reg ] [ Z C N V ];
|
||||
|
||||
:mov reg,N is op=0 & N & reg {
|
||||
<label1>
|
||||
tmp:1 = N;
|
||||
if (tmp == 0) goto <label1>;
|
||||
reg = tmp;
|
||||
}
|
||||
|
||||
:mov reg,N is op=0 & N & reg {
|
||||
tmp = N; # tmp should not resolve
|
||||
}
|
||||
'''.parse
|
||||
// model.assertNoErrors
|
||||
// temp should not resolve
|
||||
model.assertError(
|
||||
SleighPackage::eINSTANCE.getassignSym(),
|
||||
Diagnostic.LINKING_DIAGNOSTIC,
|
||||
353,
|
||||
3,
|
||||
"tmp"
|
||||
)
|
||||
}
|
||||
|
||||
@Test def void testCrossbuildReferences() {
|
||||
// Macro should have access to registers (globals)
|
||||
var model = '''
|
||||
define space register size=2 type=register_space wordsize=1 default;
|
||||
define register offset=0 size=1 [ Z C N V pc ];
|
||||
|
||||
define token instr(16)
|
||||
op = (0,15)
|
||||
reg = (0,1)
|
||||
cc = (2,3)
|
||||
;
|
||||
|
||||
attach variables [ reg ] [ Z C N V ];
|
||||
|
||||
CrossbuildAddr0: loc is epsilon [ loc = inst_start; ] { export *:4 loc; }
|
||||
|
||||
Parallel32: "" is op=0x0 & CrossbuildAddr0 {
|
||||
crossbuild CrossbuildAddr0,COMMIT;
|
||||
crossbuild CrossbuildAddr0,LOOP;
|
||||
}
|
||||
|
||||
:^instruction is cc=0x1 & instruction {
|
||||
build instruction;
|
||||
<<LOOP>>
|
||||
pc = 0;
|
||||
goto [pc];
|
||||
}
|
||||
|
||||
:L is op=0x999 {
|
||||
build Parallel32;
|
||||
<<COMMIT>>
|
||||
pc = 0;
|
||||
}
|
||||
'''.parse
|
||||
model.assertNoErrors
|
||||
}
|
||||
|
||||
|
||||
@Test def void testSubPieceReferences() {
|
||||
var model = '''
|
||||
define space register size=2 type=register_space wordsize=1 default;
|
||||
define register offset=0 size=1 [ Z C N V ];
|
||||
define register offset=0 size=4 [ BR ];
|
||||
|
||||
define token instr(16)
|
||||
op = (0,15)
|
||||
reg = (0,1)
|
||||
cc = (2,3)
|
||||
;
|
||||
|
||||
attach variables [ reg ] [ Z C N V ];
|
||||
|
||||
macro macro_a(arg1,arg2) {
|
||||
local foo = 1;
|
||||
foo = (~foo & foo | foo) << foo;
|
||||
Z = 1;
|
||||
arg1 = 3;
|
||||
arg2 = foo;
|
||||
}
|
||||
|
||||
:mov reg,N,op is op=0 & N & reg & op & op=1 {
|
||||
tmp:1 = 1;
|
||||
tmp2:1 = reg(4);
|
||||
macro_a(reg,tmp);
|
||||
tmp2:2 = BR:2;
|
||||
tmp2:2 = BR(2);
|
||||
tmp2:2 = reg:2;
|
||||
}
|
||||
'''.parse
|
||||
model.assertNoErrors
|
||||
}
|
||||
|
||||
@Test def void testglobalsetReferences() {
|
||||
var model = '''
|
||||
define space register size=2 type=register_space wordsize=1 default;
|
||||
define register offset=0 size=1 [ Z C N V contextreg ];
|
||||
define register offset=0 size=4 [ BR ];
|
||||
|
||||
define context contextreg
|
||||
TMode = (0,0)
|
||||
;
|
||||
|
||||
define token instr(16)
|
||||
op = (0,15)
|
||||
reg = (0,1)
|
||||
cc = (2,3)
|
||||
;
|
||||
|
||||
attach variables [ reg ] [ Z C N V ];
|
||||
|
||||
GS: reloff is op=100
|
||||
[ reloff = inst_start + 8; TMode=1; globalset(reloff,TMode); globalset(inst_next,TMode); ]
|
||||
{
|
||||
export *:4 reloff;
|
||||
}
|
||||
|
||||
'''.parse
|
||||
model.assertNoErrors
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.xtext.sleigh.tests
|
||||
|
||||
import com.google.inject.Inject
|
||||
import org.eclipse.xtext.diagnostics.Diagnostic
|
||||
import org.eclipse.xtext.testing.InjectWith
|
||||
import org.eclipse.xtext.testing.extensions.InjectionExtension
|
||||
import org.eclipse.xtext.testing.util.ParseHelper
|
||||
import org.eclipse.xtext.testing.validation.ValidationTestHelper
|
||||
import ghidra.xtext.sleigh.sleigh.Model
|
||||
import ghidra.xtext.sleigh.sleigh.SleighPackage
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.^extension.ExtendWith
|
||||
|
||||
@ExtendWith(InjectionExtension)
|
||||
@InjectWith(SleighInjectorProvider)
|
||||
class SleighMacroTest {
|
||||
|
||||
@Inject extension ParseHelper<Model>
|
||||
@Inject extension ValidationTestHelper
|
||||
|
||||
@Test def void testMacros() {
|
||||
var model = '''
|
||||
macro xyz(tom,dick,harry) {
|
||||
tom = dick;
|
||||
harry = tom;
|
||||
tom = 1;
|
||||
}
|
||||
|
||||
macro ijk(do,wop) {
|
||||
do = 1;
|
||||
wop = 1;
|
||||
}
|
||||
'''.parse
|
||||
model.assertNoErrors
|
||||
}
|
||||
|
||||
@Test def void testMacroReferences() {
|
||||
// Macro should have access to registers (globals)
|
||||
var model = '''
|
||||
define space register size=2 type=register_space wordsize=1 default;
|
||||
define register offset=0 size=1 [ Z ];
|
||||
|
||||
macro a() {
|
||||
Z = 1;
|
||||
}
|
||||
'''.parse
|
||||
model.assertNoErrors
|
||||
}
|
||||
|
||||
@Test def void testCrossedMacroRefs() {
|
||||
// Macro should not have cross parameter reference
|
||||
var model = '''
|
||||
macro xyz(tom,dick,harry) {
|
||||
tom = dick;
|
||||
harry = do;
|
||||
}
|
||||
|
||||
macro ijk(do,wop) {
|
||||
do = 1;
|
||||
tom = wop;
|
||||
}
|
||||
'''.parse
|
||||
model.assertError(
|
||||
SleighPackage::eINSTANCE.getassignSym(),
|
||||
Diagnostic.LINKING_DIAGNOSTIC,
|
||||
"Couldn't resolve reference to lhsvarnode 'tom'."
|
||||
)
|
||||
model.assertError(
|
||||
SleighPackage::eINSTANCE.getexprSym(),
|
||||
Diagnostic.LINKING_DIAGNOSTIC,
|
||||
"Couldn't resolve reference to EObject 'do'."
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.xtext.sleigh.tests
|
||||
|
||||
import com.google.inject.Inject
|
||||
import org.eclipse.xtext.testing.InjectWith
|
||||
import org.eclipse.xtext.testing.extensions.InjectionExtension
|
||||
import org.eclipse.xtext.testing.util.ParseHelper
|
||||
import org.eclipse.xtext.testing.validation.ValidationTestHelper
|
||||
import ghidra.xtext.sleigh.sleigh.Model
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.^extension.ExtendWith
|
||||
|
||||
@ExtendWith(InjectionExtension)
|
||||
@InjectWith(SleighInjectorProvider)
|
||||
class SleighParsingTest {
|
||||
|
||||
@Inject
|
||||
ParseHelper<Model> parseHelper
|
||||
|
||||
@Inject extension ValidationTestHelper
|
||||
|
||||
@Test def void testEndian() {
|
||||
var model = parseHelper.parse('''
|
||||
define endian= big;
|
||||
''')
|
||||
model.assertNoErrors
|
||||
|
||||
model = parseHelper.parse('''
|
||||
define endian= little;
|
||||
''')
|
||||
model.assertNoErrors
|
||||
|
||||
|
||||
model = parseHelper.parse('''
|
||||
define endian= little;
|
||||
''')
|
||||
|
||||
}
|
||||
|
||||
@Test def void macroUse() {
|
||||
var model = parseHelper.parse('''
|
||||
define space register size=2 type=register_space wordsize=1 default;
|
||||
define register offset=0 size=1 [ Z C N V
|
||||
@if ENDIAN == "little"
|
||||
EF
|
||||
@else
|
||||
BF
|
||||
@endif
|
||||
];
|
||||
|
||||
define register offset=100 size=1 [ contReg
|
||||
@if defined(ENDIAN)
|
||||
ifReg
|
||||
@endif
|
||||
];
|
||||
|
||||
define token instr(16)
|
||||
op = (0,15)
|
||||
@if ENDIAN == "big"
|
||||
reg = (0,1)
|
||||
@endif
|
||||
cc = (2,3)
|
||||
@else
|
||||
;
|
||||
|
||||
define context contReg
|
||||
contFlag = (0,0)
|
||||
;
|
||||
|
||||
attach variables [ reg ] [ Z C N V
|
||||
@if ENDIAN == "little"
|
||||
EF
|
||||
@else
|
||||
BF
|
||||
@endif
|
||||
];
|
||||
|
||||
macro a(arg1,arg2) {
|
||||
local foo = 1;
|
||||
@if defined(ENDIAN)
|
||||
foo = (~foo & foo | foo) << foo;
|
||||
@endif
|
||||
Z = 1;
|
||||
arg1 = 3;
|
||||
arg2 = foo;
|
||||
}
|
||||
|
||||
CC: "ne" is cc=0x1 { local tmp = !Z; C = 1; tmp = C; export tmp; }
|
||||
CC: "lt" is cc=0x2 { local tmp = N != V; export tmp; }
|
||||
CC: "lt" is cc=0x2 { local tmp:1 = N != V; export tmp; }
|
||||
CC: "lt" is cc=0x2 { tmp:1 = N != V; export tmp; }
|
||||
CC: "lt" is cc=0x2 { tmp:1 = N != V; export tmp; tmp = 1; }
|
||||
|
||||
:mov reg,N,op is op=0 & CC & N & reg & op & op=1
|
||||
{ tmp:1 = CC;
|
||||
@if defined(ENDIAN)
|
||||
reg = tmp;
|
||||
@endif
|
||||
}
|
||||
|
||||
Dest: loc is op=0 [ loc = inst_next; ] { export loc; }
|
||||
:jmp Dest is Dest { call Dest; }
|
||||
|
||||
:set reg is contFlag=0 & op=0 [ contFlag = 1; ] {}
|
||||
''')
|
||||
model.assertNoErrors
|
||||
}
|
||||
|
||||
@Test def void testWith() {
|
||||
var model = parseHelper.parse('''
|
||||
define space register size=2 type=register_space wordsize=1 default;
|
||||
define register offset=0 size=1 [ Z C N V
|
||||
@if ENDIAN == "little"
|
||||
EF
|
||||
@else
|
||||
BF
|
||||
@endif
|
||||
];
|
||||
|
||||
define register offset=100 size=1 [ contReg
|
||||
@if defined(ENDIAN)
|
||||
ifReg
|
||||
@endif
|
||||
];
|
||||
|
||||
define token instr(16)
|
||||
op = (0,15)
|
||||
@if ENDIAN == "big"
|
||||
reg = (0,1)
|
||||
@endif
|
||||
cc = (2,3)
|
||||
@else
|
||||
;
|
||||
|
||||
define context contReg
|
||||
contFlag = (0,0)
|
||||
;
|
||||
|
||||
attach variables [ reg ] [ Z C N V
|
||||
@if ENDIAN == "little"
|
||||
EF
|
||||
@else
|
||||
BF
|
||||
@endif
|
||||
];
|
||||
|
||||
macro a(arg1,arg2) {
|
||||
local foo = 1;
|
||||
@if defined(ENDIAN)
|
||||
foo = (~foo & foo | foo) << foo;
|
||||
@endif
|
||||
Z = 1;
|
||||
arg1 = 3;
|
||||
arg2 = foo;
|
||||
}
|
||||
|
||||
with CC : cc=0x1 {
|
||||
CC: "ne" is cc=0x1 { local tmp = !Z; C = 1; tmp = C; export tmp; }
|
||||
CC: "lt" is cc=0x2 { local tmp = N != V; export tmp; }
|
||||
CC: "lt" is cc=0x2 { local tmp:1 = N != V; export tmp; }
|
||||
CC: "lt" is cc=0x2 { tmp:1 = N != V; export tmp; }
|
||||
CC: "lt" is cc=0x2 { tmp:1 = N != V; export tmp; tmp = 1; }
|
||||
}
|
||||
|
||||
:mov reg,N,op is op=0 & CC & N & reg & op & op=1
|
||||
{ tmp:1 = CC;
|
||||
@if defined(ENDIAN)
|
||||
reg = tmp;
|
||||
@endif
|
||||
}
|
||||
|
||||
Dest: loc is op=0 [ loc = inst_next; ] { export loc; }
|
||||
:jmp Dest is Dest { call Dest; }
|
||||
|
||||
:set reg is contFlag=0 & op=0 [ contFlag = 1; ] {}
|
||||
''')
|
||||
model.assertNoErrors
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,301 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.xtext.sleigh.tests
|
||||
|
||||
import com.google.inject.Inject
|
||||
import com.google.inject.Provider
|
||||
import org.eclipse.emf.ecore.util.EcoreUtil
|
||||
import org.eclipse.xtext.diagnostics.Diagnostic
|
||||
import org.eclipse.xtext.resource.XtextResourceSet
|
||||
import org.eclipse.xtext.testing.InjectWith
|
||||
import org.eclipse.xtext.testing.extensions.InjectionExtension
|
||||
import org.eclipse.xtext.testing.util.ParseHelper
|
||||
import org.eclipse.xtext.testing.validation.ValidationTestHelper
|
||||
import ghidra.xtext.sleigh.sleigh.Model
|
||||
import ghidra.xtext.sleigh.sleigh.SleighPackage
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.^extension.ExtendWith
|
||||
|
||||
@ExtendWith(InjectionExtension)
|
||||
@InjectWith(SleighInjectorProvider)
|
||||
class SleighScopeTest {
|
||||
|
||||
@Inject extension ParseHelper<Model> parser
|
||||
@Inject extension ValidationTestHelper validationTester
|
||||
|
||||
@Inject
|
||||
private Provider<XtextResourceSet> resourceSetProvider;
|
||||
|
||||
// Sample to use for testing
|
||||
// var model = '''
|
||||
// define space register size=2 type=register_space wordsize=1 default;
|
||||
// define register offset=0 size=1 [ Z C N V ];
|
||||
//
|
||||
// define token instr(16)
|
||||
// op = (0,15)
|
||||
// reg = (0,1)
|
||||
// cc = (2,3)
|
||||
// ;
|
||||
//
|
||||
// attach variables [ reg ] [ Z C N V ];
|
||||
//
|
||||
// macro a() {
|
||||
// Z = 1;
|
||||
// }
|
||||
//
|
||||
// CC: "ne" is cc=0x1 { local tmp = !Z; C = 1; tmp = C; export tmp; }
|
||||
// CC: "lt" is cc=0x2 { local tmp = N != V; export tmp; }
|
||||
// CC: "lt" is cc=0x2 { local tmp:1 = N != V; export tmp; }
|
||||
// CC: "lt" is cc=0x2 { tmp:1 = N != V; export tmp; }
|
||||
// CC: "lt" is cc=0x2 { tmp:1 = N != V; export tmp; tmp = 1; }
|
||||
//
|
||||
// :mov reg,N is op=0 & CC & N & reg { tmp:1 = CC; reg = tmp; }
|
||||
// '''.parse
|
||||
|
||||
@Test def void testReferences() {
|
||||
// tmp should not resolve
|
||||
var model = '''
|
||||
define space register size=2 type=register_space wordsize=1 default;
|
||||
define register offset=0 size=1 [ Z C N V ];
|
||||
|
||||
define token instr(16)
|
||||
op = (0,15)
|
||||
reg = (0,1)
|
||||
cc = (2,3)
|
||||
;
|
||||
|
||||
attach variables [ reg ] [ Z C N V ];
|
||||
|
||||
:mov reg,N is op=0 & C & N & reg { tmp:1 = 1; }
|
||||
|
||||
:mov reg,N is op=0 & C & N & reg { tmp = C; }
|
||||
'''.parse
|
||||
|
||||
assertError(model,
|
||||
SleighPackage::eINSTANCE.getassignSym(),
|
||||
Diagnostic.LINKING_DIAGNOSTIC, 311, 3,
|
||||
"Couldn't resolve reference to lhsvarnode 'tmp'."
|
||||
)
|
||||
|
||||
// tmp should not resolve
|
||||
model = '''
|
||||
define space register size=2 type=register_space wordsize=1 default;
|
||||
define register offset=0 size=1 [ Z C N V ];
|
||||
|
||||
define token instr(16)
|
||||
op = (0,15)
|
||||
reg = (0,1)
|
||||
cc = (2,3)
|
||||
;
|
||||
|
||||
attach variables [ reg ] [ Z C N V ];
|
||||
|
||||
:mov reg,N is op=0 & C & N & reg { tmp:1 = 1; }
|
||||
|
||||
:mov reg,N is op=0 & C & N & reg { reg = tmp; }
|
||||
'''.parse
|
||||
|
||||
assertError(model,
|
||||
SleighPackage::eINSTANCE.getexprSym(),
|
||||
Diagnostic.LINKING_DIAGNOSTIC, 314, 3,
|
||||
"Couldn't resolve reference to EObject 'tmp'."
|
||||
)
|
||||
}
|
||||
|
||||
@Test def void testMacroReferences() {
|
||||
var model = '''
|
||||
define space register size=2 type=register_space wordsize=1 default;
|
||||
define register offset=0 size=1 [ Z C N V ];
|
||||
|
||||
define token instr(16)
|
||||
op = (0,15)
|
||||
reg = (0,1)
|
||||
cc = (2,3)
|
||||
;
|
||||
|
||||
attach variables [ reg ] [ Z C N V ];
|
||||
|
||||
macro macro_a(arg1,arg2) {
|
||||
local foo = 1;
|
||||
foo = (~foo & foo | foo) << foo;
|
||||
Z = 1;
|
||||
arg1 = 3;
|
||||
arg2 = foo;
|
||||
}
|
||||
|
||||
:mov reg,N,op is op=0 & N & reg & op & op=1 {
|
||||
tmp:1 = 1;
|
||||
tmp2:1 = reg(4);
|
||||
macro_a(reg,tmp);
|
||||
}
|
||||
'''.parse
|
||||
model.assertNoErrors
|
||||
}
|
||||
|
||||
|
||||
@Test def void testBadAliasReferences() {
|
||||
var model = '''
|
||||
define space register size=2 type=register_space wordsize=1 default;
|
||||
|
||||
define token instr(16)
|
||||
op = (0,15)
|
||||
reg = (0,1)
|
||||
cc = (2,3)
|
||||
;
|
||||
|
||||
:mov AliasRef is op=0 & AliasRef [ AliasRef = inst_next; ] { tmp:1 = AliasRef; } #AliasRef in constraint
|
||||
'''.parse
|
||||
|
||||
assertError(model,
|
||||
SleighPackage::eINSTANCE.getconstraint(),
|
||||
Diagnostic.LINKING_DIAGNOSTIC, 164,8,
|
||||
"Couldn't resolve reference to EObject 'AliasRef'."
|
||||
)
|
||||
|
||||
model = '''
|
||||
define space register size=2 type=register_space wordsize=1 default;
|
||||
|
||||
define token instr(16)
|
||||
op = (0,15)
|
||||
reg = (0,1)
|
||||
cc = (2,3)
|
||||
;
|
||||
|
||||
AliasRef: "empty" is op=0 {}
|
||||
|
||||
:mov AliasRef is op=0 [ AliasRef = inst_next; ] { tmp:1 = AliasRef; } #AliasRef in constraint
|
||||
'''.parse
|
||||
|
||||
var references = EcoreUtil.UsageCrossReferencer.find(model.elements)
|
||||
|
||||
references.forEach[p1, p2 |
|
||||
System.out.println(p1 + " -> " + p2)
|
||||
]
|
||||
}
|
||||
|
||||
@Test def void testAliasRefOverrid() {
|
||||
|
||||
var XtextResourceSet resourceSet = resourceSetProvider.get();
|
||||
|
||||
parser.parse("REGGsrc: reg is reg { export reg; } ", resourceSet)
|
||||
|
||||
var model = parser.parse('''
|
||||
define space register size=2 type=register_space wordsize=1 default;
|
||||
define register offset=0 size=1 [ Z C N V ];
|
||||
define register offset=100 size=1 [ contReg ];
|
||||
|
||||
define token instr(16)
|
||||
op = (0,15)
|
||||
reg = (0,1)
|
||||
cc = (2,3)
|
||||
;
|
||||
|
||||
define context contReg
|
||||
contFlag = (0,0)
|
||||
;
|
||||
|
||||
attach variables [ reg ] [ Z C N V ];
|
||||
|
||||
macro a(arg1,arg2) {
|
||||
local foo = 1;
|
||||
foo = (~foo & foo | foo) << foo;
|
||||
Z = 1;
|
||||
arg1 = 3;
|
||||
arg2 = foo;
|
||||
}
|
||||
|
||||
CC: "ne" is cc=0x1 { local tmp = !Z; C = 1; tmp = C; export tmp; }
|
||||
CC: "lt" is cc=0x2 { local tmp = N != V; export tmp; }
|
||||
CC: "lt" is cc=0x2 { local tmp:1 = N != V; export tmp; }
|
||||
CC: "lt" is cc=0x2 { tmp:1 = N != V; export tmp; }
|
||||
CC: "lt" is cc=0x2 { tmp:1 = N != V; export tmp; tmp = 1; }
|
||||
|
||||
:mov reg,N,op is op=0 & CC & N & reg & op & op=1 { tmp:1 = CC; reg = tmp; }
|
||||
|
||||
:mov REGGsrc,N,op is op=0 & CC & N & reg & REGGsrc & op & op=1 { REGGsrc = op; }
|
||||
|
||||
Dest: loc is op=0 [ loc = inst_next; ] { export loc; }
|
||||
:jmp Dest is Dest { call Dest; }
|
||||
|
||||
:set reg is contFlag=0 & op=0 [ contFlag = 1; ] {}
|
||||
''', resourceSet)
|
||||
model.assertNoErrors;
|
||||
|
||||
var references = EcoreUtil.UsageCrossReferencer.find(model.elements)
|
||||
|
||||
references.forEach[p1, p2 |
|
||||
System.out.println(p1 + " -> " + p2)
|
||||
]
|
||||
|
||||
|
||||
//
|
||||
// model.eAllContents.filter[elem |
|
||||
// elem instanceof SUBTABLESYM
|
||||
// ].forEach[
|
||||
// elem | var list = elem.eCrossReferences; System.out.println(list)
|
||||
// ]
|
||||
//
|
||||
// // now need to verify xref of reg,N,op are not aliases in the match or pcode
|
||||
// var refs = model.eCrossReferences;
|
||||
// refs.forEach[
|
||||
// element | println(element);
|
||||
// ]
|
||||
//
|
||||
// need to verify that an alias in the context var stays as an alias var
|
||||
// unless it is also a global symbol
|
||||
}
|
||||
|
||||
@Test def void testContextAliasRef() {
|
||||
|
||||
var XtextResourceSet resourceSet = resourceSetProvider.get();
|
||||
|
||||
parser.parse("REGGsrc: reg is reg { export reg; } ", resourceSet)
|
||||
|
||||
var model = parser.parse('''
|
||||
define space register size=2 type=register_space wordsize=1 default;
|
||||
define register offset=0 size=1 [ Z C N V ];
|
||||
define register offset=100 size=1 [ contReg ];
|
||||
|
||||
define token instr(16)
|
||||
op = (0,15)
|
||||
reg = (0,1)
|
||||
cc = (2,3)
|
||||
;
|
||||
|
||||
define context contReg
|
||||
contFlag = (0,0)
|
||||
cont2 = (1,1)
|
||||
;
|
||||
|
||||
attach variables [ reg ] [ Z C N V ];
|
||||
|
||||
|
||||
#:mov reg,N,op,vis is op=0 & N & reg & op & op=1 [ vis = op << 20; ] { tmp:1 = vis reg = tmp; }
|
||||
|
||||
#:mov reg,N,op,vis is op=0 & N & reg & op & op=1 [ vis = op << 20; contFlag=op; cont2=contFlag; ] { tmp:1 = vis; reg = tmp; }
|
||||
|
||||
:mov reg,vis is op=0 & reg [ vis = 20; contFlag=vis; ] { tmp:1 = vis; reg = tmp; }
|
||||
|
||||
''', resourceSet)
|
||||
model.assertNoErrors;
|
||||
|
||||
var references = EcoreUtil.UsageCrossReferencer.find(model.elements)
|
||||
|
||||
references.forEach[p1, p2 |
|
||||
System.out.println(p1 + " -> " + p2)
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
Manifest-Version: 1.0
|
||||
Automatic-Module-Name: ghidra.xtext.sleigh.ui.tests
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: ghidra.xtext.sleigh.ui.tests
|
||||
Bundle-Vendor: Ghidra
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-SymbolicName: ghidra.xtext.sleigh.ui.tests; singleton:=true
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: ghidra.xtext.sleigh.ui,
|
||||
org.junit.jupiter.api;bundle-version="[5.0.0,6.0.0)",
|
||||
org.eclipse.xtext.testing,
|
||||
org.eclipse.xtext.xbase.testing,
|
||||
org.eclipse.xtext.junit4,
|
||||
org.eclipse.xtext.xbase.junit,
|
||||
org.eclipse.core.runtime,
|
||||
org.eclipse.ui.workbench;resolution:=optional
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Export-Package: ghidra.xtext.sleigh.ui.tests;x-internal=true
|
||||
@@ -0,0 +1,40 @@
|
||||
apply plugin: 'java'
|
||||
|
||||
// This project requires the Eclipse DSL plugin. To create Eclipse files for this project, run
|
||||
// "gradle eclipse -PeclipseDSL"
|
||||
if (hasProperty("eclipseDSL")) {
|
||||
apply plugin: 'eclipse'
|
||||
eclipse {
|
||||
project {
|
||||
name = 'Eclipse SleighEditor UI Tests'
|
||||
buildCommand 'org.eclipse.pde.ManifestBuilder'
|
||||
buildCommand 'org.eclipse.pde.SchemaBuilder'
|
||||
buildCommand 'org.eclipse.xtext.ui.shared.xtextBuilder'
|
||||
natures 'org.eclipse.pde.PluginNature'
|
||||
natures 'org.eclipse.xtext.ui.shared.xtextNature'
|
||||
classpath.file {
|
||||
def requiredPlugins = 'org.eclipse.pde.core.requiredPlugins'
|
||||
beforeMerged { classpath ->
|
||||
classpath.entries.removeAll { entry ->
|
||||
entry.path == requiredPlugins
|
||||
}
|
||||
}
|
||||
whenMerged { classpath ->
|
||||
withXml {
|
||||
def node = it.asNode()
|
||||
node.appendNode('classpathentry', [kind: 'con', path: requiredPlugins])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
srcDir 'src'
|
||||
srcDir 'src-gen'
|
||||
srcDir 'xtend-gen'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
source.. = src/,\
|
||||
src-gen/,\
|
||||
xtend-gen/
|
||||
bin.includes = .,\
|
||||
META-INF/
|
||||
bin.excludes = **/*.xtend
|
||||
@@ -0,0 +1,27 @@
|
||||
Manifest-Version: 1.0
|
||||
Automatic-Module-Name: ghidra.xtext.sleigh.ui
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: ghidra.xtext.sleigh.ui
|
||||
Bundle-Vendor: Ghidra
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-SymbolicName: ghidra.xtext.sleigh.ui; singleton:=true
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: ghidra.xtext.sleigh,
|
||||
ghidra.xtext.sleigh.ide,
|
||||
org.eclipse.xtext.ui,
|
||||
org.eclipse.xtext.ui.shared,
|
||||
org.eclipse.xtext.ui.codetemplates.ui,
|
||||
org.eclipse.ui.editors;bundle-version="3.5.0",
|
||||
org.eclipse.ui.ide;bundle-version="3.5.0",
|
||||
org.eclipse.ui,
|
||||
org.eclipse.compare,
|
||||
org.eclipse.xtext.builder,
|
||||
org.eclipse.xtext.xbase.lib;bundle-version="2.14.0",
|
||||
org.eclipse.xtend.lib;bundle-version="2.14.0";resolution:=optional,
|
||||
org.eclipse.ui.console
|
||||
Import-Package: org.apache.log4j
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Export-Package: ghidra.xtext.sleigh.ui.internal,
|
||||
ghidra.xtext.sleigh.ui.contentassist,
|
||||
ghidra.xtext.sleigh.ui.quickfix
|
||||
Bundle-Activator: ghidra.xtext.sleigh.ui.internal.SleighActivator
|
||||
@@ -0,0 +1,40 @@
|
||||
apply plugin: 'java'
|
||||
|
||||
// This project requires the Eclipse DSL plugin. To create Eclipse files for this project, run
|
||||
// "gradle eclipse -PeclipseDSL"
|
||||
if (hasProperty("eclipseDSL")) {
|
||||
apply plugin: 'eclipse'
|
||||
eclipse {
|
||||
project {
|
||||
name = 'Eclipse SleighEditor UI'
|
||||
buildCommand 'org.eclipse.pde.ManifestBuilder'
|
||||
buildCommand 'org.eclipse.pde.SchemaBuilder'
|
||||
buildCommand 'org.eclipse.xtext.ui.shared.xtextBuilder'
|
||||
natures 'org.eclipse.pde.PluginNature'
|
||||
natures 'org.eclipse.xtext.ui.shared.xtextNature'
|
||||
classpath.file {
|
||||
def requiredPlugins = 'org.eclipse.pde.core.requiredPlugins'
|
||||
beforeMerged { classpath ->
|
||||
classpath.entries.removeAll { entry ->
|
||||
entry.path == requiredPlugins
|
||||
}
|
||||
}
|
||||
whenMerged { classpath ->
|
||||
withXml {
|
||||
def node = it.asNode()
|
||||
node.appendNode('classpathentry', [kind: 'con', path: requiredPlugins])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
srcDir 'src'
|
||||
srcDir 'src-gen'
|
||||
srcDir 'xtend-gen'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
source.. = src/,\
|
||||
src-gen/,\
|
||||
xtend-gen/
|
||||
bin.includes = .,\
|
||||
META-INF/,\
|
||||
plugin.xml
|
||||
bin.excludes = **/*.xtend
|
||||
@@ -0,0 +1,571 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?eclipse version="3.0"?>
|
||||
<plugin>
|
||||
<extension
|
||||
point="org.eclipse.ui.editors">
|
||||
<editor
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.editor.XtextEditor"
|
||||
contributorClass="org.eclipse.ui.editors.text.TextEditorActionContributor"
|
||||
default="true"
|
||||
extensions="slaspec,sinc"
|
||||
id="ghidra.xtext.sleigh.Sleigh"
|
||||
name="Sleigh Editor">
|
||||
</editor>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.ui.handlers">
|
||||
<handler
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.editor.hyperlinking.OpenDeclarationHandler"
|
||||
commandId="org.eclipse.xtext.ui.editor.hyperlinking.OpenDeclaration">
|
||||
<activeWhen>
|
||||
<reference
|
||||
definitionId="ghidra.xtext.sleigh.Sleigh.Editor.opened">
|
||||
</reference>
|
||||
</activeWhen>
|
||||
</handler>
|
||||
<handler
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.editor.handler.ValidateActionHandler"
|
||||
commandId="ghidra.xtext.sleigh.Sleigh.validate">
|
||||
<activeWhen>
|
||||
<reference
|
||||
definitionId="ghidra.xtext.sleigh.Sleigh.Editor.opened">
|
||||
</reference>
|
||||
</activeWhen>
|
||||
</handler>
|
||||
<!-- copy qualified name -->
|
||||
<handler
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.editor.copyqualifiedname.EditorCopyQualifiedNameHandler"
|
||||
commandId="org.eclipse.xtext.ui.editor.copyqualifiedname.EditorCopyQualifiedName">
|
||||
<activeWhen>
|
||||
<reference definitionId="ghidra.xtext.sleigh.Sleigh.Editor.opened" />
|
||||
</activeWhen>
|
||||
</handler>
|
||||
<handler
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.editor.copyqualifiedname.OutlineCopyQualifiedNameHandler"
|
||||
commandId="org.eclipse.xtext.ui.editor.copyqualifiedname.OutlineCopyQualifiedName">
|
||||
<activeWhen>
|
||||
<and>
|
||||
<reference definitionId="ghidra.xtext.sleigh.Sleigh.XtextEditor.opened" />
|
||||
<iterate>
|
||||
<adapt type="org.eclipse.xtext.ui.editor.outline.IOutlineNode" />
|
||||
</iterate>
|
||||
</and>
|
||||
</activeWhen>
|
||||
</handler>
|
||||
</extension>
|
||||
<extension point="org.eclipse.core.expressions.definitions">
|
||||
<definition id="ghidra.xtext.sleigh.Sleigh.Editor.opened">
|
||||
<and>
|
||||
<reference definitionId="isActiveEditorAnInstanceOfXtextEditor"/>
|
||||
<with variable="activeEditor">
|
||||
<test property="org.eclipse.xtext.ui.editor.XtextEditor.languageName"
|
||||
value="ghidra.xtext.sleigh.Sleigh"
|
||||
forcePluginActivation="true"/>
|
||||
</with>
|
||||
</and>
|
||||
</definition>
|
||||
<definition id="ghidra.xtext.sleigh.Sleigh.XtextEditor.opened">
|
||||
<and>
|
||||
<reference definitionId="isXtextEditorActive"/>
|
||||
<with variable="activeEditor">
|
||||
<test property="org.eclipse.xtext.ui.editor.XtextEditor.languageName"
|
||||
value="ghidra.xtext.sleigh.Sleigh"
|
||||
forcePluginActivation="true"/>
|
||||
</with>
|
||||
</and>
|
||||
</definition>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.ui.preferencePages">
|
||||
<page
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.editor.preferences.LanguageRootPreferencePage"
|
||||
id="ghidra.xtext.sleigh.Sleigh"
|
||||
name="Sleigh">
|
||||
<keywordReference id="ghidra.xtext.sleigh.ui.keyword_Sleigh"/>
|
||||
</page>
|
||||
<page
|
||||
category="ghidra.xtext.sleigh.Sleigh"
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.editor.syntaxcoloring.SyntaxColoringPreferencePage"
|
||||
id="ghidra.xtext.sleigh.Sleigh.coloring"
|
||||
name="Syntax Coloring">
|
||||
<keywordReference id="ghidra.xtext.sleigh.ui.keyword_Sleigh"/>
|
||||
</page>
|
||||
<page
|
||||
category="ghidra.xtext.sleigh.Sleigh"
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.editor.templates.XtextTemplatePreferencePage"
|
||||
id="ghidra.xtext.sleigh.Sleigh.templates"
|
||||
name="Templates">
|
||||
<keywordReference id="ghidra.xtext.sleigh.ui.keyword_Sleigh"/>
|
||||
</page>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.ui.propertyPages">
|
||||
<page
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.editor.preferences.LanguageRootPreferencePage"
|
||||
id="ghidra.xtext.sleigh.Sleigh"
|
||||
name="Sleigh">
|
||||
<keywordReference id="ghidra.xtext.sleigh.ui.keyword_Sleigh"/>
|
||||
<enabledWhen>
|
||||
<adapt type="org.eclipse.core.resources.IProject"/>
|
||||
</enabledWhen>
|
||||
<filter name="projectNature" value="org.eclipse.xtext.ui.shared.xtextNature"/>
|
||||
</page>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.ui.keywords">
|
||||
<keyword
|
||||
id="ghidra.xtext.sleigh.ui.keyword_Sleigh"
|
||||
label="Sleigh"/>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.ui.commands">
|
||||
<command
|
||||
description="Trigger expensive validation"
|
||||
id="ghidra.xtext.sleigh.Sleigh.validate"
|
||||
name="Validate">
|
||||
</command>
|
||||
<!-- copy qualified name -->
|
||||
<command
|
||||
id="org.eclipse.xtext.ui.editor.copyqualifiedname.EditorCopyQualifiedName"
|
||||
categoryId="org.eclipse.ui.category.edit"
|
||||
description="Copy the qualified name for the selected element"
|
||||
name="Copy Qualified Name">
|
||||
</command>
|
||||
<command
|
||||
id="org.eclipse.xtext.ui.editor.copyqualifiedname.OutlineCopyQualifiedName"
|
||||
categoryId="org.eclipse.ui.category.edit"
|
||||
description="Copy the qualified name for the selected element"
|
||||
name="Copy Qualified Name">
|
||||
</command>
|
||||
</extension>
|
||||
<extension point="org.eclipse.ui.menus">
|
||||
<menuContribution
|
||||
locationURI="popup:#TextEditorContext?after=group.edit">
|
||||
<command
|
||||
commandId="ghidra.xtext.sleigh.Sleigh.validate"
|
||||
style="push"
|
||||
tooltip="Trigger expensive validation">
|
||||
<visibleWhen checkEnabled="false">
|
||||
<reference
|
||||
definitionId="ghidra.xtext.sleigh.Sleigh.Editor.opened">
|
||||
</reference>
|
||||
</visibleWhen>
|
||||
</command>
|
||||
</menuContribution>
|
||||
<!-- copy qualified name -->
|
||||
<menuContribution locationURI="popup:#TextEditorContext?after=copy">
|
||||
<command commandId="org.eclipse.xtext.ui.editor.copyqualifiedname.EditorCopyQualifiedName"
|
||||
style="push" tooltip="Copy Qualified Name">
|
||||
<visibleWhen checkEnabled="false">
|
||||
<reference definitionId="ghidra.xtext.sleigh.Sleigh.Editor.opened" />
|
||||
</visibleWhen>
|
||||
</command>
|
||||
</menuContribution>
|
||||
<menuContribution locationURI="menu:edit?after=copy">
|
||||
<command commandId="org.eclipse.xtext.ui.editor.copyqualifiedname.EditorCopyQualifiedName"
|
||||
style="push" tooltip="Copy Qualified Name">
|
||||
<visibleWhen checkEnabled="false">
|
||||
<reference definitionId="ghidra.xtext.sleigh.Sleigh.Editor.opened" />
|
||||
</visibleWhen>
|
||||
</command>
|
||||
</menuContribution>
|
||||
<menuContribution locationURI="popup:org.eclipse.xtext.ui.outline?after=additions">
|
||||
<command commandId="org.eclipse.xtext.ui.editor.copyqualifiedname.OutlineCopyQualifiedName"
|
||||
style="push" tooltip="Copy Qualified Name">
|
||||
<visibleWhen checkEnabled="false">
|
||||
<and>
|
||||
<reference definitionId="ghidra.xtext.sleigh.Sleigh.XtextEditor.opened" />
|
||||
<iterate>
|
||||
<adapt type="org.eclipse.xtext.ui.editor.outline.IOutlineNode" />
|
||||
</iterate>
|
||||
</and>
|
||||
</visibleWhen>
|
||||
</command>
|
||||
</menuContribution>
|
||||
</extension>
|
||||
<extension point="org.eclipse.ui.menus">
|
||||
<menuContribution locationURI="popup:#TextEditorContext?endof=group.find">
|
||||
<command commandId="org.eclipse.xtext.ui.editor.FindReferences">
|
||||
<visibleWhen checkEnabled="false">
|
||||
<reference definitionId="ghidra.xtext.sleigh.Sleigh.Editor.opened">
|
||||
</reference>
|
||||
</visibleWhen>
|
||||
</command>
|
||||
</menuContribution>
|
||||
</extension>
|
||||
<extension point="org.eclipse.ui.handlers">
|
||||
<handler
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.editor.findrefs.FindReferencesHandler"
|
||||
commandId="org.eclipse.xtext.ui.editor.FindReferences">
|
||||
<activeWhen>
|
||||
<reference
|
||||
definitionId="ghidra.xtext.sleigh.Sleigh.Editor.opened">
|
||||
</reference>
|
||||
</activeWhen>
|
||||
</handler>
|
||||
</extension>
|
||||
<extension point="org.eclipse.core.contenttype.contentTypes">
|
||||
<content-type
|
||||
base-type="org.eclipse.core.runtime.text"
|
||||
file-extensions="slaspec,sinc"
|
||||
id="ghidra.xtext.sleigh.Sleigh.contenttype"
|
||||
name="Sleigh File"
|
||||
priority="normal">
|
||||
</content-type>
|
||||
</extension>
|
||||
<!-- adding resource factories -->
|
||||
<extension
|
||||
point="org.eclipse.emf.ecore.extension_parser">
|
||||
<parser
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.resource.IResourceFactory"
|
||||
type="slaspec">
|
||||
</parser>
|
||||
</extension>
|
||||
<extension point="org.eclipse.xtext.extension_resourceServiceProvider">
|
||||
<resourceServiceProvider
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.resource.IResourceUIServiceProvider"
|
||||
uriExtension="slaspec">
|
||||
</resourceServiceProvider>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.emf.ecore.extension_parser">
|
||||
<parser
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.resource.IResourceFactory"
|
||||
type="sinc">
|
||||
</parser>
|
||||
</extension>
|
||||
<extension point="org.eclipse.xtext.extension_resourceServiceProvider">
|
||||
<resourceServiceProvider
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.resource.IResourceUIServiceProvider"
|
||||
uriExtension="sinc">
|
||||
</resourceServiceProvider>
|
||||
</extension>
|
||||
<!-- marker definitions for ghidra.xtext.sleigh.Sleigh -->
|
||||
<extension
|
||||
id="sleigh.check.fast"
|
||||
name="Sleigh Problem"
|
||||
point="org.eclipse.core.resources.markers">
|
||||
<super type="org.eclipse.xtext.ui.check.fast"/>
|
||||
<persistent value="true"/>
|
||||
</extension>
|
||||
<extension
|
||||
id="sleigh.check.normal"
|
||||
name="Sleigh Problem"
|
||||
point="org.eclipse.core.resources.markers">
|
||||
<super type="org.eclipse.xtext.ui.check.normal"/>
|
||||
<persistent value="true"/>
|
||||
</extension>
|
||||
<extension
|
||||
id="sleigh.check.expensive"
|
||||
name="Sleigh Problem"
|
||||
point="org.eclipse.core.resources.markers">
|
||||
<super type="org.eclipse.xtext.ui.check.expensive"/>
|
||||
<persistent value="true"/>
|
||||
</extension>
|
||||
<extension point="org.eclipse.ui.preferencePages">
|
||||
<page
|
||||
category="ghidra.xtext.sleigh.Sleigh"
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.validation.ValidatorPreferencePage"
|
||||
id="ghidra.xtext.sleigh.Sleigh.validator.preferencePage"
|
||||
name="Errors/Warnings">
|
||||
<keywordReference id="ghidra.xtext.sleigh.ui.keyword_Sleigh"/>
|
||||
</page>
|
||||
</extension>
|
||||
<extension point="org.eclipse.xtext.builder.participant">
|
||||
<participant
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.builder.IXtextBuilderParticipant"
|
||||
fileExtensions="slaspec,sinc"/>
|
||||
</extension>
|
||||
<extension point="org.eclipse.ui.preferencePages">
|
||||
<page
|
||||
category="ghidra.xtext.sleigh.Sleigh"
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.builder.preferences.BuilderPreferencePage"
|
||||
id="ghidra.xtext.sleigh.Sleigh.compiler.preferencePage"
|
||||
name="Compiler">
|
||||
<keywordReference id="ghidra.xtext.sleigh.ui.keyword_Sleigh"/>
|
||||
</page>
|
||||
</extension>
|
||||
<extension point="org.eclipse.ui.propertyPages">
|
||||
<page
|
||||
category="ghidra.xtext.sleigh.Sleigh"
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.builder.preferences.BuilderPreferencePage"
|
||||
id="ghidra.xtext.sleigh.Sleigh.compiler.propertyPage"
|
||||
name="Compiler">
|
||||
<keywordReference id="ghidra.xtext.sleigh.ui.keyword_Sleigh"/>
|
||||
<enabledWhen>
|
||||
<adapt type="org.eclipse.core.resources.IProject"/>
|
||||
</enabledWhen>
|
||||
<filter name="projectNature" value="org.eclipse.xtext.ui.shared.xtextNature"/>
|
||||
</page>
|
||||
</extension>
|
||||
<extension point="org.eclipse.ui.menus">
|
||||
<menuContribution locationURI="popup:#TextEditorContext?after=xtext.ui.openDeclaration">
|
||||
<command
|
||||
commandId="org.eclipse.xtext.ui.OpenGeneratedFileCommand"
|
||||
id="ghidra.xtext.sleigh.Sleigh.OpenGeneratedCode"
|
||||
style="push">
|
||||
<visibleWhen checkEnabled="false">
|
||||
<reference definitionId="ghidra.xtext.sleigh.Sleigh.Editor.opened" />
|
||||
</visibleWhen>
|
||||
</command>
|
||||
</menuContribution>
|
||||
</extension>
|
||||
<extension point="org.eclipse.ui.handlers">
|
||||
<handler
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.generator.trace.OpenGeneratedFileHandler"
|
||||
commandId="org.eclipse.xtext.ui.OpenGeneratedFileCommand">
|
||||
<activeWhen>
|
||||
<reference definitionId="ghidra.xtext.sleigh.Sleigh.Editor.opened" />
|
||||
</activeWhen>
|
||||
</handler>
|
||||
</extension>
|
||||
<!-- Quick Outline -->
|
||||
<extension
|
||||
point="org.eclipse.ui.handlers">
|
||||
<handler
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.editor.outline.quickoutline.ShowQuickOutlineActionHandler"
|
||||
commandId="org.eclipse.xtext.ui.editor.outline.QuickOutline">
|
||||
<activeWhen>
|
||||
<reference
|
||||
definitionId="ghidra.xtext.sleigh.Sleigh.Editor.opened">
|
||||
</reference>
|
||||
</activeWhen>
|
||||
</handler>
|
||||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.ui.commands">
|
||||
<command
|
||||
description="Open the quick outline."
|
||||
id="org.eclipse.xtext.ui.editor.outline.QuickOutline"
|
||||
name="Quick Outline">
|
||||
</command>
|
||||
</extension>
|
||||
<extension point="org.eclipse.ui.menus">
|
||||
<menuContribution
|
||||
locationURI="popup:#TextEditorContext?after=group.open">
|
||||
<command commandId="org.eclipse.xtext.ui.editor.outline.QuickOutline"
|
||||
style="push"
|
||||
tooltip="Open Quick Outline">
|
||||
<visibleWhen checkEnabled="false">
|
||||
<reference definitionId="ghidra.xtext.sleigh.Sleigh.Editor.opened"/>
|
||||
</visibleWhen>
|
||||
</command>
|
||||
</menuContribution>
|
||||
</extension>
|
||||
<!-- quickfix marker resolution generator for ghidra.xtext.sleigh.Sleigh -->
|
||||
<extension
|
||||
point="org.eclipse.ui.ide.markerResolution">
|
||||
<markerResolutionGenerator
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.editor.quickfix.MarkerResolutionGenerator"
|
||||
markerType="ghidra.xtext.sleigh.ui.sleigh.check.fast">
|
||||
<attribute
|
||||
name="FIXABLE_KEY"
|
||||
value="true">
|
||||
</attribute>
|
||||
</markerResolutionGenerator>
|
||||
<markerResolutionGenerator
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.editor.quickfix.MarkerResolutionGenerator"
|
||||
markerType="ghidra.xtext.sleigh.ui.sleigh.check.normal">
|
||||
<attribute
|
||||
name="FIXABLE_KEY"
|
||||
value="true">
|
||||
</attribute>
|
||||
</markerResolutionGenerator>
|
||||
<markerResolutionGenerator
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.editor.quickfix.MarkerResolutionGenerator"
|
||||
markerType="ghidra.xtext.sleigh.ui.sleigh.check.expensive">
|
||||
<attribute
|
||||
name="FIXABLE_KEY"
|
||||
value="true">
|
||||
</attribute>
|
||||
</markerResolutionGenerator>
|
||||
</extension>
|
||||
<!-- Rename Refactoring -->
|
||||
<extension point="org.eclipse.ui.handlers">
|
||||
<handler
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.refactoring.ui.DefaultRenameElementHandler"
|
||||
commandId="org.eclipse.xtext.ui.refactoring.RenameElement">
|
||||
<activeWhen>
|
||||
<reference
|
||||
definitionId="ghidra.xtext.sleigh.Sleigh.Editor.opened">
|
||||
</reference>
|
||||
</activeWhen>
|
||||
</handler>
|
||||
</extension>
|
||||
<extension point="org.eclipse.ui.menus">
|
||||
<menuContribution
|
||||
locationURI="popup:#TextEditorContext?after=group.edit">
|
||||
<command commandId="org.eclipse.xtext.ui.refactoring.RenameElement"
|
||||
style="push">
|
||||
<visibleWhen checkEnabled="false">
|
||||
<reference
|
||||
definitionId="ghidra.xtext.sleigh.Sleigh.Editor.opened">
|
||||
</reference>
|
||||
</visibleWhen>
|
||||
</command>
|
||||
</menuContribution>
|
||||
</extension>
|
||||
<extension point="org.eclipse.ui.preferencePages">
|
||||
<page
|
||||
category="ghidra.xtext.sleigh.Sleigh"
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.refactoring.ui.RefactoringPreferencePage"
|
||||
id="ghidra.xtext.sleigh.Sleigh.refactoring"
|
||||
name="Refactoring">
|
||||
<keywordReference id="ghidra.xtext.sleigh.ui.keyword_Sleigh"/>
|
||||
</page>
|
||||
</extension>
|
||||
<extension point="org.eclipse.compare.contentViewers">
|
||||
<viewer id="ghidra.xtext.sleigh.Sleigh.compare.contentViewers"
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.compare.InjectableViewerCreator"
|
||||
extensions="slaspec,sinc">
|
||||
</viewer>
|
||||
<contentTypeBinding
|
||||
contentTypeId="ghidra.xtext.sleigh.Sleigh.contenttype"
|
||||
contentViewerId="ghidra.xtext.sleigh.Sleigh.compare.contentViewers" />
|
||||
</extension>
|
||||
<extension point="org.eclipse.compare.contentMergeViewers">
|
||||
<viewer id="ghidra.xtext.sleigh.Sleigh.compare.contentMergeViewers"
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.compare.InjectableViewerCreator"
|
||||
extensions="slaspec,sinc" label="Sleigh Compare">
|
||||
</viewer>
|
||||
<contentTypeBinding
|
||||
contentTypeId="ghidra.xtext.sleigh.Sleigh.contenttype"
|
||||
contentMergeViewerId="ghidra.xtext.sleigh.Sleigh.compare.contentMergeViewers" />
|
||||
</extension>
|
||||
<extension point="org.eclipse.ui.editors.documentProviders">
|
||||
<provider id="ghidra.xtext.sleigh.Sleigh.editors.documentProviders"
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.editor.model.XtextDocumentProvider"
|
||||
extensions="slaspec,sinc">
|
||||
</provider>
|
||||
</extension>
|
||||
<extension point="org.eclipse.team.core.fileTypes">
|
||||
<fileTypes
|
||||
extension="slaspec"
|
||||
type="text">
|
||||
</fileTypes>
|
||||
<fileTypes
|
||||
extension="sinc"
|
||||
type="text">
|
||||
</fileTypes>
|
||||
</extension>
|
||||
<!-- quickfix marker resolution generator for ghidra.xtext.sleigh.Sleigh -->
|
||||
<extension
|
||||
point="org.eclipse.ui.ide.markerResolution">
|
||||
<markerResolutionGenerator
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.editor.quickfix.MarkerResolutionGenerator"
|
||||
markerType="ghidra.xtext.sleigh.ui.sleigh.check.fast">
|
||||
<attribute
|
||||
name="FIXABLE_KEY"
|
||||
value="true">
|
||||
</attribute>
|
||||
</markerResolutionGenerator>
|
||||
<markerResolutionGenerator
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.editor.quickfix.MarkerResolutionGenerator"
|
||||
markerType="ghidra.xtext.sleigh.ui.sleigh.check.normal">
|
||||
<attribute
|
||||
name="FIXABLE_KEY"
|
||||
value="true">
|
||||
</attribute>
|
||||
</markerResolutionGenerator>
|
||||
<markerResolutionGenerator
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.editor.quickfix.MarkerResolutionGenerator"
|
||||
markerType="ghidra.xtext.sleigh.ui.sleigh.check.expensive">
|
||||
<attribute
|
||||
name="FIXABLE_KEY"
|
||||
value="true">
|
||||
</attribute>
|
||||
</markerResolutionGenerator>
|
||||
</extension>
|
||||
<!-- Rename Refactoring -->
|
||||
<extension point="org.eclipse.ui.handlers">
|
||||
<handler
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.refactoring.ui.DefaultRenameElementHandler"
|
||||
commandId="org.eclipse.xtext.ui.refactoring.RenameElement">
|
||||
<activeWhen>
|
||||
<reference
|
||||
definitionId="ghidra.xtext.sleigh.Sleigh.Editor.opened">
|
||||
</reference>
|
||||
</activeWhen>
|
||||
</handler>
|
||||
</extension>
|
||||
<extension point="org.eclipse.ui.menus">
|
||||
<menuContribution
|
||||
locationURI="popup:#TextEditorContext?after=group.edit">
|
||||
<command commandId="org.eclipse.xtext.ui.refactoring.RenameElement"
|
||||
style="push">
|
||||
<visibleWhen checkEnabled="false">
|
||||
<reference
|
||||
definitionId="ghidra.xtext.sleigh.Sleigh.Editor.opened">
|
||||
</reference>
|
||||
</visibleWhen>
|
||||
</command>
|
||||
</menuContribution>
|
||||
</extension>
|
||||
<extension point="org.eclipse.ui.preferencePages">
|
||||
<page
|
||||
category="ghidra.xtext.sleigh.Sleigh"
|
||||
class="ghidra.xtext.sleigh.ui.SleighExecutableExtensionFactory:org.eclipse.xtext.ui.refactoring.ui.RefactoringPreferencePage"
|
||||
id="ghidra.xtext.sleigh.Sleigh.refactoring"
|
||||
name="Refactoring">
|
||||
<keywordReference id="ghidra.xtext.sleigh.ui.keyword_Sleigh"/>
|
||||
</page>
|
||||
</extension>
|
||||
<!-- Console Extensions -->
|
||||
<extension
|
||||
point="org.eclipse.debug.ui.consoleLineTrackers">
|
||||
<consoleLineTracker
|
||||
class="ghidra.xtext.sleigh.ui.console.ConsoleLineTracker"
|
||||
processType="org.eclipse.ant.ui.antProcess"
|
||||
id="ghidra.xtext.sleigh.taskLineTracker">
|
||||
</consoleLineTracker>
|
||||
</extension>
|
||||
|
||||
<extension
|
||||
point="org.eclipse.ui.console.consolePatternMatchListeners">
|
||||
<consolePatternMatchListener
|
||||
class="ghidra.xtext.sleigh.ui.console.ConsoleHyperlinking"
|
||||
id="ghidra.xtext.sleigh.ui.consoleHyperlinking.Compiling"
|
||||
qualifier="javac"
|
||||
regex="Compiling .*.slaspec(:\d+)">
|
||||
<enablement>
|
||||
<test property="org.eclipse.debug.ui.processTypeTest" value="org.eclipse.ant.ui.antProcess"/>
|
||||
</enablement>
|
||||
</consolePatternMatchListener>
|
||||
<consolePatternMatchListener
|
||||
class="ghidra.xtext.sleigh.ui.console.ConsoleHyperlinking"
|
||||
id="ghidra.xtext.sleigh.ui.console.ConsoleHyperlinking.All"
|
||||
regex="\[java\] .*\.slaspec failed to compile">
|
||||
<enablement>
|
||||
<or>
|
||||
<test property="org.eclipse.ui.console.consoleTypeTest" value="javaStackTraceConsole"/>
|
||||
<test property="org.eclipse.debug.ui.processTypeTest" value="java"/>
|
||||
<test property="org.eclipse.debug.ui.processTypeTest" value="org.eclipse.ant.ui.antProcess"/>
|
||||
</or>
|
||||
</enablement>
|
||||
</consolePatternMatchListener>
|
||||
<consolePatternMatchListener
|
||||
class="ghidra.xtext.sleigh.ui.console.ConsoleHyperlinking"
|
||||
id="ghidra.xtext.sleigh.ui.console.ConsoleHyperlinking.All"
|
||||
regex="Compiling .*\.slaspec">
|
||||
<enablement>
|
||||
<or>
|
||||
<test property="org.eclipse.ui.console.consoleTypeTest" value="javaStackTraceConsole"/>
|
||||
<test property="org.eclipse.debug.ui.processTypeTest" value="java"/>
|
||||
<test property="org.eclipse.debug.ui.processTypeTest" value="org.eclipse.ant.ui.antProcess"/>
|
||||
</or>
|
||||
</enablement>
|
||||
</consolePatternMatchListener>
|
||||
<consolePatternMatchListener
|
||||
class="ghidra.xtext.sleigh.ui.console.ConsoleHyperlinking"
|
||||
id="ghidra.xtext.sleigh.ui.console.ConsoleHyperlinking.All"
|
||||
regex="\w+\.slaspec(:\d+)|\w+\.sinc(:\d+)">
|
||||
<enablement>
|
||||
<or>
|
||||
<test property="org.eclipse.ui.console.consoleTypeTest" value="javaStackTraceConsole"/>
|
||||
<test property="org.eclipse.debug.ui.processTypeTest" value="java"/>
|
||||
<test property="org.eclipse.debug.ui.processTypeTest" value="org.eclipse.ant.ui.antProcess"/>
|
||||
</or>
|
||||
</enablement>
|
||||
</consolePatternMatchListener>
|
||||
</extension>
|
||||
</plugin>
|
||||
@@ -0,0 +1,43 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.xtext.sleigh.ui;
|
||||
|
||||
import org.eclipse.debug.core.model.IProcess;
|
||||
import org.eclipse.debug.ui.console.IConsole;
|
||||
import org.eclipse.debug.ui.console.IConsoleLineTracker;
|
||||
import org.eclipse.jface.text.IRegion;
|
||||
|
||||
public class ConsoleLineTracker implements IConsoleLineTracker {
|
||||
|
||||
@Override
|
||||
public void init(IConsole console) {
|
||||
IProcess process = console.getProcess();
|
||||
|
||||
System.out.println(process.getLabel());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lineAppended(IRegion line) {
|
||||
System.out.println(line.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.xtext.sleigh.ui
|
||||
|
||||
import ghidra.xtext.sleigh.sleigh.DefineSym
|
||||
import ghidra.xtext.sleigh.sleigh.SUBTABLESYM
|
||||
import ghidra.xtext.sleigh.sleigh.aliasSym
|
||||
import ghidra.xtext.sleigh.sleigh.integerValue
|
||||
import ghidra.xtext.sleigh.sleigh.macroDefine
|
||||
import ghidra.xtext.sleigh.sleigh.printpiece
|
||||
import ghidra.xtext.sleigh.sleigh.subconstructor
|
||||
import java.math.BigInteger
|
||||
import org.eclipse.emf.common.util.EList
|
||||
import org.eclipse.emf.ecore.EObject
|
||||
import org.eclipse.xtext.conversion.ValueConverterException
|
||||
import org.eclipse.xtext.nodemodel.util.NodeModelUtils
|
||||
import org.eclipse.xtext.ui.editor.hover.html.DefaultEObjectHoverProvider
|
||||
import org.eclipse.xtext.util.Strings
|
||||
|
||||
class SleighEObjectHoverProvider extends DefaultEObjectHoverProvider {
|
||||
|
||||
EObject model
|
||||
|
||||
override boolean hasHover(EObject o) {
|
||||
if (o instanceof integerValue) { return true; }
|
||||
return super.hasHover(o)
|
||||
}
|
||||
|
||||
override String getFirstLine(EObject o) {
|
||||
var label = getLabel(o);
|
||||
var str = o.eClass().getName();
|
||||
if (label == null) {
|
||||
str += "";
|
||||
} else {
|
||||
str = " <b>" + label + "</b>";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
override String getLabel(EObject element) {
|
||||
switch element {
|
||||
DefineSym:
|
||||
return " <b>" + element.name + "</b>"
|
||||
default:
|
||||
return super.getLabel(element)
|
||||
}
|
||||
}
|
||||
|
||||
override String getDocumentation(EObject element) {
|
||||
switch element {
|
||||
DefineSym:
|
||||
return getDefineSymText(element)
|
||||
SUBTABLESYM:
|
||||
return getSubTableText(element)
|
||||
aliasSym:
|
||||
return getSubTableText(element)
|
||||
integerValue:
|
||||
return getIntegerFormats(element)
|
||||
default:
|
||||
return super.getDocumentation(element)
|
||||
}
|
||||
}
|
||||
|
||||
def getIntegerFormats(integerValue value) {
|
||||
var retStr = "";
|
||||
var valueOf = getIntValue(value)
|
||||
|
||||
retStr = retStr + "<p style=\"color:red;line-height:50%;\">" + "0b" + valueOf.toString(2) + "</p>\n"
|
||||
retStr = retStr + "<p style=\"color:red;line-height:50%;\">" + "0x" + valueOf.toString(16) + "</p>\n"
|
||||
retStr = retStr + "<p style=\"color:red;line-height:50%;\">" + " " + valueOf.toString(10) + "</p>\n"
|
||||
|
||||
if (retStr.length == 0) {
|
||||
return value.value;
|
||||
}
|
||||
return retStr;
|
||||
}
|
||||
|
||||
def getIntValue(integerValue value) {
|
||||
var parseString = value.value;
|
||||
var string = value.value
|
||||
if (Strings.isEmpty(parseString))
|
||||
throw new NumberFormatException("Couldn't convert empty string to an int value.");
|
||||
try {
|
||||
var radix = 10;
|
||||
if (parseString.startsWith("0x") || parseString.startsWith("0X")) {
|
||||
parseString = string.substring(2);
|
||||
radix=16;
|
||||
}
|
||||
if (parseString.startsWith("0b") || parseString.startsWith("0B")) {
|
||||
parseString = string.substring(2);
|
||||
radix=2;
|
||||
}
|
||||
return new BigInteger(parseString,radix);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new NumberFormatException("Couldn't convert '" + string + "' to a BigInteger value.");
|
||||
}
|
||||
}
|
||||
|
||||
def getDefineSymText(DefineSym element) {
|
||||
var retStr = "";
|
||||
model = element.eResource.contents.get(0);
|
||||
var macDefs = model.eAllContents.filter(typeof(macroDefine));
|
||||
var len = "";
|
||||
while (macDefs.hasNext) {
|
||||
var next = macDefs.next;
|
||||
if (next.defineType.equals("@define")) {
|
||||
if (next.definename.name == element.name) {
|
||||
retStr = retStr + "<p style=\"color:red;line-height:100%;\">" + next.value + "</p>\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
if (retStr.length == 0) {
|
||||
return element.name;
|
||||
}
|
||||
return retStr;
|
||||
}
|
||||
|
||||
def getSubTableText(SUBTABLESYM element) {
|
||||
var retStr = "";
|
||||
model = element.eResource.contents.get(0);
|
||||
var subs = model.eAllContents.filter(typeof(subconstructor));
|
||||
var len = "";
|
||||
while (subs.hasNext) {
|
||||
var next = subs.next;
|
||||
if (next.tableName.name == element.name) {
|
||||
retStr = retStr + "<p style=\"color:red;line-height:100%;\">" + formatString(next.print.printpieces) +
|
||||
" is " + formatConstraintString(next.match.constraints) + "</p>\n"
|
||||
}
|
||||
}
|
||||
if (retStr.length == 0) {
|
||||
return element.name;
|
||||
}
|
||||
return retStr;
|
||||
}
|
||||
|
||||
def getSubTableText(aliasSym element) {
|
||||
var retStr = "";
|
||||
model = element.eResource.contents.get(0);
|
||||
var subs = model.eAllContents.filter(typeof(subconstructor));
|
||||
while (subs.hasNext) {
|
||||
var next = subs.next;
|
||||
if (next.tableName.name == element.sym) {
|
||||
retStr = retStr + "<p style=\"color:red;line-height:100%;\">" + formatString(next.print.printpieces) +
|
||||
" is " + formatConstraintString(next.match.constraints) + "</p>\n"
|
||||
}
|
||||
}
|
||||
if (retStr.length != 0) {
|
||||
return retStr;
|
||||
}
|
||||
var macDefs = model.eAllContents.filter(typeof(macroDefine));
|
||||
while (macDefs.hasNext) {
|
||||
var next = macDefs.next;
|
||||
if (next.defineType.equals("@define")) {
|
||||
if (next.definename.name == element.sym) {
|
||||
retStr = retStr + "<p style=\"color:red;line-height:100%;\">" + next.value + "</p>\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
if (retStr.length == 0) {
|
||||
return element.sym;
|
||||
}
|
||||
return retStr;
|
||||
}
|
||||
|
||||
def String formatString(EList<printpiece> list) {
|
||||
var str = "<span style=\"color:#0000FF;\">";
|
||||
var iter = list.iterator;
|
||||
while (iter.hasNext) {
|
||||
var piece = iter.next;
|
||||
if (piece.str == null) {
|
||||
if (piece.sym != null) {
|
||||
str += piece.sym.sym;
|
||||
} else {
|
||||
str = '{empty}'
|
||||
}
|
||||
} else {
|
||||
str += piece.str;
|
||||
}
|
||||
}
|
||||
str += "</span>"
|
||||
str
|
||||
}
|
||||
|
||||
def String formatConstraintString(EObject o) {
|
||||
var node = NodeModelUtils.getNode(o);
|
||||
return node.text
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.xtext.sleigh.ui;
|
||||
|
||||
import static org.eclipse.xtext.ui.editor.syntaxcoloring.DefaultHighlightingConfiguration.COMMENT_ID;
|
||||
import static org.eclipse.xtext.ui.editor.syntaxcoloring.DefaultHighlightingConfiguration.KEYWORD_ID;
|
||||
import static ghidra.xtext.sleigh.ui.SleighHighlightingConfiguration.CONTEXTFIELD;
|
||||
import static ghidra.xtext.sleigh.ui.SleighHighlightingConfiguration.LOCAL;
|
||||
import static ghidra.xtext.sleigh.ui.SleighHighlightingConfiguration.PRINTPIECE;
|
||||
import static ghidra.xtext.sleigh.ui.SleighHighlightingConfiguration.SUBTABLE;
|
||||
import static ghidra.xtext.sleigh.ui.SleighHighlightingConfiguration.TOKENFIELD;
|
||||
import static ghidra.xtext.sleigh.ui.SleighHighlightingConfiguration.VARIABLE;
|
||||
|
||||
import org.eclipse.emf.ecore.EObject;
|
||||
import org.eclipse.xtext.CrossReference;
|
||||
import org.eclipse.xtext.impl.TerminalRuleImpl;
|
||||
import org.eclipse.xtext.nodemodel.BidiIterator;
|
||||
import org.eclipse.xtext.nodemodel.BidiTreeIterator;
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
import org.eclipse.xtext.nodemodel.impl.HiddenLeafNode;
|
||||
import org.eclipse.xtext.nodemodel.impl.LeafNode;
|
||||
import org.eclipse.xtext.resource.XtextResource;
|
||||
import org.eclipse.xtext.util.CancelIndicator;
|
||||
import org.eclipse.xtext.ide.editor.syntaxcoloring.DefaultSemanticHighlightingCalculator;
|
||||
import org.eclipse.xtext.ide.editor.syntaxcoloring.IHighlightedPositionAcceptor;
|
||||
|
||||
import ghidra.xtext.sleigh.sleigh.CONTEXTSYM;
|
||||
import ghidra.xtext.sleigh.sleigh.LOCALSYM;
|
||||
import ghidra.xtext.sleigh.sleigh.SUBTABLESYM;
|
||||
import ghidra.xtext.sleigh.sleigh.TOKENSYM;
|
||||
import ghidra.xtext.sleigh.sleigh.VARSYM;
|
||||
import ghidra.xtext.sleigh.sleigh.aliasSym;
|
||||
import ghidra.xtext.sleigh.sleigh.anysymbol;
|
||||
import ghidra.xtext.sleigh.sleigh.assignSym;
|
||||
import ghidra.xtext.sleigh.sleigh.constraint;
|
||||
import ghidra.xtext.sleigh.sleigh.exprSym;
|
||||
import ghidra.xtext.sleigh.sleigh.fielddef;
|
||||
import ghidra.xtext.sleigh.sleigh.isKeyword;
|
||||
import ghidra.xtext.sleigh.sleigh.pexprSym;
|
||||
import ghidra.xtext.sleigh.sleigh.printpiece;
|
||||
import ghidra.xtext.sleigh.sleigh.valuepart;
|
||||
import ghidra.xtext.sleigh.sleigh.varpart;
|
||||
|
||||
public class SleighHighlightingCalculator extends DefaultSemanticHighlightingCalculator {
|
||||
|
||||
@Override
|
||||
public void provideHighlightingFor(XtextResource resource, IHighlightedPositionAcceptor acceptor,
|
||||
CancelIndicator cancelIndicator) {
|
||||
|
||||
if (resource == null || resource.getParseResult() == null)
|
||||
return;
|
||||
|
||||
super.provideHighlightingFor(resource, acceptor, cancelIndicator);
|
||||
|
||||
INode root = resource.getParseResult().getRootNode();
|
||||
BidiTreeIterator<INode> it = root.getAsTreeIterable().iterator();
|
||||
while (it.hasNext()) {
|
||||
INode node = it.next();
|
||||
EObject grammarElement = node.getGrammarElement();
|
||||
EObject semanticElement = node.getSemanticElement();
|
||||
printNodeInfo(node, grammarElement, semanticElement);
|
||||
|
||||
// if (node instanceof CompositeNodeWithSemanticElement
|
||||
// && semanticElement instanceof contextfielddef) {
|
||||
// setStyles(acceptor, it, CONTEXTFIELD, "GROUP", CONTEXTFIELD);
|
||||
// setStyles(acceptor, node.getAsTreeIterable().reverse()
|
||||
// .iterator(), null, CONTEXTFIELD);
|
||||
// } else
|
||||
if (semanticElement instanceof VARSYM) {
|
||||
setNodeStyle(acceptor, node, VARIABLE);
|
||||
// } else if (grammarElement instanceof Keyword) {
|
||||
// setStyles(acceptor, it, KEYWORD_ID);
|
||||
} else if (semanticElement instanceof CONTEXTSYM) {
|
||||
setNodeStyle(acceptor, node, CONTEXTFIELD);
|
||||
} else if (semanticElement instanceof LOCALSYM) {
|
||||
setNodeStyle(acceptor, node, LOCAL);
|
||||
} else if (semanticElement instanceof TOKENSYM) {
|
||||
setNodeStyle(acceptor, node, TOKENFIELD);
|
||||
} else if (semanticElement instanceof fielddef) {
|
||||
setNodeStyle(acceptor, node, TOKENFIELD);
|
||||
} else if (semanticElement instanceof anysymbol) {
|
||||
setStyle(acceptor, node, semanticElement);
|
||||
} else if (grammarElement instanceof CrossReference) {
|
||||
CrossReference defn = (CrossReference) grammarElement;
|
||||
EObject semElem = semanticElement;
|
||||
if (semElem instanceof varpart || semElem instanceof valuepart) {
|
||||
setNodeStyle(acceptor, node, VARIABLE);
|
||||
} else if (semElem instanceof LOCALSYM) {
|
||||
setNodeStyle(acceptor, node, LOCAL);
|
||||
} else if (semElem instanceof exprSym) {
|
||||
exprSym sym = (exprSym) semElem;
|
||||
EObject vnode = sym.getVnode();
|
||||
if (vnode != null) {
|
||||
setStyle(acceptor, node, vnode);
|
||||
} else {
|
||||
// System.out.println(" exprSym--" + semElem);
|
||||
}
|
||||
} else if (semElem instanceof assignSym) {
|
||||
// TODO: Causing a lazy linking error sometimes
|
||||
// Possibly something wrong with the grammer for [lhsvarnode]
|
||||
// ERROR org.eclipse.xtext.linking.lazy.LazyLinkingResource - An element of type ghidra.xtext.sleigh.sleigh.impl.aliasSymImpl is not assignable to the reference assignSym.symref
|
||||
assignSym sym = (assignSym) semElem;
|
||||
EObject vnode = sym.getSymref();
|
||||
if (vnode != null) {
|
||||
setStyle(acceptor, node, vnode);
|
||||
} else {
|
||||
// System.out.println(" exprSym--" + semElem);
|
||||
}
|
||||
}
|
||||
else if (semElem instanceof constraint) {
|
||||
constraint sym = (constraint) semElem;
|
||||
EObject vnode = sym.getSym();
|
||||
if (vnode != null) {
|
||||
setStyle(acceptor, node, vnode);
|
||||
} else {
|
||||
// System.out.println(" exprSym--" + semElem);
|
||||
}
|
||||
}
|
||||
else if (semElem instanceof pexprSym) {
|
||||
pexprSym sym = (pexprSym) semElem;
|
||||
EObject vnode = sym.getSym();
|
||||
if (vnode != null) {
|
||||
setStyle(acceptor, node, vnode);
|
||||
} else {
|
||||
// System.out.println(" exprSym--" + semElem);
|
||||
}
|
||||
}
|
||||
else if (semElem instanceof aliasSym) {
|
||||
System.out.println(" semElem="+semElem);
|
||||
}
|
||||
else {
|
||||
// System.out.println(" semElem="+semElem);
|
||||
}
|
||||
} else if (semanticElement instanceof isKeyword) {
|
||||
setStyles(acceptor, it, KEYWORD_ID);
|
||||
} else if (semanticElement instanceof aliasSym && semanticElement.eContainer() instanceof printpiece) {
|
||||
setStyles(acceptor, it, PRINTPIECE);
|
||||
} else if (semanticElement instanceof printpiece) {
|
||||
setStyles(acceptor, it, PRINTPIECE);
|
||||
} else if (node instanceof HiddenLeafNode
|
||||
&& grammarElement instanceof TerminalRuleImpl) {
|
||||
processHiddenNode(acceptor, (HiddenLeafNode) node);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void setStyle(IHighlightedPositionAcceptor acceptor, INode n, EObject vnode) {
|
||||
if (vnode instanceof LOCALSYM) {
|
||||
setNodeStyle(acceptor, n, LOCAL);
|
||||
} else if (vnode instanceof VARSYM) {
|
||||
setNodeStyle(acceptor, n, VARIABLE);
|
||||
} else if (vnode instanceof SUBTABLESYM) {
|
||||
setNodeStyle(acceptor, n, SUBTABLE);
|
||||
} else if (vnode instanceof fielddef) {
|
||||
setNodeStyle(acceptor, n, TOKENFIELD);
|
||||
} else {
|
||||
// System.out.println(" symtype = " + vnode);
|
||||
}
|
||||
}
|
||||
|
||||
private void setNodeStyle(IHighlightedPositionAcceptor acceptor, INode n, String styleName) {
|
||||
acceptor.addPosition(n.getOffset(), n.getLength(), styleName);
|
||||
}
|
||||
|
||||
private void printNodeInfo(INode node, EObject grammarElement,
|
||||
EObject semanticElement) {
|
||||
String grammar = "<no-grammar>";
|
||||
String semantic = "<no-semantic>";
|
||||
|
||||
if (grammarElement != null) {
|
||||
grammar = grammarElement.getClass().getSimpleName();
|
||||
}
|
||||
if (semanticElement != null) {
|
||||
semantic = semanticElement.getClass().getSimpleName();
|
||||
}
|
||||
if (grammarElement instanceof TerminalRuleImpl) return;
|
||||
if (! (node instanceof LeafNode)) return;
|
||||
// System.err.println( "Node: " + node.getClass().getSimpleName() +
|
||||
// "\t\t\t\t" + grammar + " =\t\t\t\t" + semantic + "\"" + node.getText() + "\"");
|
||||
}
|
||||
|
||||
void setStyles(IHighlightedPositionAcceptor acceptor,
|
||||
BidiIterator<INode> it, String... styles) {
|
||||
for (String s : styles) {
|
||||
if (!it.hasNext())
|
||||
return;
|
||||
INode n = skipWhiteSpace(acceptor, it);
|
||||
if (n != null && s != null)
|
||||
acceptor.addPosition(n.getOffset(), n.getLength(), s);
|
||||
}
|
||||
}
|
||||
|
||||
INode skipWhiteSpace(IHighlightedPositionAcceptor acceptor,
|
||||
BidiIterator<INode> it) {
|
||||
INode n = null;
|
||||
while (it.hasNext()
|
||||
&& (n = it.next()).getClass() == HiddenLeafNode.class)
|
||||
processHiddenNode(acceptor, (HiddenLeafNode) n);
|
||||
return n;
|
||||
}
|
||||
|
||||
INode skipWhiteSpaceBackwards(IHighlightedPositionAcceptor acceptor,
|
||||
BidiIterator<INode> it) {
|
||||
INode n = null;
|
||||
while (it.hasPrevious()
|
||||
&& (n = it.previous()).getClass() == HiddenLeafNode.class)
|
||||
processHiddenNode(acceptor, (HiddenLeafNode) n);
|
||||
return n;
|
||||
}
|
||||
|
||||
void processHiddenNode(IHighlightedPositionAcceptor acceptor,
|
||||
HiddenLeafNode node) {
|
||||
if (node.getGrammarElement() instanceof TerminalRuleImpl) {
|
||||
TerminalRuleImpl ge = (TerminalRuleImpl) node.getGrammarElement();
|
||||
String name = ge.getName();
|
||||
if (name.equalsIgnoreCase("PDL_COMMENT") || name.equalsIgnoreCase("ML_COMMENT") || name.equalsIgnoreCase("SL_COMMENT")) {
|
||||
acceptor.addPosition(node.getOffset(), node.getLength(), COMMENT_ID);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.xtext.sleigh.ui;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.graphics.RGB;
|
||||
import org.eclipse.xtext.ui.editor.syntaxcoloring.DefaultHighlightingConfiguration;
|
||||
import org.eclipse.xtext.ui.editor.syntaxcoloring.IHighlightingConfigurationAcceptor;
|
||||
import org.eclipse.xtext.ui.editor.utils.TextStyle;
|
||||
|
||||
public class SleighHighlightingConfiguration extends DefaultHighlightingConfiguration {
|
||||
// provide an id string for the highlighting calculator
|
||||
public static final String CONTEXTFIELD = "Context Field";
|
||||
public static final String TOKENFIELD = "Token Field";
|
||||
public static final String SYMBOL = "Symbol";
|
||||
public static final String VARIABLE = "Variable";
|
||||
public static final String ATTACHEDSYM = "Attached Symbol";
|
||||
public static final String PRINTPIECE = "Print Piece";
|
||||
public static final String LOCAL = "Local Symbol";
|
||||
public static final String SUBTABLE = "SubTable";
|
||||
|
||||
public void configure(IHighlightingConfigurationAcceptor acceptor) {
|
||||
super.configure(acceptor);
|
||||
addType(acceptor, CONTEXTFIELD, 50, 50, 0, SWT.ITALIC);
|
||||
addType(acceptor, TOKENFIELD, 50, 50, 0, SWT.NORMAL);
|
||||
addType(acceptor, SYMBOL, 50, 50, 50, TextStyle.DEFAULT_FONT_STYLE);
|
||||
addType(acceptor, VARIABLE, 106, 62, 63, SWT.BOLD);
|
||||
addType(acceptor, ATTACHEDSYM, 50, 50, 50, SWT.BOLD);
|
||||
addType(acceptor, PRINTPIECE, 0,0,255, SWT.BOLD);
|
||||
addType(acceptor, LOCAL, 40,40,40, SWT.ITALIC);
|
||||
addType(acceptor, SUBTABLE, 192, 82, 5, SWT.NORMAL);
|
||||
}
|
||||
|
||||
public void addType(IHighlightingConfigurationAcceptor acceptor, String s,
|
||||
int r, int g, int b, int style) {
|
||||
addType(acceptor, s, new RGB(r,g,b), style);
|
||||
}
|
||||
|
||||
public void addType(IHighlightingConfigurationAcceptor acceptor, String s,
|
||||
RGB rgb, int style) {
|
||||
TextStyle textStyle = new TextStyle();
|
||||
textStyle.setBackgroundColor(new RGB(255, 255, 255));
|
||||
textStyle.setColor(rgb);
|
||||
textStyle.setStyle(style);
|
||||
acceptor.acceptDefaultHighlighting(s, s, textStyle);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package ghidra.xtext.sleigh.ui
|
||||
|
||||
import org.eclipse.xtext.resource.SaveOptions
|
||||
import org.eclipse.xtext.ui.editor.model.edit.DefaultTextEditComposer
|
||||
|
||||
class SleighTextEditComposer extends DefaultTextEditComposer {
|
||||
|
||||
override SaveOptions getSaveOptions() {
|
||||
return SaveOptions.newBuilder().format().getOptions();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.xtext.sleigh.ui
|
||||
|
||||
import com.google.inject.Binder
|
||||
import ghidra.xtext.sleigh.ui.labeling.SleighLabelProvider
|
||||
import org.eclipse.jface.viewers.ILabelProvider
|
||||
import org.eclipse.xtend.lib.annotations.FinalFieldsConstructor
|
||||
import org.eclipse.xtext.ide.editor.syntaxcoloring.ISemanticHighlightingCalculator
|
||||
import org.eclipse.xtext.ui.editor.contentassist.ContentProposalLabelProvider
|
||||
import org.eclipse.xtext.ui.editor.hover.IEObjectHoverProvider
|
||||
import org.eclipse.xtext.ui.editor.model.edit.ITextEditComposer
|
||||
import org.eclipse.xtext.ui.editor.syntaxcoloring.IHighlightingConfiguration
|
||||
|
||||
/**
|
||||
* Use this class to register components to be used within the Eclipse IDE.
|
||||
*/
|
||||
@FinalFieldsConstructor
|
||||
class SleighUiModule extends AbstractSleighUiModule {
|
||||
|
||||
override void configureContentProposalLabelProvider(Binder binder) {
|
||||
binder.bind(ILabelProvider).annotatedWith(ContentProposalLabelProvider).to(SleighLabelProvider);
|
||||
}
|
||||
|
||||
def Class<? extends IHighlightingConfiguration> bindIHighlightingConfiguration() {
|
||||
return SleighHighlightingConfiguration
|
||||
}
|
||||
|
||||
def Class<? extends ISemanticHighlightingCalculator> bindISemanticHighlightingCalculator() {
|
||||
return SleighHighlightingCalculator
|
||||
}
|
||||
|
||||
def Class<? extends IEObjectHoverProvider> bindIEObjectHoverProvider() {
|
||||
return SleighEObjectHoverProvider
|
||||
}
|
||||
|
||||
def Class<? extends ITextEditComposer> bindITextEditComposer() {
|
||||
return SleighTextEditComposer
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package ghidra.xtext.sleigh.ui.console
|
||||
|
||||
import java.util.HashMap
|
||||
import java.util.Map
|
||||
import org.eclipse.core.resources.IFile
|
||||
import org.eclipse.core.resources.ResourcesPlugin
|
||||
import org.eclipse.core.runtime.Path
|
||||
import org.eclipse.debug.ui.console.FileLink
|
||||
import org.eclipse.jface.text.BadLocationException
|
||||
import org.eclipse.ui.console.IPatternMatchListenerDelegate
|
||||
import org.eclipse.ui.console.PatternMatchEvent
|
||||
import org.eclipse.ui.console.TextConsole
|
||||
|
||||
class ConsoleHyperlinking implements IPatternMatchListenerDelegate {
|
||||
|
||||
static final String compilingBase = "Compiling ";
|
||||
static final String failedBase = " failed to compile";
|
||||
static final String javaPrefix = "[java] ";
|
||||
Map<String, IFile> fFileNameToIFile = new HashMap();
|
||||
|
||||
static String lastBase = ""; // last full path base name found
|
||||
|
||||
TextConsole console
|
||||
|
||||
override matchFound(PatternMatchEvent event) {
|
||||
try {
|
||||
var offset = event.getOffset();
|
||||
var length = event.getLength();
|
||||
var _str = console.document.get(offset, length);
|
||||
var setBase = false;
|
||||
|
||||
if (_str.indexOf(compilingBase) != -1) {
|
||||
_str = _str.replace(compilingBase, "");
|
||||
setBase = true;
|
||||
offset += compilingBase.length
|
||||
length -= compilingBase.length
|
||||
}
|
||||
|
||||
if (_str.indexOf(failedBase) != -1) {
|
||||
_str = _str.replace(failedBase, "");
|
||||
_str = _str.replace(javaPrefix, "");
|
||||
setBase = true;
|
||||
offset += javaPrefix.length
|
||||
length -= failedBase.length + javaPrefix.length
|
||||
}
|
||||
|
||||
// get filename and optional linenumber after ':'
|
||||
val indexOfColon = _str.indexOf(":")
|
||||
var fileName = ""
|
||||
var lineNumber = 1
|
||||
if (indexOfColon != -1) {
|
||||
fileName = _str.substring(0, indexOfColon)
|
||||
lineNumber = Integer.valueOf(_str.substring(indexOfColon + 1))
|
||||
} else {
|
||||
fileName = _str
|
||||
}
|
||||
|
||||
var file = getIFile(fileName, setBase);
|
||||
|
||||
if (file !== null) {
|
||||
val link = new FileLink(file, null, -1, -1, lineNumber);
|
||||
console.addHyperlink(link, offset, length);
|
||||
}
|
||||
} catch (BadLocationException | NumberFormatException e) {
|
||||
}
|
||||
}
|
||||
|
||||
override connect(TextConsole console) {
|
||||
this.console = console
|
||||
lastBase = ""
|
||||
}
|
||||
|
||||
override disconnect() {
|
||||
this.console = null
|
||||
fFileNameToIFile.clear();
|
||||
}
|
||||
|
||||
def IFile getIFile(String filePath, boolean setBase) {
|
||||
if (filePath === null) {
|
||||
return null;
|
||||
}
|
||||
// check the name to IFile cache
|
||||
var file = fFileNameToIFile.get(filePath);
|
||||
if (file === null) {
|
||||
var f = new Path(filePath).toFile()
|
||||
var uri = f.toURI();
|
||||
var files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(uri);
|
||||
if (files.length <= 0) {
|
||||
// didn't find the file, try tacking on the lastbase path
|
||||
f = new Path(lastBase + Path.SEPARATOR + filePath).toFile()
|
||||
f.toURI();
|
||||
uri = f.toURI()
|
||||
files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(uri);
|
||||
}
|
||||
if (files.length > 0) {
|
||||
file = files.get(0);
|
||||
fFileNameToIFile.put(filePath, file);
|
||||
if (setBase) {
|
||||
lastBase = f.parent
|
||||
}
|
||||
}
|
||||
}
|
||||
return file;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.xtext.sleigh.ui.console;
|
||||
|
||||
import org.eclipse.debug.core.model.IProcess;
|
||||
import org.eclipse.debug.ui.console.IConsole;
|
||||
import org.eclipse.debug.ui.console.IConsoleLineTracker;
|
||||
import org.eclipse.jface.text.IRegion;
|
||||
|
||||
//import org.eclipse.ant.internal.ui.launchConfigurations.TaskLinkManager;
|
||||
|
||||
public class ConsoleLineTracker implements IConsoleLineTracker {
|
||||
|
||||
private IConsole fConsole;
|
||||
|
||||
/**
|
||||
* @see org.eclipse.debug.ui.console.IConsoleLineTracker#init(org.eclipse.debug.ui.console.IConsole)
|
||||
*/
|
||||
@Override
|
||||
public void init(IConsole console) {
|
||||
IProcess process = console.getProcess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lineAppended(IRegion line) {
|
||||
// TaskLinkManager.processNewLine(fConsole, line);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
fConsole = null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.xtext.sleigh.ui.contentassist
|
||||
|
||||
|
||||
/**
|
||||
* See https://www.eclipse.org/Xtext/documentation/304_ide_concepts.html#content-assist
|
||||
* on how to customize the content assistant.
|
||||
*/
|
||||
class SleighProposalProvider extends AbstractSleighProposalProvider {
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.xtext.sleigh.ui.labeling
|
||||
|
||||
import com.google.inject.Inject
|
||||
import org.eclipse.emf.ecore.EObject
|
||||
import org.eclipse.emf.ecore.resource.ResourceSet
|
||||
import org.eclipse.xtext.nodemodel.util.NodeModelUtils
|
||||
import org.eclipse.xtext.resource.IEObjectDescription
|
||||
import org.eclipse.xtext.resource.IReferenceDescription
|
||||
import org.eclipse.xtext.ui.label.DefaultDescriptionLabelProvider
|
||||
import ghidra.xtext.sleigh.sleigh.exportStmt
|
||||
import ghidra.xtext.sleigh.sleigh.pequation
|
||||
import ghidra.xtext.sleigh.sleigh.statement
|
||||
|
||||
/**
|
||||
* Provides labels for IEObjectDescriptions and IResourceDescriptions.
|
||||
*
|
||||
* See https://www.eclipse.org/Xtext/documentation/304_ide_concepts.html#label-provider
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides labels for a IEObjectDescriptions and IResourceDescriptions.
|
||||
*
|
||||
* see http://www.eclipse.org/Xtext/documentation.html#labelProvider
|
||||
*/
|
||||
class SleighDescriptionLabelProvider extends DefaultDescriptionLabelProvider {
|
||||
|
||||
@Inject ResourceSet rdp
|
||||
|
||||
// Labels and icons can be computed like this:
|
||||
override String getText(Object element) {
|
||||
var ele = element;
|
||||
|
||||
if (element instanceof IReferenceDescription) {
|
||||
var o = rdp.getEObject(element.sourceEObjectUri,true);
|
||||
if (o != null){
|
||||
return containerLine(o);
|
||||
}
|
||||
return element.EReference.name
|
||||
}
|
||||
return super.getText(ele);
|
||||
}
|
||||
|
||||
def String containerLine(EObject o) {
|
||||
var c = o;
|
||||
var text = NodeModelUtils.getNode(o).text
|
||||
while (c.eContainer != null) {
|
||||
if (c instanceof pequation) {
|
||||
return NodeModelUtils.getNode(c).text
|
||||
}
|
||||
if (c instanceof statement ||
|
||||
c instanceof exportStmt
|
||||
) {
|
||||
text = NodeModelUtils.getNode(c).text
|
||||
text = text.trim()
|
||||
return text
|
||||
}
|
||||
c = c.eContainer
|
||||
}
|
||||
return text
|
||||
}
|
||||
override text(IEObjectDescription ele) {
|
||||
return super.text(ele);
|
||||
}
|
||||
|
||||
override image(IEObjectDescription ele) {
|
||||
ele.EClass.name + '.gif'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.xtext.sleigh.ui.labeling
|
||||
|
||||
import com.google.inject.Inject
|
||||
import java.util.Iterator
|
||||
import org.eclipse.emf.common.util.EList
|
||||
import org.eclipse.emf.ecore.EObject
|
||||
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider
|
||||
import org.eclipse.jface.viewers.StyledString
|
||||
import org.eclipse.xtext.naming.IQualifiedNameProvider
|
||||
import org.eclipse.xtext.naming.QualifiedName
|
||||
import org.eclipse.xtext.ui.label.DefaultEObjectLabelProvider
|
||||
import ghidra.xtext.sleigh.sleigh.DefineSym
|
||||
import ghidra.xtext.sleigh.sleigh.SUBTABLESYM
|
||||
import ghidra.xtext.sleigh.sleigh.VARSYM
|
||||
import ghidra.xtext.sleigh.sleigh.baseconstructor
|
||||
import ghidra.xtext.sleigh.sleigh.constraint
|
||||
import ghidra.xtext.sleigh.sleigh.constructprint
|
||||
import ghidra.xtext.sleigh.sleigh.contextfielddef
|
||||
import ghidra.xtext.sleigh.sleigh.fielddef
|
||||
import ghidra.xtext.sleigh.sleigh.integerValue
|
||||
import ghidra.xtext.sleigh.sleigh.macroDefine
|
||||
import ghidra.xtext.sleigh.sleigh.printpiece
|
||||
import ghidra.xtext.sleigh.sleigh.subconstructor
|
||||
import ghidra.xtext.sleigh.sleigh.varattach
|
||||
import ghidra.xtext.sleigh.sleigh.varnodedef
|
||||
|
||||
import static extension org.eclipse.emf.ecore.util.EcoreUtil.*
|
||||
import static extension org.eclipse.xtext.EcoreUtil2.*
|
||||
|
||||
/**
|
||||
* Provides labels for EObjects.
|
||||
*
|
||||
* See https://www.eclipse.org/Xtext/documentation/304_ide_concepts.html#label-provider
|
||||
*/
|
||||
class SleighLabelProvider extends DefaultEObjectLabelProvider {
|
||||
@Inject
|
||||
new(AdapterFactoryLabelProvider delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
@Inject
|
||||
private IQualifiedNameProvider nameProvider;
|
||||
|
||||
QualifiedName qn
|
||||
|
||||
EObject model
|
||||
|
||||
Iterator<varattach> varatt
|
||||
|
||||
def String text(EObject eObject) {
|
||||
qn = nameProvider.getFullyQualifiedName(eObject);
|
||||
if(qn == null) {
|
||||
return getObjectText(eObject);
|
||||
}
|
||||
|
||||
return qn.toString();
|
||||
}
|
||||
|
||||
def String getObjectText(EObject element) {
|
||||
switch element {
|
||||
macroDefine:
|
||||
element.defineType // + element.definename.name + " = " + element.value
|
||||
VARSYM:
|
||||
element.name + " : " + getSizeStr((element.eContainer.eContainer as varnodedef).size)
|
||||
SUBTABLESYM:
|
||||
element.name
|
||||
contextfielddef:
|
||||
element.name
|
||||
fielddef:
|
||||
element.name
|
||||
subconstructor:
|
||||
doGetText(element.tableName) + ':'
|
||||
baseconstructor:
|
||||
':' + doGetText(element.print)
|
||||
constructprint:
|
||||
formatString(element.printpieces)
|
||||
constraint:
|
||||
element.eClass.baseName
|
||||
default: {
|
||||
//System.out.println(element.class.simpleName)
|
||||
element.class.simpleName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String possible;
|
||||
|
||||
def getfielddefText(fielddef element) {
|
||||
// find all var attaches and display possible names
|
||||
var len = getVarAttachesForElement(element)
|
||||
return convertToStyledString('field ' + element.name).append(
|
||||
" " + len + " " + ' (' + element.start.value + ',' + element.end.value + ')' +
|
||||
(if(element.isSigned()) ' signed' else ''), StyledString::QUALIFIER_STYLER).append("\n\n" + possible);
|
||||
}
|
||||
|
||||
def getcontextfielddefText(contextfielddef element) {
|
||||
// find all var attaches and display possible names
|
||||
var len = getVarAttachesForElement(element)
|
||||
// is in a context, put out the name
|
||||
return convertToStyledString('context ' + element.name).append(
|
||||
" " + len + " " + ' (' + element.start.value + ',' + element.end.value + ')' +
|
||||
(if(element.isSigned()) ' signed' else ''), StyledString::QUALIFIER_STYLER).append("\n\n" + possible);
|
||||
}
|
||||
|
||||
protected def String getVarAttachesForElement(EObject element) {
|
||||
model = element.eResource.contents.get(0);
|
||||
varatt = model.eAllContents.filter(typeof(varattach));
|
||||
possible = "";
|
||||
var len = "";
|
||||
while (varatt.hasNext) {
|
||||
var next = varatt.next;
|
||||
var vlist = next.valuelist.valuelist.listIterator;
|
||||
while (vlist.hasNext) {
|
||||
var v = vlist.next;
|
||||
if (v.sym.equals(element)) {
|
||||
var viter = next.vlist.varDefList.iterator;
|
||||
possible = "attached to: "
|
||||
while (viter.hasNext) {
|
||||
var varname = viter.next;
|
||||
var vref = varname.varpart;
|
||||
if (vref != null) {
|
||||
var vdef = vref.getContainerOfType(typeof(varnodedef));
|
||||
if (vdef != null) {
|
||||
var size = vdef.size.value;
|
||||
len = size; // works even if is a $Define
|
||||
}
|
||||
possible = possible + vref.name + " ";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
len
|
||||
}
|
||||
|
||||
def getDefineSymText(DefineSym element) {
|
||||
// find all var attaches and display possible names
|
||||
var retStr = "";
|
||||
model = element.eResource.contents.get(0);
|
||||
var macDefs = model.eAllContents.filter(typeof(macroDefine));
|
||||
possible = "";
|
||||
var len = "";
|
||||
while (macDefs.hasNext) {
|
||||
var next = macDefs.next;
|
||||
if (next.defineType.equals("@define")) {
|
||||
if (next.definename.name == element.name) {
|
||||
retStr = retStr + next.value + "\r\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
if (retStr.length == 0) {
|
||||
return super.doGetText(element);
|
||||
}
|
||||
return retStr;
|
||||
}
|
||||
|
||||
override protected doGetText(Object element) {
|
||||
if(element == null) return null;
|
||||
// System.out.println("Label:" + element.class.baseName + " : " + element);
|
||||
switch element {
|
||||
macroDefine:
|
||||
element.defineType // + element.definename.name + " = " + element.value
|
||||
VARSYM:
|
||||
element.name + " : " + getSizeStr((element.getContainerOfType(typeof(varnodedef))).size)
|
||||
SUBTABLESYM:
|
||||
element.name
|
||||
contextfielddef:
|
||||
getcontextfielddefText(element)
|
||||
fielddef:
|
||||
getfielddefText(element)
|
||||
subconstructor:
|
||||
doGetText(element.tableName) + ':'
|
||||
baseconstructor:
|
||||
':' + doGetText(element.print)
|
||||
constructprint:
|
||||
formatString(element.printpieces)
|
||||
constraint:
|
||||
doGetText(element.sym)
|
||||
DefineSym:
|
||||
getDefineSymText(element)
|
||||
default:
|
||||
super.doGetText(element)
|
||||
}
|
||||
}
|
||||
|
||||
def getSizeStr(integerValue size) {
|
||||
if (size.value != null) {
|
||||
return size.value
|
||||
}
|
||||
if (size.sym != null) {
|
||||
return size.sym.getText
|
||||
}
|
||||
return "?"
|
||||
}
|
||||
|
||||
def getBaseName(Object element) {
|
||||
element.class.name.substring(element.class.name.lastIndexOf('.') + 1)
|
||||
}
|
||||
|
||||
def String formatString(EList<printpiece> list) {
|
||||
var str = "";
|
||||
var iter = list.iterator;
|
||||
while (iter.hasNext) {
|
||||
var piece = iter.next;
|
||||
if (piece.str == null) {
|
||||
if (piece.sym != null) {
|
||||
str += piece.sym.sym;
|
||||
} else {
|
||||
str = '{empty}'
|
||||
}
|
||||
} else {
|
||||
str += piece.str;
|
||||
}
|
||||
}
|
||||
str
|
||||
}
|
||||
|
||||
override protected doGetImage(Object element) {
|
||||
// icons are stored in the 'icons' folder of this project.
|
||||
// when adding such a folder, don't forget to add it to the 'bin.includes' section in the build.properties
|
||||
switch element {
|
||||
// fielddef:
|
||||
// 'F-blue.png'
|
||||
// contextfielddef:
|
||||
// 'C-blue.png'
|
||||
// VARSYM:
|
||||
// 'F-blue.png'
|
||||
default:
|
||||
super.doGetImage(element)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.xtext.sleigh.ui.outline
|
||||
|
||||
import java.util.ArrayList
|
||||
import org.eclipse.emf.ecore.EObject
|
||||
import org.eclipse.xtext.ui.editor.model.IXtextDocument
|
||||
import org.eclipse.xtext.ui.editor.outline.IOutlineNode
|
||||
import org.eclipse.xtext.ui.editor.outline.impl.DefaultOutlineTreeProvider
|
||||
import org.eclipse.xtext.util.concurrent.IUnitOfWork
|
||||
|
||||
/**
|
||||
* Customization of the default outline structure.
|
||||
*
|
||||
* See https://www.eclipse.org/Xtext/documentation/310_eclipse_support.html#outline
|
||||
*/
|
||||
class SleighOutlineTreeProvider extends DefaultOutlineTreeProvider {
|
||||
|
||||
// This controls the size of the outline
|
||||
// Displaying the outline can be expensive
|
||||
// TODO: figure out performance issue, possibly carefully
|
||||
// building the outline based on Sleigh ideas not pure grammer
|
||||
|
||||
override createRoot(IXtextDocument document) {
|
||||
if (document.numberOfLines < 100) {
|
||||
super.createRoot(document);
|
||||
} else {
|
||||
new IOutlineNode() {
|
||||
|
||||
override getChildren() {
|
||||
new ArrayList<IOutlineNode>();
|
||||
}
|
||||
|
||||
override getFullTextRegion() {
|
||||
throw new UnsupportedOperationException("TODO: auto-generated method stub")
|
||||
}
|
||||
|
||||
override getImage() {
|
||||
return null
|
||||
}
|
||||
|
||||
override getParent() {
|
||||
return null
|
||||
}
|
||||
|
||||
override getSignificantTextRegion() {
|
||||
throw new UnsupportedOperationException("TODO: auto-generated method stub")
|
||||
}
|
||||
|
||||
override getText() {
|
||||
return "suppressed outline"
|
||||
}
|
||||
|
||||
override hasChildren() {
|
||||
return false
|
||||
}
|
||||
|
||||
override <T> getAdapter(Class<T> adapter) {
|
||||
throw new UnsupportedOperationException("TODO: auto-generated method stub")
|
||||
}
|
||||
|
||||
override <Result> readOnly(IUnitOfWork<Result, EObject> work) {
|
||||
throw new UnsupportedOperationException("TODO: auto-generated method stub")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,323 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.xtext.sleigh.ui.quickfix
|
||||
|
||||
import org.eclipse.emf.ecore.EObject
|
||||
import org.eclipse.emf.ecore.util.EcoreUtil
|
||||
import org.eclipse.xtext.EcoreUtil2
|
||||
import org.eclipse.xtext.diagnostics.Diagnostic
|
||||
import org.eclipse.xtext.resource.XtextResource
|
||||
import org.eclipse.xtext.ui.editor.quickfix.DefaultQuickfixProvider
|
||||
import org.eclipse.xtext.ui.editor.quickfix.Fix
|
||||
import org.eclipse.xtext.ui.editor.quickfix.IssueResolutionAcceptor
|
||||
import org.eclipse.xtext.util.concurrent.IUnitOfWork
|
||||
import org.eclipse.xtext.validation.Issue
|
||||
import ghidra.xtext.sleigh.sleigh.Expression
|
||||
import ghidra.xtext.sleigh.sleigh.LOCALSYM
|
||||
import ghidra.xtext.sleigh.sleigh.Model
|
||||
import ghidra.xtext.sleigh.sleigh.SleighFactory
|
||||
import ghidra.xtext.sleigh.sleigh.VARSYM
|
||||
import ghidra.xtext.sleigh.sleigh.constraint
|
||||
import ghidra.xtext.sleigh.sleigh.constructor
|
||||
import ghidra.xtext.sleigh.sleigh.exprSym
|
||||
import ghidra.xtext.sleigh.sleigh.fielddef
|
||||
import ghidra.xtext.sleigh.sleigh.integerValue
|
||||
import ghidra.xtext.sleigh.sleigh.lhsvarnode
|
||||
import ghidra.xtext.sleigh.sleigh.localDefine
|
||||
import ghidra.xtext.sleigh.sleigh.macroOrPcode
|
||||
import ghidra.xtext.sleigh.sleigh.statement
|
||||
import ghidra.xtext.sleigh.sleigh.tokendef
|
||||
import ghidra.xtext.sleigh.sleigh.varattach
|
||||
import ghidra.xtext.sleigh.sleigh.varnodedef
|
||||
import ghidra.xtext.sleigh.sleigh.vnoderef
|
||||
|
||||
import static extension org.eclipse.emf.ecore.util.EcoreUtil.*
|
||||
import static extension org.eclipse.xtext.EcoreUtil2.*
|
||||
|
||||
/**
|
||||
* Custom quickfixes.
|
||||
*
|
||||
* See https://www.eclipse.org/Xtext/documentation/310_eclipse_support.html#quick-fixes
|
||||
*/
|
||||
class SleighQuickfixProvider extends DefaultQuickfixProvider {
|
||||
|
||||
@Fix(Diagnostic::LINKING_DIAGNOSTIC)
|
||||
def void createMissingVariable(Issue issue, IssueResolutionAcceptor acceptor) {
|
||||
var message = issue.message;
|
||||
var to = getToName(message);
|
||||
var linkName = getLinkName(message);
|
||||
var sname = macroOrPcode.simpleName.toString();
|
||||
switch (to) {
|
||||
case macroOrPcode.simpleName:
|
||||
missingPseudoOp(issue, acceptor, to, linkName)
|
||||
case lhsvarnode.simpleName:
|
||||
createLocalVarnode(issue, acceptor, to, linkName)
|
||||
case EObject.simpleName:
|
||||
missingEObjectLink(issue, acceptor, to, linkName)
|
||||
}
|
||||
}
|
||||
|
||||
def missingPseudoOp(Issue issue, IssueResolutionAcceptor acceptor, String to, String linkName) {
|
||||
acceptor.accept(
|
||||
issue,
|
||||
"Create pcodeop '" + linkName + "'",
|
||||
"Create pcodeop '" + linkName + "'",
|
||||
"",
|
||||
[ element, context |
|
||||
val currentEntity = EcoreUtil2.getContainerOfType(element,constructor)
|
||||
val model = currentEntity.eContainer as Model
|
||||
val newdef = SleighFactory::eINSTANCE.createpcodeopdef() => [
|
||||
ops.add(SleighFactory::eINSTANCE.createUSEROPSYM() => [
|
||||
name = context.xtextDocument.get(issue.offset, issue.length)
|
||||
])
|
||||
];
|
||||
model.elements.add(model.elements.indexOf(currentEntity), newdef)
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
def missingEObjectLink(Issue issue, IssueResolutionAcceptor acceptor, String to, String linkName) {
|
||||
val modificationContext = getModificationContextFactory().createModificationContext(issue);
|
||||
val xtextDocument = modificationContext.getXtextDocument();
|
||||
xtextDocument.readOnly(
|
||||
new IUnitOfWork.Void<XtextResource>() {
|
||||
|
||||
override process(XtextResource state) throws Exception {
|
||||
var cause = state.getResourceSet().getEObject(issue.getUriToProblem(), false);
|
||||
if (cause instanceof constraint) {
|
||||
missingConstraint(issue, acceptor, to, linkName, cause)
|
||||
missingSubConstructor(issue, acceptor, to, linkName, cause)
|
||||
}
|
||||
// switch cause {
|
||||
// case constraint:
|
||||
//
|
||||
// default: {
|
||||
// var x = cause
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
def missingConstraint(Issue issue, IssueResolutionAcceptor acceptor, String to, String linkName, EObject cause) {
|
||||
acceptor.accept(
|
||||
issue,
|
||||
"Create fieldef '" + linkName + "'",
|
||||
"Create fieldef '" + linkName + "'",
|
||||
"",
|
||||
[ element, context |
|
||||
var root = EcoreUtil2.getRootContainer(cause) as Model;
|
||||
// find fielddef
|
||||
var tokendefs = root.getAllContentsOfType(typeof(tokendef))
|
||||
if(tokendefs.size <= 0) return;
|
||||
var tokendef = tokendefs.get(0);
|
||||
|
||||
// if found, put at end
|
||||
val newfielddef = SleighFactory::eINSTANCE.createfielddef() => [
|
||||
name = linkName
|
||||
// TODO: try to figure out start/end
|
||||
// TODO: ask start / end
|
||||
start = SleighFactory.eINSTANCE.createintegerValue() => [
|
||||
value = '0';
|
||||
]
|
||||
end = SleighFactory.eINSTANCE.createintegerValue() => [
|
||||
value = '0';
|
||||
]
|
||||
];
|
||||
// add
|
||||
tokendef.fields.tokens.add(newfielddef)
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
def missingSubConstructor(Issue issue, IssueResolutionAcceptor acceptor, String to, String linkName, EObject cause) {
|
||||
acceptor.accept(
|
||||
issue,
|
||||
"Create SubConstruct '" + linkName + "'",
|
||||
"Create SubConstruct '" + linkName + "'",
|
||||
"",
|
||||
[ element, context |
|
||||
var model = cause.rootContainer as Model;
|
||||
|
||||
var container = EcoreUtil2.getContainerOfType(cause, constructor)
|
||||
|
||||
// create subconstructor template
|
||||
val sub = SleighFactory::eINSTANCE.createsubconstructor() => [
|
||||
tableName = SleighFactory.eINSTANCE.createSUBTABLESYM() => [
|
||||
name = linkName;
|
||||
]
|
||||
print = SleighFactory.eINSTANCE.createconstructprint() => [
|
||||
var pp = SleighFactory.eINSTANCE.createprintpiece() => [
|
||||
str = ""
|
||||
]
|
||||
printpieces.add(pp)
|
||||
is = SleighFactory.eINSTANCE.createisKeyword() => []
|
||||
]
|
||||
match = SleighFactory.eINSTANCE.createpequation() => [
|
||||
constraints = SleighFactory.eINSTANCE.createconstraint() => [
|
||||
isepsilon = true
|
||||
]
|
||||
]
|
||||
body = SleighFactory.eINSTANCE.creatertlbody() => [
|
||||
unimpl = true
|
||||
]
|
||||
];
|
||||
// add before this instance
|
||||
model.elements.add(model.elements.indexOf(container), sub)
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
def createLocalVarnode(Issue issue, IssueResolutionAcceptor acceptor, String to, String linkName) {
|
||||
acceptor.accept(
|
||||
issue,
|
||||
"Create local '" + linkName + "'",
|
||||
"Create local '" + linkName + "'",
|
||||
"",
|
||||
[ element, context |
|
||||
// find size of first element if it can
|
||||
val s = findElementSize(element);
|
||||
if (s == null) {
|
||||
val newdef = SleighFactory::eINSTANCE.createassignSym() => [
|
||||
local = SleighFactory::eINSTANCE.createlocalDefine() => [
|
||||
sym = SleighFactory.eINSTANCE.createLOCALSYM() => [
|
||||
name = linkName;
|
||||
]
|
||||
]
|
||||
];
|
||||
element.replace(newdef);
|
||||
} else {
|
||||
val newdef = SleighFactory::eINSTANCE.createassignSym() => [
|
||||
local = SleighFactory::eINSTANCE.createlocalDefine() => [
|
||||
sym = SleighFactory.eINSTANCE.createLOCALSYM() => [
|
||||
name = linkName;
|
||||
]
|
||||
size = SleighFactory.eINSTANCE.createintegerValue() => [
|
||||
value = s.value;
|
||||
sym = s.sym;
|
||||
]
|
||||
]
|
||||
];
|
||||
element.replace(newdef);
|
||||
}
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
def integerValue findElementSize(EObject element) {
|
||||
val currentEntity = EcoreUtil2.getContainerOfType(element, statement)
|
||||
val rhs = currentEntity.rhs;
|
||||
val s = findSize(rhs);
|
||||
return s;
|
||||
}
|
||||
|
||||
var integerValue len;
|
||||
|
||||
def integerValue findSize(Expression rhs) {
|
||||
len = null;
|
||||
if (rhs instanceof exprSym) {
|
||||
return getExprSymLength(rhs);
|
||||
}
|
||||
var vlist = rhs.getAllContentsOfType(typeof(exprSym));
|
||||
vlist.forEach [ it |
|
||||
getExprSymLength(it)
|
||||
]
|
||||
return len;
|
||||
}
|
||||
|
||||
def getExprSymLength(exprSym sym) {
|
||||
var node = sym.vnode;
|
||||
switch node {
|
||||
VARSYM: {
|
||||
var def = node.getContainerOfType(typeof(varnodedef));
|
||||
if (def != null && def.size != null) {
|
||||
if (len == null) {
|
||||
len = def.size;
|
||||
}
|
||||
} else if (len != def.size) {
|
||||
len = null;
|
||||
}
|
||||
}
|
||||
fielddef: {
|
||||
len = findVarAttachLen(node);
|
||||
}
|
||||
LOCALSYM: {
|
||||
var ldef = node.getContainerOfType(typeof(localDefine));
|
||||
if (ldef != null && ldef.size != null) {
|
||||
if (len == null) {
|
||||
len = ldef.size;
|
||||
}
|
||||
} else if (len != ldef.size) {
|
||||
len = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def integerValue findVarAttachLen(fielddef fdef) {
|
||||
// find all var attaches and display possible names
|
||||
var model = fdef.eResource.contents.get(0);
|
||||
var varatt = model.eAllContents.filter(typeof(varattach));
|
||||
while (varatt.hasNext) {
|
||||
var next = varatt.next;
|
||||
var vlist = next.valuelist.valuelist.listIterator;
|
||||
while (vlist.hasNext) {
|
||||
var v = vlist.next;
|
||||
if (v.sym.equals(fdef)) {
|
||||
var viter = next.vlist.varDefList.iterator;
|
||||
while (viter.hasNext) {
|
||||
var varname = viter.next;
|
||||
var vref = varname.varpart;
|
||||
if (vref != null) {
|
||||
var vdef = vref.getContainerOfType(typeof(varnodedef));
|
||||
if (vdef != null) {
|
||||
var size = vdef.size;
|
||||
return size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
def findVnodeSize(vnoderef ref) {
|
||||
System.out.println(' printit ' + ref.ID);
|
||||
}
|
||||
|
||||
def String getLinkName(String str) {
|
||||
var end = str.lastIndexOf('\'')
|
||||
var start = str.lastIndexOf('\'', end - 1)
|
||||
return str.substring(start + 1, end)
|
||||
}
|
||||
|
||||
def String getToName(String str) {
|
||||
val refString = "reference to ";
|
||||
|
||||
var index = str.indexOf(refString);
|
||||
if (index == -1) {
|
||||
return null;
|
||||
}
|
||||
var start = index + refString.length;
|
||||
var refStr = str.substring(start);
|
||||
refStr = refStr.substring(0, refStr.indexOf(' '));
|
||||
return refStr;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="org.eclipse.emf.mwe2.launch.Mwe2LaunchConfigurationType">
|
||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
|
||||
<listEntry value="/ghidra.xtext.sleigh"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
|
||||
<listEntry value="4"/>
|
||||
</listAttribute>
|
||||
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
|
||||
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
|
||||
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${working_set:<?xml version="1.0" encoding="UTF-8"?> <resources> <item path="/ghidra.xtext.sleigh" type="4"/> <item path="/ghidra.xtext.sleigh.ide" type="4"/> <item path="/ghidra.xtext.sleigh.ui" type="4"/> <item path="/ghidra.xtext.sleigh.feature" type="4"/> <item path="/ghidra.xtext.sleigh.tests" type="4"/> <item path="/ghidra.xtext.sleigh.ui.tests" type="4"/> <item path="/ghidra.xtext.sleigh.tests" type="4"/> <item path="/ghidra.xtext.sleigh.ui.tests" type="4"/> ;</resources>}"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.emf.mwe2.launch.runtime.Mwe2Launcher"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="ghidra.xtext.sleigh.GenerateSleigh"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="ghidra.xtext.sleigh"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx512m"/>
|
||||
</launchConfiguration>
|
||||
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="org.eclipse.pde.ui.RuntimeWorkbench">
|
||||
<booleanAttribute key="append.args" value="true"/>
|
||||
<booleanAttribute key="askclear" value="true"/>
|
||||
<booleanAttribute key="automaticAdd" value="true"/>
|
||||
<booleanAttribute key="automaticValidate" value="false"/>
|
||||
<stringAttribute key="bad_container_name" value="/ghidra.xtext.sleigh/.launch/"/>
|
||||
<stringAttribute key="bootstrap" value=""/>
|
||||
<stringAttribute key="checked" value="[NONE]"/>
|
||||
<booleanAttribute key="clearConfig" value="false"/>
|
||||
<booleanAttribute key="clearws" value="false"/>
|
||||
<booleanAttribute key="clearwslog" value="false"/>
|
||||
<stringAttribute key="configLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.pde.core/Launch Runtime Eclipse"/>
|
||||
<booleanAttribute key="default" value="true"/>
|
||||
<booleanAttribute key="includeOptional" value="true"/>
|
||||
<stringAttribute key="location" value="${workspace_loc}/../runtime-EclipseXtext"/>
|
||||
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
|
||||
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
|
||||
<listEntry value="org.eclipse.debug.ui.launchGroup.run"/>
|
||||
</listAttribute>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl}"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xms40m -Xmx512m"/>
|
||||
<stringAttribute key="pde.version" value="3.3"/>
|
||||
<stringAttribute key="product" value="org.eclipse.platform.ide"/>
|
||||
<booleanAttribute key="show_selected_only" value="false"/>
|
||||
<stringAttribute key="templateConfig" value="${target_home}/configuration/config.ini"/>
|
||||
<booleanAttribute key="tracing" value="false"/>
|
||||
<booleanAttribute key="useDefaultConfig" value="true"/>
|
||||
<booleanAttribute key="useDefaultConfigArea" value="true"/>
|
||||
<booleanAttribute key="useProduct" value="true"/>
|
||||
<booleanAttribute key="usefeatures" value="false"/>
|
||||
</launchConfiguration>
|
||||
@@ -0,0 +1,201 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>GhidraSleighEditor README</title>
|
||||
<style name="text/css">
|
||||
li { font-family:times new roman; font-size:14pt; font-family:times new roman; font-size:14pt; margin-bottom: 12px; }
|
||||
h1 { color:#000080; font-family:times new roman; font-size:36pt; font-style:italic; font-weight:bold; text-align:center; }
|
||||
h2 { padding-top:30px; color:#984c4c; font-family:times new roman; font-size:18pt; font-weight:bold; }
|
||||
p { font-family:times new roman; font-size:14pt; }
|
||||
td { font-family:times new roman; font-size:14pt; padding-left:10px; padding-right:10px; }
|
||||
th { font-family:times new roman; font-size:14pt; font-weight:bold; padding-left:10px; padding-right:10px; }
|
||||
code { color:black; font-family:courier new font-size: 14pt; }
|
||||
span.code { font-family:courier new font-size: 14pt; color:#000000; }
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>GhidraSleighEditor README</h1>
|
||||
<p>GhidraSleighEditor makes developing and modifying Ghidra Sleigh processor modules much more enjoyable by providing a modern
|
||||
day context sensitive editor with syntax highlighting, navigation, context sensitive error notation, quick fixes, and more. The
|
||||
editor is built with the excellent XTEXT DSL framework within Eclipse.
|
||||
</p>
|
||||
<p>The information provided in this document is effective as of Ghidra Sleigh Editor 1.0.0 and is subject to
|
||||
change with future releases.</p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href="#MinimumRequirements">Minimum Requirements</a></li>
|
||||
<li><a href="#Install">Installing</a></li>
|
||||
<ul>
|
||||
<li><a href="#InstallpreBuilt">Installation pre-build editor in Eclipse</a></li>
|
||||
<li><a href="#Building">Building Eclipse Sleigh Editor</a></li>
|
||||
</ul>
|
||||
<li><a href="#Uninstall">Uninstalling</a></li>
|
||||
<li><a href="#Upgrade">Upgrading</a></li>
|
||||
<li><a href="#Features">Sleigh Editor Features</a></li>
|
||||
<ul>
|
||||
<li><a href="#Hilite">Syntax Highlighting</a></li>
|
||||
<li><a href="#Validate">Validation</a></li>
|
||||
<li><a href="#QuickFix">QuickFix</a></li>
|
||||
<li><a href="#Hover">Hover</a></li>
|
||||
<li><a href="#References">Find References</a></li>
|
||||
<li><a href="#Rename">Renaming</a></li>
|
||||
<li><a href="#Format">Code Formating</a></li>
|
||||
</ul>
|
||||
<li><a href="#ChangeHistory">Change History</a></li>
|
||||
</ul>
|
||||
|
||||
<h2><a name="MinimumRequirements"></a>Minimum Requirements</h2>
|
||||
<ul>
|
||||
<li>Eclipse 2019-3 with DSL and XTEXT 2.17 or later</li>
|
||||
<li>Ghidra 9.0 or later</li>
|
||||
</ul>
|
||||
<p>(<a href="#top">Back to Top</a>)</p>
|
||||
|
||||
|
||||
<h2><a name="Install"></a>Installing GhidraSleighEditor</h2>
|
||||
<p>GhidraSleighEditor is installed manually into Eclipse and should be installed by anyone interested in working with
|
||||
processor module sleigh specifications. The Sleigh Editor must be manually installed in Eclipse. In the future the extension
|
||||
may be installed automatically along with the GhidraDev Eclipse plugin when setting up Eclipse for Ghidra scripting and plugin development.</p>
|
||||
|
||||
<h3><a name="InstallpreBuilt"></a>Install pre-Built</h3>
|
||||
<p>GhidraSleighEditor can be installed into an existing installation of Eclipse the same way most Eclipse
|
||||
plugins are installed. From Eclipse:</p>
|
||||
<ol>
|
||||
<li>Click <b>Help → Install New Software...</b></li>
|
||||
<li>Click <b>Add...</b></li>
|
||||
<li>Click <b>Archive...</b></li>
|
||||
<li>
|
||||
Select GhidraSleighEditor zip file from <i><GhidraInstallDir></i>/Extensions/Eclipse/GhidraSleighEditor/
|
||||
</li>
|
||||
<li>Click <b>OK</b> (name field can be blank)</li>
|
||||
<li>Check <b>Ghidra</b> category (or <b>Ghidra Sleigh Editor</b> entry)</li>
|
||||
<li>Click <b>Next</b></li>
|
||||
<li>Click <b>Next</b></li>
|
||||
<li>Accept the terms of the license agreement</li>
|
||||
<li>Click <b>Finish</b></li>
|
||||
<li>Click <b>Install anyway</b></li>
|
||||
<li>Click <b>Restart Now</b></li>
|
||||
</ol>
|
||||
<h3><a name="Building"></a>Building Eclipse Sleigh Editor</h3>
|
||||
<ol>
|
||||
<p>To build the Sleigh Editor, follow the instructions in ghidra/DevGuide.md to setup eclipse
|
||||
for development. Then follow the directions in
|
||||
<i>ghidra/GhidraBuild/EclipsePlugins/GhidraSleighEditor/ghidra.xtext.sleigh.feature/build_README.txt</i>.</p>
|
||||
</ol>
|
||||
|
||||
<h2><a name="Uninstall"></a>Uninstalling</h2>
|
||||
<p>GhidraSleighEditor can be uninstalled as follows from
|
||||
Eclipse:</p>
|
||||
<ol>
|
||||
<li>Click <b>Help → About Eclipse</b></li>
|
||||
<ul>
|
||||
<li><i>For macOS:</i> <b>Eclipse → About Eclipse</b></li>
|
||||
</ul>
|
||||
<li>Click <b>Installation Details</b></li>
|
||||
<li>Select Ghidra Sleigh Editor</li>
|
||||
<li>Click <b>Uninstall...</b></li>
|
||||
<li>Select Ghidra Sleigh Editor</li>
|
||||
<li>Click <b>Finish</b></li>
|
||||
<li>Click <b>Restart Now</b></li>
|
||||
</ol>
|
||||
<p>(<a href="#top">Back to Top</a>)</p>
|
||||
|
||||
<h2><a name="Upgrade"></a>Upgrading</h2>
|
||||
<p> GhidraSleighEditor can be upgraded the same way it was initially installed.</p>
|
||||
<p>(<a href="#top">Back to Top</a>)</p>
|
||||
|
||||
<h2><a name="Features"></a>Sleigh Editor Features</h2>
|
||||
<p>The Ghidra Sleigh Editor provides a variety of features one would expect in any modern IDE to make viewing, modifying, debugging,
|
||||
and creating Sleigh processor specifications as painless as possible.
|
||||
Once installed, any .sinc or .slaspec file that is edited will be brought up in the sleigh editor.</p>
|
||||
<p>The editor provides the following capabilities:</p>
|
||||
<ul>
|
||||
<li><a name="Hilite"></a>Syntax Highlighting</li>
|
||||
<ul>
|
||||
<p>Keywords, Tokens, Sub-constructor names, Comments, Instruction Formats, Strings, Variables, and more can be colorized to make
|
||||
the sliegh specification more readable. In the <b>Window → Preferences → Sleigh</b> preferences panel, the color and font style can be changed
|
||||
for any sleigh file tokens.</p>
|
||||
</ul>
|
||||
|
||||
<li><a name="Validate"></a>Validation</li>
|
||||
<ul>
|
||||
<p>The structure of a sleigh file while fairly simple can lend itself to errors when using a straight text editor. The editor understands
|
||||
the syntax and all constructs of a sleigh file. Instead of waiting for the sleigh compiler to produce an error, many but not all syntax
|
||||
errors can be caught and displayed with a red error marker.</p>
|
||||
<p>The editor validates the definition of variables including locals.
|
||||
Though legal in the sleigh compiler, it has been found that not declaring local variables leads to
|
||||
errors that are not be caught by the sleigh compiler. For example, assigning to a variable 'ro' when the actual register name is 'r0' may go
|
||||
unnoticed. All local variables must be defined with with the 'local' keyword or with an initial ':size'.</p>
|
||||
<p>Warnings on duplicate names of tokens is marked in yellow. Complex matching patterns such as <i>'!='  '<'  '>'</i> are warnings as well. Using
|
||||
comparison matching operators can cause the generated .sla file to be much larger than necessary. Comparison matching should really never be used on any
|
||||
tokens that are bigger than a few bits as the number of match cases generated will be large. Their use is unavoidable in some cases.<p>
|
||||
<p>There are some artificial enforcements in the editor that, while valid sleigh syntax, cause the syntax to be unparsable. Because the sleigh
|
||||
Domain Specific Language (DSL) is a context sensitive grammer, as well as using define-like pre-processing expansion, the editor only allows define
|
||||
<b>$()</b> variables at certain locations where a single token would reside. The most common flagged error is embedding a connecting '&' in a define and then
|
||||
using it an a match pattern:
|
||||
<ul>
|
||||
<p><b>:MOV ax, bx is t1=1 $(BadDefine) {}</b> is not allowed, and instead should be <b>:MOV ax, bx is t1=1 & $(GoodDefine) {}</b>.</p>
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
<li><a name="QuickFix"></a>QuickFix</li>
|
||||
<ul>
|
||||
<p>Some simple syntax errors can be fixed quickly with QuickFix suggestions. Pressing Crtl-1 on an error will bring up available quick-fixes.</p>
|
||||
<li>Undefined local variable - insert 'local' or the ':size" form if the size can be detected.</li>
|
||||
<li>Undefined user pcodeop - can insert a user pcodeop definition for an unknown identifier</li>
|
||||
<li>Undefined macro - can insert a macro definition for an unknown identifier</li>
|
||||
<li>Add token field definition - for an unknown token in the match pattern</li>
|
||||
</ul>
|
||||
<p>More quick-fixes may be added in the future. Please note quickfixes can be slow on large files such as the AARCH64.</p>
|
||||
|
||||
<li><a name="Hover"></a>Hover</li>
|
||||
<ul>
|
||||
<p>There are many constructs in a sleigh file that, when hovered over, will display additional information. This is especially useful for tokens to get their
|
||||
size without having to navigate to the token field definition. More hovers will be added.<p>
|
||||
<li>Sub-Constructors will display all the defined sub-constructors with the same name.</li>
|
||||
<li>Token field definitions will display their size, and if attached, the set of registers.</li>
|
||||
<li>Registers display their size.</li>
|
||||
<li>Numeric values will display in Hex, Binary, and Decimal.</li>
|
||||
<li>$(Defines) display all the possible defines for the name, since the actual define used can't be known.</li>
|
||||
</ul>
|
||||
|
||||
<li><a name="Navigate"></a>Navigation</li>
|
||||
<p>If you have edited a sleigh processor specification in a regular text editor, you will appreciate the forward and backward navigation supported on
|
||||
various variable name use and their associated definition. Navigation is supported on sub-constructor names, field token names, registers, macros names, local variables, define names, and user
|
||||
define pcodeop's.</p>
|
||||
<p>Navigate by pressing <b><F3></b> on a variable, using the forward/backward navigation arrows, or my favorite the <-* that will navigate
|
||||
back to the last edit location.<p>
|
||||
|
||||
<li><a name="References"></a>Find References</li>
|
||||
<p>Instead of keyword searching, the editor provides a find all uses of a variable. Each found use is listed in a search window with the text of the line where it is used displayed.
|
||||
Each found location can also be navigated to by double clicking on the found reference.</p>
|
||||
<p>Use the editor popup menu <b>Find References</b> action.</p>
|
||||
|
||||
<li><a name="Rename"></a>Renaming</li>
|
||||
<p>The name of variables can be very important, and instead of doing a search and replace on a string, the editor can refactor a name and change all other uses of that name. The name
|
||||
is even changed in other .sinc and .slaspec files.<p>
|
||||
<p>Use the editor popup menu <b>Rename Element</b> action.</p>
|
||||
|
||||
<li><a name="Format"></a>Code Formating</li>
|
||||
<p>Sleigh files can get large and messy during development. Instead of paying much attention to format, or trying to format by hand you can use the Source Format action.
|
||||
Common constructs are lined up, for example the token definitions will find the longest token and line up all other tokens and their definition. All sub-constructors of the
|
||||
same name will be lined up on the 'is' keyword, the match pattern, and the semantic definitions. All constructors 'is' keywords will be generally lined up based on the longest
|
||||
print peice for each constructor. Statements will also be indented consistently. Multi-line attach definitions will have each entry lined up.
|
||||
Formatting can be restricted to a selection of lines to stop formatting from entirely re-formatting carefully formatted files.
|
||||
Additional formatting may be added in the future, and the formatter may become more configurable in the future.<p>
|
||||
<p>Use the editor popup menu <b>Source → Format</b> action.</p>
|
||||
</ul>
|
||||
<h2><a name="ChangeHistory"></a>Change History</h2>
|
||||
<p><u><b>1.0.0</b>:</u> Initial release in Ghidra 9.1</p>
|
||||
<p>(<a href="#top">Back to Top</a>)</p>
|
||||
|
||||
<!-- Some padding -->
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,31 @@
|
||||
Manifest-Version: 1.0
|
||||
Automatic-Module-Name: ghidra.xtext.sleigh
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: ghidra.xtext.sleigh
|
||||
Bundle-Vendor: Ghidra
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-SymbolicName: ghidra.xtext.sleigh; singleton:=true
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Require-Bundle: org.eclipse.xtext,
|
||||
org.eclipse.xtext.xbase,
|
||||
org.eclipse.equinox.common;bundle-version="3.5.0",
|
||||
org.eclipse.emf.ecore,
|
||||
org.eclipse.xtext.xbase.lib;bundle-version="2.14.0",
|
||||
org.eclipse.xtext.util,
|
||||
org.eclipse.emf.common,
|
||||
org.eclipse.xtend.lib;bundle-version="2.14.0",
|
||||
org.antlr.runtime;bundle-version="[3.2.0,3.2.1)"
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Export-Package: ghidra.xtext.sleigh.formatting2,
|
||||
ghidra.xtext.sleigh,
|
||||
ghidra.xtext.sleigh.sleigh.impl,
|
||||
ghidra.xtext.sleigh.validation,
|
||||
ghidra.xtext.sleigh.scoping,
|
||||
ghidra.xtext.sleigh.sleigh,
|
||||
ghidra.xtext.sleigh.serializer,
|
||||
ghidra.xtext.sleigh.parser.antlr.internal,
|
||||
ghidra.xtext.sleigh.services,
|
||||
ghidra.xtext.sleigh.sleigh.util,
|
||||
ghidra.xtext.sleigh.generator,
|
||||
ghidra.xtext.sleigh.parser.antlr
|
||||
Import-Package: org.apache.log4j
|
||||
@@ -0,0 +1,40 @@
|
||||
apply plugin: 'java'
|
||||
|
||||
// This project requires the Eclipse DSL plugin. To create Eclipse files for this project, run
|
||||
// "gradle eclipse -PeclipseDSL"
|
||||
if (hasProperty("eclipseDSL")) {
|
||||
apply plugin: 'eclipse'
|
||||
eclipse {
|
||||
project {
|
||||
name = 'Eclipse SleighEditor'
|
||||
buildCommand 'org.eclipse.pde.ManifestBuilder'
|
||||
buildCommand 'org.eclipse.pde.SchemaBuilder'
|
||||
buildCommand 'org.eclipse.xtext.ui.shared.xtextBuilder'
|
||||
natures 'org.eclipse.pde.PluginNature'
|
||||
natures 'org.eclipse.xtext.ui.shared.xtextNature'
|
||||
classpath.file {
|
||||
def requiredPlugins = 'org.eclipse.pde.core.requiredPlugins'
|
||||
beforeMerged { classpath ->
|
||||
classpath.entries.removeAll { entry ->
|
||||
entry.path == requiredPlugins
|
||||
}
|
||||
}
|
||||
whenMerged { classpath ->
|
||||
withXml {
|
||||
def node = it.asNode()
|
||||
node.appendNode('classpathentry', [kind: 'con', path: requiredPlugins])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
srcDir 'src'
|
||||
srcDir 'src-gen'
|
||||
srcDir 'xtend-gen'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
source.. = src/,\
|
||||
src-gen/,\
|
||||
xtend-gen/
|
||||
bin.includes = model/generated/,\
|
||||
.,\
|
||||
META-INF/,\
|
||||
plugin.xml
|
||||
bin.excludes = **/*.mwe2,\
|
||||
**/*.xtend
|
||||
additional.bundles = org.eclipse.xtext.xbase,\
|
||||
org.eclipse.xtext.common.types,\
|
||||
org.eclipse.xtext.xtext.generator,\
|
||||
org.eclipse.emf.codegen.ecore,\
|
||||
org.eclipse.emf.mwe.utils,\
|
||||
org.eclipse.emf.mwe2.launch,\
|
||||
org.eclipse.emf.mwe2.lib,\
|
||||
org.objectweb.asm,\
|
||||
org.apache.commons.logging,\
|
||||
org.apache.log4j,\
|
||||
com.ibm.icu
|
||||
@@ -0,0 +1,83 @@
|
||||
The Ghidra Sleigh Editor for Eclipse is currently built from Eclipse and checked into the bin repo.
|
||||
Ideally we will use Gradle one day, but we aren't there yet. We do rely on Gradle prepDev to generate
|
||||
the Eclipse project and build GhidraSleighEditor's dependencies though, hence the build.gradle file.
|
||||
|
||||
Required: Eclipse IDE with Java and DSL version 2019-03 or later, XTEXT 2.17 or later.
|
||||
The following instructions assume that you have setup Eclipse.
|
||||
|
||||
It is also suggested that you use the Eclipse IDE with DSL extensions already installed if you will
|
||||
use the GhidraSleighEditor. You can build the GhidraSleighEditor installation zip with the XTEXT runtime
|
||||
in the plugin. The XTEXT runtime was not included in the distribution build because it would
|
||||
have added 80Meg.
|
||||
|
||||
|
||||
Importing GhidraSleighEditor Eclipse projects (they are deactivated by default):
|
||||
1) Uncomment the line in settings.gradle that includes the GhidraSleighEditor project.
|
||||
2) Run "gradle eclipse -PSleighEditor" to generate the GhidraSleighEditor Eclipse projects.
|
||||
3) From Eclipse, File --> Import --> General --> Existing Projects into Workspace
|
||||
4) From the ghidra repo, import all "Eclipse GhidraSleighEditor *" projects.
|
||||
|
||||
|
||||
Generating all Sleigh XTEXT generated files:
|
||||
1) open ghidra.xtext.sleigh project
|
||||
2) navigate to the file src --> ghidra.xtext.sleigh --> GenerateSleigh.mwe2
|
||||
3) NOTE: the following will download a jar file from the internet (not from NSA)
|
||||
unless you pre-download.
|
||||
3a) Download the file http://download.itemis.com/antlr-generator-3.2.0-patch.jar
|
||||
3b) Put the file in ghidra/GhidraBuild/EclipsePlugins/SleighEditor/ghidra.xtext.sleigh
|
||||
3c) Rename the file to .antlr-generator-3.2.0-patch.jar
|
||||
3) From the popup menu RunAs --> MWE2 Workflow
|
||||
- Files in xtend-gen and src-gen will be created
|
||||
- The project should rebuild, and there should be no red Problem errors
|
||||
|
||||
|
||||
Try out the Sleigh Editor
|
||||
1) Navigate to the 'Eclipse SleighEditor' and chose RunAs --> Eclipse Runtime
|
||||
2) Add a sleigh processor module
|
||||
2a) File --> NewJavaProject...
|
||||
- Uncheck default location and navigate to a processor in Ghidra/Processors/<X>
|
||||
- The project be automatically named <X>
|
||||
- Finish
|
||||
- Cancel Module creation
|
||||
- Navigate to a <X>/data/languages/<file>.sinc or <file>.slaspec
|
||||
- On the popup asking to convert to an XTEXT project, choose "Yes"
|
||||
2b) -OR-
|
||||
- drop a .slaspec or .sinc file from the file browser on eclipse
|
||||
- this is good for quick viewing, however navigation across files may not work.
|
||||
|
||||
|
||||
Optional: Changing version number (GhidraSleighEditor is versioned independently of Ghidra):
|
||||
1) Open feature.xml in the GhidraSleighEditor Feature project.
|
||||
2) In the "Overview" tab, update the "Version" field to x.y.z.qualifier and save.
|
||||
3) Open category.xml in the GhidraSleighEditor Feature project.
|
||||
4) Highlight ghidra.xtext.sleigh.editor (x.y.z.qualifier), and click "Remove".
|
||||
5) Highlight ghidra.xtext.sleigh.editor, and click "Add Feature".
|
||||
6) Select ghidra.ghidradev (x.y.z.qualifer), click "OK", and save.
|
||||
7) Update GhidraDev_README.html "Change History" section if necessary.
|
||||
|
||||
|
||||
Optional: Including the XTEXT runtime
|
||||
You can include the XTEXT runtime or redist module in the .zip file which will negate the need
|
||||
to have Eclipse with the DSL in the Eclipse into which the Eclipse Sleigh Editor is installed to run.
|
||||
1) Navigate to the ghidra.xtext.sleigh.feature
|
||||
2) bring up the feature.xml with the Feature Manager Editor (dbl-click on it).
|
||||
3) Go to the Included Features tab
|
||||
4) Add...
|
||||
5) Filter by 'redist' and add org.eclipse.xtext.redist
|
||||
|
||||
|
||||
Creating an installation zip file to install in Eclipse:
|
||||
1) Do a Gradle prepDev to ensure GhidraDev's dependencies are up-to-date.
|
||||
2) File --> Export --> Plug-in Development --> Deployable plugins and fragments
|
||||
4) Select "Archive file" and choose a directory to save it to. It must end up in
|
||||
ghidra.bin/GhidraBuild/Eclipse/GhidraDev/. Name it GhidraDev-x.y.z.zip.
|
||||
5) In the "Options" tab make sure things look like this:
|
||||
- Export source: UNCHECKED
|
||||
- Package as individual JAR archives: CHECKED
|
||||
- Generate p2 repository: CHECKED
|
||||
- Categorize repository: CHECKED.
|
||||
- Qualifier replacement: CHECKED + clear field so default is used
|
||||
- Save as Ant script: UNCHECKED
|
||||
- Allow for binary cycles in target platform: CHECKED
|
||||
- Use class files compiled in the workspace: UNCHECKED
|
||||
6) Finish
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?eclipse version="3.0"?>
|
||||
<plugin>
|
||||
<extension point="org.eclipse.emf.ecore.generated_package">
|
||||
<package
|
||||
uri = "http://www.xtext.ghidra/sleigh/Sleigh"
|
||||
class = "ghidra.xtext.sleigh.sleigh.SleighPackage"
|
||||
genModel = "model/generated/Sleigh.genmodel" />
|
||||
</extension>
|
||||
</plugin>
|
||||
@@ -0,0 +1,58 @@
|
||||
module ghidra.xtext.sleigh.GenerateSleigh
|
||||
|
||||
import org.eclipse.xtext.xtext.generator.*
|
||||
import org.eclipse.xtext.xtext.generator.model.project.*
|
||||
|
||||
var rootPath = ".."
|
||||
|
||||
Workflow {
|
||||
|
||||
component = XtextGenerator {
|
||||
configuration = {
|
||||
project = StandardProjectConfig {
|
||||
baseName = "ghidra.xtext.sleigh"
|
||||
rootPath = rootPath
|
||||
runtimeTest = {
|
||||
enabled = true
|
||||
}
|
||||
eclipsePlugin = {
|
||||
enabled = true
|
||||
}
|
||||
eclipsePluginTest = {
|
||||
enabled = true
|
||||
}
|
||||
createEclipseMetaData = true
|
||||
}
|
||||
code = {
|
||||
encoding = "UTF-8"
|
||||
lineDelimiter = "\n"
|
||||
fileHeader = "/*\n * generated by Xtext \${version}\n */"
|
||||
}
|
||||
}
|
||||
language = StandardLanguage {
|
||||
name = "ghidra.xtext.sleigh.Sleigh"
|
||||
fileExtensions = "slaspec,sinc"
|
||||
|
||||
serializer = {
|
||||
generateStub = false
|
||||
}
|
||||
validator = {
|
||||
// composedCheck = "org.eclipse.xtext.validation.NamesAreUniqueValidator"
|
||||
// Generates checks for @Deprecated grammar annotations, an IssueProvider and a corresponding PropertyPage
|
||||
generateDeprecationValidation = true
|
||||
}
|
||||
fragment = ui.labeling.LabelProviderFragment2 {}
|
||||
|
||||
fragment = formatting.Formatter2Fragment2 {}
|
||||
|
||||
fragment = ui.quickfix.QuickfixProviderFragment2 {}
|
||||
|
||||
// enable rename refactoring
|
||||
fragment = ui.refactoring.RefactorElementNameFragment2 {}
|
||||
|
||||
junitSupport = {
|
||||
junitVersion = "5"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,23 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.xtext.sleigh
|
||||
|
||||
|
||||
/**
|
||||
* Use this class to register components to be used at runtime / without the Equinox extension registry.
|
||||
*/
|
||||
class SleighRuntimeModule extends AbstractSleighRuntimeModule {
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.xtext.sleigh
|
||||
|
||||
|
||||
/**
|
||||
* Initialization support for running Xtext languages without Equinox extension registry.
|
||||
*/
|
||||
class SleighStandaloneSetup extends SleighStandaloneSetupGenerated {
|
||||
|
||||
def static void doSetup() {
|
||||
new SleighStandaloneSetup().createInjectorAndDoEMFRegistration()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.xtext.sleigh.converter;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Map;
|
||||
|
||||
import org.antlr.runtime.Token;
|
||||
import org.antlr.runtime.TokenSource;
|
||||
import org.eclipse.xtext.AbstractRule;
|
||||
import org.eclipse.xtext.conversion.ValueConverterException;
|
||||
import org.eclipse.xtext.conversion.impl.AbstractLexerBasedConverter;
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
import org.eclipse.xtext.parser.antlr.ITokenDefProvider;
|
||||
import org.eclipse.xtext.parser.antlr.Lexer;
|
||||
import org.eclipse.xtext.util.Strings;
|
||||
|
||||
import com.google.inject.Provider;
|
||||
|
||||
public class IntValueConverter extends AbstractLexerBasedConverter<BigInteger> {
|
||||
|
||||
@Override
|
||||
protected String toEscapedString(BigInteger value) {
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assertValidValue(BigInteger value) {
|
||||
super.assertValidValue(value);
|
||||
if (value.compareTo(BigInteger.ZERO) < 0)
|
||||
throw new ValueConverterException(getRuleName() + "-value may not be negative (value: " + value + ").", null, null);
|
||||
}
|
||||
|
||||
public BigInteger toValue(String string, INode node) {
|
||||
if (Strings.isEmpty(string))
|
||||
throw new ValueConverterException("Couldn't convert empty string to an int value.", node, null);
|
||||
try {
|
||||
String parseString = string;
|
||||
int radix = 10;
|
||||
if (parseString.startsWith("0x") || parseString.startsWith("0X")) {
|
||||
parseString = string.substring(2);
|
||||
radix=16;
|
||||
}
|
||||
if (parseString.startsWith("0b") || parseString.startsWith("0B")) {
|
||||
parseString = string.substring(2);
|
||||
radix=2;
|
||||
}
|
||||
return new BigInteger(parseString,radix);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ValueConverterException("Couldn't convert '" + string + "' to a BigInteger value.", node, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.xtext.sleigh.converter;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.eclipse.xtext.common.services.DefaultTerminalConverters;
|
||||
import org.eclipse.xtext.conversion.IValueConverter;
|
||||
import org.eclipse.xtext.conversion.ValueConverter;
|
||||
import org.eclipse.xtext.conversion.ValueConverterException;
|
||||
import org.eclipse.xtext.conversion.impl.INTValueConverter;
|
||||
import org.eclipse.xtext.nodemodel.INode;
|
||||
import org.eclipse.xtext.util.Strings;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
public class SleighValueConverter extends DefaultTerminalConverters {
|
||||
|
||||
@Inject
|
||||
private IntValueConverter hexValueConverter;
|
||||
|
||||
@ValueConverter(rule = "HEXVAL")
|
||||
public IValueConverter<BigInteger> HEXVAL() {
|
||||
return hexValueConverter;
|
||||
}
|
||||
|
||||
@Inject
|
||||
private IntValueConverter numValueConverter;
|
||||
|
||||
@ValueConverter(rule = "NUMVAL")
|
||||
public IValueConverter<BigInteger> NUMVAL() {
|
||||
return numValueConverter;
|
||||
}
|
||||
|
||||
@Inject
|
||||
private IntValueConverter binValueConverter;
|
||||
|
||||
@ValueConverter(rule = "BINVAL")
|
||||
public IValueConverter<BigInteger> BINVAL() {
|
||||
return binValueConverter;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,32 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.xtext.sleigh.generator
|
||||
|
||||
import org.eclipse.emf.ecore.resource.Resource
|
||||
import org.eclipse.xtext.generator.AbstractGenerator
|
||||
import org.eclipse.xtext.generator.IFileSystemAccess2
|
||||
import org.eclipse.xtext.generator.IGeneratorContext
|
||||
|
||||
/**
|
||||
* Generates code from your model files on save.
|
||||
*
|
||||
* See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#code-generation
|
||||
*/
|
||||
class SleighGenerator extends AbstractGenerator {
|
||||
|
||||
override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.xtext.sleigh.scoping
|
||||
|
||||
|
||||
import com.google.common.base.Function
|
||||
import com.google.common.base.Predicate
|
||||
import java.util.ArrayList
|
||||
import java.util.List
|
||||
import org.eclipse.emf.ecore.EObject
|
||||
import org.eclipse.emf.ecore.EReference
|
||||
import org.eclipse.xtext.naming.QualifiedName
|
||||
import org.eclipse.xtext.resource.IEObjectDescription
|
||||
import org.eclipse.xtext.scoping.IScope
|
||||
import org.eclipse.xtext.scoping.Scopes
|
||||
import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider
|
||||
import org.eclipse.xtext.scoping.impl.FilteringScope
|
||||
import org.eclipse.xtext.scoping.impl.ScopeBasedSelectable
|
||||
import org.eclipse.xtext.scoping.impl.SelectableBasedScope
|
||||
import ghidra.xtext.sleigh.sleigh.LOCALSYM
|
||||
import ghidra.xtext.sleigh.sleigh.aliasSym
|
||||
import ghidra.xtext.sleigh.sleigh.assignSym
|
||||
import ghidra.xtext.sleigh.sleigh.constraint
|
||||
import ghidra.xtext.sleigh.sleigh.constructor
|
||||
import ghidra.xtext.sleigh.sleigh.contextblock
|
||||
import ghidra.xtext.sleigh.sleigh.contextentry
|
||||
import ghidra.xtext.sleigh.sleigh.exportedSym
|
||||
import ghidra.xtext.sleigh.sleigh.exprSym
|
||||
import ghidra.xtext.sleigh.sleigh.globalLoc
|
||||
import ghidra.xtext.sleigh.sleigh.macrodef
|
||||
import ghidra.xtext.sleigh.sleigh.pexprSym
|
||||
import ghidra.xtext.sleigh.sleigh.rtlbody
|
||||
import ghidra.xtext.sleigh.sleigh.rtlmid
|
||||
import ghidra.xtext.sleigh.sleigh.statement
|
||||
import ghidra.xtext.sleigh.sleigh.xrtl
|
||||
|
||||
import static extension org.eclipse.xtext.EcoreUtil2.*
|
||||
|
||||
/**
|
||||
* This class contains custom scoping description.
|
||||
*
|
||||
* See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#scoping
|
||||
* on how and when to use it.
|
||||
*/
|
||||
public class SleighScopeProvider extends AbstractDeclarativeScopeProvider {
|
||||
|
||||
override getScope(EObject context, EReference ref) {
|
||||
//System.out.println(context.class.name + " - " + ref.name + " : ")
|
||||
var scope = super.getScope(context, ref)
|
||||
//System.out.println(" " + scope.toString)
|
||||
return scope
|
||||
}
|
||||
|
||||
def IScope scope_assignSym_symref(assignSym context, EReference eReference) {
|
||||
var localScope = context.eContainer.symbolsDefinedBefore(context)
|
||||
var cont = context.getContainerOfType(typeof(rtlbody));
|
||||
var superscope = super.getDelegate().getScope(cont, eReference)
|
||||
return createFilteredLocalScope(superscope, localScope, eReference)
|
||||
}
|
||||
|
||||
def IScope scope_exprSym_vnode(exprSym context, EReference eReference) {
|
||||
var localScope = context.eContainer.symbolsDefinedBefore(context)
|
||||
var cont = context.getContainerOfType(typeof(rtlbody));
|
||||
var superscope = super.getDelegate().getScope(cont, eReference)
|
||||
return createFilteredLocalScope(superscope, localScope, eReference)
|
||||
}
|
||||
|
||||
def IScope scope_exportedSym_symref(exportedSym context, EReference eReference) {
|
||||
var localScope = context.eContainer.symbolsDefinedBefore(context)
|
||||
var cont = context.getContainerOfType(typeof(rtlbody));
|
||||
var superscope = super.getDelegate().getScope(cont, eReference)
|
||||
createFilteredLocalScope(superscope, localScope, eReference)
|
||||
}
|
||||
|
||||
|
||||
def IScope scope_pexprSym_sym(pexprSym context, EReference eReference) {
|
||||
var localScope = context.eContainer.symbolsDefinedBefore(context)
|
||||
var cont = context.getContainerOfType(typeof(constructor));
|
||||
var superscope = super.getDelegate().getScope(cont, eReference)
|
||||
createFilteredLocalScope(superscope, localScope, eReference)
|
||||
}
|
||||
|
||||
|
||||
def IScope scope_constraint_sym(constraint context, EReference eReference) {
|
||||
var cont = context.getContainerOfType(typeof(constructor));
|
||||
var superscope = super.getDelegate().getScope(cont, eReference)
|
||||
var scope= createFilteredLocalScope(superscope, IScope.NULLSCOPE, eReference)
|
||||
scope
|
||||
}
|
||||
|
||||
def IScope scope_aliasSym_symref(aliasSym context, EReference eReference) {
|
||||
var cont = context.getContainerOfType(typeof(constructor));
|
||||
var localScope = printPieceScope(cont,IScope.NULLSCOPE);
|
||||
localScope
|
||||
}
|
||||
|
||||
def IScope scope_contextentry_lhs(contextentry context, EReference eReference) {
|
||||
var cont = context.getContainerOfType(typeof(constructor));
|
||||
var localScope = printPieceScope(cont,IScope.NULLSCOPE);
|
||||
var superscope = super.getDelegate().getScope(cont, eReference)
|
||||
createFilteredLocalScope(superscope, localScope, eReference)
|
||||
}
|
||||
|
||||
def IScope scope_globalLoc_tsym(globalLoc context, EReference eReference) {
|
||||
var cont = context.getContainerOfType(typeof(constructor));
|
||||
var localScope = printPieceScope(cont,IScope.NULLSCOPE);
|
||||
var superscope = super.getDelegate().getScope(cont, eReference)
|
||||
createFilteredLocalScope(superscope, localScope, eReference)
|
||||
}
|
||||
|
||||
def IScope createFilteredLocalScope(IScope supscope, IScope localScope, EReference eReference) {
|
||||
var filtscope = new FilteringScope(supscope, new Predicate<IEObjectDescription>() {
|
||||
override apply(IEObjectDescription input) {
|
||||
val sym = input.getEObjectOrProxy()
|
||||
var notAliasOrLocal = !((sym instanceof LOCALSYM) || (sym instanceof aliasSym))
|
||||
return notAliasOrLocal
|
||||
}
|
||||
});
|
||||
|
||||
// Do scope in reverse, aliasSyms are just and alias, choose global scope over alias
|
||||
// The global scope has all LOCALSYM and aliasSym filtered out.
|
||||
// This may not be the most efficient method, but works.
|
||||
// Also for LOCALSYM, a Global sym may shadow it. Not quite right
|
||||
// Should really be (LOCALSYM, Global(outerscope), AliasSym)
|
||||
var scope = SelectableBasedScope.createScope(localScope, new ScopeBasedSelectable(filtscope),
|
||||
eReference.getEReferenceType(), false)
|
||||
scope
|
||||
}
|
||||
|
||||
def dispatch IScope symbolsDefinedBefore(EObject context, EObject o) {
|
||||
context.eContainer.symbolsDefinedBefore(o)
|
||||
}
|
||||
|
||||
def dispatch IScope symbolsDefinedBefore(macrodef context, EObject o) {
|
||||
Scopes::scopeFor(
|
||||
context.args.args,
|
||||
context.symbolsDefinedBefore(o.eContainer)
|
||||
)
|
||||
}
|
||||
|
||||
def dispatch IScope symbolsDefinedBefore(constructor s, EObject o) {
|
||||
var scope = Scopes::scopeFor(s.eContents)
|
||||
printPieceScope(s,scope);
|
||||
}
|
||||
|
||||
def dispatch IScope symbolsDefinedBefore(contextblock s, EObject o) {
|
||||
var scope = Scopes::scopeFor(s.eContents, s.eContainer.symbolsDefinedBefore(o.eContainer))
|
||||
var cont = s.getContainerOfType(typeof(constructor))
|
||||
printPieceScope(cont,scope);
|
||||
}
|
||||
|
||||
def dispatch IScope symbolsDefinedBefore(rtlbody b, EObject o) {
|
||||
var scope = Scopes::scopeFor(
|
||||
b.body.statements.rtllist.variablesDeclaredBefore(o)
|
||||
)
|
||||
var cont = b.getContainerOfType(typeof(constructor));
|
||||
printPieceScope(cont,scope);
|
||||
}
|
||||
|
||||
def dispatch IScope symbolsDefinedBefore(rtlmid b, EObject o) {
|
||||
return symbolsDefinedBefore(b.eContainer, o);
|
||||
}
|
||||
|
||||
def dispatch IScope symbolsDefinedBefore(xrtl b, EObject o) {
|
||||
var syms = b.statements.rtllist.variablesDeclaredBefore(null);
|
||||
if (b.additionalStatements != null) {
|
||||
syms.addAll(b.additionalStatements.rtllist.variablesDeclaredBefore(null))
|
||||
}
|
||||
var scope = Scopes::scopeFor(syms)
|
||||
var cont = b.getContainerOfType(typeof(constructor));
|
||||
printPieceScope(cont,scope);
|
||||
}
|
||||
|
||||
// Create a scope for all ID symbols in printpiece
|
||||
def printPieceScope(constructor cont, IScope outerScope) {
|
||||
if (cont == null) return outerScope
|
||||
var vars = cont.variablesDeclaredIn()
|
||||
var q = QualifiedName.wrapper(new Function<aliasSym, String>() {
|
||||
|
||||
override apply(aliasSym input) {
|
||||
if (input == null) return null;
|
||||
input.sym
|
||||
}
|
||||
})
|
||||
var localScope = Scopes.scopeFor(vars, q, outerScope)
|
||||
localScope
|
||||
}
|
||||
|
||||
// things in context block must be in printpieces
|
||||
def private variablesDeclaredIn(constructor b) {
|
||||
var iter = b.print.printpieces.iterator;
|
||||
var List<aliasSym> list = new ArrayList<aliasSym>();
|
||||
while (iter.hasNext) {
|
||||
var piece = iter.next;
|
||||
if (piece.sym instanceof aliasSym) {
|
||||
list.add(piece.sym)
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
def private variablesDeclaredBefore(List<statement> list, EObject o) {
|
||||
var end = list.size - 1;
|
||||
if (o != null) {
|
||||
end = list.indexOf(o);
|
||||
}
|
||||
val sublist = list.subList(0, end + 1);
|
||||
var iter = sublist.iterator;
|
||||
var List<LOCALSYM> locList = new ArrayList<LOCALSYM>();
|
||||
while (iter.hasNext) {
|
||||
var obj = iter.next;
|
||||
if (obj instanceof statement) {
|
||||
var stmt = obj as statement;
|
||||
if (stmt.lhs != null && stmt.lhs.local != null && stmt.lhs.local.sym instanceof LOCALSYM) {
|
||||
locList.add(stmt.lhs.local.sym as LOCALSYM);
|
||||
}
|
||||
if (stmt.ldef != null && stmt.ldef.sym instanceof LOCALSYM) {
|
||||
locList.add(stmt.ldef.sym as LOCALSYM);
|
||||
}
|
||||
}
|
||||
}
|
||||
return locList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.xtext.sleigh.validation
|
||||
|
||||
|
||||
|
||||
import java.util.HashMap
|
||||
import java.util.HashSet
|
||||
import org.eclipse.xtext.validation.Check
|
||||
import ghidra.xtext.sleigh.sleigh.Model
|
||||
import ghidra.xtext.sleigh.sleigh.SleighPackage
|
||||
import ghidra.xtext.sleigh.sleigh.VARSYM
|
||||
import ghidra.xtext.sleigh.sleigh.constraint
|
||||
import ghidra.xtext.sleigh.sleigh.contextdef
|
||||
import ghidra.xtext.sleigh.sleigh.contextfielddef
|
||||
import ghidra.xtext.sleigh.sleigh.fielddef
|
||||
import ghidra.xtext.sleigh.sleigh.tokendef
|
||||
import ghidra.xtext.sleigh.sleigh.vardef
|
||||
import ghidra.xtext.sleigh.sleigh.varnodedef
|
||||
|
||||
import static extension org.eclipse.emf.ecore.util.EcoreUtil.*
|
||||
import static extension org.eclipse.xtext.EcoreUtil2.*
|
||||
|
||||
/**
|
||||
* This class contains custom validation rules.
|
||||
*
|
||||
* See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#validation
|
||||
*/
|
||||
class SleighValidator extends AbstractSleighValidator {
|
||||
|
||||
var HashMap<Object,HashMap<String,HashSet<Object>>> typeMap;
|
||||
|
||||
@Check
|
||||
def void checkModelInitialize(Model m) {
|
||||
// model should be validated each time before the sub objects
|
||||
// are validated, so initialize the cache
|
||||
typeMap = new HashMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a name entry to the set of names->definitions Object map
|
||||
*/
|
||||
def addNameEntryToSet(HashMap<String, HashSet<Object>> map, String name, Object other) {
|
||||
var HashSet<Object> set = map.get(name);
|
||||
if (set == null) {
|
||||
set = new HashSet<Object>();
|
||||
map.put(name,set);
|
||||
}
|
||||
set.add(other)
|
||||
}
|
||||
|
||||
@Check
|
||||
def void checkTokenNameIsUnique(fielddef f) {
|
||||
if (checkDuplicate(f)) {
|
||||
warning("token field names have to be unique", SleighPackage.eINSTANCE.getfielddef_Name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
def boolean checkDuplicate(fielddef f) {
|
||||
var type = typeof(tokendef)
|
||||
var HashMap<String,HashSet<Object>> map = typeMap.get(type);
|
||||
if (map == null) {
|
||||
map = new HashMap<String,HashSet<Object>>();
|
||||
typeMap.put(type,map);
|
||||
var defList = f.getRootContainer(true).getAllContentsOfType(type)
|
||||
var iter = defList.iterator;
|
||||
while (iter.hasNext()) {
|
||||
var def = iter.next();
|
||||
var fiter = def.getAllContentsOfType(typeof(fielddef)).iterator;
|
||||
while (fiter.hasNext()) {
|
||||
var other = fiter.next();
|
||||
var name = other.getName();
|
||||
addNameEntryToSet(map, name, other);
|
||||
}
|
||||
}
|
||||
}
|
||||
var HashSet<Object> set = map.get(f.name);
|
||||
return (set != null && set.size > 1)
|
||||
}
|
||||
|
||||
@Check
|
||||
def void checkTokenNameIsUnique(contextfielddef f) {
|
||||
if (checkDuplicate(f)) {
|
||||
warning("context field names have to be unique", SleighPackage.eINSTANCE.getcontextfielddef_Name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
def boolean checkDuplicate(contextfielddef f) {
|
||||
var type = typeof(contextdef)
|
||||
var HashMap<String,HashSet<Object>> map = typeMap.get(type);
|
||||
// if map hasn't been initialized, initialize it
|
||||
if (map == null) {
|
||||
map = new HashMap<String,HashSet<Object>>()
|
||||
typeMap.put(type,map)
|
||||
var defList = f.getRootContainer(true).getAllContentsOfType(type)
|
||||
var iter = defList.iterator
|
||||
while (iter.hasNext()) {
|
||||
var def = iter.next()
|
||||
var fiter = def.getAllContentsOfType(typeof(contextfielddef)).iterator
|
||||
while (fiter.hasNext()) {
|
||||
var other = fiter.next()
|
||||
var name = other.getName()
|
||||
addNameEntryToSet(map, name, other)
|
||||
}
|
||||
}
|
||||
}
|
||||
var HashSet<Object> set = map.get(f.name);
|
||||
return (set != null && set.size > 1)
|
||||
}
|
||||
|
||||
@Check
|
||||
def void checkTokenNameIsUnique(VARSYM v) {
|
||||
if (checkDuplicate(v)) {
|
||||
warning("var names have to be unique", SleighPackage.eINSTANCE.VARSYM_Name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
def boolean checkDuplicate(VARSYM v) {
|
||||
var type = typeof(varnodedef)
|
||||
var HashMap<String,HashSet<Object>> map = typeMap.get(type);
|
||||
if (map == null) {
|
||||
map = new HashMap<String,HashSet<Object>>();
|
||||
typeMap.put(type,map);
|
||||
var defList = v.getRootContainer(true).getAllContentsOfType(type)
|
||||
var iter = defList.iterator;
|
||||
while (iter.hasNext()) {
|
||||
var def = iter.next();
|
||||
var fiter = def.getAllContentsOfType(typeof(vardef)).iterator;
|
||||
while (fiter.hasNext()) {
|
||||
var other = fiter.next();
|
||||
var name = other.varname.name;
|
||||
addNameEntryToSet(map, name, other);
|
||||
}
|
||||
}
|
||||
}
|
||||
var HashSet<Object> set = map.get(v.name);
|
||||
return (set != null && set.size > 1)
|
||||
}
|
||||
|
||||
@Check
|
||||
def void checkWarnExpensiveOperation(constraint c) {
|
||||
var op = c.compareOp
|
||||
if (op == null || op.equals('=')) {
|
||||
return;
|
||||
}
|
||||
// TODO: Could check if the op token size is small, don't warn
|
||||
// For token sizes, this should not be so expensive 2,3
|
||||
|
||||
// comparison operations can be expensive
|
||||
warning("comparison can be expensive, and should be used sparingly", SleighPackage.eINSTANCE.getconstraint_CompareOp)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user