/******************************************************************************* * Copyright (c) 2000, 2008 QNX Software Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * QNX Software Systems - Initial API and implementation *******************************************************************************/ package org.eclipse.cdt.utils.elf; import java.io.File; import java.io.IOException; import java.util.Vector; import org.eclipse.cdt.utils.elf.Elf.Dynamic; import org.eclipse.cdt.utils.elf.Elf.Symbol; /** * <code>ElfHelper</code> is a wrapper class for the <code>Elf</code> class * to provide higher level API for sorting/searching the ELF data. * * @see Elf */ public class ElfHelper { private Elf elf; private Elf.Symbol[] dynsyms; private Elf.Symbol[] symbols; private Elf.Section[] sections; private Elf.Dynamic[] dynamics; public void dispose() { if (elf != null) { elf.dispose(); elf = null; } } public class Sizes { public long text; public long data; public long bss; public long total; public Sizes(long t, long d, long b) { text = t; data = d; bss = b; total = text + data + bss; } } private void loadSymbols() throws IOException { if (symbols == null) { elf.loadSymbols(); symbols = elf.getSymtabSymbols(); dynsyms = elf.getDynamicSymbols(); if (symbols.length <= 0) symbols = dynsyms; if (dynsyms.length <= 0) dynsyms = symbols; } } private void loadSections() throws IOException { if (sections == null) sections = elf.getSections(); } private void loadDynamics() throws IOException { if (dynamics == null) { dynamics = new Elf.Dynamic[0]; Elf.Section dynSect = elf.getSectionByName(".dynamic"); //$NON-NLS-1$ if (dynSect != null) { dynamics = elf.getDynamicSections(dynSect); } } } /** * Create a new <code>ElfHelper</code> using an existing <code>Elf</code> * object. * * @param elf * An existing Elf object to wrap. * @throws IOException * Error processing the Elf file. */ public ElfHelper(Elf elf) throws IOException { this.elf = elf; } /** * Create a new <code>ElfHelper</code> based on the given filename. * * @param filename * The file to use for creating a new Elf object. * @throws IOException * Error processing the Elf file. * @see Elf#Elf( String ) */ public ElfHelper(String filename) throws IOException { elf = new Elf(filename); } /** * Create a new <code>ElfHelper</code> based on the given filename. * * @param filename * The file to use for creating a new Elf object. * @throws IOException * Error processing the Elf file. * @see Elf#Elf( String ) */ public ElfHelper(String filename, long fileoffset) throws IOException { elf = new Elf(filename, fileoffset); } /** Give back the Elf object that this helper is wrapping */ public Elf getElf() { return elf; } public Elf.Symbol[] getExternalFunctions() throws IOException { Vector<Symbol> v = new Vector<Symbol>(); loadSymbols(); loadSections(); for (int i = 0; i < dynsyms.length; i++) { if (dynsyms[i].st_bind() == Elf.Symbol.STB_GLOBAL && dynsyms[i].st_type() == Elf.Symbol.STT_FUNC) { int idx = dynsyms[i].st_shndx; if (idx < Elf.Symbol.SHN_HIPROC && idx > Elf.Symbol.SHN_LOPROC) { String name = dynsyms[i].toString(); if (name != null && name.trim().length() > 0) v.add(dynsyms[i]); } else if (idx >= 0 && sections[idx].sh_type == Elf.Section.SHT_NULL) { v.add(dynsyms[i]); } } } Elf.Symbol[] ret = v.toArray(new Elf.Symbol[v.size()]); return ret; } public Elf.Symbol[] getExternalObjects() throws IOException { Vector<Symbol> v = new Vector<Symbol>(); loadSymbols(); loadSections(); for (int i = 0; i < dynsyms.length; i++) { if (dynsyms[i].st_bind() == Elf.Symbol.STB_GLOBAL && dynsyms[i].st_type() == Elf.Symbol.STT_OBJECT) { int idx = dynsyms[i].st_shndx; if (idx < Elf.Symbol.SHN_HIPROC && idx > Elf.Symbol.SHN_LOPROC) { String name = dynsyms[i].toString(); if (name != null && name.trim().length() > 0) v.add(dynsyms[i]); } else if (idx >= 0 && sections[idx].sh_type == Elf.Section.SHT_NULL) { v.add(dynsyms[i]); } } } Elf.Symbol[] ret = v.toArray(new Elf.Symbol[v.size()]); return ret; } public Elf.Symbol[] getUndefined() throws IOException { Vector<Symbol> v = new Vector<Symbol>(); loadSymbols(); for (int i = 0; i < dynsyms.length; i++) { if (dynsyms[i].st_shndx == Elf.Symbol.SHN_UNDEF) v.add(dynsyms[i]); } Elf.Symbol[] ret = v.toArray(new Elf.Symbol[v.size()]); return ret; } public Elf.Symbol[] getLocalFunctions() throws IOException { Vector<Symbol> v = new Vector<Symbol>(); loadSymbols(); loadSections(); for (int i = 0; i < symbols.length; i++) { if ( symbols[i].st_type() == Elf.Symbol.STT_FUNC) { int idx = symbols[i].st_shndx; if (idx < Elf.Symbol.SHN_HIPROC && idx > Elf.Symbol.SHN_LOPROC) { String name = symbols[i].toString(); if (name != null && name.trim().length() > 0) v.add(symbols[i]); } else if (idx >= 0 && sections[idx].sh_type != Elf.Section.SHT_NULL) { v.add(symbols[i]); } } } Elf.Symbol[] ret = v.toArray(new Elf.Symbol[v.size()]); return ret; } public Elf.Symbol[] getLocalObjects() throws IOException { Vector<Symbol> v = new Vector<Symbol>(); loadSymbols(); loadSections(); for (int i = 0; i < symbols.length; i++) { if ( symbols[i].st_type() == Elf.Symbol.STT_OBJECT) { int idx = symbols[i].st_shndx; if (idx < Elf.Symbol.SHN_HIPROC && idx > Elf.Symbol.SHN_LOPROC) { String name = symbols[i].toString(); if (name != null && name.trim().length() > 0) v.add(symbols[i]); } else if (idx >= 0 && sections[idx].sh_type != Elf.Section.SHT_NULL) { v.add(symbols[i]); } } } Elf.Symbol[] ret = v.toArray(new Elf.Symbol[v.size()]); return ret; } public Elf.Symbol[] getCommonObjects() throws IOException { Vector<Symbol> v = new Vector<Symbol>(); loadSymbols(); loadSections(); for (int i = 0; i < symbols.length; i++) { if (symbols[i].st_bind() == Elf.Symbol.STB_GLOBAL && symbols[i].st_type() == Elf.Symbol.STT_OBJECT) { int idx = symbols[i].st_shndx; if (idx == Elf.Symbol.SHN_COMMON) { v.add(symbols[i]); } } } Elf.Symbol[] ret = v.toArray(new Elf.Symbol[v.size()]); return ret; } public Elf.Dynamic[] getNeeded() throws IOException { Vector<Dynamic> v = new Vector<Dynamic>(); loadDynamics(); for (int i = 0; i < dynamics.length; i++) { if (dynamics[i].d_tag == Elf.Dynamic.DT_NEEDED) v.add(dynamics[i]); } return v.toArray(new Elf.Dynamic[v.size()]); } public String getSoname() throws IOException { String soname = ""; //$NON-NLS-1$ loadDynamics(); for (int i = 0; i < dynamics.length; i++) { if (dynamics[i].d_tag == Elf.Dynamic.DT_SONAME) soname = dynamics[i].toString(); } return soname; } private String getSubUsage(String full, String name) { int start, end; //boolean has_names = false; //boolean has_languages = false; start = 0; end = 0; for (int i = 0; i < full.length(); i++) { if (full.charAt(i) == '%') { if (full.charAt(i + 1) == '-') { if (start == 0) { int eol = full.indexOf('\n', i + 2); String temp = full.substring(i + 2, eol); if (temp.compareTo(name) == 0) start = eol; //has_names = true; } else if (end == 0) { end = i - 1; } } //if( full.charAt( i+1 ) == '=' ) //has_languages = true; } } if (end == 0) end = full.length(); if (start == 0) return full; return full.substring(start, end); } public String getQnxUsage() throws IOException { loadSections(); for (int i = 0; i < sections.length; i++) { if (sections[i].toString().compareTo("QNX_usage") == 0) { //$NON-NLS-1$ File file = new File(elf.getFilename()); String full_usage = new String(sections[i].loadSectionData()); String usage = getSubUsage(full_usage, file.getName()); StringBuffer buffer = new StringBuffer(usage); for (int j = 0; j < buffer.length(); j++) { if (buffer.charAt(j) == '%') { if (buffer.charAt(j + 1) == 'C') buffer.replace(j, j + 2, file.getName()); } } return buffer.toString(); } } return new String(""); //$NON-NLS-1$ } public Sizes getSizes() throws IOException { long text, data, bss; text = 0; data = 0; bss = 0; loadSections(); for (int i = 0; i < sections.length; i++) { if (sections[i].sh_type != Elf.Section.SHT_NOBITS) { if (sections[i].sh_flags == (Elf.Section.SHF_WRITE | Elf.Section.SHF_ALLOC)) { data += sections[i].sh_size; } else if ( (sections[i].sh_flags & Elf.Section.SHF_ALLOC) != 0) { text += sections[i].sh_size; } } else { if (sections[i].sh_flags == (Elf.Section.SHF_WRITE | Elf.Section.SHF_ALLOC)) { bss += sections[i].sh_size; } } } return new Sizes(text, data, bss); } }