Commits

Jason S committed d4c5333

rudimentary bitcode file parsing implemented

Comments (0)

Files changed (7)

+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
+syntax: glob
+bin/**
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>jllvmbc</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
 jllvmbc -- Java LLVM bitcode library
 Copyright 2012 Jason M. Sachs
 
+This attempts to provide utility classes for reading and writing the
+LLVM bitcode format as described in http://llvm.org/docs/BitCodeFormat.html
+
 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

src/org/bitbucket/jason_s/jllvm/BitcodeHandler.java

+package org.bitbucket.jason_s.jllvm;
+
+public interface BitcodeHandler {
+
+}

src/org/bitbucket/jason_s/jllvm/BitcodeReader.java

+package org.bitbucket.jason_s.jllvm;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileChannel.MapMode;
+
+public class BitcodeReader {
+	public static void main(String[] args) {
+		try {
+			new BitcodeReader().read(new FileInputStream(args[0]));
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+
+	private void read(FileInputStream is) throws IOException {
+		FileChannel fc = is.getChannel();
+		MappedByteBuffer bbuf = fc.map(MapMode.READ_ONLY, 0, fc.size());
+		bbuf.order(ByteOrder.LITTLE_ENDIAN);
+		int magic = bbuf.getInt();	
+		if (magic == 0x0B17C0DE)
+		{
+			int version = bbuf.getInt();
+			int ofs = bbuf.getInt();
+			int size = bbuf.getInt();
+			int cputype = bbuf.getInt();
+			ByteBuffer wrapped = bbuf.duplicate();
+			wrapped.position(ofs).limit(ofs+size);
+			decode(wrapped);
+		}
+		System.out.println();
+	}
+
+	interface Item
+	{
+		
+	}
+	
+	private void decode(ByteBuffer wrapped) {
+		byte b0 = wrapped.get();
+		byte b1 = wrapped.get();
+		if (b0 != 0x42 || b1 != 0x43)
+			throw new IllegalStateException();
+		short asmn = wrapped.getShort();
+		if (asmn != (short)0xC0DE)
+			throw new IllegalStateException();
+		System.out.println();
+		readItem(new BitReader(wrapped), new AbbrevContext(2));
+	}
+
+	static class AbbrevContext
+	{
+		final private int abbrevLength;
+		public AbbrevContext(int abbrevLength)
+		{
+			this.abbrevLength = abbrevLength;
+		}
+		public int getAbbrevLength() { return this.abbrevLength; }
+
+		public Item readItem(BitReader bitReader) {
+			final int abbrevID = bitReader.readBits(getAbbrevLength());
+			switch (abbrevID)
+			{
+			case 0: // END_BLOCK
+				return readEndBlock(bitReader);
+			case 1: // ENTER_SUBBLOCK
+				return readSubBlock(bitReader);
+			case 2: // DEFINE_ABBREV
+				return readDefineAbbrev(bitReader);
+			case 3: // UNABBREV_RECORD
+				return readUnabbrevRecord(bitReader);
+				
+				
+			}
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+
+		private Item readEndBlock(BitReader bitReader) {
+			bitReader.align32();
+			System.out.println("end block");
+			return null;
+		}
+		private Item readDefineAbbrev(BitReader bitReader) {
+			int numabbr = bitReader.readVBR(5);
+			for (int i = 0; i < numabbr; ++i)
+			{
+				boolean literal = bitReader.readBits64(1) == 1;
+				if (literal)
+				{
+					int litvalue = bitReader.readVBR(8);
+				}
+				else
+				{
+					int encoding = bitReader.readBits(3);
+					switch (encoding)
+					{
+					case 1: // FIXED
+					{
+						int width = bitReader.readVBR(5);
+					}
+					break;
+					case 2: // VBR
+					{
+						int width = bitReader.readVBR(5);
+					}
+						break;
+					case 3: // ARRAY
+						break;
+					case 4: // CHAR6
+						break;
+					case 5: // BLOB
+						break;
+					default:
+						throw new IllegalStateException("unknown ABBREV encoding "+encoding);
+					}
+				}
+			}
+			return null;
+		}
+		private Item readUnabbrevRecord(BitReader bitReader) {
+			int code = bitReader.readVBR(6);
+			int numops = bitReader.readVBR(6);
+			for (int i = 0; i < numops; ++i)
+			{
+				int op = bitReader.readVBR(6);
+			}
+			return null;
+		}
+		private Item readSubBlock(BitReader bitReader) {
+			int blockID = bitReader.readVBR(8);
+			int abbrlen = bitReader.readVBR(4);
+			bitReader.align32();
+			int blocklen = bitReader.readVBR(32);
+			System.out.println("block "+blockID+" abbrlen="+abbrlen+" blocklen="+blocklen);
+			
+			AbbrevContext subcontext = new AbbrevContext(abbrlen);
+			int pos = bitReader.position();
+			while (bitReader.position() < pos+blocklen*4)
+			{
+				Item item = subcontext.readItem(bitReader);
+			}
+			return null;
+		}
+	}
+	
+	static class BitReader
+	{
+		final private ByteBuffer bbuf;
+		long x = 0;
+		int nbits = 0;
+		int nread = 0;
+		
+		public BitReader(ByteBuffer bbuf) { this.bbuf = bbuf; }
+
+		public int position() { return this.nread; }
+
+		public long readVBRLong(int n) {
+			long x = 0;
+			int shift = 0;
+			while (true)
+			{
+				long xi = readBits64(n);
+				long mask = 1 << (n-1);
+				x |= (xi & (mask-1)) << shift;
+				if ((xi & mask) == 0)
+					return x;
+				shift += (n-1);					
+			}
+		}
+		public int readVBR(int n) { return (int) readVBRLong(n); }
+
+		public int readBits(int n) { return (int) readBits64(n); }
+		public long readBits64(int n) {
+			while (this.nbits < n)
+				fetchByte();
+			long result = this.x & ((1L << n) - 1);
+			this.x >>>= n;
+			this.nbits -= n;
+			return result;
+		}
+
+		private void fetchByte() {
+			long b = this.bbuf.get() & 0xff;
+			this.x |= b << this.nbits;
+			this.nbits += 8;		
+			++this.nread;
+		}
+
+		public void align32() {
+			while ((this.nread & 3) != 0)
+			{
+				this.bbuf.get();
+				++this.nread;
+			}
+			this.x = 0;
+			this.nbits = 0;
+		}
+	}
+	
+	private void readItem(BitReader bitReader, AbbrevContext ctx) {
+		ctx.readItem(bitReader);
+	}
+}

src/org/bitbucket/jason_s/jllvm/Main.java

+package org.bitbucket.jason_s.jllvm;
+
+public class Main {
+
+}