package io.trygvis.ld; import io.trygvis.ld.antlr.GnuLdLexer; import io.trygvis.ld.antlr.GnuLdParser; import org.antlr.v4.runtime.ANTLRFileStream; import org.antlr.v4.runtime.BufferedTokenStream; import org.antlr.v4.runtime.ConsoleErrorListener; import java.io.File; import java.math.BigInteger; import java.util.List; import java.util.Set; public class LdLoader { public final List memoryAreas; public LdLoader(List memoryAreas) { this.memoryAreas = memoryAreas; } public enum MemoryAttribute { R, W, X, A, I, } public static class MemoryArea { private final BigInteger MEGA = BigInteger.valueOf(1024 * 1024); private final BigInteger KILO = BigInteger.valueOf(1024); String name; BigInteger origin; BigInteger length; Set attributes; @Override public String toString() { return "MemoryArea{" + "name='" + name + '\'' + ", origin=" + origin + ", length=" + length + ", attributes='" + attributes + '\'' + '}'; } public String prettyOrigin() { if (origin == null) { return ""; } String hex = origin.toString(16); return "0x" + ("00000000").substring(0, 8 - hex.length()) + hex; } public String prettyLength() { if (length == null) { return ""; } if (length.compareTo(MEGA) >= 0 && length.mod(MEGA).equals(BigInteger.ZERO)) { return length.divide(MEGA) + "M"; } if (length.compareTo(KILO) >= 0 && length.mod(KILO).equals(BigInteger.ZERO)) { return length.divide(KILO) + "k"; } return String.valueOf(length); } public String prettyAttributes() { String s = ""; for (MemoryAttribute attribute : attributes) { s += attribute.name().toLowerCase(); } return s; } } public static LdLoader load(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); ElfinfoGnuLdListener listener = new ElfinfoGnuLdListener(); parser.addParseListener(listener); GnuLdParser.FileContext file = parser.file(); if (parser.getNumberOfSyntaxErrors() > 0) { throw new ParseErrorException(lexer, tokens, parser, collectingErrorListener.errors ); } // ElfinfoGnuLdVisitor visitor = new ElfinfoGnuLdVisitor(); // visitor.visit(file); // return new LdLoader(visitor.memoryAreas); return new LdLoader(listener.memoryAreas); } public static class ParseErrorException extends Exception { public final GnuLdLexer lexer; public final BufferedTokenStream tokens; public final GnuLdParser parser; public final List errors; public ParseErrorException(GnuLdLexer lexer, BufferedTokenStream tokens, GnuLdParser parser, List errors) { this.lexer = lexer; this.tokens = tokens; this.parser = parser; this.errors = errors; } } }