summaryrefslogtreecommitdiff
path: root/cmake/elfinfo/src
diff options
context:
space:
mode:
Diffstat (limited to 'cmake/elfinfo/src')
-rw-r--r--cmake/elfinfo/src/main/antlr4/Test1Lexer.g422
-rw-r--r--cmake/elfinfo/src/main/antlr4/Test1Parser.g423
-rw-r--r--cmake/elfinfo/src/main/java/io/trygvis/ld/CollectingErrorListener.java17
-rw-r--r--cmake/elfinfo/src/main/java/io/trygvis/ld/LdScript.java73
-rw-r--r--cmake/elfinfo/src/main/java/io/trygvis/ld/StringGnuLdVisitor.java59
-rw-r--r--cmake/elfinfo/src/main/test/io/trygvis/ld/FullScriptsTest.java34
-rw-r--r--cmake/elfinfo/src/main/test/io/trygvis/ld/InputSectionSpecTest.java38
-rw-r--r--cmake/elfinfo/src/main/test/io/trygvis/ld/NameTest.java50
-rw-r--r--cmake/elfinfo/src/main/test/io/trygvis/ld/SystemOutReportingErrorListener.java32
-rw-r--r--cmake/elfinfo/src/main/test/io/trygvis/ld/test1/Test1Test.java102
10 files changed, 421 insertions, 29 deletions
diff --git a/cmake/elfinfo/src/main/antlr4/Test1Lexer.g4 b/cmake/elfinfo/src/main/antlr4/Test1Lexer.g4
new file mode 100644
index 0000000..142229d
--- /dev/null
+++ b/cmake/elfinfo/src/main/antlr4/Test1Lexer.g4
@@ -0,0 +1,22 @@
+lexer grammar Test1Lexer;
+
+channels {
+ WHITESPACE_CHANNEL
+}
+
+NAME : [a-z]+;
+
+// Characters
+C_PLUS : '+';
+C_MINUS : '-';
+C_QUOTE : '"' -> skip, pushMode(STRING);
+
+//SPACE : [ ];
+
+WS
+ : [ \t\r\n]+ -> channel(WHITESPACE_CHANNEL)
+ ;
+
+mode STRING;
+STRING_ANY : ~'"';
+STRING_END_QUOTE : '"' -> skip, popMode;
diff --git a/cmake/elfinfo/src/main/antlr4/Test1Parser.g4 b/cmake/elfinfo/src/main/antlr4/Test1Parser.g4
new file mode 100644
index 0000000..affdfe5
--- /dev/null
+++ b/cmake/elfinfo/src/main/antlr4/Test1Parser.g4
@@ -0,0 +1,23 @@
+parser grammar Test1Parser;
+
+options {
+ tokenVocab = Test1Lexer;
+}
+
+name
+ : NAME
+ | STRING_ANY*
+ ;
+
+file
+ : stmt*
+ ;
+
+stmt
+ : expr
+ ;
+
+expr
+ : name C_PLUS name
+ | name C_MINUS name
+ ;
diff --git a/cmake/elfinfo/src/main/java/io/trygvis/ld/CollectingErrorListener.java b/cmake/elfinfo/src/main/java/io/trygvis/ld/CollectingErrorListener.java
new file mode 100644
index 0000000..968a02b
--- /dev/null
+++ b/cmake/elfinfo/src/main/java/io/trygvis/ld/CollectingErrorListener.java
@@ -0,0 +1,17 @@
+package io.trygvis.ld;
+
+import org.antlr.v4.runtime.BaseErrorListener;
+import org.antlr.v4.runtime.RecognitionException;
+import org.antlr.v4.runtime.Recognizer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CollectingErrorListener extends BaseErrorListener {
+ public final List<String> errors = new ArrayList<>();
+
+ public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
+ String s = line + ":" + charPositionInLine + " " + msg;
+ errors.add(s);
+ }
+}
diff --git a/cmake/elfinfo/src/main/java/io/trygvis/ld/LdScript.java b/cmake/elfinfo/src/main/java/io/trygvis/ld/LdScript.java
index f827a8b..f3c93ac 100644
--- a/cmake/elfinfo/src/main/java/io/trygvis/ld/LdScript.java
+++ b/cmake/elfinfo/src/main/java/io/trygvis/ld/LdScript.java
@@ -1,12 +1,14 @@
package io.trygvis.ld;
-import io.trygvis.ld.antlr.GnuLdBaseVisitor;
import io.trygvis.ld.antlr.GnuLdLexer;
import io.trygvis.ld.antlr.GnuLdParser;
+import io.trygvis.ld.antlr.GnuLdParserBaseVisitor;
import org.antlr.v4.runtime.ANTLRFileStream;
import org.antlr.v4.runtime.BufferedTokenStream;
+import org.antlr.v4.runtime.ConsoleErrorListener;
import org.antlr.v4.runtime.tree.ParseTreeProperty;
+import java.io.File;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashSet;
@@ -15,6 +17,12 @@ import java.util.Set;
public class LdScript {
+ public final List<MemoryArea> memoryAreas;
+
+ public LdScript(List<MemoryArea> memoryAreas) {
+ this.memoryAreas = memoryAreas;
+ }
+
public enum MemoryAttribute {
R, W, X, A, I,
}
@@ -76,39 +84,31 @@ public class LdScript {
String name;
}
- public static void main(String[] args) throws Exception {
- try {
- work(args);
- } catch (Exception e) {
- e.printStackTrace(System.out);
- }
- }
-
- private static void work(String[] args) throws Exception {
- args = new String[]{"lds/d2000.ld"};
+ public static LdScript parse(File path) throws Exception {
+ GnuLdLexer lexer = new GnuLdLexer(new ANTLRFileStream(path.getAbsolutePath()));
+ BufferedTokenStream tokens = new BufferedTokenStream(lexer);
+ GnuLdParser parser = new GnuLdParser(tokens);
+ parser.setBuildParseTree(true);
+ parser.removeErrorListeners();
+ ConsoleErrorListener errorListener = new ConsoleErrorListener();
+ parser.addErrorListener(errorListener);
+ CollectingErrorListener collectingErrorListener = new CollectingErrorListener();
+ parser.addErrorListener(collectingErrorListener);
- GnuLdLexer lexer = new GnuLdLexer(new ANTLRFileStream(args[0]));
- GnuLdParser parser = new GnuLdParser(new BufferedTokenStream(lexer));
+ GnuLdParser.FileContext file = parser.file();
-// ElfInfoGnuLdBaseListener listener = new ElfInfoGnuLdBaseListener();
-// parser.addParseListener(listener);
-//
-// parser.file();
-//
-// for (Section section : listener.sections) {
-// System.out.println("section.name = " + section.name);
-// }
+ if (parser.getNumberOfSyntaxErrors() > 0) {
+ throw new ParseErrorException(lexer, tokens, parser, collectingErrorListener.errors
+ );
+ }
ElfinfoGnuLdBaseVisitor visitor = new ElfinfoGnuLdBaseVisitor();
- visitor.visit(parser.file());
+ visitor.visit(file);
- System.out.println("--------------------------------------------------------");
- for (MemoryArea area : visitor.memoryAreas) {
- System.out.println(" " + area.name + "(" + area.prettyAttributes() + ") : ORIGIN = " + area.prettyOrigin() + ", LENGTH=" + area.prettyLength());
- }
+ return new LdScript(visitor.memoryAreas);
}
- private static class ElfinfoExprGnuLdBaseVisitor extends GnuLdBaseVisitor<ElfinfoExprGnuLdBaseVisitor> {
+ private static class ElfinfoExprGnuLdBaseVisitor extends GnuLdParserBaseVisitor<ElfinfoExprGnuLdBaseVisitor> {
private BigInteger value;
private ParseTreeProperty<BigInteger> es = new ParseTreeProperty<>();
@@ -227,7 +227,7 @@ public class LdScript {
}
@Override
- public ElfinfoExprGnuLdBaseVisitor visitExpAlign2(GnuLdParser.ExpAlign2Context ctx) {
+ public ElfinfoExprGnuLdBaseVisitor visitExpAlignK(GnuLdParser.ExpAlignKContext ctx) {
return visitChildren(ctx);
}
@@ -416,7 +416,7 @@ public class LdScript {
}
}
- private static class ElfinfoGnuLdBaseVisitor extends GnuLdBaseVisitor<ElfinfoGnuLdBaseVisitor> {
+ public static class ElfinfoGnuLdBaseVisitor extends GnuLdParserBaseVisitor<ElfinfoGnuLdBaseVisitor> {
public List<MemoryArea> memoryAreas = new ArrayList<>();
public List<Section> sections = new ArrayList<>();
@@ -473,6 +473,7 @@ public class LdScript {
if (!attributes.isEmpty()) {
throw new RuntimeException("Attributes for memory areas can only be attributesInverted (with '!') as the first character in a specification; foo(!rw), not foo(x!rw).");
}
+// String name = ctx.name().getText();
String name = ctx.NAME().getText();
System.out.println("ctx.ATTRIBUTE().getText() = " + name);
@@ -480,4 +481,18 @@ public class LdScript {
return visitChildren(ctx);
}
}
+
+ public static class ParseErrorException extends Exception {
+ public final GnuLdLexer lexer;
+ public final BufferedTokenStream tokens;
+ public final GnuLdParser parser;
+ public final List<String> errors;
+
+ public ParseErrorException(GnuLdLexer lexer, BufferedTokenStream tokens, GnuLdParser parser, List<String> errors) {
+ this.lexer = lexer;
+ this.tokens = tokens;
+ this.parser = parser;
+ this.errors = errors;
+ }
+ }
}
diff --git a/cmake/elfinfo/src/main/java/io/trygvis/ld/StringGnuLdVisitor.java b/cmake/elfinfo/src/main/java/io/trygvis/ld/StringGnuLdVisitor.java
new file mode 100644
index 0000000..a975497
--- /dev/null
+++ b/cmake/elfinfo/src/main/java/io/trygvis/ld/StringGnuLdVisitor.java
@@ -0,0 +1,59 @@
+package io.trygvis.ld;
+
+import io.trygvis.ld.antlr.GnuLdParserBaseVisitor;
+import io.trygvis.ld.antlr.GnuLdParser;
+import org.antlr.v4.runtime.tree.ParseTree;
+
+import java.util.List;
+
+class StringGnuLdVisitor extends GnuLdParserBaseVisitor<String> {
+
+// public static String parseName(GnuLdParser.NameContext ctx) {
+// return "";
+// }
+
+ /*
+ public static String parseName(GnuLdParser.NameContext ctx) {
+ StringGnuLdVisitor v = new StringGnuLdVisitor();
+ return v.visit(ctx);
+ }
+
+ private StringBuilder string = new StringBuilder();
+
+ @Override
+ public String visitNamePlain(GnuLdParser.NamePlainContext ctx) {
+ System.out.println("NameTest.visitNamePlain");
+ String s = ctx.NAME().getText();
+ string.append(s);
+ return s;
+ }
+
+// @Override
+// public String visitName_or_space(GnuLdParser.Name_or_spaceContext ctx) {
+// System.out.println("StringGnuLdBaseVisitor.visitName_or_space");
+//
+// TerminalNode name = ctx.NAME();
+// String s = name != null ? name.getText() : " ";
+// string.append(s);
+// return s;
+// }
+
+ @Override
+ public String visitNameQuoted(GnuLdParser.NameQuotedContext ctx) {
+ System.out.println("StringGnuLdBaseVisitor.visitNameQuoted");
+ List<ParseTree> children = ctx.children;
+ System.out.println("children.size()) = " + children.size());
+
+ String s = "";
+ for (int i = 1; i < children.size() - 1; i++) {
+ ParseTree part = children.get(i);
+ System.out.println("part.getText() = " + part.getText());
+ s += part.getText();
+ }
+
+ return s;
+//
+// return visitChildren(ctx);
+ }
+ */
+}
diff --git a/cmake/elfinfo/src/main/test/io/trygvis/ld/FullScriptsTest.java b/cmake/elfinfo/src/main/test/io/trygvis/ld/FullScriptsTest.java
new file mode 100644
index 0000000..1452f1f
--- /dev/null
+++ b/cmake/elfinfo/src/main/test/io/trygvis/ld/FullScriptsTest.java
@@ -0,0 +1,34 @@
+package io.trygvis.ld;
+
+import io.trygvis.ld.test1.Test1Test;
+import org.junit.Test;
+
+import java.io.File;
+
+public class FullScriptsTest {
+
+ @Test
+ public void testD2000() throws Exception {
+ fullScript2("lds/d2000.ld");
+ }
+
+ @Test
+ public void testStm32() throws Exception {
+ fullScript2("lds/stm32.ld");
+ }
+
+ private void fullScript2(String fileName) throws Exception {
+ try {
+ LdScript script = LdScript.parse(new File(fileName));
+
+ System.out.println("--------------------------------------------------------");
+ for (LdScript.MemoryArea area : script.memoryAreas) {
+ System.out.println(" " + area.name + "(" + area.prettyAttributes() + ") : ORIGIN = " + area.prettyOrigin() + ", LENGTH=" + area.prettyLength());
+ }
+ } catch (LdScript.ParseErrorException e) {
+ Test1Test.showTokens(e.tokens, e.parser);
+ System.out.println("Got " + e.errors.size() + " errors:");
+ e.errors.forEach(System.out::println);
+ }
+ }
+}
diff --git a/cmake/elfinfo/src/main/test/io/trygvis/ld/InputSectionSpecTest.java b/cmake/elfinfo/src/main/test/io/trygvis/ld/InputSectionSpecTest.java
new file mode 100644
index 0000000..2950061
--- /dev/null
+++ b/cmake/elfinfo/src/main/test/io/trygvis/ld/InputSectionSpecTest.java
@@ -0,0 +1,38 @@
+package io.trygvis.ld;
+
+import io.trygvis.ld.antlr.GnuLdLexer;
+import io.trygvis.ld.antlr.GnuLdParser;
+import org.antlr.v4.runtime.ANTLRInputStream;
+import org.antlr.v4.runtime.CommonTokenStream;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class InputSectionSpecTest {
+ @Test
+ public void testName1() throws Exception {
+ a("*(.text)", "(input_section_spec (input_section_spec_no_keep (wildcard_spec (wildcard_name *)) ( (file_name_list (wildcard_spec (wildcard_name .text))) )))");
+ }
+
+ // This doesn't feel right
+ @Test
+ public void testName2() throws Exception {
+ a("*(.text.*)", "(input_section_spec (input_section_spec_no_keep (wildcard_spec (wildcard_name *)) ( (file_name_list (file_name_list (wildcard_spec (wildcard_name .text.))) opt_comma (wildcard_spec (wildcard_name *))) )))");
+ }
+
+ @Test
+ public void testName3() throws Exception {
+ a("KEEP(*/init_high.cpp.obj(.isr_vectors))", "(input_section_spec KEEP ( (input_section_spec_no_keep (wildcard_spec (wildcard_name *)) / init_high.cpp.obj ( .isr_vectors) ))");
+ }
+
+ private void a(String input, String expected) {
+ GnuLdParser parser = new GnuLdParser(new CommonTokenStream(new GnuLdLexer(new ANTLRInputStream(input))));
+ parser.setBuildParseTree(true);
+ parser.removeErrorListeners();
+ parser.addErrorListener(new SystemOutReportingErrorListener(input));
+ GnuLdParser.Input_section_specContext input_section_spec = parser.input_section_spec();
+
+ assertEquals(input, expected, input_section_spec.toStringTree(parser));
+ assertEquals(0, parser.getNumberOfSyntaxErrors());
+ }
+}
diff --git a/cmake/elfinfo/src/main/test/io/trygvis/ld/NameTest.java b/cmake/elfinfo/src/main/test/io/trygvis/ld/NameTest.java
new file mode 100644
index 0000000..8d7502f
--- /dev/null
+++ b/cmake/elfinfo/src/main/test/io/trygvis/ld/NameTest.java
@@ -0,0 +1,50 @@
+package io.trygvis.ld;
+
+import io.trygvis.ld.antlr.GnuLdLexer;
+import io.trygvis.ld.antlr.GnuLdParser;
+import org.antlr.v4.runtime.ANTLRInputStream;
+import org.antlr.v4.runtime.CommonTokenStream;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class NameTest {
+ @Test
+ public void testName1() throws Exception {
+ a("foo", "foo");
+ }
+
+ @Test
+ public void testName2() throws Exception {
+ a("\"foo bar\"", "foo bar");
+ }
+
+ // TODO: not really expected
+ @Test
+ public void testName3() throws Exception {
+ a("\"foo bar\"", "foo bar");
+ }
+
+ private void a(String input, String expected) {
+ /*
+ CommonTokenStream tokens = new CommonTokenStream(new GnuLdLexer(new ANTLRInputStream(input)));
+ tokens.fill();
+ for (Object tok : tokens.getTokens()) {
+ System.out.println(tok);
+ }
+ GnuLdParser parser = new GnuLdParser(tokens);
+
+// StringGnuLdVisitor visitor = new StringGnuLdVisitor();
+ GnuLdParser.NameContext name = parser.name();
+
+ System.out.println("Input : |" + input + "|");
+ System.out.println("String tree: " + name.toStringTree(parser));
+
+// visitor.visit(name);
+ String actual = StringGnuLdVisitor.parseName(name);
+
+ parser.setTrace(true);
+ assertEquals(input + "\n" + name.toStringTree(), expected, actual);
+ */
+ }
+}
diff --git a/cmake/elfinfo/src/main/test/io/trygvis/ld/SystemOutReportingErrorListener.java b/cmake/elfinfo/src/main/test/io/trygvis/ld/SystemOutReportingErrorListener.java
new file mode 100644
index 0000000..c21a2e2
--- /dev/null
+++ b/cmake/elfinfo/src/main/test/io/trygvis/ld/SystemOutReportingErrorListener.java
@@ -0,0 +1,32 @@
+package io.trygvis.ld;
+
+import org.antlr.v4.runtime.BaseErrorListener;
+import org.antlr.v4.runtime.RecognitionException;
+import org.antlr.v4.runtime.Recognizer;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+public class SystemOutReportingErrorListener extends BaseErrorListener {
+ @Nullable
+ private final String input;
+
+ public SystemOutReportingErrorListener(@Nonnull String input) {
+ this.input = input;
+ }
+
+ public SystemOutReportingErrorListener() {
+ input = null;
+ }
+
+ public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
+ System.out.println("line " + line + ":" + charPositionInLine + " " + msg);
+ if (input != null) {
+ System.out.println(input);
+ for (int i = 1; i < charPositionInLine; i++) {
+ System.out.print(' ');
+ }
+ }
+ System.out.println('^');
+ }
+}
diff --git a/cmake/elfinfo/src/main/test/io/trygvis/ld/test1/Test1Test.java b/cmake/elfinfo/src/main/test/io/trygvis/ld/test1/Test1Test.java
new file mode 100644
index 0000000..ca3f49a
--- /dev/null
+++ b/cmake/elfinfo/src/main/test/io/trygvis/ld/test1/Test1Test.java
@@ -0,0 +1,102 @@
+package io.trygvis.ld.test1;
+
+import org.antlr.v4.runtime.ANTLRInputStream;
+import org.antlr.v4.runtime.BufferedTokenStream;
+import org.antlr.v4.runtime.CommonToken;
+import org.antlr.v4.runtime.CommonTokenStream;
+import org.antlr.v4.runtime.Parser;
+import org.antlr.v4.runtime.Token;
+import org.junit.Test;
+
+import javax.annotation.Nonnull;
+
+import static org.junit.Assert.assertEquals;
+
+public class Test1Test {
+
+ @Test
+ public void test1() {
+ name("foo", "foo");
+ }
+
+ @Test
+ public void test2() {
+ name("\"foo bar\"", "foo bar");
+ }
+
+ private void name(String input, String expected) {
+ Test1Parser parser = load(input);
+
+ Test1Parser.NameContext name = parser.name();
+ System.out.println("String tree: " + name.toStringTree(parser));
+
+ String actual = name.getText();
+ assertEquals(input + "\n" + name.toStringTree(parser), expected, actual);
+ }
+
+ @Test
+ public void expr1() {
+ expr("a + b", "(expr (name a) + (name b))");
+ }
+
+ @Test
+ public void expr2() {
+ expr("\"foo bar\" + b", "(expr (name f o o b a r) + (name b))");
+ }
+
+ @Test
+ public void expr3() {
+ expr("\n\n\r\n\t\"foo bar\" + b\r\r\t", "(expr (name f o o b a r) + (name b))");
+ }
+
+ private void expr(String input, String expected) {
+ Test1Parser parser = load(input);
+
+ Test1Parser.ExprContext expr = parser.expr();
+ String stringTree = expr.toStringTree(parser);
+
+ assertEquals(expected, stringTree);
+ }
+
+ @Nonnull
+ private Test1Parser load(String input) {
+ System.out.println("Input : |" + input + "|");
+ CommonTokenStream tokens = new CommonTokenStream(new Test1Lexer(new ANTLRInputStream(input)));
+ Test1Parser parser = new Test1Parser(tokens);
+ parser.setBuildParseTree(true);
+ parser.setTrace(true);
+
+ tokens.fill();
+ showTokens(tokens, parser);
+ return parser;
+ }
+
+ public static void showTokens(BufferedTokenStream tokens, Parser parser) {
+ for (Token tok : tokens.getTokens()) {
+ String s;
+ if (tok instanceof CommonToken) {
+ CommonToken t = (CommonToken) tok;
+
+ String channelStr = "";
+ if (t.getChannel() > 0) {
+ channelStr = ",channel=" + t.getChannel();
+ }
+
+ String txt = t.getText();
+ if (txt != null) {
+ txt = txt.replace("\n", "\\n");
+ txt = txt.replace("\r", "\\r");
+ txt = txt.replace("\t", "\\t");
+ } else {
+ txt = "<no text>";
+ }
+
+ String type = parser.getVocabulary().getDisplayName(t.getType());
+ s = "[@" + t.getTokenIndex() + "," + t.getStartIndex() + ":" + t.getStopIndex() + "=\'" + txt + "\',<" + type + ">" + channelStr + "," + t.getLine() + ":" + t.getCharPositionInLine() + "]";
+ } else {
+ s = tok.toString();
+ }
+ System.out.println(s);
+ }
+ }
+}