blob: b4d91e7d0e00301cb1f3a7047d396e2cdef9d800 [file] [log] [blame]
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);
}
}