| package org.eclipse.cdt.utils.elf; |
| |
| /* |
| * (c) Copyright QNX Software Systems Ltd. 2002. |
| * All Rights Reserved. |
| */ |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.Arrays; |
| import java.util.Vector; |
| |
| /** |
| * <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.ELFhdr hdr; |
| private Elf.Attribute attrib; |
| 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"); |
| if (dynSect != null) { |
| dynamics = elf.getDynamicSections(dynSect); |
| } |
| |
| } |
| } |
| |
| /** Common code used by all constructors */ |
| private void commonSetup() throws IOException { |
| hdr = elf.getELFhdr(); |
| attrib = elf.getAttributes(); |
| } |
| |
| /** |
| * 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; |
| commonSetup(); |
| } |
| |
| /** |
| * 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); |
| commonSetup(); |
| } |
| |
| public ElfHelper(String filename, boolean filton) throws IOException { |
| elf = new Elf(filename, filton); |
| commonSetup(); |
| } |
| |
| /** Give back the Elf object that this helper is wrapping */ |
| public Elf getElf() { |
| return elf; |
| } |
| |
| public Elf.Symbol[] getExternalFunctions() throws IOException { |
| Vector v = new Vector(); |
| |
| 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 = (Elf.Symbol[]) v.toArray(new Elf.Symbol[0]); |
| Arrays.sort(ret, new SymbolSortCompare()); |
| return ret; |
| } |
| |
| public Elf.Symbol[] getExternalObjects() throws IOException { |
| Vector v = new Vector(); |
| |
| 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 = (Elf.Symbol[]) v.toArray(new Elf.Symbol[0]); |
| Arrays.sort(ret, new SymbolSortCompare()); |
| return ret; |
| } |
| |
| public Elf.Symbol[] getUndefined() throws IOException { |
| Vector v = new Vector(); |
| |
| 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 = (Elf.Symbol[]) v.toArray(new Elf.Symbol[0]); |
| Arrays.sort(ret, new SymbolSortCompare()); |
| return ret; |
| } |
| |
| public Elf.Symbol[] getLocalFunctions() throws IOException { |
| Vector v = new Vector(); |
| |
| 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_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 = (Elf.Symbol[]) v.toArray(new Elf.Symbol[0]); |
| Arrays.sort(ret, new SymbolSortCompare()); |
| return ret; |
| } |
| |
| public Elf.Symbol[] getLocalObjects() throws IOException { |
| Vector v = new Vector(); |
| |
| 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_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 = (Elf.Symbol[]) v.toArray(new Elf.Symbol[0]); |
| Arrays.sort(ret, new SymbolSortCompare()); |
| return ret; |
| } |
| |
| public Elf.Symbol[] getCommonObjects() throws IOException { |
| Vector v = new Vector(); |
| |
| 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 = (Elf.Symbol[]) v.toArray(new Elf.Symbol[0]); |
| Arrays.sort(ret, new SymbolSortCompare()); |
| return ret; |
| } |
| |
| public Elf.Dynamic[] getNeeded() throws IOException { |
| Vector v = new Vector(); |
| |
| loadDynamics(); |
| |
| for (int i = 0; i < dynamics.length; i++) { |
| if (dynamics[i].d_tag == Elf.Dynamic.DT_NEEDED) |
| v.add(dynamics[i]); |
| } |
| return (Elf.Dynamic[]) v.toArray(new Elf.Dynamic[0]); |
| } |
| |
| public String getSoname() throws IOException { |
| String soname = ""; |
| |
| 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) { |
| 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(""); |
| } |
| |
| 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); |
| } |
| |
| } |