Package se.sics.mspsim.util

Source Code of se.sics.mspsim.util.ELF$FileInfo

/**
* Copyright (c) 2007, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
*    may be used to endorse or promote products derived from this software
*    without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of MSPSim.
*
* -----------------------------------------------------------------
*
* ELF
*
* Author  : Joakim Eriksson
* Created : Sun Oct 21 22:00:00 2007
*/

package se.sics.mspsim.util;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import se.sics.mspsim.debug.DwarfReader;
import se.sics.mspsim.debug.StabDebug;

public class ELF {

  // private static final int EI_NIDENT = 16;
  private static final int EI_ENCODING = 5;
  private static final int[] MAGIC = new int[] {0x7f, 'E', 'L', 'F'};
 
  public static final boolean DEBUG = false;
 
 
  boolean encMSB = true;
  int type;
  int machine;
  int version;
  int entry;
  int phoff;
  int shoff;
  int flags;
  int ehsize;
  int phentsize;
  int phnum;
  int shentsize;
  int shnum;
  int shstrndx;

  byte[] elfData;
  private int pos = 0;

  private ELFSection sections[];
  private ELFProgram programs[];
  private ArrayList<FileInfo> files = new ArrayList<FileInfo>();

  ELFSection strTable;
  ELFSection symTable;
  ELFSection dbgStab;
  public ELFSection dbgStabStr;

  ELFDebug debug;

  public ELF(byte[] data) {
    elfData = data;
    setPos(0);
  }

  /* check if the file exists and is an ELF file */
  public static boolean isELF(File file) {
    try {
      InputStream input = new BufferedInputStream(new FileInputStream(file));
      for (int i = 0; i < MAGIC.length; i++) {
        if (MAGIC[i] != input.read()) {
          input.close();
          return false;
        }
      }
      input.close();
      return true;
    } catch(IOException ioe) {
      // ignore and return false - this is not an elf.
      return false;
    }
  }

  private void readHeader() throws ELFException {
    for (int i = 0; i < MAGIC.length; i++) {
      if (elfData[i] != (byte) (MAGIC[i] & 0xff)) {
        throw new ELFException("Not an elf file");
      }
    }
   
    if (elfData[EI_ENCODING] == 2) {
      encMSB = true;
    } else if (elfData[EI_ENCODING] == 1) {
      encMSB = false;
    } else {
      throw new ELFException("Illegal encoding: " + elfData[EI_ENCODING]);
    }
   
    setPos(getPos() + 16);
    type = readElf16();
    machine = readElf16();
    version = readElf32();
    entry = readElf32();
    phoff = readElf32();
    shoff = readElf32();
    flags = readElf32();
    ehsize = readElf16();
    phentsize = readElf16();
    phnum = readElf16();
    shentsize = readElf16();
    shnum = readElf16();
    shstrndx = readElf16();

    if (DEBUG) {
      System.out.println("-- ELF Header --");
      System.out.println("type: " + Integer.toString(type, 16));
      System.out.println("machine: " + Integer.toString(machine, 16));
      System.out.println("version: " + Integer.toString(version, 16));
      System.out.println("entry: " + Integer.toString(entry, 16));
      System.out.println("phoff: " + Integer.toString(phoff, 16));
      System.out.println("shoff: " + Integer.toString(shoff, 16));
      System.out.println("flags: " + Integer.toString(flags, 16));
      System.out.println("ehsize: " + Integer.toString(ehsize, 16));
      System.out.println("phentsize: " + Integer.toString(phentsize, 16));
      System.out.println("phentnum: " + Integer.toString(phnum, 16));
      System.out.println("shentsize: " + Integer.toString(shentsize, 16));
      System.out.println("shentnum: " + Integer.toString(shnum, 16));
      System.out.println("shstrndx: " + Integer.toString(shstrndx, 16));
    }
  }

  private ELFSection readSectionHeader() {
    ELFSection sec = new ELFSection();
    sec.name = readElf32();
    sec.type = readElf32();
    sec.flags = readElf32();
    sec.addr = readElf32();
    sec.setOffset(readElf32());
    sec.size = readElf32();
    sec.link = readElf32();
    sec.info = readElf32();
    sec.addralign = readElf32();
    sec.setEntrySize(readElf32());
    sec.elf = this;
    return sec;
  }

  private ELFProgram readProgramHeader() {
    ELFProgram pHeader = new ELFProgram();
    pHeader.type = readElf32();
    pHeader.offset = readElf32();
    pHeader.vaddr = readElf32();
    pHeader.paddr = readElf32();
    pHeader.fileSize = readElf32();
    pHeader.memSize = readElf32();
    pHeader.flags = readElf32();
    pHeader.align = readElf32();
    // 8 * 4 = 32
    if (phentsize > 32) {
      System.out.println("Program Header Entry SIZE differs from specs?!?!??!?!?***");
    }
    return pHeader;
  }

  public int getSectionCount() {
      return shnum;
  }

  public ELFSection getSection(int index) {
      return sections[index];
  }

  public int readElf32() {
      int val = readElf32(getPos());
      setPos(getPos() + 4);
      return val;
  }

  public int readElf16() {
      int val = readElf16(getPos());
      setPos(getPos() + 2);
      return val;
  }
 
  public int readElf8() {
      int val = readElf16(getPos());
      setPos(getPos() + 1);
      return val;
  }
 
  int readElf32(int pos) {
    int b = 0;
    if (encMSB) {
      b = (elfData[pos++] & 0xff) << 24 |
  ((elfData[pos++] & 0xff) << 16) |
  ((elfData[pos++] & 0xff) << 8) |
  (elfData[pos++] & 0xff);
    } else {
      b = (elfData[pos++] & 0xff) |
  ((elfData[pos++] & 0xff) << 8) |
  ((elfData[pos++] & 0xff) << 16) |
  ((elfData[pos++] & 0xff) << 24);
    }
    return b;
  }

  int readElf16(int pos) {
    int b = 0;
    if (encMSB) {
      b = ((elfData[pos++] & 0xff) << 8) |
  (elfData[pos++] & 0xff);
    } else {
      b = (elfData[pos++] & 0xff) |
  ((elfData[pos++] & 0xff) << 8);
    }
    return b;
  }

  int readElf8(int pos) {
    return elfData[pos++] & 0xff;
  }

  public static void printBytes(String name, byte[] data) {
    System.out.print(name + " ");
    for (byte element : data) {
      System.out.print("" + (char) element);
    }
    System.out.println("");
  }

  private void readSections() {
    setPos(shoff);

    sections = new ELFSection[shnum];
    for (int i = 0, n = shnum; i < n; i++) {
      sections[i] = readSectionHeader();
      if (sections[i].type == ELFSection.TYPE_SYMTAB) {
  symTable = sections[i];
      }
      if (i == shstrndx) {
  strTable = sections[i];
      }
    }

    boolean readDwarf = false;
    /* Find sections */
    for (int i = 0, n = shnum; i < n; i++) {
        String name = sections[i].getSectionName();
        if (DEBUG) {
          System.out.println("ELF-Section: " + name);
        }
      if (".stabstr".equals(name)) {
  dbgStabStr = sections[i];
      }
      if (".stab".equals(name)) {
  dbgStab = sections[i];
      }
      if (".debug_aranges".equals(name) ||
          ".debug_line".equals(name)) {
          readDwarf = true;
      }
    }
    if (readDwarf) {
        DwarfReader dwarf = new DwarfReader(this);
        dwarf.read();
        debug = dwarf;
    }

  }

  private void readPrograms() {
    setPos(phoff);
    programs = new ELFProgram[phnum];
    for (int i = 0, n = phnum; i < n; i++) {
      programs[i] = readProgramHeader();
      if (DEBUG) {
  System.out.println("-- Program header --\n" + programs[i].toString());
      }
    }
  }

  public void readAll() throws ELFException {
    readHeader();
    readPrograms();
    readSections();
    if (dbgStab != null) {
      debug = new StabDebug(this, dbgStab, dbgStabStr);
    }
  }

  public void loadPrograms(int[] memory) {
    for (int i = 0, n = phnum; i < n; i++) {
      // paddr or vaddr???
      loadBytes(memory, programs[i].offset, programs[i].paddr,
    programs[i].fileSize, programs[i].memSize);
    }
  }

  private void loadBytes(int[] memory, int offset, int addr, int len,
       int fill) {
    if (DEBUG) {
      System.out.println("Loading " + len + " bytes into " +
             Integer.toString(addr, 16) + " fill " + fill);
    }
    for (int i = 0, n = len; i < n; i++) {
      memory[addr++] = elfData[offset++] & 0xff;
    }
    if (fill > len) {
      int n = fill - len;
      if (n + addr > memory.length) {
  n = memory.length - addr;
      }
      for (int i = 0; i < n; i++) {
  memory[addr++] = 0;
      }
    }
  }

  public ELFDebug getDebug() {
    return debug;
  }

  public DebugInfo getDebugInfo(int adr) {
      if (debug != null) {
          return debug.getDebugInfo(adr);
      }
      return null;
  }

  public String lookupFile(int address) {
    if (debug != null) {
        DebugInfo di = debug.getDebugInfo(address);
        if (di != null) {
            return di.getFile();
        }
    }
    for (int i = 0; i < files.size(); i++) {
      FileInfo fi = files.get(i);
      if (address >= fi.start && address <= fi.end) {
        return fi.name;
      }
    }
    return null;
  }

  public MapTable getMap() {
    MapTable map = new MapTable();
    int sAddrHighest = -1;

    ELFSection name = sections[symTable.link];
    int len = symTable.size;
    int count = len / symTable.getEntrySize();
    int addr = symTable.getOffset();
    String currentFile = null;
    if (DEBUG) {
      System.out.println("Number of symbols:" + count);
    }
    int currentAddress = 0;
    for (int i = 0, n = count; i < n; i++) {
      setPos(addr);
      int nI = readElf32();
      String sn = name.getName(nI);
      int sAddr = readElf32();
      int size = readElf32();
      int info = readElf8();
      int bind = info >> 4;
      int type = info & 0xf;

      if (type == ELFSection.SYMTYPE_NONE && sn != null){
        if ("Letext".equals(sn)) {
          if (currentFile != null) {
            files.add(new FileInfo(currentFile, currentAddress, sAddr));
            currentAddress = sAddr;
          }
        } else if (!sn.startsWith("_")) {
            map.setEntry(new MapEntry(MapEntry.TYPE.variable, sAddr, 0, sn, currentFile,
                    false));
        }
      }
      if (type == ELFSection.SYMTYPE_FILE) {
  currentFile = sn;
      }

      if (DEBUG) {
        System.out.println("Found symbol: " + sn + " at " +
               Integer.toString(sAddr, 16) + " bind: " + bind +
               " type: " + type + " size: " + size);
      }

      if (sAddr > 0 && sAddr < 0x100000) {
  String symbolName = sn;
 
  if (sAddr < 0x5c00 && sAddr > sAddrHighest) {
    sAddrHighest = sAddr;
  }
//  if (bind == ELFSection.SYMBIND_LOCAL) {
//    symbolName += " (" + currentFile + ')';
//  }
  if ("_end".equals(symbolName)) {
    map.setHeapStart(sAddr);
  } else if ("__stack".equals(symbolName)){
    map.setStackStart(sAddr);
  }


  if (type == ELFSection.SYMTYPE_FUNCTION) {
          String file = lookupFile(sAddr);
          if (file == null) {
            file = currentFile;
          }
    map.setEntry(new MapEntry(MapEntry.TYPE.function, sAddr, 0, symbolName, file,
        bind == ELFSection.SYMBIND_LOCAL));
  } else if (type == ELFSection.SYMTYPE_OBJECT) {
          String file = lookupFile(sAddr);
          if (file == null) {
            file = currentFile;
          }
    map.setEntry(new MapEntry(MapEntry.TYPE.variable, sAddr, size, symbolName, file,
        bind == ELFSection.SYMBIND_LOCAL));
  } else {
    if (DEBUG) {
      System.out.println("Skipping entry: '" + symbolName + "' @ 0x" + Integer.toString(sAddr, 16) + " (" + currentFile + ")");
    }
  }

      }
      addr += symTable.getEntrySize();
    }

    if (map.getHeapStart() <= 0 && sAddrHighest > 0) {
      System.err.printf("Warning: Unable to parse _end symbol. I'm guessing that heap starts at 0x%05x\n", sAddrHighest);
      map.setHeapStart(sAddrHighest);
    }

    return map;
  }

  public static ELF readELF(String file) throws IOException {
    DataInputStream input = new DataInputStream(new FileInputStream(file));
    ByteArrayOutputStream baous = new ByteArrayOutputStream();
    byte[] buf = new byte[2048];
    for(int read; (read = input.read(buf)) != -1; baous.write(buf, 0, read)) {
      ;
    }
    input.close();
    buf = null;
    byte[] data = baous.toByteArray();
    if (DEBUG) {
      System.out.println("Length of data: " + data.length);
    }

    ELF elf = new ELF(data);
    elf.readAll();

    return elf;
  }

  public static void main(String[] args) throws Exception {
    ELF elf = readELF(args[0]);

    if (args.length < 2) {
      for (int i = 0, n = elf.shnum; i < n; i++) {
        if (DEBUG) {
          System.out.println("-- Section header " + i + " --\n" + elf.sections[i]);
        }
        if (".stab".equals(elf.sections[i].getSectionName()) ||
            ".stabstr".equals(elf.sections[i].getSectionName())) {
          int adr = elf.sections[i].getOffset();
          if (DEBUG) {
            System.out.println(" == Section data ==");
          }
          for (int j = 0, m = 2000; j < m; j++) {
            if (DEBUG) {
              System.out.print((char) elf.elfData[adr++]);
              if (i % 20 == 19) {
                System.out.println();
              }
            }
          }
        }
        System.out.println();
      }
    }
    elf.getMap();
    if (args.length > 1) {
      DebugInfo dbg = elf.getDebugInfo(Integer.parseInt(args[1]));
      if (dbg != null) {
  System.out.println("File: " + dbg.getFile());
  System.out.println("Function: " + dbg.getFunction());
  System.out.println("LineNo: " + dbg.getLine());
      }
    }
  }

  public void setPos(int pos) {
    this.pos = pos;
  }

  public int getPos() {
    return pos;
  }

  private static class FileInfo {
      public final String name;
      public final int start;
      public final int end;

      FileInfo(String name, int start, int end) {
          this.name = name;
          this.start = start;
          this.end = end;
      }

  }

} // ELF
TOP

Related Classes of se.sics.mspsim.util.ELF$FileInfo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.