⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 elf.java

📁 纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统
💻 JAVA
字号:
// ----------------------------------------
//  Elf ( support ELF format (32bit for i[34]86))
//
//  Copyright (C) 1999  Kiyoka Nishiyama
//
//  $Date: 2003/11/25 11:54:01 $ 
//  $Id: Elf.java,v 1.1 2003/11/25 11:54:01 epr Exp $
// ----------------------------------------
package org.jnode.linker;

//
//
// typedef struct elf32_hdr{
//   EI_NIDENT = 16;
//   char	e_ident[EI_NIDENT];      :  e_ident[0...3] = '\x7f' "ELF" $B$G$"$k$3$H(B
//   Elf32_Half	e_type;                  :  ET_EXEC $B$G$"$k$3$H(B
//   Elf32_Half	e_machine;               :  EM_386 $B$G$"$k$3$H(B ($B>-Mh(B EM_486$B%5%]!<%H$9$k(B)
//   Elf32_Word	e_version;
//   Elf32_Addr	e_entry;  /* Entry point */
//   Elf32_Off	e_phoff;
//   Elf32_Off	e_shoff;
//   Elf32_Word	e_flags;
//   Elf32_Half	e_ehsize;
//   Elf32_Half	e_phentsize;
//   Elf32_Half	e_phnum;
//   Elf32_Half	e_shentsize;
//   Elf32_Half	e_shnum;
//   Elf32_Half	e_shstrndx;
// } Elf32_Ehdr;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Collection;
import java.util.Iterator;
import java.util.Vector;

import org.jnode.assembler.x86.X86Stream;
import org.jnode.assembler.x86.X86Stream.X86ObjectRef;


public class Elf {
	static final short ET_NONE = 0; /* No file type */
	static final short ET_REL = 1; /* Relocatable file */
	static final short ET_EXEC = 2; /* Executable file */
	static final short ET_DYN = 3; /* Shared object file */
	static final short ET_CORE = 4; /* Core file */
	static final short ET_NUM = 5; /* Number of defined types.  */

	/* These constants define the various ELF target machines */
	static final short EM_386 = 3;
	static final short EM_486 = 6; /* Perhaps disused */

	/* Version constants */
	static final int EV_NONE = 0;
	static final int EV_CURRENT = 1;

	// These constants define the sizes of the various structures
	static final short EHSIZE = 52; // Elf header size
	static final short EHSIZE_EXT = 64; // Elf header size + alignment
	static final short SHENTSIZE = 40; // Section header entry size
	// Align on 4 bytes
	static final short ALIGN = 4;

	static final short EI_MAG0 = 0; //File identification
	static final short EI_MAG1 = 1; //File identification
	static final short EI_MAG2 = 2; //File identification
	static final short EI_MAG3 = 3; //File identification
	static final short EI_CLASS = 4; //File class
	static final short EI_DATA = 5; //Data encoding
	static final short EI_VERSION = 6; //File version
	static final short EI_PAD = 7; //Start of padding bytes
	static final short EI_NIDENT = 16; //Size of e_ident[]

	byte e_ident[] = new byte[EI_NIDENT]; //   :  e_ident[0...3] = '\x7f' "ELF"
	short e_type;
	short e_machine;
	int e_version;
	int e_entry; // Entry point
	int e_phoff;
	int e_shoff;
	int e_flags;
	short e_shentsize;
	short e_shstrndx;

	Vector sections;
	Section symSection;
	Section strSection;
	Section shstrSection;
	Section textSection;
	Section reltextSection;
	Section dataSection;
	Section reldataSection;
	Section bssSection;

	private Elf(short type) {
		e_ident[EI_MAG0] = 0x7f;
		e_ident[EI_MAG1] = (byte) 'E';
		e_ident[EI_MAG2] = (byte) 'L';
		e_ident[EI_MAG3] = (byte) 'F';
		e_ident[EI_CLASS] = 1; // 0=none, 1=32-bit, 2=64-bit
		e_ident[EI_DATA] = 1; // 0=none, 1=lsb, 2=msb
		e_ident[EI_VERSION] = (byte) EV_CURRENT;
		e_type = type;
		e_machine = EM_386;
		e_version = EV_CURRENT;
		e_entry = 0;
		e_phoff = 0;
		e_shoff = 0;
		e_flags = 0;
		e_shstrndx = 0;
		sections = new Vector();
		if (e_type != ET_NONE) {
			// Section 0 should be NULL
			sections.addElement(Section.newNullInstance(this));

			// Add this sections first! Otherwise we cannot create names for the sections
			sections.addElement(shstrSection = Section.newStrTabSection(this));
			e_shstrndx = (short) (sections.size() - 1);

			// Now add a String table
			sections.addElement(strSection = Section.newStrTabSection(this));

			// Now add a Symbol table
			sections.addElement(symSection = Section.newSymTabSection(this));

			// Add a .text section
			sections.addElement(textSection = Section.newTextSection(this));

			// Add a .data section
			sections.addElement(dataSection = Section.newDataSection(this));

			// Add a .bss section
			sections.addElement(bssSection = Section.newBssSection(this));

			// Add a .rel.text section			
			sections.addElement(
				reltextSection =
					Section.newRelTabSection(this, symSection, textSection));

			// Add a .rel.data section			
			sections.addElement(
				reldataSection =
					Section.newRelTabSection(this, symSection, dataSection));
		}
	}

	private Elf() {
		this(ET_NONE);
	}

	public static Elf newRelInstance() {
		return new Elf(ET_REL);
	}

	public static Elf newExeInstance() {
		return new Elf(ET_EXEC);
	}

	public static Elf newFromFile(String filename) throws IOException {
		Elf elf = new Elf();
		elf.load(filename);
		return elf;
	}

	/**
	 * Wrap my contents into an elf object file.
	 * @return Elf
	 */
	public static Elf toElf(X86Stream stream) {
		final Elf elf = Elf.newRelInstance();
		// Store the emitted objects in the text section		
		final Section textSection = elf.getSectionByName(".text");
		final Section relTextSection = elf.getRelTextSection();
		textSection.setBody(stream.getBytes(), 0, stream.getLength());

		// Add all symbols & relocs
		final Collection objectRefs = stream.getObjectRefs();
		System.out.println("Creating " + objectRefs.size() + " symbols");
		int cnt = 0;
		for (Iterator i = objectRefs.iterator(); i.hasNext(); cnt++) {
			/*if ((cnt % 1000) == 0) {
				long end = System.currentTimeMillis();
				System.out.println("At " + cnt + ", it took " + (end-start) + "ms");
				start = end;
			}*/
			final X86ObjectRef ref = (X86ObjectRef) i.next();
			final Object obj = ref.getObject();
			final Symbol sym;
			if (ref.isResolved()) {
				sym = new Symbol(elf, obj.toString(), ref.getOffset(), textSection);
			} else {
				final int[] offsets = ref.getUnresolvedOffsets();
				sym = new Symbol(elf, obj.toString(), 0, null);
				for (int j = 0; j < offsets.length; j++) {
					if (ref.isRelJump()) {
						relTextSection.addPcRelReloc(sym, offsets[j]);
					} else {
						relTextSection.addAbsReloc(sym, offsets[j]);
					}
				}
			}
			if (ref.isPublic()) {
				sym.setBind(Symbol.STB_GLOBAL);
			} else {
				sym.setBind(Symbol.STB_LOCAL);
			}
			elf.addSymbol(sym);
		}
		return elf;
	}

	// --------------------------------------------
	// Header
	// --------------------------------------------
	public boolean isRel() {
		return (e_type == ET_REL);
	}
	public boolean isExe() {
		return (e_type == ET_EXEC);
	}

	public int getEntry() {
		return e_entry;
	}
	public void setEntry(int e) {
		e_entry = e;
	}

	// --------------------------------------------
	// Strings
	// --------------------------------------------
	public String getString(int addr) {
		return strSection.getString(addr);
	}
	public int addString(String name) {
		return strSection.addString(name);
	}
	public String getSHString(int addr) {
		return shstrSection.getString(addr);
	}
	protected Section getSHStrSection() {
		return shstrSection;
	}

	// --------------------------------------------
	// Symbols
	// --------------------------------------------
	public int getNoSymbols() {
		return symSection.getNoSymbols();
	}
	public Symbol getSymbol(int index) {
		return symSection.getSymbol(index);
	}
	public Symbol getSymbolByAddress(int address) {
		return symSection.getSymbolByAddress(address);
	}
	public void addSymbol(Symbol s) {
		symSection.addSymbol(s);
	}
	public int getIndexOfSymbol(Symbol symbol) {
		return symSection.getIndexOfSymbol(symbol);
	}

	// --------------------------------------------
	// Relocs
	// --------------------------------------------
	public Section getRelTextSection() {
		return reltextSection;
	}
	public Section getRelDataSection() {
		return reldataSection;
	}

	// --------------------------------------------
	// Sections
	// --------------------------------------------
	public int getNoSections() {
		return sections.size();
	}
	public Section getSection(int index) {
		return ((index >= 0) && (index < getNoSections()))
			? (Section) sections.elementAt(index)
			: null;
	}
	public Section getSectionByName(String name) {
		for (int i = 1; i < getNoSections(); i++) {
			Section s = getSection(i);
			if (s.getName().equals(name))
				return s;
		}
		return null;
	}
	protected int getSectionIndex(Section s) {
		for (int i = 0; i < getNoSections(); i++) {
			if (s == getSection(i))
				return i;
		}
		return -1;
	}

	// --------------------------------------------
	// Loading & Storing
	// --------------------------------------------

	// Load the ELF data to file
	private void load(String filename) throws IOException {
		RandomAccessFile in;
		int i;
		int e_shnum;
		in = new RandomAccessFile(filename, "r");
		try {	
			// Load the elf header
			LoadUtil.bytes(in, e_ident);
			e_type = LoadUtil.little16(in);
			e_machine = LoadUtil.little16(in);
			e_version = LoadUtil.little32(in);
			e_entry = LoadUtil.little32(in);
			e_phoff = LoadUtil.little32(in);
			e_shoff = LoadUtil.little32(in);
			e_flags = LoadUtil.little32(in);
			/*e_ehsize      =*/
			LoadUtil.little16(in);
			/*e_phentsize   =*/
			LoadUtil.little16(in);
			/*e_phnum       =*/
			LoadUtil.little16(in);
			e_shentsize = LoadUtil.little16(in);
			e_shnum = LoadUtil.little16(in);
			e_shstrndx = LoadUtil.little16(in);
	
			if (!((e_ident[0] == 0x7F)
				&& (e_ident[1] == 'E')
				&& (e_ident[2] == 'L')
				&& (e_ident[3] == 'F'))) {
				throw new IOException("Not Elf Format :" + filename);
			}
	
			if (e_machine != EM_386) {
				throw new IOException("Not Match CPU Type :" + filename);
			}
	
			// Load the program header (ignored for now)
			in.seek(e_phoff);
	
			// Load the section headers
			in.seek(e_shoff);
			for (i = 0; i < e_shnum; i++) {
				Section s = Section.newInstance(this, in);
				sections.addElement(s);
				//System.out.println("Read section " + i);
			}
	
			// Load the sections
			for (i = 0; i < e_shnum; i++) {
				//System.out.println("Read section body " + i);
				Section s = (Section) sections.elementAt(i);
				s.loadBody(in);
				if (i == e_shstrndx)
					shstrSection = s;
				else if (s.isSymTab())
					symSection = s;
				else if (s.isStrTab())
					strSection = s;
			}
		} finally {
			in.close();
		}
	}

	// Store the ELF data from file
	public boolean store(String filename) throws IOException {
		FileOutputStream out;
		int i;
		int ofs = 0;
		out = new FileOutputStream(filename);

		// Prepare to store the sections and initialize their offsets
		ofs = EHSIZE_EXT;

		// Skip section 0, since it is always 0
		for (i = 1; i < getNoSections(); i++) {
			Section s = getSection(i);
			s.setOffset(ofs);
			ofs += s.prepareStoreBody();
			// align
			while ((ofs % ALIGN) != 0)
				ofs++;
		}
		e_shoff = ofs;

		// Now start storing
		ofs = 0;

		// Store the header
		ofs += StoreUtil.bytes(out, e_ident);
		ofs += StoreUtil.little16(out, e_type);
		ofs += StoreUtil.little16(out, e_machine);
		ofs += StoreUtil.little32(out, e_version);
		ofs += StoreUtil.little32(out, e_entry);
		ofs += StoreUtil.little32(out, 0);
		ofs += StoreUtil.little32(out, e_shoff);
		ofs += StoreUtil.little32(out, e_flags);
		ofs += StoreUtil.little16(out, EHSIZE);
		ofs += StoreUtil.little16(out, 0);
		ofs += StoreUtil.little16(out, 0);
		ofs += StoreUtil.little16(out, SHENTSIZE);
		ofs += StoreUtil.little16(out, getNoSections());
		ofs += StoreUtil.little16(out, e_shstrndx);

		// Align till 0x40
		ofs += StoreUtil.little32(out, 0);
		ofs += StoreUtil.little32(out, 0);
		ofs += StoreUtil.little32(out, 0);

		// Just a check
		if (ofs != EHSIZE_EXT) {
			throw new RuntimeException("Strange, invalid header size");
		}

		// Write the section bodies
		// Here again, skip section 0, since it is always empty
		for (i = 1; i < getNoSections(); i++) {
			Section s = getSection(i);
			if (s.getOffset() != ofs) {
				throw new RuntimeException(
					"Strange, offset mismatch in section-body (section="
						+ i
						+ ", ofs="
						+ ofs
						+ ", expected="
						+ s.getOffset());
			}
			ofs += s.storeBody(out);
			// align
			while ((ofs % ALIGN) != 0) {
				ofs += StoreUtil.little8(out, 0);
			}
			System.out.println("store section " + i + ", ofs=" + ofs + ", name=" + s.getName());
		}

		// Write the section headers
		for (i = 0; i < getNoSections(); i++) {
			ofs += getSection(i).store(out);
		}

		out.close();

		return (true);
	}

	public void print() {
		System.out.println("----- Elf Header -----");
		System.out.println("e_type        : " + Integer.toString(e_type, 16));
		System.out.println(
			"e_machine     : " + Integer.toString(e_machine, 16));
		System.out.println(
			"e_version     : " + Integer.toString(e_version, 16));
		System.out.println("e_entry       : " + Integer.toString(e_entry, 16));
		//		System.out.println( "e_phentsize   : " + Integer.toString( e_phentsize,    16));
		//	System.out.println( "e_phnum       : " + Integer.toString( e_phnum,        16));
		System.out.println("e_phoff       : " + Integer.toString(e_phoff, 16));
		System.out.println(
			"e_shnum       : " + Integer.toString(getNoSections(), 16));
		System.out.println("e_shoff       : " + Integer.toString(e_shoff, 16));
		System.out.println(
			"e_shstrndx    : " + Integer.toString(e_shstrndx, 16));
		System.out.println(" ----- BRK ----- ");
		//		System.out.println( " strtab = [" + strtab + "]");
	}

	public static void main(String args[]) throws Exception {
		Elf elf = newFromFile("test.o");
		elf.print();

		System.out.println("\nNow do the store");
		elf = newRelInstance();
		elf.store("test-elf.o");
		elf.print();

		//		System.out.println("\nNow try to read it back again");
		//		elf = newFromFile("test-elf.o");
		//		elf.print();
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -