aboutsummaryrefslogtreecommitdiff
path: root/java/src/main/java/io/trygvis/ld/ElfinfoGnuLdListener.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/main/java/io/trygvis/ld/ElfinfoGnuLdListener.java')
-rw-r--r--java/src/main/java/io/trygvis/ld/ElfinfoGnuLdListener.java170
1 files changed, 170 insertions, 0 deletions
diff --git a/java/src/main/java/io/trygvis/ld/ElfinfoGnuLdListener.java b/java/src/main/java/io/trygvis/ld/ElfinfoGnuLdListener.java
new file mode 100644
index 0000000..fe40547
--- /dev/null
+++ b/java/src/main/java/io/trygvis/ld/ElfinfoGnuLdListener.java
@@ -0,0 +1,170 @@
+package io.trygvis.ld;
+
+import io.trygvis.ld.antlr.GnuLdParser;
+import io.trygvis.ld.antlr.GnuLdParserBaseListener;
+import org.antlr.v4.runtime.tree.ParseTreeProperty;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+class ElfinfoGnuLdListener extends GnuLdParserBaseListener {
+ public List<LdLoader.MemoryArea> memoryAreas = new ArrayList<>();
+
+ private final ParseTreeProperty<BigInteger> expr = new ParseTreeProperty<>();
+
+ @Override
+ public void exitExpInt(GnuLdParser.ExpIntContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.exitExpInt: ctx.INT().getText() = " + ctx.INT().getText());
+ expr.put(ctx, ElfinfoExprVisitor.parseInt(ctx.INT().getText()));
+ }
+
+ @Override
+ public void exitExpSub(GnuLdParser.ExpSubContext ctx) {
+ BigInteger a = expr.get(ctx.exp(0));
+ BigInteger b = expr.get(ctx.exp(1));
+ BigInteger x = a.subtract(b);
+ expr.put(ctx, x);
+ }
+
+ @Override
+ public void exitExpAdd(GnuLdParser.ExpAddContext ctx) {
+ BigInteger a = expr.get(ctx.exp(0));
+ BigInteger b = expr.get(ctx.exp(1));
+ BigInteger x = a.add(b);
+ expr.put(ctx, x);
+ }
+
+ @Override
+ public void exitExpName(GnuLdParser.ExpNameContext ctx) {
+ expr.put(ctx, BigInteger.ZERO);
+ }
+
+ @Override
+ public void exitExpAddr(GnuLdParser.ExpAddrContext ctx) {
+ expr.put(ctx, BigInteger.ZERO);
+ }
+
+ @Override
+ public void exitExpSizeof(GnuLdParser.ExpSizeofContext ctx) {
+ expr.put(ctx, BigInteger.ZERO);
+ }
+
+ @Override
+ public void exitExpLengthExp(GnuLdParser.ExpLengthExpContext ctx) {
+ LdLoader.MemoryArea ma = getMemoryArea(ctx.NAME().getText());
+// System.out.println("ma.length = " + ma.length);
+ expr.put(ctx, ma.length);
+ }
+
+ @Override
+ public void exitExpOrigin(GnuLdParser.ExpOriginContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.exitExpOrigin: " + ctx.getText());
+ LdLoader.MemoryArea ma = getMemoryArea(ctx.NAME().getText());
+// System.out.println("ma.origin = " + ma.origin);
+ expr.put(ctx, ma.origin);
+ }
+
+ private LdLoader.MemoryArea getMemoryArea(String name) {
+ LdLoader.MemoryArea m = null;
+ for (LdLoader.MemoryArea ma : memoryAreas) {
+ if (ma.name.equals(name)) {
+ m = ma;
+ }
+ }
+ if (m == null) {
+ throw new RuntimeException("No such memory area: " + name);
+ }
+ return m;
+ }
+
+ @Override
+ public void enterMustbe_exp(GnuLdParser.Mustbe_expContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.enterMustbe_exp");
+ }
+
+ @Override
+ public void exitMustbe_exp(GnuLdParser.Mustbe_expContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.exitMustbe_exp");
+
+ expr.put(ctx, expr.get(ctx.exp()));
+ }
+
+
+ @Override
+ public void enterOrigin_spec(GnuLdParser.Origin_specContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.enterOrigin_spec");
+ }
+
+ @Override
+ public void exitOrigin_spec(GnuLdParser.Origin_specContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.exitOrigin_spec");
+ }
+
+ @Override
+ public void enterLength_spec(GnuLdParser.Length_specContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.enterLength_spec");
+ }
+
+ @Override
+ public void exitLength_spec(GnuLdParser.Length_specContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.exitLength_spec");
+ }
+
+ @Override
+ public void enterMemory_spec(GnuLdParser.Memory_specContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.enterMemory_spec");
+ }
+
+ @Override
+ public void exitMemory_spec(GnuLdParser.Memory_specContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.exitMemory_spec");
+ LdLoader.MemoryArea ma = new LdLoader.MemoryArea();
+ ma.name = ctx.NAME().getText();
+ ma.attributes = attributes;
+// System.out.println("ctx.origin_spec() = " + ctx.origin_spec());
+ ma.origin = expr.get(ctx.origin_spec().mustbe_exp());
+ ma.length = expr.get(ctx.length_spec().mustbe_exp());
+ System.out.println(ma);
+ memoryAreas.add(ma);
+ }
+
+ LdLoader.MemoryAttribute attribute;
+ boolean attributesInverted;
+ Set<LdLoader.MemoryAttribute> attributes;
+
+ @Override
+ public void exitAttributes_opt(GnuLdParser.Attributes_optContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.exitAttributes_opt");
+ attributes = new HashSet<>();
+ }
+
+ @Override
+ public void enterAttributeInverted(GnuLdParser.AttributeInvertedContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.enterAttributeInverted");
+
+ 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);
+
+ attributesInverted = true;
+ }
+
+ @Override
+ public void enterAttributeNormal(GnuLdParser.AttributeNormalContext ctx) {
+// System.out.println("ElfinfoGnuLdListener.enterAttributeNormal");
+
+ String name = ctx.NAME().getText();
+// System.out.println("ctx.ATTRIBUTE().getText() = " + name);
+ for (int i = 0; i < name.length(); i++) {
+ attribute = LdLoader.MemoryAttribute.valueOf(String.valueOf(Character.toUpperCase(name.charAt(i))));
+ attributes.add(attribute);
+ }
+ attributesInverted = false;
+ }
+}