/******************************************************************************* * Copyright (c) 2000, 2009 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 * Craig Watson * Apple Computer - work on performance optimizations *******************************************************************************/ package org.eclipse.cdt.utils.macho; import java.io.IOException; import java.util.Vector; import org.eclipse.cdt.utils.macho.MachO64.DyLib; import org.eclipse.cdt.utils.macho.MachO64.Section; import org.eclipse.cdt.utils.macho.MachO64.Symbol; /** * <code>MachOHelper64</code> is a wrapper class for the <code>MachO64</code> class * to provide higher level API for sorting/searching the MachO data. * * @see MachO64 * @since 5.2 */ public class MachOHelper64 { private MachO64 macho; private MachO64.Symbol[] dynsyms; private MachO64.Symbol[] symbols; private MachO64.Section[] sections; private MachO64.DyLib[] needed; private MachO64.DyLib[] sonames; public void dispose() { if (macho != null) { macho.dispose(); macho = null; } } public boolean is64() { return macho.is64(); } 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 loadBinary() throws IOException { if (symbols == null) { macho.loadBinary(); symbols = macho.getSymtabSymbols(); dynsyms = macho.getDynamicSymbols(); sections = macho.getSections(); needed = macho.getDyLibs(MachO64.LoadCommand.LC_LOAD_DYLIB); sonames = macho.getDyLibs(MachO64.LoadCommand.LC_ID_DYLIB); if (dynsyms == null) dynsyms = symbols; } } /** * Create a new <code>MachOHelper64</code> using an existing <code>MachO64</code> * object. * @param macho An existing MachO64 object to wrap. * @throws IOException Error processing the MachO file. */ public MachOHelper64(MachO64 macho) throws IOException { this.macho = macho; } /** * Create a new <code>MachOHelper64</code> based on the given filename. * * @param filename The file to use for creating a new MachO64 object. * @throws IOException Error processing the MachO file. * @see MachO64#MachO64( String ) */ public MachOHelper64(String filename) throws IOException { macho = new MachO64(filename); } /** * Create a new <code>MachOHelper64</code> based on the given filename. * * @param filename The file to use for creating a new MachO64 object. * @throws IOException Error processing the MachO file. * @see MachO64#MachO64( String ) */ public MachOHelper64(String filename, long offset) throws IOException { macho = new MachO64(filename, offset); } public MachOHelper64(String filename, boolean filton) throws IOException { macho = new MachO64(filename, filton); } /** Give back the MachO64 object that this helper is wrapping */ public MachO64 getMachO() { return macho; } public MachO64.Symbol[] getExternalFunctions() throws IOException { Vector<Symbol> v = new Vector<Symbol>(); loadBinary(); for (Symbol sym : dynsyms) { if ((sym.n_type_mask(MachO64.Symbol.N_PEXT) || sym.n_type_mask(MachO64.Symbol.N_EXT)) && sym.n_desc(MachO64.Symbol.REFERENCE_FLAG_UNDEFINED_LAZY)) { String name = sym.toString(); if (name != null && name.trim().length() > 0) v.add(sym); } } MachO64.Symbol[] ret = v.toArray(new MachO64.Symbol[0]); return ret; } public MachO64.Symbol[] getExternalObjects() throws IOException { Vector<Symbol> v = new Vector<Symbol>(); loadBinary(); for (Symbol sym : dynsyms) { if ((sym.n_type_mask(MachO64.Symbol.N_PEXT) || sym.n_type_mask(MachO64.Symbol.N_EXT)) && sym.n_desc(MachO64.Symbol.REFERENCE_FLAG_UNDEFINED_NON_LAZY)) { String name = sym.toString(); if (name != null && name.trim().length() > 0) v.add(sym); } } MachO64.Symbol[] ret = v.toArray(new MachO64.Symbol[0]); return ret; } public MachO64.Symbol[] getUndefined() throws IOException { Vector<Symbol> v = new Vector<Symbol>(); loadBinary(); for (Symbol dynsym : dynsyms) { if (dynsym.n_type(MachO64.Symbol.N_UNDF)) v.add(dynsym); } MachO64.Symbol[] ret = v.toArray(new MachO64.Symbol[0]); return ret; } /* * TODO: I'm not sure if this are correct. Need to check */ public MachO64.Symbol[] getLocalFunctions() throws IOException { Vector<Symbol> v = new Vector<Symbol>(); loadBinary(); for (Symbol sym : dynsyms) { if ((!sym.n_type_mask(MachO64.Symbol.N_PEXT) && !sym.n_type_mask(MachO64.Symbol.N_EXT)) && sym.n_desc(MachO64.Symbol.REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY)) { String name = sym.toString(); if (name != null && name.trim().length() > 0) v.add(sym); } } MachO64.Symbol[] ret = v.toArray(new MachO64.Symbol[0]); return ret; } /* * TODO: I'm not sure if this are correct. Need to check */ public MachO64.Symbol[] getLocalObjects() throws IOException { Vector<Symbol> v = new Vector<Symbol>(); loadBinary(); for (Symbol sym : dynsyms) { if ((!sym.n_type_mask(MachO64.Symbol.N_PEXT) && !sym.n_type_mask(MachO64.Symbol.N_EXT)) && sym.n_desc(MachO64.Symbol.REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY)) { String name = sym.toString(); if (name != null && name.trim().length() > 0) v.add(sym); } } MachO64.Symbol[] ret = v.toArray(new MachO64.Symbol[0]); return ret; } public MachO64.Symbol[] getCommonObjects() throws IOException { Vector<Symbol> v = new Vector<Symbol>(); loadBinary(); for (int i = 0; i < dynsyms.length; i++) { MachO64.Symbol sym = dynsyms[i]; if (sym.n_type_mask(MachO64.Symbol.N_EXT) && sym.n_type(MachO64.Symbol.N_UNDF) && sym.n_value != 0) { v.add(symbols[i]); } } MachO64.Symbol[] ret = v.toArray(new MachO64.Symbol[0]); return ret; } public String[] getNeeded() throws IOException { Vector<String> v = new Vector<String>(); loadBinary(); for (DyLib element : needed) { v.add(element.toString()); } return v.toArray(new String[0]); } public String getSoname() throws IOException { String soname = ""; //$NON-NLS-1$ loadBinary(); for (DyLib soname2 : sonames) { soname = soname2.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 { return new String(""); //$NON-NLS-1$ } public Sizes getSizes() throws IOException { long text, data, bss; text = 0; data = 0; bss = 0; // TODO further optimization // TODO we only need to load the sections, not the whole shebang loadBinary(); for (Section section : sections) { MachO64.SegmentCommand seg = section.segment; if (section.flags(MachO64.Section.SECTION_TYP) != MachO64.Section.S_ZEROFILL) { if (seg.prot(MachO64.SegmentCommand.VM_PROT_EXECUTE)) { text += section.size; } else if (!seg.prot(MachO64.SegmentCommand.VM_PROT_WRITE)) { data += section.size; } } else { if (seg.prot(MachO64.SegmentCommand.VM_PROT_WRITE)) { bss += section.size; } } } return new Sizes(text, data, bss); } }