GP-1 Hard-wired DefaultLanguageService into SleighLanguageProvider and

eliminated single-ldef usage.
This commit is contained in:
ghidra1 2022-12-12 11:47:24 -05:00
parent 1a99e2518d
commit 12cb9010c5
13 changed files with 77 additions and 136 deletions

View file

@ -62,12 +62,26 @@ public class SleighLanguageProvider implements LanguageProvider {
public final static String LANGUAGE_DIR_NAME = "languages";
public SleighLanguageProvider() throws Exception {
createLanguages();
private static SleighLanguageProvider instance; // sleigh language provider instance (singleton)
public static synchronized SleighLanguageProvider getSleighLanguageProvider() {
if (instance == null) {
instance = new SleighLanguageProvider();
try {
instance.createLanguages();
}
catch (Exception e) {
Msg.error(SleighLanguageProvider.class,
"Sleigh language provider initiailization failed", e);
}
}
return instance;
}
public SleighLanguageProvider(ResourceFile ldefsFile) throws Exception {
createLanguages(ldefsFile);
/**
* Construct sleigh language provider (singleton)
*/
private SleighLanguageProvider() {
}
private void createLanguages() throws Exception {
@ -96,7 +110,11 @@ public class SleighLanguageProvider implements LanguageProvider {
@Override
public Language getLanguage(LanguageID languageId) {
return getNewSleigh(languageId);
Language language = languages.get(languageId);
if (language == null) {
language = getNewSleigh(languageId);
}
return language;
}
@Override
@ -104,7 +122,7 @@ public class SleighLanguageProvider implements LanguageProvider {
return languages.get(languageId) != null;
}
private Language getNewSleigh(LanguageID languageId) {
private SleighLanguage getNewSleigh(LanguageID languageId) {
SleighLanguageDescription description = descriptions.get(languageId);
SleighLanguage lang = languages.get(languageId);
if (lang == null) {

View file

@ -30,7 +30,8 @@ public interface LanguageProvider extends ExtensionPoint {
* Returns the language with the given name or null if no language has that name
*
* @param languageId the name of the language to be retrieved
* @return the {@link Language} with the given name
* @return the {@link Language} with the given name or null if not found
* @throws RuntimeException if language instantiation error occurs
*/
Language getLanguage(LanguageID languageId);

View file

@ -17,28 +17,22 @@ package ghidra.program.util;
import java.util.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import generic.jar.ResourceFile;
import ghidra.app.plugin.processors.sleigh.SleighLanguageProvider;
import ghidra.program.model.lang.*;
import ghidra.util.classfinder.ClassSearcher;
import ghidra.util.task.TaskBuilder;
/**
* Default Language service used gather up all the languages that were found
* during the class search (search was for language providers)
*/
public class DefaultLanguageService implements LanguageService, ChangeListener {
public class DefaultLanguageService implements LanguageService {
private static final Logger log = LogManager.getLogger(DefaultLanguageService.class);
private List<LanguageInfo> languageInfos = new ArrayList<>();
private HashMap<LanguageID, LanguageInfo> languageMap = new HashMap<>();
private boolean searchCompleted = false;
private static DefaultLanguageService languageService;
@ -50,59 +44,18 @@ public class DefaultLanguageService implements LanguageService, ChangeListener {
if (languageService == null) {
languageService = new DefaultLanguageService();
}
else if (!languageService.searchCompleted) {
languageService.searchForProviders();
}
return languageService;
}
/**
* Return the single instance of the DefaultLanguageService. If not already
* instantiated in the default mode, the factory will be lazy and limit
* it set of languages to those defined by the specified Sleigh language definition
* file (*.ldefs) or those provided by subsequent calls to this method.
* @param sleighLdefsFile sleigh language definition file
* @return language factory instance
* @throws Exception if an error occurs while parsing the specified definition file
*/
public static synchronized LanguageService getLanguageService(ResourceFile sleighLdefsFile)
throws Exception {
SleighLanguageProvider provider = new SleighLanguageProvider(sleighLdefsFile);
if (languageService == null) {
languageService = new DefaultLanguageService(provider);
}
languageService.addLanguages(provider);
return languageService;
}
private DefaultLanguageService() {
searchForProviders();
ClassSearcher.addChangeListener(this);
addLanguages(SleighLanguageProvider.getSleighLanguageProvider());
}
private DefaultLanguageService(LanguageProvider provider) {
addLanguages(provider);
}
private void searchForProviders() {
List<LanguageProvider> languageProviders =
ClassSearcher.getInstances(LanguageProvider.class);
searchCompleted = true;
//@formatter:off
TaskBuilder.withRunnable(monitor -> {
processProviders(languageProviders); // load and cache
})
.setTitle("Language Search")
.setCanCancel(false)
.setHasProgress(false)
.launchModal()
;
//@formatter:on
}
@Override
@Override
public Language getLanguage(LanguageID languageID) throws LanguageNotFoundException {
LanguageInfo info = languageMap.get(languageID);
if (info == null) {
@ -338,12 +291,6 @@ public class DefaultLanguageService implements LanguageService, ChangeListener {
throw new LanguageNotFoundException(processor);
}
private void processProviders(List<LanguageProvider> providers) {
for (LanguageProvider provider : providers) {
addLanguages(provider);
}
}
private void addLanguages(LanguageProvider provider) {
LanguageDescription[] lds = provider.getLanguageDescriptions();
for (LanguageDescription description : lds) {
@ -414,10 +361,4 @@ public class DefaultLanguageService implements LanguageService, ChangeListener {
}
}
@Override
public void stateChanged(ChangeEvent e) {
// NOTE: this is only intended to pickup new language providers
// which is not really supported with the introduction of Sleigh.
searchForProviders();
}
}

View file

@ -15,7 +15,7 @@
*/
package ghidra.app.plugin.assembler.sleigh;
import static org.junit.Assert.fail;
import static org.junit.Assert.*;
import java.util.*;
@ -29,13 +29,15 @@ import ghidra.app.plugin.assembler.sleigh.parse.*;
import ghidra.app.plugin.assembler.sleigh.sem.*;
import ghidra.app.plugin.assembler.sleigh.tree.AssemblyParseTreeNode;
import ghidra.app.plugin.assembler.sleigh.util.DbgTimer;
import ghidra.app.plugin.processors.sleigh.*;
import ghidra.app.plugin.processors.sleigh.SleighInstructionPrototype;
import ghidra.app.plugin.processors.sleigh.SleighLanguage;
import ghidra.app.util.PseudoInstruction;
import ghidra.generic.util.datastruct.TreeSetValuedTreeMap;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressOverflowException;
import ghidra.program.model.lang.*;
import ghidra.program.model.mem.*;
import ghidra.program.util.DefaultLanguageService;
import ghidra.util.Msg;
import ghidra.util.NumericUtilities;
@ -70,8 +72,7 @@ public abstract class AbstractAssemblyTest extends AbstractGenericTest {
public void setUp() throws Exception {
LanguageID langID = getLanguageID();
if (!setupLangID.equals(langID.toString())) {
SleighLanguageProvider provider = new SleighLanguageProvider();
lang = (SleighLanguage) provider.getLanguage(langID);
lang = getLanguage(langID);
context = new AssemblyDefaultContext(lang);
setupLangID = langID.toString();
}
@ -83,6 +84,11 @@ public abstract class AbstractAssemblyTest extends AbstractGenericTest {
//dbg.resetOutputStream(oldOutput).close();
}
private static SleighLanguage getLanguage(LanguageID langID) throws LanguageNotFoundException {
LanguageService languageService = DefaultLanguageService.getLanguageService();
return (SleighLanguage) languageService.getLanguage(langID);
}
/**
* Print a collection of parse trees to the debug printer
*

View file

@ -15,7 +15,7 @@
*/
package ghidra.app.plugin.assembler.sleigh;
import static org.junit.Assert.fail;
import static org.junit.Assert.*;
import java.util.*;
@ -72,7 +72,7 @@ public abstract class AssemblyTestCase extends AbstractGenericTest {
public void setUp() throws Exception {
LanguageID langID = getLanguageID();
if (!setupLangID.equals(langID.toString())) {
SleighLanguageProvider provider = new SleighLanguageProvider();
SleighLanguageProvider provider = SleighLanguageProvider.getSleighLanguageProvider();
lang = (SleighLanguage) provider.getLanguage(langID);
context = new AssemblyDefaultContext(lang);
setupLangID = langID.toString();

View file

@ -15,8 +15,7 @@
*/
package ghidra.app.plugin.assembler.sleigh;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.List;
@ -25,14 +24,13 @@ import org.junit.*;
import generic.test.AbstractGenericTest;
import ghidra.app.plugin.assembler.*;
import ghidra.app.plugin.processors.sleigh.SleighLanguageProvider;
import ghidra.program.database.ProgramDB;
import ghidra.program.database.util.ProgramTransaction;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressOverflowException;
import ghidra.program.model.lang.Language;
import ghidra.program.model.lang.LanguageID;
import ghidra.program.model.lang.*;
import ghidra.program.model.listing.*;
import ghidra.program.util.DefaultLanguageService;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskMonitor;
@ -44,9 +42,8 @@ public class PublicAPITest extends AbstractGenericTest {
@Before
public void setUp() throws Exception {
SleighLanguageProvider provider = new SleighLanguageProvider();
x86 = provider.getLanguage(new LanguageID("x86:LE:64:default"));
toy = provider.getLanguage(new LanguageID("Toy:BE:64:default"));
x86 = getLanguage("x86:LE:64:default");
toy = getLanguage("Toy:BE:64:default");
}
@After
@ -55,6 +52,11 @@ public class PublicAPITest extends AbstractGenericTest {
program.release(this);
}
}
private static Language getLanguage(String languageName) throws LanguageNotFoundException {
LanguageService languageService = DefaultLanguageService.getLanguageService();
return languageService.getLanguage(new LanguageID(languageName));
}
@Test
public void testADD0() throws AssemblySyntaxException, AssemblySemanticException {

View file

@ -36,7 +36,8 @@ import ghidra.app.plugin.processors.sleigh.template.ConstructTpl;
import ghidra.app.plugin.processors.sleigh.template.HandleTpl;
import ghidra.framework.Application;
import ghidra.framework.ApplicationConfiguration;
import ghidra.program.model.lang.LanguageID;
import ghidra.program.model.lang.*;
import ghidra.program.util.DefaultLanguageService;
import ghidra.util.Msg;
import ghidra.xml.XmlPullParser;
import ghidra.xml.XmlPullParserFactory;
@ -182,6 +183,11 @@ public class SolverTest {
AssemblyResolution e = AssemblyResolvedPatterns.fromString("ins:X7:X8", "Test", null);
assertEquals(e, res);
}
private static Language getLanguage(String languageName) throws LanguageNotFoundException {
LanguageService languageService = DefaultLanguageService.getLanguageService();
return languageService.getLanguage(new LanguageID(languageName));
}
public static Constructor findConstructor(String langId, String subtableName, String patternStr)
throws Exception {
@ -189,7 +195,7 @@ public class SolverTest {
Application.initializeApplication(new GhidraApplicationLayout(),
new ApplicationConfiguration());
}
SleighLanguageProvider provider = new SleighLanguageProvider();
SleighLanguageProvider provider = SleighLanguageProvider.getSleighLanguageProvider();
SleighLanguage lang = (SleighLanguage) provider.getLanguage(new LanguageID(langId));
AtomicReference<Constructor> consref = new AtomicReference<>();
SleighLanguages.traverseConstructors(lang, new ConstructorEntryVisitor() {
@ -213,7 +219,7 @@ public class SolverTest {
Application.initializeApplication(new GhidraApplicationLayout(),
new ApplicationConfiguration());
}
SleighLanguageProvider provider = new SleighLanguageProvider();
SleighLanguageProvider provider = SleighLanguageProvider.getSleighLanguageProvider();
SleighLanguage lang = (SleighLanguage) provider.getLanguage(new LanguageID(langId));
AtomicReference<Constructor> consref = new AtomicReference<>();
SleighLanguages.traverseConstructors(lang, new ConstructorEntryVisitor() {

View file

@ -24,9 +24,7 @@ import org.junit.*;
import db.*;
import db.buffers.BufferFile;
import generic.jar.ResourceFile;
import generic.test.AbstractGenericTest;
import ghidra.framework.Application;
import ghidra.framework.store.db.PrivateDatabase;
import ghidra.program.database.ProgramDB;
import ghidra.program.model.lang.*;
@ -292,14 +290,8 @@ public class FileBytesTest extends AbstractGenericTest {
program.release(this);
}
private Language getLanguage(String languageName) throws Exception {
ResourceFile ldefFile = Application.getModuleDataFile("Toy", "languages/toy.ldefs");
if (ldefFile != null) {
LanguageService languageService = DefaultLanguageService.getLanguageService(ldefFile);
Language language = languageService.getLanguage(new LanguageID(languageName));
return language;
}
throw new LanguageNotFoundException("Unsupported test language: " + languageName);
private static Language getLanguage(String languageName) throws LanguageNotFoundException {
LanguageService languageService = DefaultLanguageService.getLanguageService();
return languageService.getLanguage(new LanguageID(languageName));
}
}

View file

@ -25,9 +25,7 @@ import org.junit.*;
import db.DBConstants;
import db.DBHandle;
import generic.jar.ResourceFile;
import generic.test.AbstractGenericTest;
import ghidra.framework.Application;
import ghidra.program.database.ProgramDB;
import ghidra.program.database.map.AddressMapDB;
import ghidra.program.model.address.*;
@ -1024,14 +1022,9 @@ public class MemBlockDBTest extends AbstractGenericTest {
return addressFactory.getDefaultAddressSpace().getAddress(offset);
}
private Language getLanguage(String languageName) throws Exception {
ResourceFile ldefFile = Application.getModuleDataFile("Toy", "languages/toy.ldefs");
if (ldefFile != null) {
LanguageService languageService = DefaultLanguageService.getLanguageService(ldefFile);
Language language = languageService.getLanguage(new LanguageID(languageName));
return language;
}
throw new LanguageNotFoundException("Unsupported test language: " + languageName);
private static Language getLanguage(String languageName) throws LanguageNotFoundException {
LanguageService languageService = DefaultLanguageService.getLanguageService();
return languageService.getLanguage(new LanguageID(languageName));
}
}

View file

@ -20,9 +20,7 @@ import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import generic.jar.ResourceFile;
import generic.test.AbstractGenericTest;
import ghidra.framework.Application;
import ghidra.program.database.ProgramDB;
import ghidra.program.model.data.*;
import ghidra.program.model.lang.*;
@ -39,14 +37,9 @@ public class VariableUtilitiesTest extends AbstractGenericTest {
program = new ProgramDB("Test", language, compilerSpec, this);
}
private Language getLanguage(String languageName) throws Exception {
ResourceFile ldefFile = Application.getModuleDataFile("Toy", "languages/toy.ldefs");
if (ldefFile != null) {
LanguageService languageService = DefaultLanguageService.getLanguageService(ldefFile);
Language language = languageService.getLanguage(new LanguageID(languageName));
return language;
}
throw new LanguageNotFoundException("Unsupported test language: " + languageName);
private static Language getLanguage(String languageName) throws LanguageNotFoundException {
LanguageService languageService = DefaultLanguageService.getLanguageService();
return languageService.getLanguage(new LanguageID(languageName));
}
@Test