GT-113_emteere Adding initial SleighEditor to public version.

This commit is contained in:
emteere 2019-06-11 17:18:52 -04:00 committed by ghidra1
parent dd15435371
commit 1779fdd94d
46 changed files with 6060 additions and 0 deletions

6
.gitignore vendored
View File

@ -62,3 +62,9 @@ Release
.project
.classpath
.settings/
# Ignore XTEXT generated dirs/files
*/*/*/*/xtend-gen
*/*/*/*/src-gen
*/*/*/*/model/generated
*/*/*/*/test-bin

View File

@ -0,0 +1,42 @@
##VERSION: 2.0
##MODULE IP: BSD
##MODULE IP: Eclipse Public License 1.0
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.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.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.properties||GHIDRA||||END|
ghidra.xtext.sleigh.ui/META-INF/MANIFEST.MF||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/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/META-INF/MANIFEST.MF||GHIDRA||||END|
ghidra.xtext.sleigh/build.properties||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|

View File

@ -0,0 +1,2 @@
bin.includes = feature.xml,\
category.xml

View File

@ -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="Sleigh Editor"/>
</site>

View File

@ -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">
<license url="">
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
* 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 &quot;AS IS&quot; 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>

View File

@ -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: My Company
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-11
Export-Package: ghidra.xtext.sleigh.ide.contentassist.antlr,
ghidra.xtext.sleigh.ide.contentassist.antlr.internal

View File

@ -0,0 +1,6 @@
source.. = src/,\
src-gen/,\
xtend-gen/
bin.includes = .,\
META-INF/
bin.excludes = **/*.xtend

View File

@ -0,0 +1,23 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
* 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 &quot;AS IS&quot; 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 {
}

View File

@ -0,0 +1,32 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
* 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 &quot;AS IS&quot; 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))
}
}

View File

@ -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: My Company
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-11
Export-Package: ghidra.xtext.sleigh.tests;x-internal=true

View File

@ -0,0 +1,6 @@
source.. = src/,\
src-gen/,\
xtend-gen/
bin.includes = .,\
META-INF/
bin.excludes = **/*.xtend

View File

@ -0,0 +1,171 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
* 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 &quot;AS IS&quot; 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
}
}

View File

@ -0,0 +1,89 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
* 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 &quot;AS IS&quot; 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'."
)
}
}

View File

@ -0,0 +1,194 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
* 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 &quot;AS IS&quot; 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
}
}

View File

@ -0,0 +1,301 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
* 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 &quot;AS IS&quot; 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)
]
}
}

View File

@ -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: My Company
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-11
Export-Package: ghidra.xtext.sleigh.ui.tests;x-internal=true

View File

@ -0,0 +1,6 @@
source.. = src/,\
src-gen/,\
xtend-gen/
bin.includes = .,\
META-INF/
bin.excludes = **/*.xtend

View File

@ -0,0 +1,26 @@
Manifest-Version: 1.0
Automatic-Module-Name: ghidra.xtext.sleigh.ui
Bundle-ManifestVersion: 2
Bundle-Name: ghidra.xtext.sleigh.ui
Bundle-Vendor: My Company
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
Import-Package: org.apache.log4j
Bundle-RequiredExecutionEnvironment: JavaSE-11
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

View File

@ -0,0 +1,7 @@
source.. = src/,\
src-gen/,\
xtend-gen/
bin.includes = .,\
META-INF/,\
plugin.xml
bin.excludes = **/*.xtend

View File

@ -0,0 +1,513 @@
<?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>
</plugin>

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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);
}
}
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -0,0 +1,53 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
* 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 &quot;AS IS&quot; 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
}
}

View File

@ -0,0 +1,24 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
* 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 &quot;AS IS&quot; 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 {
}

View File

@ -0,0 +1,83 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
* 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 &quot;AS IS&quot; 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'
}
}

View File

@ -0,0 +1,248 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
* 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 &quot;AS IS&quot; 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)
}
}
}

View File

@ -0,0 +1,82 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
* 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 &quot;AS IS&quot; 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")
}
}
}
}
}

View File

@ -0,0 +1,323 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
* 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 &quot;AS IS&quot; 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;
}
}

View File

@ -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:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;resources&gt;&#10;&lt;item path=&quot;/ghidra.xtext.sleigh&quot; type=&quot;4&quot;/&gt;&#10;&lt;item path=&quot;/ghidra.xtext.sleigh.ide&quot; type=&quot;4&quot;/&gt;&#10;&lt;item path=&quot;/ghidra.xtext.sleigh.ui&quot; type=&quot;4&quot;/&gt;&#10;&lt;item path=&quot;/ghidra.xtext.sleigh.feature&quot; type=&quot;4&quot;/&gt;&#10;&lt;item path=&quot;/ghidra.xtext.sleigh.tests&quot; type=&quot;4&quot;/&gt;&#10;&lt;item path=&quot;/ghidra.xtext.sleigh.ui.tests&quot; type=&quot;4&quot;/&gt;&#10;&lt;item path=&quot;/ghidra.xtext.sleigh.tests&quot; type=&quot;4&quot;/&gt;&#10;&lt;item path=&quot;/ghidra.xtext.sleigh.ui.tests&quot; type=&quot;4&quot;/&gt;&#10;;&lt;/resources&gt;}"/>
<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>

View File

@ -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>

View File

@ -0,0 +1,31 @@
Manifest-Version: 1.0
Automatic-Module-Name: ghidra.xtext.sleigh
Bundle-ManifestVersion: 2
Bundle-Name: ghidra.xtext.sleigh
Bundle-Vendor: My Company
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-11
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

View File

@ -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

View File

@ -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>

View File

@ -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"
}
}
}
}

View File

@ -0,0 +1,23 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
* 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 &quot;AS IS&quot; 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 {
}

View File

@ -0,0 +1,27 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
* 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 &quot;AS IS&quot; 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()
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,32 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
* 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 &quot;AS IS&quot; 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) {
}
}

View File

@ -0,0 +1,237 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
* 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 &quot;AS IS&quot; 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;
}
}

View File

@ -0,0 +1,169 @@
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
* 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 &quot;AS IS&quot; 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)
}
}