You are viewing a plain text version of this content. The canonical link for it is here.
Posted to kato-commits@incubator.apache.org by cc...@apache.org on 2009/03/16 16:41:41 UTC

svn commit: r754943 [3/3] - in /incubator/kato/trunk/import/org.apache.kato.common: ./ .settings/ src/ src/com/ src/com/ibm/ src/com/ibm/dtfj/ src/com/ibm/dtfj/addressspace/ src/com/ibm/dtfj/binaryreaders/ src/com/ibm/dtfj/corereaders/

Added: incubator/kato/trunk/import/org.apache.kato.common/src/com/ibm/dtfj/corereaders/NewElfDump.java
URL: http://svn.apache.org/viewvc/incubator/kato/trunk/import/org.apache.kato.common/src/com/ibm/dtfj/corereaders/NewElfDump.java?rev=754943&view=auto
==============================================================================
--- incubator/kato/trunk/import/org.apache.kato.common/src/com/ibm/dtfj/corereaders/NewElfDump.java (added)
+++ incubator/kato/trunk/import/org.apache.kato.common/src/com/ibm/dtfj/corereaders/NewElfDump.java Mon Mar 16 16:41:40 2009
@@ -0,0 +1,1716 @@
+/*******************************************************************************
+ * 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
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+package com.ibm.dtfj.corereaders;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.TreeMap;
+import java.util.Vector;
+
+/**
+ * struct and constant reference: /usr/include/elf.h
+ */
+public class NewElfDump extends CoreReaderSupport {
+	private static final int ELF_NOTE_HEADER_SIZE = 12; // 3 32-bit words
+	private final static int EI_NIDENT = 16;
+	private final static int ELF_PRARGSZ = 80;
+
+	private final static int ELFCLASS32 = 1;
+	private final static int ELFCLASS64 = 2;
+
+	private final static int ELFDATA2LSB = 1;
+	private final static int ELFDATA2MSB = 2;
+
+	//private final static int ARCH_SPARC = 2;
+	private final static int ARCH_IA32 = 3;
+	private final static int ARCH_PPC32 = 20;
+	private final static int ARCH_PPC64 = 21;
+	private final static int ARCH_S390 = 22;
+	private final static int ARCH_IA64 = 50;
+	private final static int ARCH_AMD64 = 62;
+	
+	private final static int DT_NULL = 0;
+	private final static int DT_DEBUG = 21;
+
+    private static final int NT_PRSTATUS = 1; // prstatus_t
+    //private static final int NT_PRFPREG  = 2; // prfpregset_t
+    private static final int NT_PRPSINFO = 3; // prpsinfo_t
+    //private static final int NT_TASKSTRUCT = 4;
+    private static final int NT_AUXV = 6; // Contains copy of auxv array
+    //private static final int NT_PRXFPREG = 0x46e62b7f; // User_xfpregs
+
+    private static final int AT_NULL = 0; // End of vector
+    private static final int AT_ENTRY = 9; // Entry point of program
+    private static final int AT_PLATFORM = 15; // String identifying platform
+    private static final int AT_HWCAP = 16; // Machine dependent hints about processor capabilities
+
+    private static abstract class Address {
+    	private long _value;
+    	private Address(long value) {
+    		_value = value;
+    	}
+    	long getValue() {
+    		return _value;
+    	}
+    	abstract Address add(long offset);
+    	boolean isNil() {
+    		return 0L == getValue();
+    	}
+    	abstract Number asNumber();
+    	abstract Address nil();
+    }
+    
+    private static class Address32 extends Address {
+    	Address32(int value) {
+    		super(value & 0xffffffffL);
+    	}
+    	Address add(long offset) {
+    		long result = getValue() + offset;
+    		return new Address32((int) result);
+    	}
+    	Number asNumber() {
+    		return new Integer((int) getValue());
+    	}
+    	Address nil() {
+    		return new Address32(0);
+    	}
+    }
+    
+    private static class Address64 extends Address {
+    	Address64(long value) {
+    		super(value);
+    	}
+    	Address add(long offset) {
+    		return new Address64(getValue() + offset);
+    	}
+    	Number asNumber() {
+    		return new Long(getValue());
+    	}
+    	Address nil() {
+    		return new Address64(0);
+    	}
+    }
+    
+    private static interface Arch {
+    	Map readRegisters(ElfFile file, Builder builder, Object addressSpace) throws IOException;
+    	long readUID(ElfFile file) throws IOException;
+		Address getStackPointerFrom(Map registers);
+		Address getBasePointerFrom(Map registers);
+		Address getInstructionPointerFrom(Map registers);
+		Address getLinkRegisterFrom(Map registers);
+    }
+    
+    private static class ArchPPC64 implements Arch {
+		public Map readRegisters(ElfFile file, Builder builder, Object addressSpace) throws IOException {
+			Map registers = new TreeMap();
+			for (int i = 0; i < 32; i++) {
+				registers.put("gpr" + i, file.readElfWordAsAddress());
+			}
+
+			registers.put("pc", file.readElfWordAsAddress());
+			file.readElfWordAsAddress(); // skip
+			file.readElfWordAsAddress(); // skip
+			registers.put("ctr", file.readElfWordAsAddress());
+			registers.put("lr", file.readElfWordAsAddress());
+			
+			// xer is a 32-bit register. Read 64 bits then shift right
+			long l = (file.readLong() >> 32) & 0xffffffffL;
+			registers.put("xer", new Address64(l));
+			
+			// cr is a 32-bit register. Read 64 bits then shift right
+			l = (file.readLong() >> 32) & 0xffffffffL;
+			registers.put("cr", new Address64(l));
+			
+			return registers;
+		}
+
+		public Address getStackPointerFrom(Map registers) {
+			return (Address) registers.get("gpr1");
+		}
+
+		public Address getBasePointerFrom(Map registers) {
+			//Note:  Most RISC ISAs do not distinguish between base pointer and stack pointer
+			return getStackPointerFrom(registers);
+		}
+
+		public Address getInstructionPointerFrom(Map registers) {
+			return (Address) registers.get("pc");
+		}
+
+		public Address getLinkRegisterFrom(Map registers) {
+			return (Address) registers.get("lr");
+		}
+
+		public long readUID(ElfFile file) throws IOException {
+			return file.readInt() & 0xffffffffL;
+		}
+    }
+    
+    private static class ArchPPC32 extends ArchPPC64 {
+    	public Map readRegisters(ElfFile file, Builder builder, Object addressSpace) throws IOException {
+			Map registers = new TreeMap();
+			for (int i = 0; i < 32; i++) {
+				registers.put("gpr" + i, file.readElfWordAsAddress());
+			}
+
+			registers.put("pc", file.readElfWordAsAddress());
+			file.readElfWordAsAddress(); // skip
+			file.readElfWordAsAddress(); // skip
+			registers.put("ctr", file.readElfWordAsAddress());
+			registers.put("lr", file.readElfWordAsAddress());
+			registers.put("xer", file.readElfWordAsAddress());
+			registers.put("cr", file.readElfWordAsAddress());
+			
+			return registers;
+    	}
+    	
+    	public long readUID(ElfFile file) throws IOException {
+			return file.readShort() & 0xffffL;
+		}
+    }
+    
+    private static class ArchS390 implements Arch {
+		public Map readRegisters(ElfFile file, Builder builder, Object addressSpace) throws IOException {
+			Map registers = new TreeMap();
+			registers.put("mask", file.readElfWordAsAddress());
+			registers.put("addr", file.readElfWordAsAddress());
+			for (int i = 0; i < 16; i++)
+				registers.put("gpr" + i, file.readElfWordAsAddress());
+			for (int i = 0; i < 16; i++)
+				registers.put("acr" + i, file.readElfWordAsAddress());
+			registers.put("origgpr2", file.readElfWordAsAddress());
+			registers.put("trap", file.readElfWordAsAddress());
+			return registers;
+		}
+
+		public Address getStackPointerFrom(Map registers) {
+			return (Address) registers.get("gpr15");
+		}
+
+		public Address getBasePointerFrom(Map registers) {
+			return getStackPointerFrom(registers);
+		}
+
+		public Address getInstructionPointerFrom(Map registers) {
+			return (Address) registers.get("addr");
+		}
+
+		public Address getLinkRegisterFrom(Map registers) {
+			return nil(registers);
+		}
+
+		public long readUID(ElfFile file) throws IOException {
+			return file.readInt() & 0xffffffffL;
+		}
+		
+		private Address nil(Map registers) {
+			Address gpr15 = (Address) registers.get("gpr15");
+			return gpr15.nil();
+		}
+    }
+    
+    private static class ArchS390_32 extends ArchS390 {
+    	public Map readRegisters(ElfFile file, Builder builder, Object addressSpace) throws IOException {
+    		Map registers = super.readRegisters(file, builder, addressSpace);
+    		registers.put("old_ilc", file.readElfWordAsAddress());
+    		return registers;
+    	}
+
+		public long readUID(ElfFile file) throws IOException {
+			return file.readShort() & 0xffffL;
+		}
+    }
+    
+    private static class ArchIA32 implements Arch {
+		public Map readRegisters(ElfFile file, Builder builder, Object addressSpace) throws IOException {
+			String[] names1 = {"ebx", "ecx", "edx", "esi", "edi", "ebp", "eax", "ds", "es", "fs", "gs"};
+			String[] names2 = {"eip", "cs", "efl", "esp", "ss"};
+			Map registers = new TreeMap();
+			for (int i = 0; i < names1.length; i++)
+				registers.put(names1[i], new Address32(file.readInt()));
+			file.readInt(); // Ignore originalEax
+			for (int i = 0; i < names2.length; i++)
+				registers.put(names2[i], new Address32(file.readInt()));
+			return registers;
+		}
+
+		public Address getStackPointerFrom(Map registers) {
+			return (Address) registers.get("esp");
+		}
+
+		public Address getBasePointerFrom(Map registers) {
+			return (Address) registers.get("ebp");
+		}
+
+		public Address getInstructionPointerFrom(Map registers) {
+			return (Address) registers.get("eip");
+		}
+
+		public Address getLinkRegisterFrom(Map registers) {
+			return new Address32(0);
+		}
+
+		public long readUID(ElfFile file) throws IOException {
+			return file.readShort() & 0xffffL;
+		}
+    }
+    
+    private static class ArchIA64 implements Arch {
+		public Map readRegisters(ElfFile file, Builder builder, Object addressSpace) throws IOException {
+			// Ignore the R Set of 32 registers
+			for (int i = 0; i < 32; i++)
+				file.readLong();
+			
+			Map registers = new TreeMap();
+			registers.put("nat", new Address64(file.readLong()));
+			registers.put("pr", new Address64(file.readLong()));
+    		
+			// Ignore the B Set of 8 registers
+			for (int i = 0; i < 8; i++)
+				file.readLong();
+
+			String[] names = {"ip", "cfm", "psr", "rsc", "bsp", "bspstore", "rnat", "ccv", "unat", "fpsr", "pfs", "lc", "ec"};
+			for (int i = 0; i < names.length; i++)
+				registers.put(names[i], new Address64(file.readLong()));
+
+			// The register structure contains 128 words: 32 R, 8 B, 15 irregular and 73 reserved.
+			// It is not really necessary to read the reserved words.
+			// for (int i = 0; i < 73; i++)
+			//		reader.readLong();
+
+			return registers;
+		}
+
+		public Address getStackPointerFrom(Map registers) {
+			return new Address64(0);
+		}
+
+		public Address getBasePointerFrom(Map registers) {
+			return new Address64(0);
+		}
+
+		public Address getInstructionPointerFrom(Map registers) {
+			return new Address64(0);
+		}
+
+		public Address getLinkRegisterFrom(Map registers) {
+			return new Address64(0);
+		}
+
+		public long readUID(ElfFile file) throws IOException {
+			return file.readInt() & 0xffffffffL;
+		}
+    }
+
+    private static class ArchAMD64 implements Arch {
+		public Map readRegisters(ElfFile file, Builder builder, Object addressSpace) throws IOException {
+			String[] names1 = {"r15", "r14", "r13", "r12", "rbp", "rbx", "r11", "r10", "r9", "r8", "rax", "rcx", "rdx", "rsi", "rdi"};
+			String[] names2 = {"rip", "cs", "eflags", "rsp", "ss", "fs_base", "gs_base", "ds", "es", "fs", "gs"};
+			Map registers = new TreeMap();
+			for (int i = 0; i < names1.length; i++)
+				registers.put(names1[i], new Address64(file.readLong()));
+			file.readLong(); // Ignore originalEax
+			for (int i = 0; i < names2.length; i++)
+				registers.put(names2[i], new Address64(file.readLong()));
+			return registers;
+		}
+
+		public Address getStackPointerFrom(Map registers) {
+			return (Address) registers.get("rsp");
+		}
+
+		public Address getBasePointerFrom(Map registers) {
+			return (Address) registers.get("rbp");
+		}
+
+		public Address getInstructionPointerFrom(Map registers) {
+			return (Address) registers.get("rip");
+		}
+
+		public Address getLinkRegisterFrom(Map registers) {
+			return new Address64(0);
+		}
+
+		public long readUID(ElfFile file) throws IOException {
+			return file.readInt() & 0xffffffffL;
+		}
+    }
+
+    private static class DataEntry {
+    	final long offset;
+    	final long size;
+    	
+    	DataEntry(long offset, long size) {
+    		this.offset = offset;
+    		this.size = size;
+    	}
+    }
+    
+    private static class Symbol {
+    	private static final byte STT_FUNC = 2;
+    	private static final byte ST_TYPE_MASK = 0xf;
+    	
+    	final long name;
+    	final long value;
+    	//private long _size;
+    	private byte _info;
+    	//private byte _other;
+    	//private int _sectionIndex;
+    	
+    	Symbol(long name, long value, long size, byte info, byte other, int sectionIndex) {
+    		this.name = name;
+    		this.value = value;
+    		//_size = size;
+    		_info = info;
+    		//_other = other;
+    		//_sectionIndex = sectionIndex;
+    	}
+
+		boolean isFunction() {
+			return STT_FUNC == (_info & ST_TYPE_MASK);
+		}
+    }
+    
+    private static class SectionHeaderEntry {
+		private static final int SHT_SYMTAB = 2; // Symbol table in this section
+		//private static final int SHT_STRTAB = 3; // String table in this section
+		private static final int SHT_DYNSYM = 11; // Symbol table in this section
+		//private static final int SHT_DYNSTR = 99; // String table in this section
+
+    	private long _name; // index into section header string table 
+    	private long _type;
+    	//private long _flags;
+    	//private long _address;
+    	final long offset;
+    	final long size;
+    	final long link;
+    	//private long _info;
+
+    	SectionHeaderEntry(long name, long type, long flags, long address, long offset, long size, long link, long info) {
+			_name = name;
+			_type = type;
+			//_flags = flags;
+			//_address = address;
+			this.offset = offset;
+			this.size = size;
+			this.link = link;
+			//_info = info;
+		}
+    	
+    	boolean isSymbolTable() {
+    		return SHT_SYMTAB == _type || SHT_DYNSYM == _type;
+    	}
+    }
+
+	private static class ProgramHeaderEntry {
+		// Program Headers defined in /usr/include/linux/elf.h
+		//type constants
+		//private static final int PT_NULL = 0;
+		//private static final int PT_LOAD = 1;
+		private static final int PT_DYNAMIC = 2;
+		//private static final int PT_INTERP = 3;
+		private static final int PT_NOTE = 4;
+		//private static final int PT_SHLIB = 5;
+		//private static final int PT_PHDR = 6;
+		//private static final int PT_TLS = 7;
+		private static final int PF_X = 1;
+		private static final int PF_W = 2;
+		//private static final int PF_R = 4;
+
+		//PHE structure definitions:
+		private int _type;
+		final long fileOffset;
+		final long fileSize; // if fileSize == 0 then we have to map memory from external lib file.
+		final long virtualAddress;
+		//private long _physicalAddress;
+		final long memorySize;
+		private int _flags;
+		//private long _alignment;
+
+		ProgramHeaderEntry(int type, long fileOffset, long fileSize, long virtualAddress, long physicalAddress, long memorySize, int flags, long alignment) {
+			_type = type;
+			this.fileOffset = fileOffset;
+			this.fileSize = fileSize;
+			this.virtualAddress = virtualAddress;
+			//_physicalAddress = physicalAddress;
+			this.memorySize = memorySize;
+			_flags = flags;
+			//_alignment = alignment;
+		}
+
+		boolean isEmpty() {
+			//if the core is not a complete dump of the address space, there will be missing pieces.  These are manifested as program header entries with a real memory size but a zero file size
+			//	That is, even though they do occupy space in memory, they are represented in none of the code
+			return 0 == fileSize;
+		}
+
+		boolean isDynamic() {
+			return PT_DYNAMIC == _type;
+		}
+
+		boolean isNote() {
+			return PT_NOTE == _type;
+		}
+
+		MemoryRange asMemoryRange() {
+			boolean w = (_flags & PF_W) != 0;
+			boolean x = (_flags & PF_X) != 0;
+			return new MemoryRange(virtualAddress, fileOffset, memorySize, 0, false, !w, x, !isEmpty());
+		}
+
+		boolean validInProcess(long address) {
+			return virtualAddress <= address && address < virtualAddress + memorySize;
+		}
+		
+		boolean contains(long address) {
+			return false == isEmpty() && validInProcess(address);
+		}
+	}
+	
+	private static abstract class ElfFile {
+		private DumpReader _reader;
+		private Arch _arch = null;
+		private long _programHeaderOffset = -1;
+		private long _sectionHeaderOffset = -1;
+		private short _programHeaderEntrySize = 0;
+		private short _programHeaderCount = 0;
+		private short _sectionHeaderEntrySize = 0;
+		private short _sectionHeaderCount = 0;
+		private List _processEntries = new ArrayList();
+		private List _threadEntries = new ArrayList();
+		private List _auxiliaryVectorEntries = new ArrayList();
+		private List _programHeaderEntries = new ArrayList();
+		private List _sectionHeaderEntries = new ArrayList();
+		
+		private short _objectType = 0;
+		private int _version = 0;
+		private int _e_flags = 0;
+
+		protected abstract long padToWordBoundary(long l);
+		protected abstract ProgramHeaderEntry readProgramHeaderEntry() throws IOException;
+		protected abstract long readElfWord() throws IOException;
+		protected abstract Address readElfWordAsAddress() throws IOException;
+
+		ElfFile(DumpReader reader) {
+			_reader = reader;
+		}
+		
+		Iterator processEntries() {
+			return _processEntries.iterator();
+		}
+		
+		Iterator threadEntries() {
+			return _threadEntries.iterator();
+		}
+		
+		Iterator auxiliaryVectorEntries() {
+			return _auxiliaryVectorEntries.iterator();
+		}
+
+		Iterator programHeaderEntries() {
+			return _programHeaderEntries.iterator();
+		}
+		
+		Iterator sectionHeaderEntries() {
+			return _sectionHeaderEntries.iterator();
+		}
+		
+		SectionHeaderEntry sectionHeaderEntryAt(int i) {
+			return (SectionHeaderEntry) _sectionHeaderEntries.get(i);
+		}
+
+		protected void readFile() throws IOException
+		{
+			seek(0);
+			readHeader();
+			readSectionHeader();
+			readProgramHeader();
+		}
+
+		private void readHeader() throws IOException
+		{
+			readBytes(EI_NIDENT);
+			_objectType = readShort(); //  objectType
+			short machineType = readShort();
+			_arch = architectureFor(machineType);
+			_version = readInt(); // Ignore version
+			readElfWord(); // Ignore entryPoint
+			_programHeaderOffset = readElfWord();
+			_sectionHeaderOffset = readElfWord();
+			_e_flags = readInt(); //  e_flags
+			readShort(); // Ignore elfHeaderSize
+			_programHeaderEntrySize = readShort();
+			_programHeaderCount = readShort();
+			_sectionHeaderEntrySize = readShort();
+			_sectionHeaderCount = readShort();
+			readShort(); // Ignore stringTable
+		}
+		
+		protected Arch architectureFor(short s) {
+			switch (s) {
+			case ARCH_PPC32:
+				return new ArchPPC32();
+			case ARCH_PPC64:
+				return new ArchPPC64();
+			case ARCH_IA64:
+				return new ArchIA64();
+			case ARCH_S390:
+				return new ArchS390();
+			case ARCH_IA32:
+				return new ArchIA32();
+			case ARCH_AMD64:
+				return new ArchAMD64();
+			default:
+				// TODO throw exception for unsupported arch?
+				return null;
+			}
+		}
+
+		private SectionHeaderEntry readSectionHeaderEntry() throws IOException {
+			long name = readInt() & 0xffffffffL;
+			long type = readInt() & 0xffffffffL;
+			long flags = readElfWord();
+			long address = readElfWord();
+			long offset = readElfWord();
+			long size = readElfWord();
+			long link = readInt() & 0xffffffffL;
+			long info = readInt() & 0xffffffffL;
+			return new SectionHeaderEntry(name, type, flags, address, offset, size, link, info);
+		}
+		
+		private void readSectionHeader() throws IOException {
+			for (int i = 0; i < _sectionHeaderCount; i++) {
+				seek(_sectionHeaderOffset + i * _sectionHeaderEntrySize);
+				SectionHeaderEntry entry = readSectionHeaderEntry();
+				_sectionHeaderEntries.add(entry);
+			}
+		}
+
+		private void readProgramHeader() throws IOException {
+			for (int i = 0; i < _programHeaderCount; i++) {
+				seek(_programHeaderOffset + i * _programHeaderEntrySize);
+				_programHeaderEntries.add(readProgramHeaderEntry());
+			}
+			for (Iterator iter = _programHeaderEntries.iterator(); iter.hasNext();) {
+				ProgramHeaderEntry entry = (ProgramHeaderEntry) iter.next();
+				if (entry.isNote())
+					readNotes(entry);
+			}
+		}
+
+		private void readNotes(ProgramHeaderEntry entry) throws IOException {
+			long offset = entry.fileOffset;
+			long limit = offset + entry.fileSize;
+			while (offset < limit)
+				offset = readNote(offset);
+		}
+
+		private long readNote(long offset) throws IOException {
+			seek(offset);
+			long nameLength = padToWordBoundary(readInt());
+			long dataSize = readInt();
+			long type = readInt();
+			readBytes((int)nameLength); // Ignore name
+			
+			long dataOffset = offset + ELF_NOTE_HEADER_SIZE + nameLength;
+			
+			if (NT_PRSTATUS == type)
+				addThreadEntry(dataOffset, dataSize);
+			else if (NT_PRPSINFO == type)
+				addProcessEntry(dataOffset, dataSize);
+			else if (NT_AUXV == type)
+				addAuxiliaryVectorEntry(dataOffset, dataSize);
+			
+			return dataOffset + padToWordBoundary(dataSize);
+		}
+
+		protected void addProcessEntry(long offset, long size) {
+			_processEntries.add(new DataEntry(offset, size));
+		}
+
+		protected void addThreadEntry(long offset, long size) {
+			_threadEntries.add(new DataEntry(offset, size));
+		}
+
+		private void addAuxiliaryVectorEntry(long offset, long size) {
+			_auxiliaryVectorEntries .add(new DataEntry(offset, size));
+		}
+
+		protected byte readByte() throws IOException {
+			return _reader.readByte();
+		}
+
+		protected byte[] readBytes(int n) throws IOException {
+			return _reader.readBytes(n);
+		}
+
+		protected int readInt() throws IOException {
+			return _reader.readInt();
+		}
+
+		protected long readLong() throws IOException {
+			return _reader.readLong();
+		}
+
+		protected short readShort() throws IOException {
+			return _reader.readShort();
+		}
+
+		protected void seek(long position) throws IOException {
+			_reader.seek(position);
+		}
+
+		long readUID() throws IOException {
+			return _arch.readUID(this);
+		}
+		
+		Address getStackPointerFrom(Map registers) {
+			return _arch.getStackPointerFrom(registers);
+		}
+		
+		Address getBasePointerFrom(Map registers) {
+			return _arch.getBasePointerFrom(registers);
+		}
+		
+		Address getInstructionPointerFrom(Map registers) {
+			return _arch.getInstructionPointerFrom(registers);
+		}
+		
+		Address getLinkRegisterFrom(Map registers) {
+			return _arch.getLinkRegisterFrom(registers);
+		}
+		
+		Map readRegisters(Builder builder, Object addressSpace) throws IOException {
+			return _arch.readRegisters(this, builder, addressSpace);
+		}
+
+		abstract Iterator readSymbolsAt(SectionHeaderEntry entry) throws IOException;
+		abstract int addressSize();
+		
+		/* file types corresponding to the _objectType field */
+		private final static short ET_NONE = 0;               /* No file type */
+		private final static short ET_REL = 1;               /* Relocatable file */
+		private final static short ET_EXEC = 2;               /* Executable file */
+		private final static short ET_DYN = 3;               /* Shared object file */
+		private final static short ET_CORE = 4;               /* Core file */
+		private final static short ET_NUM = 5;               /* Number of defined types */
+		//these are unsigned values so the constants can't be shorts
+		private final static int ET_LOOS = 0xfe00;          /* OS-specific range start */
+		private final static int ET_HIOS = 0xfeff;          /* OS-specific range end */
+		private final static int ET_LOPROC = 0xff00;          /* Processor-specific range start */
+		private final static int ET_HIPROC = 0xffff;         /* Processor-specific range end */
+		
+		public Properties getProperties()
+		{
+			Properties props = new Properties();
+			props.setProperty("Object file type", _nameForFileType(_objectType));
+			props.setProperty("Object file version", Integer.toHexString(_version));
+			props.setProperty("Processor-specific flags", Integer.toHexString(_e_flags));
+			
+			return props;
+		}
+		
+		private String _nameForFileType(short type)
+		{
+			String fileType = "Unknown";
+			int typeAsInt = 0xFFFF & type;
+			
+			if (ET_NONE == type) {
+				fileType = "No file type";
+			} else if (ET_REL == type) {
+				fileType = "Relocatable file";
+			} else if (ET_EXEC == type) {
+				fileType = "Executable file";
+			} else if (ET_DYN == type) {
+				fileType = "Shared object file";
+			} else if (ET_CORE == type) {
+				fileType = "Core file";
+			} else if (ET_NUM == type) {
+				fileType = "Number of defined types";
+			} else if ((ET_LOOS <= typeAsInt) && (typeAsInt <= ET_HIOS)) {
+				fileType = "OS-specific (" + Integer.toHexString(typeAsInt) + ")";
+			} else if ((ET_LOPROC <= typeAsInt) && (typeAsInt <= ET_HIPROC)) {
+				fileType = "Processor-specific (" + Integer.toHexString(typeAsInt) + ")";
+			}
+			return fileType;
+		}
+	}
+	
+	/*
+	 * 32-bit Elf header
+	 *
+	 *	typedef struct
+	 *	{
+	 *	  unsigned char e_ident[EI_NIDENT];     // Magic number and other info
+	 *	  Elf32_Half    e_type;                 // Object file type
+	 *	  Elf32_Half    e_machine;              // Architecture
+	 *	  Elf32_Word    e_version;              // Object file version
+	 *	  Elf32_Addr    e_entry;                // Entry point virtual address
+	 *	  Elf32_Off     e_phoff;                // Program header table file offset
+	 *	  Elf32_Off     e_shoff;                // Section header table file offset
+	 *	  Elf32_Word    e_flags;                // Processor-specific flags
+	 *	  Elf32_Half    e_ehsize;               // ELF header size in bytes
+	 *	  Elf32_Half    e_phentsize;            // Program header table entry size
+	 *	  Elf32_Half    e_phnum;                // Program header table entry count
+	 *	  Elf32_Half    e_shentsize;            // Section header table entry size
+	 *	  Elf32_Half    e_shnum;                // Section header table entry count
+	 *	  Elf32_Half    e_shstrndx;             // Section header string table index
+	 *	} Elf32_Ehdr;
+	 */
+	private static class Elf32File extends ElfFile {
+		protected Arch architectureFor(short s) {
+			if (ARCH_S390 == s)
+				return new ArchS390_32();
+			return super.architectureFor(s);
+		}
+
+		Elf32File(DumpReader reader) throws IOException {
+			super(reader);
+			readFile();
+		}
+
+		protected ProgramHeaderEntry readProgramHeaderEntry() throws IOException {
+			int type = readInt();
+			long fileOffset = unsigned(readInt());
+			long virtualAddress = unsigned(readInt());
+			long physicalAddress = unsigned(readInt());
+			long fileSize = unsigned(readInt());
+			long memorySize = unsigned(readInt());
+			int flags = readInt();
+			long alignment = unsigned(readInt());
+			return new ProgramHeaderEntry(type, fileOffset, fileSize, virtualAddress, physicalAddress, memorySize, flags, alignment);
+		}
+
+		private long unsigned(int i) {
+			return i & 0xffffffffL;
+		}
+
+		protected long padToWordBoundary(long l) {
+			return ((l + 3) / 4) * 4;
+		}
+
+		protected long readElfWord() throws IOException {
+			return readInt() & 0xffffffffL;
+		}
+
+		protected Address readElfWordAsAddress() throws IOException {
+			return new Address32(readInt());
+		}
+
+		int addressSize() {
+			return 32;
+		}
+
+		Iterator readSymbolsAt(SectionHeaderEntry entry) throws IOException {
+			seek(entry.offset);
+			List symbols = new ArrayList();
+			long count = entry.size / 16;
+			for (long i = 0; i < count; i++) {
+				long name = readInt() & 0xffffffffL;
+				long value = readInt() & 0xffffffffL;
+				long size = readInt() & 0xffffffffL;
+				byte info = readByte();
+				byte other = readByte();
+				int sectionIndex = readShort() & 0xffff;
+				symbols.add(new Symbol(name, value, size, info, other, sectionIndex));
+			}
+			return symbols.iterator();
+		}
+	}
+	
+	/*
+	 * Elf 64-bit header
+	 * 
+	 *	typedef struct
+	 *	{
+	 *	  unsigned char e_ident[EI_NIDENT];     // Magic number and other info
+	 *	  Elf64_Half    e_type;                 // Object file type
+	 *	  Elf64_Half    e_machine;              // Architecture
+	 *	  Elf64_Word    e_version;              // Object file version
+	 *	  Elf64_Addr    e_entry;                // Entry point virtual address
+	 *	  Elf64_Off     e_phoff;                // Program header table file offset
+	 *	  Elf64_Off     e_shoff;                // Section header table file offset
+	 *	  Elf64_Word    e_flags;                // Processor-specific flags
+	 *	  Elf64_Half    e_ehsize;               // ELF header size in bytes
+	 *	  Elf64_Half    e_phentsize;            // Program header table entry size
+	 *	  Elf64_Half    e_phnum;                // Program header table entry count
+	 *	  Elf64_Half    e_shentsize;            // Section header table entry size
+	 *	  Elf64_Half    e_shnum;                // Section header table entry count
+	 *	  Elf64_Half    e_shstrndx;             // Section header string table index
+	 *	} Elf64_Ehdr;
+	 */
+	private static class Elf64File extends ElfFile {
+		Elf64File(DumpReader reader) throws IOException {
+			super(reader);
+			readFile();
+		}
+
+		protected ProgramHeaderEntry readProgramHeaderEntry() throws IOException {
+			int type = readInt();
+			int flags = readInt();
+			long fileOffset = readLong();
+			long virtualAddress = readLong();
+			long physicalAddress = readLong();
+			long fileSize = readLong();
+			long memorySize = readLong();
+			long alignment = readLong();
+			return new ProgramHeaderEntry(type, fileOffset, fileSize, virtualAddress, physicalAddress, memorySize, flags, alignment);
+		}
+
+		protected long padToWordBoundary(long l) {
+			return ((l + 7) / 8) * 8;
+		}
+
+		protected long readElfWord() throws IOException {
+			return readLong();
+		}
+
+		protected Address readElfWordAsAddress() throws IOException {
+			return new Address64(readLong());
+		}
+
+		int addressSize() {
+			return 64;
+		}
+
+		Iterator readSymbolsAt(SectionHeaderEntry entry) throws IOException {
+			seek(entry.offset);
+			List symbols = new ArrayList();
+			long count = entry.size / 24;
+			for (long i = 0; i < count; i++) {
+				long name = readInt() & 0xffffffffL;
+				byte info = readByte();
+				byte other = readByte();
+				int sectionIndex = readShort() & 0xffff;
+				long value = readLong();
+				long size = readLong();
+				symbols.add(new Symbol(name, value, size, info, other, sectionIndex));
+			}
+			return symbols.iterator();
+		}
+	}
+
+	private List _memoryRanges = new ArrayList();
+	private List _additionalFileNames = new ArrayList();
+	private long _platformIdAddress = 0;
+	private ElfFile _file;
+	private boolean _isLittleEndian;
+	private boolean _is64Bit;
+	private boolean _verbose;
+
+	private Object readProcess(DataEntry entry, Builder builder, Object addressSpace, List threads) throws IOException, MemoryAccessException {
+		_file.seek(entry.offset);
+		_file.readByte(); // Ignore state
+		_file.readByte(); // Ignore sname
+		_file.readByte(); // Ignore zombie
+		_file.readByte(); // Ignore nice
+		_file.seek(entry.offset + _file.padToWordBoundary(4));
+		_file.readElfWord(); // Ignore flags
+		readUID(); // Ignore uid
+		readUID(); // Ignore gid
+		long pid = _file.readInt() & 0xffffffffL;
+		_file.readInt(); // Ignore ppid
+		_file.readInt(); // Ignore pgrp
+		_file.readInt(); // Ignore sid
+
+		// Ignore filler.  Command-line is last 80 bytes (defined by ELF_PRARGSZ in elfcore.h).
+		// Command-name is 16 bytes before command-line.
+		_file.seek(entry.offset + entry.size - 96);
+		_file.readBytes(16); // Ignore command
+		String dumpCommandLine = new String(_file.readBytes(ELF_PRARGSZ), "ASCII").trim();
+		
+		int space = dumpCommandLine.indexOf(" ");
+		String executable = dumpCommandLine;
+		if (0 < space)
+			executable = executable.substring(0, space);
+
+        return buildProcess(builder, addressSpace, String.valueOf(pid), dumpCommandLine,
+				 			getEnvironmentVariables(builder), threads.get(0) /*currentThread*/,
+				 			threads.iterator(), executable);
+	}
+
+	private Object buildProcess(Builder builder, Object addressSpace, String pid, String commandLine, Properties environmentVariables, Object currentThread, Iterator threads, String executableName) throws IOException, MemoryAccessException
+	{
+		List modules = readModules(builder, addressSpace, executableName);
+		Iterator libraries = modules.iterator();
+		Object executable = null;
+		if (libraries.hasNext()) {
+			executable = libraries.next();
+		}
+		return builder.buildProcess(addressSpace, pid, commandLine, environmentVariables, currentThread, threads, executable, libraries, _file.addressSize());
+	}
+
+	/**
+	 * Returns a list of the ImageModules in the address space.  The executable will be element 0
+	 * @param builder
+	 * @param addressSpace
+	 * @param executableName
+	 * 
+	 * @throws IOException
+	 * @throws MemoryAccessException
+	 */
+	private List readModules(Builder builder, Object addressSpace, String executableName) throws IOException, MemoryAccessException
+	{
+		// Uncomment the following line for debug. There ought to be a proper verbose mode.
+		// System.err.println("NewElfDump.readModules() entered en=" + executableName);
+		
+		List modules = new ArrayList();
+		ClosingFileReader file = _findFileInPath(builder, executableName, System.getProperty("java.class.path","."));
+		
+		if (null != file) {
+			// Uncomment the following line for debug. There ought to be a proper verbose mode.
+			// System.err.println("NewElfDump.readModules() opened file");
+			
+			ElfFile executable = elfFileFrom(file);
+			if (null != executable) {
+				// Uncomment the following line for debug. There ought to be a proper verbose mode.
+				// System.err.println("NewElfDump.readModules() found executable object");
+				
+				ProgramHeaderEntry dynamic = null;
+				for (Iterator iter = executable.programHeaderEntries(); null == dynamic && iter.hasNext();) {
+					ProgramHeaderEntry entry = (ProgramHeaderEntry) iter.next();
+					if (entry.isDynamic()) {
+						dynamic = entry;
+					}
+				}
+				
+				if (null != dynamic) {
+					// Uncomment the following line for debug. There ought to be a proper verbose mode.
+					// System.err.println("NewElfDump.readModules() found 'dynamic' program header object");
+
+					List symbols = readSymbolsFrom(builder, addressSpace, executable, dynamic.virtualAddress);
+					long imageStart = dynamic.virtualAddress;
+					if (isValidAddress(imageStart)) {
+						Iterator sections = _buildModuleSections(builder, addressSpace, executable, dynamic.virtualAddress);
+						Properties properties = executable.getProperties();
+						modules.add(builder.buildModule(executableName, properties, sections, symbols.iterator(),imageStart));
+						modules.addAll(readLibrariesAt(builder, addressSpace, imageStart));
+						_additionalFileNames.add(executableName);
+					}
+				}
+			} else {
+				//call in here if we can't find the executable
+				builder.setExecutableUnavailable("Executable file \"" + executableName + "\" not found");
+			}
+		} else {
+			//call in here if we can't find the executable
+			builder.setExecutableUnavailable("File \"" + executableName + "\" not found");
+		}
+		return modules;
+	}
+
+	/**
+	 * Attempts to track down the file with given filename in :-delimited path
+	 * 
+	 * @param builder 
+	 * @param executableName
+	 * @param property
+	 * @return The file if it is found or null if the search failed
+	 */
+	private ClosingFileReader _findFileInPath(Builder builder, String filename, String path)
+	{
+		ClosingFileReader file = null;
+		
+		try{
+			//first try it as whatever we were given first
+			file = builder.openFile(filename);
+		} catch (FileNotFoundException e) {
+			//it wasn't there so fall back to the path
+			Iterator components = _componentsSeparatedBy(path, ":").iterator();
+			
+			while ((null == file) && (components.hasNext())) {
+				String component = (String)(components.next());
+				try{
+					//first try it as whatever we were given first
+					file = builder.openFile(component + "/" + filename);
+				} catch (FileNotFoundException e2) {
+					//do nothing, most of these will be file not found
+				}
+			}
+		}
+		return file;
+	}
+
+	/**
+	 * Due to our build environment, we can't use the 1.4.2 split function so this is a similar method
+	 * 
+	 * @param path
+	 * @param separator
+	 * 
+	 */
+	private static List _componentsSeparatedBy(String path, String separator)
+	{
+		Vector list = new Vector();
+		
+		while (null != path) {
+			int index = path.indexOf(separator);
+			
+			if (index >= 0) {
+				String component = path.substring(0, index);
+				
+				list.add(component);
+				path = path.substring(index + 1);
+			} else {
+				path = null;
+			}
+		}
+		return list;
+	}
+
+	private static final long SHT_STRTAB = 3;
+	
+	
+	private Iterator _buildModuleSections(Builder builder, Object addressSpace, ElfFile executable, long loadedBaseAddress) throws IOException
+	{
+		Vector sections = new Vector();
+		Iterator shentries = executable.sectionHeaderEntries();
+		byte[] strings = null;
+		
+		// Find the string table by looking for a section header entry of type string  
+		// table which, when resolved against itself, has the name ".shstrtab". 
+		// NB : If the core file is invalid, the method stringFromBytesAt() may return null.
+		while (shentries.hasNext()) {
+			SectionHeaderEntry entry = (SectionHeaderEntry) shentries.next();
+			if (SHT_STRTAB == entry._type) {
+				executable.seek(entry.offset);
+				byte[] attempt = executable.readBytes((int)(entry.size));
+				String peak = stringFromBytesAt(attempt, entry._name);
+				if (peak != null) {
+					if (peak.equals(".shstrtab")) {
+						strings = attempt;
+					}
+				} else {
+					System.err.println("Error reading section header name. The core file is invalid and the results may unpredictable");
+				}
+			}
+		}
+		
+		// Loop through the section header entries building a module section for each one
+		// NB : If the core file is invalid, the method stringFromBytesAt() may return null.
+		shentries = executable.sectionHeaderEntries();
+		while (shentries.hasNext()) {
+			SectionHeaderEntry entry = (SectionHeaderEntry) shentries.next();
+			String name = "";
+			
+			if (null != strings) {
+				name = stringFromBytesAt(strings, entry._name);
+				if (name == null) {
+					System.err.println("Error reading section header name. The core file is invalid and the results may unpredictable");
+					name = "";
+				}
+			}
+
+			Object section = builder.buildModuleSection(addressSpace, name, loadedBaseAddress + entry.offset, loadedBaseAddress + entry.offset + entry.size);
+			sections.add(section);
+		}
+		return sections.iterator();
+	}
+
+	/**
+	 * Is this virtual address valid and present in the core file.
+	 * @param address Virtual address to test
+	 * @return true if valid and present
+	 */
+	private boolean isValidAddress(long address) {
+		for (Iterator iter = _file.programHeaderEntries(); iter.hasNext();) {
+			ProgramHeaderEntry element = (ProgramHeaderEntry) iter.next();
+			if (element.contains(address)) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Is this virtual address valid in the process, though perhaps not present in the core file.
+	 * @param address Virtual address to test
+	 * @return if valid
+	 */
+	private boolean isValidAddressInProcess(long address) {
+		for (Iterator iter = _file.programHeaderEntries(); iter.hasNext();) {
+			ProgramHeaderEntry element = (ProgramHeaderEntry) iter.next();
+			if (element.validInProcess(address)) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	private List readLibrariesAt(Builder builder, Object addressSpace, long imageStart) throws MemoryAccessException, IOException {
+	
+		//System.err.println("NewElfDump.readLibrariesAt() entered is=0x" + Long.toHexString(imageStart));
+		
+		// Create the method return value
+		List libraries = new ArrayList();
+		
+		// Seek to the start of the dynamic section
+		seekToAddress(imageStart);
+
+		// Loop reading the dynamic section tag-value/pointer pairs until a 'debug'
+		// entry is found
+		long tag;
+		long address;
+
+		do {
+			// Read the tag and the value/pointer (only used after the loop has terminated)
+			tag     = _file.readElfWord();
+			address = _file.readElfWord();
+			
+			// Check that the tag is valid. As there may be some debate about the
+			// set of valid values, a message will be issued but reading will continue
+			if ( !((tag >= 0         ) && (tag <= 28        )) &&
+			     !((tag >= 0x60000000) && (tag <= 0x6FFFFFFF)) &&
+			     !((tag >= 0x70000000) && (tag <= 0x7FFFFFFF))    ) {
+				System.err.println(
+					"Error reading dynamic section. Invalid tag value '0x" + 
+					Long.toHexString(tag) +
+					"'. The core file is invalid and the results may unpredictable"
+				);
+			}
+			
+			// System.err.println("Found dynamic section tag 0x" + Long.toHexString(tag));
+		} while ((tag != DT_NULL) && (tag != DT_DEBUG));
+
+		// If there is no debug section, there is nothing to do
+		if ( tag != DT_DEBUG) {
+			return libraries;
+		}
+
+		// Seek to the start of the debug data
+		seekToAddress(address);
+			
+		// NOTE the rendezvous structure is described in /usr/include/link.h
+		//	struct r_debug {
+		//		int r_version;
+		//		struct link_map *r_map;
+		//		ElfW(Addr) r_brk;		/* Really a function pointer */
+		//		enum { ... } r_state;
+		//		ElfW(Addr) r_ldbase;
+		//	};
+		//	struct link_map {
+		   //		ElfW(Addr) l_addr;		/* Base address shared object is loaded at.  */
+		   //		char *l_name;			/* Absolute file name object was found in.  */
+		   //		ElfW(Dyn) *l_ld;		/* Dynamic section of the shared object.  */
+		   //		struct link_map *l_next, *l_prev;	/* Chain of loaded objects.  */
+		//	};
+			
+		_file.readElfWord(); // Ignore version (and alignment padding)
+		long next = _file.readElfWord();
+		while (0 != next) {
+			seekToAddress(next);
+			long loadedBaseAddress = _file.readElfWord();
+			long nameAddress = _file.readElfWord();
+			_file.readElfWord(); // Ignore dynamicSectionAddress
+			next = _file.readElfWord();
+			if (0 != loadedBaseAddress) {
+				MemoryRange range = memoryRangeFor(loadedBaseAddress);
+
+				// NOTE There is an apparent bug in the link editor on Linux x86-64.
+				// The loadedBaseAddress for libnuma.so is invalid, although it is
+				// correctly loaded and its symbols are resolved.  The library is loaded
+				// around 0x2a95c4f000 but its base is recorded in the link map as
+				// 0xfffffff09f429000.
+
+				Properties properties = new Properties();
+				List symbols = new ArrayList();
+				String name = readStringAt(nameAddress);
+				Iterator sections = (new Vector()).iterator();
+
+				// If we have a valid link_map entry, open up the actual library file to get the symbols and 
+				// library sections.
+				// Note: on SLES 10 we have seen a link_map entry with a null name, in non-corrupt dumps, so we now 
+				// ignore link_map entries with null names rather than report them as corrupt. 
+				if ((null != range) && (range.getVirtualAddress() == loadedBaseAddress) && (null != name)) {
+					try {
+						ClosingFileReader file = builder.openFile(name);
+						if (null != file) {
+							ElfFile library = elfFileFrom(file);
+							if (range.isInCoreFile() == false) {
+								// the memory range has not been loaded into the core dump, but it should be
+								// resident in the library file on disk, so add a reference to the real file.
+								range.setLibraryReader(library._reader);
+							}
+							_additionalFileNames.add(name);
+							if (null != library) {
+								symbols = readSymbolsFrom(builder, addressSpace, library, loadedBaseAddress);
+								properties = library.getProperties();
+								sections = _buildModuleSections(builder, addressSpace, library, loadedBaseAddress);
+							} else {
+								symbols.add(builder.buildCorruptData(addressSpace, "unable to find module " + name, loadedBaseAddress));
+							}
+						}
+					} catch (FileNotFoundException exc) {
+						// As for null file return above, if we can't find the library file we follow the normal
+						// DTFJ convention and leave the properties, sections and symbols iterators empty. 
+					}
+					libraries.add(builder.buildModule(name, properties, sections, symbols.iterator(),loadedBaseAddress));
+				}
+			}
+		}
+
+		return libraries;
+	}
+
+	private MemoryRange memoryRangeFor(long address)
+	{
+		//TODO:  change the callers of this method to use some mechanism which will work better within the realm of the new address spaces
+		Iterator ranges = _memoryRanges.iterator();
+		MemoryRange match = null;
+		
+		while ((null == match) && ranges.hasNext()) {
+			MemoryRange range = (MemoryRange) ranges.next();
+			
+			if (range.contains(address)) {
+				match = range;
+			}
+		}
+		return match;
+	}
+
+	private void seekToAddress(long address) throws IOException {
+		ProgramHeaderEntry matchedEntry = null;
+		
+		for (Iterator iter = _file.programHeaderEntries(); iter.hasNext();) {
+			ProgramHeaderEntry element = (ProgramHeaderEntry) iter.next();
+			if (element.contains(address)) {
+				assert (null == matchedEntry) : "Multiple mappings for the same address";
+				matchedEntry = element;
+			}
+		}
+		if (null == matchedEntry) {
+			throw new IOException("No ProgramHeaderEntry found for address");
+		} else {
+			coreSeek(matchedEntry.fileOffset + (address - matchedEntry.virtualAddress));
+		}
+	}
+
+	private static List readSymbolsFrom(Builder builder, Object addressSpace, ElfFile file, long baseAddress) throws IOException {
+		List symbols = new ArrayList();
+		for (Iterator iter = file.sectionHeaderEntries(); iter.hasNext();) {
+			SectionHeaderEntry entry = (SectionHeaderEntry) iter.next();
+			if (entry.isSymbolTable())
+				symbols.addAll(readSymbolsFrom(builder, addressSpace, file, entry, baseAddress));
+		}
+		return symbols;
+	}
+
+	private static List readSymbolsFrom(Builder builder, Object addressSpace, ElfFile file, SectionHeaderEntry entry, long baseAddress) throws IOException {
+		List symbols = new ArrayList();
+		SectionHeaderEntry stringTable = file.sectionHeaderEntryAt((int) entry.link);
+		file.seek(stringTable.offset);
+		byte[] strings = file.readBytes((int) stringTable.size);
+		for (Iterator iter = file.readSymbolsAt(entry); iter.hasNext();) {
+			Symbol sym = (Symbol) iter.next();
+			if (sym.isFunction()) {
+				String name = stringFromBytesAt(strings, sym.name);
+				if (name != null) {
+					if (sym.value != 0) {
+						symbols.add(builder.buildSymbol(addressSpace, name, baseAddress + sym.value));
+					}
+				} else {
+					System.err.println("Error reading section header name. The core file is invalid and the results may unpredictable");
+				}
+			}
+		}
+		return symbols;
+	}
+
+	/**
+	 * Method for extracting a string from a string table
+	 * 
+	 * @param strings : The byte array from which the strings are to be extracted
+	 * @param offset  : The offset of the required string
+	 * 
+	 */
+	private static String stringFromBytesAt(byte[] stringTableBytes, long offset) {
+		// Check that the offset is valid
+		if ((offset < 0) || (offset >= stringTableBytes.length)) {
+			System.err.println("Error in string table offset. The core file is invalid and the results may unpredictable");
+			return null;
+		}
+		
+		// As the offset is now known to be small (definitely fits in 32 bits), it
+		// can be safely cast to an int
+		int startOffset = (int)offset;
+		int endOffset   = startOffset;
+		
+		// Scan along the characters checking they are valid (else undefined behaviour
+		// converting to a string) and locating the terminating null (if any!!)
+		for (endOffset = startOffset; endOffset < stringTableBytes.length; endOffset++) {
+			if (stringTableBytes[endOffset] >= 128) {
+				System.err.println("Error in string table. Non ASCII character encountered. The core file is invalid and the results may unpredictable");
+				return null;				
+			} else if (stringTableBytes[endOffset] == 0) {
+				break;
+			}
+		}
+		
+		// Check that the string is null terminated
+		if (stringTableBytes[endOffset] != 0) {
+			System.err.println("Error in string table. The string is not terminated. The core file is invalid and the results may unpredictable");
+			return null;			
+		}
+
+		// Convert the bytes to a string
+		try {
+			String result = new String(stringTableBytes, startOffset, endOffset - startOffset, "ASCII");
+			// Uncomment the following line for debug. There ought to be a proper verbose mode.
+			// System.err.println("Read string '" + result + "' from string table");
+			return result;
+		} catch (UnsupportedEncodingException exception) {
+			System.err.println("Error (UnsupportedEncodingException) converting string table characters. The core file is invalid and the results may unpredictable");
+		} catch (IndexOutOfBoundsException exception) {
+			System.err.println("Error (IndexOutOfBoundsException) converting string table characters. The core file is invalid and the results may unpredictable");
+		}
+		
+		return null;
+	}
+	
+	private Properties getEnvironmentVariables(Builder builder) throws MemoryAccessException, IOException {
+		// builder.getEnvironmentAddress() points to a pointer to a null
+		// terminated list of addresses which point to strings of form x=y
+
+		// Get environment variable addresses
+		long environmentAddress = builder.getEnvironmentAddress();
+		if (0 == environmentAddress)
+			return null;
+
+		List addresses = new ArrayList();
+		seekToAddress(environmentAddress);
+		Address address = _file.readElfWordAsAddress();
+		seekToAddress(address.getValue());
+		address = _file.readElfWordAsAddress();
+		while (false == address.isNil()) {
+			addresses.add(address);
+			address = _file.readElfWordAsAddress();
+		}
+
+		// Get environment variables
+		Properties environment = new Properties();
+		for (Iterator iter = addresses.iterator(); iter.hasNext();) {
+			Address variable = (Address) iter.next();
+			StringBuffer buffer = new StringBuffer();
+			try {
+				seekToAddress(variable.getValue());
+			} catch (IOException e) {
+				// catch here rather than propagate up to method extract() - we can 
+				// carry on getting other environment variables
+				continue;
+			}
+	
+			byte b = coreReadByte();
+			while (0 != b) {
+				buffer.append(new String(new byte[] {b}, "ASCII"));
+				b = coreReadByte();
+			}
+			// Now buffer is the x=y string
+			String pair = buffer.toString();
+			int equal = pair.indexOf('=');
+			String key = pair.substring(0, equal);
+			String value = pair.substring(equal + 1);
+			environment.put(key, value);
+		}
+		
+		return environment;
+	}
+
+	private long readUID() throws IOException {
+		return _file.readUID();
+	}
+
+	/*
+	 * 
+	 */
+	private Object readThread(DataEntry entry, Builder builder, Object addressSpace) throws IOException, MemoryAccessException {
+		_file.seek(entry.offset);
+		int signalNumber = _file.readInt(); //  signalNumber
+		_file.readInt(); // Ignore code
+		_file.readInt(); // Ignore errno
+		_file.readShort(); // Ignore cursig
+		_file.readShort(); // Ignore dummy
+		_file.readElfWord(); // Ignore pending
+		_file.readElfWord(); // Ignore blocked
+	    long pid = _file.readInt() & 0xffffffffL;
+	    _file.readInt(); // Ignore ppid
+	    _file.readInt(); // Ignore pgroup
+	    _file.readInt(); // Ignore session
+	    
+	    long utimeSec   = _file.readElfWord(); // utime_sec
+	    long utimeUSec  = _file.readElfWord(); // utime_usec
+	    long stimeSec   = _file.readElfWord(); // stime_sec
+	    long stimeUSec  = _file.readElfWord(); // stime_usec
+	    _file.readElfWord(); // Ignore cutime_sec
+	    _file.readElfWord(); // Ignore cutime_usec
+	    _file.readElfWord(); // Ignore cstime_sec
+	    _file.readElfWord(); // Ignore cstime_usec
+	    
+	    Map registers = _file.readRegisters(builder, addressSpace);
+	    Properties properties = new Properties();
+	    properties.setProperty("Thread user time secs", Long.toString(utimeSec));
+	    properties.setProperty("Thread user time usecs", Long.toString(utimeUSec));
+	    properties.setProperty("Thread sys time secs", Long.toString(stimeSec));
+	    properties.setProperty("Thread sys time usecs", Long.toString(stimeUSec));
+	    
+	    return buildThread(builder, addressSpace, String.valueOf(pid), registers, properties, signalNumber);
+	}
+
+	private Object buildThread(Builder builder, Object addressSpace, String pid, Map registers, Properties properties, int signalNumber) throws MemoryAccessException, IOException
+	{
+		List frames = new ArrayList();
+		List sections = new ArrayList();
+		long stackPointer = _file.getStackPointerFrom(registers).getValue();
+		long basePointer = _file.getBasePointerFrom(registers).getValue();
+		long instructionPointer = _file.getInstructionPointerFrom(registers).getValue();
+		long previousBasePointer = 0;
+		
+		if (0 == instructionPointer || false == isValidAddressInProcess(instructionPointer)) {
+			Address linkRegister = _file.getLinkRegisterFrom(registers);
+			instructionPointer = linkRegister.getValue();
+		}
+		
+		if (0 != instructionPointer && 0 != basePointer && isValidAddressInProcess(instructionPointer) && isValidAddressInProcess(stackPointer)) {
+			MemoryRange range = memoryRangeFor(stackPointer);
+			sections.add(builder.buildStackSection(addressSpace, range.getVirtualAddress(), range.getVirtualAddress() + range.getSize()));
+			frames.add(builder.buildStackFrame(addressSpace, basePointer, instructionPointer));
+			// Loop through stack frames, starting from current frame base pointer
+			while (range.contains(basePointer) && (basePointer != previousBasePointer)) {
+				previousBasePointer = basePointer;
+				seekToAddress(basePointer);
+				basePointer = coreReadAddress();
+				instructionPointer = coreReadAddress();
+				frames.add(builder.buildStackFrame(addressSpace, basePointer, instructionPointer));
+			}
+		}
+		return builder.buildThread(pid, registersAsList(builder, registers).iterator(),
+								   sections.iterator(), frames.iterator(), properties, signalNumber);
+	}
+
+	private List registersAsList(Builder builder, Map registers) {
+		List list = new ArrayList();
+		for (Iterator iter = registers.entrySet().iterator(); iter.hasNext();) {
+			Map.Entry entry = (Map.Entry) iter.next();
+			Address value = (Address) entry.getValue();
+			list.add(builder.buildRegister((String) entry.getKey(), value.asNumber()));
+		}
+		return list;
+	}
+
+	private NewElfDump(ElfFile file, DumpReader reader, boolean isLittleEndian, boolean is64Bit, boolean verbose) {
+		super(reader);
+		_file = file;
+		_isLittleEndian = isLittleEndian;
+		_is64Bit = is64Bit;
+		_verbose = verbose;
+
+		// FIXME will we ever see multiple PHEs mapped to the same address?
+		// FIXME if so, should the first or the last entry seen take precedence?
+		if (_verbose) {
+			System.err.println("Memory segments...");
+			System.err.println("  Start               End                 File Size");
+		}
+		
+		for (Iterator iter = _file.programHeaderEntries(); iter.hasNext();) {
+			ProgramHeaderEntry entry = (ProgramHeaderEntry) iter.next();
+			
+			if (_verbose) {
+				// print out information about the memory segments :
+				// virtual address start, virtual address end
+				// and the filesize (0 if not in core). 
+				int colWidth = 20;
+				String padding = " ";
+				StringBuffer sb = new StringBuffer();
+				
+				String vaStart = "0x" + Long.toHexString(entry.virtualAddress);
+				String vaEnd = "0x" + Long.toHexString(entry.virtualAddress + entry.memorySize);
+				String fileSize = "0x" + Long.toHexString(entry.fileSize);
+				
+				sb.append("  " + vaStart);
+				for (int i = 0; i < colWidth - vaStart.length(); i++) {
+					sb.append(padding);
+				}
+				
+				sb.append(vaEnd);
+				for (int i = 0; i < colWidth - vaEnd.length(); i++) {
+					sb.append(padding);
+				}
+				
+				sb.append(fileSize);
+				for (int i = 0; i < colWidth - fileSize.length(); i++) {
+					sb.append(padding);
+				}
+				System.err.println(sb);
+			}
+
+			MemoryRange range = entry.asMemoryRange();
+			if (null != range) {
+				_memoryRanges.add(range);
+			}
+		}
+		
+		if (_verbose) {
+			System.err.println();
+		}		
+	}
+
+	private ElfFile elfFileFrom(ClosingFileReader file) throws IOException {
+		file.seek(0);
+		byte[] signature = new byte[EI_NIDENT];
+		file.readFully(signature);
+		if (-1 != new String(signature).toLowerCase().indexOf("elf")) {
+			DumpReader reader = readerForEndianess(signature[5], signature[4], file);
+			ElfFile result = fileForClass(signature[4], reader);
+			if (result.getClass().isInstance(_file))
+				return result;
+		}
+		return null;
+	}
+
+	private static DumpReader readerForEndianess(byte endianess, byte clazz, ClosingFileReader f) throws IOException
+	{
+		boolean is64Bit = (ELFCLASS64 == clazz);
+		
+		if (!is64Bit && (ELFCLASS32 != clazz)) {
+			throw new IOException("Unexpected class flag " + clazz + " detected in ELF file.");
+		}		
+		if (ELFDATA2LSB == endianess) {
+			return new LittleEndianDumpReader(f, is64Bit);
+		} else if (ELFDATA2MSB == endianess) {
+			return new DumpReader(f, is64Bit);
+		} else {
+			throw new IOException("Unknown endianess flag " + endianess + " in ELF core file");
+		}
+	}
+
+	private static ElfFile fileForClass(byte clazz, DumpReader reader) throws IOException {
+		if (ELFCLASS32 == clazz)
+			return new Elf32File(reader);
+		else if (ELFCLASS64 == clazz)
+			return new Elf64File(reader);
+		else
+			throw new IOException("Unexpected class flag " + clazz + " detected in ELF file.");
+	}
+
+	public void extract(Builder builder) {
+		// Uncomment the following line for debug. There ought to be a proper verbose mode.
+		// System.err.println("NewElfDump.extract() entered");
+		
+		try {
+			Object addressSpace = builder.buildAddressSpace("ELF Address Space", 0);
+			List threads = new ArrayList();
+			for (Iterator iter = _file.threadEntries(); iter.hasNext();) {
+				DataEntry entry = (DataEntry) iter.next();
+				threads.add(readThread(entry, builder, addressSpace));
+			}
+			List processes = new ArrayList();
+			for (Iterator iter = _file.processEntries(); iter.hasNext();) {
+				DataEntry entry = (DataEntry) iter.next();
+				processes.add(readProcess(entry, builder, addressSpace, threads));
+			}
+			for (Iterator iter = _file.auxiliaryVectorEntries(); iter.hasNext();) {
+				DataEntry entry = (DataEntry) iter.next();
+				readAuxiliaryVector(entry);
+			}
+			builder.setOSType("ELF");
+			builder.setCPUType(_file._arch.toString());
+			builder.setCPUSubType(readStringAt(_platformIdAddress));
+		} catch (IOException e) {
+			// TODO throw exception or notify builder?
+		} catch (MemoryAccessException e) {
+			// TODO throw exception or notify builder?
+		}
+		
+		// Uncomment the following line for debug. There ought to be a proper verbose mode.
+		// System.err.println("NewElfDump.extract() exited");
+	}
+
+	private void readAuxiliaryVector(DataEntry entry) throws IOException {
+		_file.seek(entry.offset);
+		if (0 != entry.size) {
+			long type = _file.readElfWord();
+			while (AT_NULL != type) {
+				if (AT_PLATFORM == type)
+					_platformIdAddress = _file.readElfWord();
+				else if (AT_ENTRY == type)
+					_file.readElfWord();
+				else if (AT_HWCAP == type)
+					_file.readElfWord(); // TODO extract features in some useful fashion
+				else
+					_file.readElfWord(); // Ignore
+				type = _file.readElfWord();
+			}
+		}
+	}
+
+	private String readStringAt(long address) throws IOException
+	{
+		String toReturn = null;
+		
+		if (isValidAddress(address)) {
+			StringBuffer buf = new StringBuffer();
+			seekToAddress(address);
+			byte b = coreReadByte();
+			for (long i = 1; 0 != b; i++) {
+				buf.append(new String(new byte[] {b}, "ASCII"));
+				b = coreReadByte();
+			}
+			toReturn = buf.toString();
+		}
+		return toReturn;
+	}
+
+	public static boolean isSupportedDump(ClosingFileReader f) throws IOException {
+		f.seek(0);
+		byte[] signature = new byte[EI_NIDENT];
+		f.readFully(signature);
+		return -1 != new String(signature).toLowerCase().indexOf("elf");
+	}
+
+	public static ICoreFileReader dumpFromFile(ClosingFileReader f, boolean verbose) throws IOException {
+		assert isSupportedDump(f);
+
+		f.seek(0);
+		byte[] signature = new byte[EI_NIDENT];
+		f.readFully(signature);
+		boolean isLittleEndian = (ELFDATA2LSB == signature[5]);
+		boolean is64Bit = (ELFCLASS64 == signature[4]);
+		DumpReader reader = readerForEndianess(signature[5], signature[4], f);
+		ElfFile file = fileForClass(signature[4], reader);
+		return new NewElfDump(file, reader, isLittleEndian, is64Bit, verbose);
+	}
+
+	public Iterator getAdditionalFileNames() {
+		return _additionalFileNames.iterator();
+	}
+
+	protected MemoryRange[] getMemoryRangesAsArray() {
+		return (MemoryRange[])_memoryRanges.toArray(new MemoryRange[_memoryRanges.size()]);
+	}
+
+	protected boolean isLittleEndian()
+	{
+		return _isLittleEndian;
+	}
+
+	protected boolean is64Bit()
+	{
+		return _is64Bit;
+	}
+}

Added: incubator/kato/trunk/import/org.apache.kato.common/src/com/ibm/dtfj/corereaders/PageCache.java
URL: http://svn.apache.org/viewvc/incubator/kato/trunk/import/org.apache.kato.common/src/com/ibm/dtfj/corereaders/PageCache.java?rev=754943&view=auto
==============================================================================
--- incubator/kato/trunk/import/org.apache.kato.common/src/com/ibm/dtfj/corereaders/PageCache.java (added)
+++ incubator/kato/trunk/import/org.apache.kato.common/src/com/ibm/dtfj/corereaders/PageCache.java Mon Mar 16 16:41:40 2009
@@ -0,0 +1,264 @@
+/*******************************************************************************
+ * 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
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+/*
+ *
+ * Simple paging cache, to speedup getMemoryBytes
+ * 
+ */
+package com.ibm.dtfj.corereaders;
+
+
+public class PageCache
+{
+	// Cached byte buffer
+	protected byte[] bytes;
+
+//==== Tuning statistics =================================================
+//	private double cacheUse = 0;
+//	private double loadCount = 0;
+//========================================================================
+
+	protected static final int NO_KEY = -1;
+
+	/*
+	 * Abstract view of a 'page' of memory
+	 */
+	public class Page
+	{
+		protected int  slot = -1;
+		protected long base = 0;
+		protected int  span = 0;
+		protected int  key  = NO_KEY;
+
+		// Auto-tuning statistics
+		protected int  used = 1;
+
+//==== Tuning statistics =================================================
+//		public void evict() {
+//			double pageUse = ((double)used)/(span+1);
+//			cacheUse = (cacheUse*loadCount + pageUse) / (loadCount+1);
+//			System.out.println("EVICT ["+
+//				(int)loadCount+"|"+
+//				slot/pageSize+"|"+
+//				(int)(pageUse*100)+"%|"+
+//				(int)(cacheUse*100)+"%|"+
+//				evictPeriod+"|"+
+//				evictGrowth+"]");
+//		}
+//========================================================================
+
+		/*
+		 * Query page status
+		 */
+		public boolean isEmpty()
+		{
+			return (key == NO_KEY);
+		}
+
+		/*
+		 * Push data into the page
+		 */
+		public void push(int forKey, long vaddr, byte[] buf)
+		{
+			// Fresh page update
+			System.arraycopy(buf, 0, bytes, slot, buf.length);
+
+			// May be truncated
+			base = vaddr;
+			span = buf.length;
+			key  = forKey;
+
+//==== Tuning statistics =================================================
+//			loadCount++;
+//========================================================================
+		}
+
+		/*
+		 * Pull data from the page
+		 */
+		public byte[] pull(int forKey, long vaddr, int size)
+		{
+			if (key != forKey || key == NO_KEY) {
+				return null;
+			}
+
+			int delta = (int)(vaddr - base);
+
+			// Safety check in case of truncation
+			if (delta > span-size) {
+				size = span-delta;
+			}
+			if (size < 0) {
+				return null;
+			}
+
+			byte[] buf = new byte[size];
+
+			// Fill byte buffer using cached data
+			System.arraycopy(bytes, slot + delta, buf, 0, size);
+			used += size;
+
+			// When we have enough, begin evicting again
+			if (used >= (span/hiUsage) && evictPeriod > 1) {
+
+				// Halve eviction delay
+				evictPeriod >>>= 1;
+				evictTick = 0;
+
+				// Drop rate of delay
+				evictGrowth = 1;
+			}
+
+			return buf;
+		}
+	}
+
+	// Default cache parameters
+	public int numPages = 16;
+	public int pageSize = 256*1024;
+
+	// Eviction throttles
+	public int hiUsage = 5;
+	public int loUsage = 20;
+
+	// Page details
+	protected Page[] pages;
+
+	// Pseudo-LRU tree
+	protected long lruBits = 0;
+
+	// Auto-tuning variables
+	protected int evictTick = 0;
+	protected int evictPeriod = 1;
+	protected int evictGrowth = 1;
+
+	// ... and their limits
+	protected int maxPeriod = 64*1024;
+	protected int maxGrowth = 32;
+
+	/*
+	 * Constructor utility
+	 */
+	protected void initialize()
+	{
+		pages = new Page[numPages];
+		bytes = new byte[numPages*pageSize];
+
+		for (int i = 0; i < numPages; i++) {
+			pages[i] = new Page();
+			pages[i].slot = i*pageSize;
+		}
+	}
+
+
+	/*
+	 * Construct a cache with default heuristics
+	 */
+	PageCache()
+	{
+		initialize();
+	}
+
+
+	/*
+	 * Construct a cache with specific heuristics
+	 */
+	PageCache(int _numPages, int _pageSize, double _hiDensity, double _loDensity)
+	{
+		numPages = _numPages;
+		pageSize = _pageSize;
+
+		hiUsage  = (int)(1.0/_hiDensity);
+		loUsage  = (int)(1.0/_loDensity);
+
+		initialize();
+	}
+
+
+	/*
+	 * Have we cached something matching this request?
+	 */
+	public Page find(int key, long vaddr, int size)
+	{
+		// Wrong size to cache
+		if (size < 0 || size > pageSize) {
+			return null;
+		}
+
+		// Match request to cached page
+		for (int i = 0; i < numPages; i++) {
+			Page p = pages[i];
+
+			if (p.key == key) {
+				int delta = (int)(vaddr - p.base);
+
+				// We're close to an existing page
+				if (0 <= delta && delta <= p.span-size) {
+					return p;
+				}
+			}
+		}
+
+		// Auto-tuning to limit bad evictions
+		if (evictTick++ % evictPeriod > 0) {
+			return null;
+		}
+
+		int index = 0;
+
+		// Find LRU page and update tree...
+		while (index < numPages) {
+
+			long lruSite = 1 << index;
+			long branch = (~lruBits) & lruSite;
+
+			// Flip LRU branch
+			lruBits &= ~lruSite;
+			lruBits |= branch;
+
+			if (branch == 0) {
+				index += index;		// left
+			} else {
+				index += (index+1);	// right
+			}
+		}
+
+		Page lruPage = pages[index-numPages];
+
+		// Peg evict rate otherwise we risk starving the cache
+		if (lruPage.used < (lruPage.span/loUsage) && evictPeriod < maxPeriod) {
+
+			// Wait longer before evicting
+			evictPeriod += evictGrowth;
+			evictTick = 1;
+
+			// Increase rate of delay
+			if (evictGrowth < maxGrowth) {
+				evictGrowth <<= 1;
+			}
+		}
+
+//==== Tuning statistics =================================================
+//		lruPage.evict();
+//========================================================================
+
+		// Reset page (span will be set when it's pushed)
+		lruPage.base = vaddr;
+		lruPage.span = 0;
+		lruPage.used = 0;
+		lruPage.key  = NO_KEY;
+
+		return lruPage;
+	}
+}

Added: incubator/kato/trunk/import/org.apache.kato.common/src/com/ibm/dtfj/corereaders/Register.java
URL: http://svn.apache.org/viewvc/incubator/kato/trunk/import/org.apache.kato.common/src/com/ibm/dtfj/corereaders/Register.java?rev=754943&view=auto
==============================================================================
--- incubator/kato/trunk/import/org.apache.kato.common/src/com/ibm/dtfj/corereaders/Register.java (added)
+++ incubator/kato/trunk/import/org.apache.kato.common/src/com/ibm/dtfj/corereaders/Register.java Mon Mar 16 16:41:40 2009
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * 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
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+/*
+ * Represents a register for a thread.  The name is very system dependent.
+ */
+package com.ibm.dtfj.corereaders;
+
+public class Register {
+	String name;
+	int size;
+	long value;
+
+	public Register(String name, int size, long value) {
+		this.name = name;
+		this.size = size;
+		long mask = 0;
+		for (int i = 0; i < size; i++)
+			mask = (mask << 1) | 1;
+		this.value = value & mask;
+	}
+
+	/**
+	 * @return the name of the register
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * @return the number of bits in the register
+	 */
+	public int getSize() {
+		return size;
+	}
+
+	/**
+	 * @return the value held in the register
+	 */
+	public long getValue() {
+		return value;
+	}
+}

Added: incubator/kato/trunk/import/org.apache.kato.common/src/com/ibm/dtfj/corereaders/StackFrame.java
URL: http://svn.apache.org/viewvc/incubator/kato/trunk/import/org.apache.kato.common/src/com/ibm/dtfj/corereaders/StackFrame.java?rev=754943&view=auto
==============================================================================
--- incubator/kato/trunk/import/org.apache.kato.common/src/com/ibm/dtfj/corereaders/StackFrame.java (added)
+++ incubator/kato/trunk/import/org.apache.kato.common/src/com/ibm/dtfj/corereaders/StackFrame.java Mon Mar 16 16:41:40 2009
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * 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
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+package com.ibm.dtfj.corereaders;
+
+ 
+public class StackFrame {
+	
+	long position;
+	long retAddr;
+	
+	
+	public StackFrame(long stackPosition, long retAddr)  {
+		this.retAddr = retAddr;
+		position = stackPosition;
+	}
+	 
+
+ 
+
+	/**
+	 * @return Returns the position.
+	 */
+	public long getPosition() {
+		return position;
+	}
+	/**
+	 * @return Returns the retAddr.
+	 */
+	public long getRetAddr() {
+		return retAddr;
+	}
+	
+	public String toString() {
+		StringBuffer sb= new StringBuffer( "(Bp: 0x");
+	 
+		String ra = Long.toHexString(position);
+//		ra = DumpUtils.padToPtrSize(ra);
+		sb.append( ra + ")");
+//		sb.append("  0x" + DumpUtils.padToPtrSize(Long.toHexString(retAddr)));
+		sb.append("  0x" + Long.toHexString(retAddr));
+		String location = Symbol.getSymbolForAddress(retAddr);
+		if (null != location) {
+			sb.append( "  <==");
+			sb.append(location);
+		}
+			 
+		return sb.toString();
+			
+		 
+		
+		
+	}	
+}

Added: incubator/kato/trunk/import/org.apache.kato.common/src/com/ibm/dtfj/corereaders/Symbol.java
URL: http://svn.apache.org/viewvc/incubator/kato/trunk/import/org.apache.kato.common/src/com/ibm/dtfj/corereaders/Symbol.java?rev=754943&view=auto
==============================================================================
--- incubator/kato/trunk/import/org.apache.kato.common/src/com/ibm/dtfj/corereaders/Symbol.java (added)
+++ incubator/kato/trunk/import/org.apache.kato.common/src/com/ibm/dtfj/corereaders/Symbol.java Mon Mar 16 16:41:40 2009
@@ -0,0 +1,206 @@
+/*******************************************************************************
+ * 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
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+/*
+ *  Class to maintain a list of addresses and coverage extents and a
+ * symbolic name - then given an input address will convert this into 
+ * a string showing offset from the symbol. 
+ */
+package com.ibm.dtfj.corereaders;
+
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+ 
+public class Symbol {
+	
+	String symbolName;
+	long symbolStart;
+	long symbolEnd;  // -1 = unknown
+	int symbolType;  // -1 = unknown
+	int symbolBinding; // -1 = unknown
+	
+	protected static HashMap knownSymbolsByName;  
+	protected static TreeMap symbolTree;
+	
+	final static int STB_UNKNOWN = -1;
+	final static int STB_LOCAL = 0;
+	final static int STB_GLOBAL = 1;
+	final static int STB_WEAK = 2;
+	
+	   // values for st_info field
+    static final int STT_NOTYPE = 0;
+    static final int STT_OBJECT = 1;
+    static final int STT_FUNC = 2;
+    static final int STT_SECTION = 3;
+    static final int STT_FILE = 4;
+    static final int STT_COMMON = 5;
+    static final int STT_TLS = 6;
+    static final int STT_LOOS = 10;
+    static final int STT_HIOS = 12;
+    static final int STT_LOPROC = 13;
+    static final int STT_HIPROC = 15;
+	
+	
+	public Symbol(String name, long address, int extent, int type, int bind) {
+		
+		// check don't already have this name 
+		
+		 
+		if (null == knownSymbolsByName) {
+			knownSymbolsByName = new HashMap();
+		}
+		Object o = knownSymbolsByName.get(name);
+		if (o == null ) {
+		
+			symbolName = name;
+			symbolStart = address;
+			symbolType = type;
+			symbolBinding = bind;
+			// we use -1 for symbols whose extent is unknown 
+			if (extent != -1) {
+				symbolEnd = address+extent;
+			} else {
+				symbolEnd = -1;
+			}
+		
+			// Now update the Hash map of symbols
+			 
+			knownSymbolsByName.put(name,this);
+			// ... and into the range tree
+			if (null == symbolTree) {
+				
+				Comparator c = new Symbol.SymbolComparator();
+				symbolTree = new TreeMap(c);
+			}
+			symbolTree.put(new Long(address),this);
+			 
+		}
+		
+	}
+	
+	public static Symbol getSymbol(String name) {
+		Symbol retSym = null;
+		
+		retSym = (Symbol)knownSymbolsByName.get(name);
+		
+		return retSym;
+		
+	}
+	
+	public static String getSymbolForAddress(long address) {
+		String retString = null;
+		 
+		SortedMap head = (SortedMap) symbolTree.headMap(new Long(address));
+		
+		// So now we look at bottom of tail and hopefully we might have a 
+		// symbol covering this address.... 
+		if (head != null && !head.isEmpty()) {
+			 
+			Symbol s = (Symbol) symbolTree.get(head.lastKey());
+			if (s.symbolEnd == -1) {
+				
+			} else {
+				if (address <= s.symbolEnd && address > s.symbolStart) {
+					long diff = address - s.symbolStart;
+					retString =  s.symbolName + "+0x" + Long.toHexString(diff); 
+				}
+			}
+		}
+		 
+		 
+		
+		 
+		return retString;
+	}
+	
+	static final class SymbolComparator implements Comparator {
+
+		/* (non-Javadoc)
+		 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
+		 */
+		public int compare(Object arg0, Object arg1) {
+			 
+			long addr0=0;
+			long addr1=0;
+			// arg0 and arg1 will be Symbol objects 
+			if (arg0 instanceof Symbol) {
+				Symbol S0 = (Symbol) arg0;
+				Symbol S1 = (Symbol) arg1;
+				addr0 = S0.symbolStart;
+				addr1 = S1.symbolStart;
+			} else {
+				addr0 = ((Long)arg0).longValue();
+				addr1 = ((Long)arg1).longValue();
+			}
+			
+			// both +ve
+			if (addr0 >= 0 && addr1 >=0) {
+				if (addr0 == addr1) return 0;
+				if (addr0 < addr1) return -1;
+				return 1;
+			}
+			
+			// both -ve 
+			if (addr0 < 0 && addr1 < 0) {
+				if (addr0 == addr1) return 0;
+				if (addr0 < addr1) return 1;
+				return -1;
+			}
+			
+			if (addr0 < 0 && addr1 >=0) {
+				return 1;
+			}
+			
+			return -1;
+		}
+		
+	}
+
+ 
+
+ 
+	/**
+	 * @return Returns the symbolEnd.
+	 */
+	public long getSymbolEnd() {
+		return symbolEnd;
+	}
+	/**
+	 * @return Returns the symbolName.
+	 */
+	public String getSymbolName() {
+		return symbolName;
+	}
+	/**
+	 * @return Returns the symbolStart.
+	 */
+	public long getSymbolStart() {
+		return symbolStart;
+	}
+	
+	public static Iterator getSymbolsIterator() {
+		return symbolTree.keySet().iterator();
+		//return knownSymbolsByName.keySet().iterator();
+		 
+	}
+	
+	public static Symbol getSymbolUsingValue(Long l) {
+		Symbol s = (Symbol) symbolTree.get(l);
+		return s;
+	}
+	 
+}