/* Copyright 2011-2016 Google Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package com.google.security.zynamics.binnavi.disassembly.Modules; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import com.google.security.zynamics.binnavi.CUtilityFunctions; import com.google.security.zynamics.binnavi.Database.Exceptions.CouldntDeleteException; import com.google.security.zynamics.binnavi.Database.Exceptions.CouldntLoadDataException; import com.google.security.zynamics.binnavi.Database.Interfaces.IDatabase; import com.google.security.zynamics.binnavi.Tagging.CTag; import com.google.security.zynamics.binnavi.debug.debugger.DebuggerProvider; import com.google.security.zynamics.binnavi.debug.debugger.ModuleTargetSettings; import com.google.security.zynamics.binnavi.debug.debugger.interfaces.IDebugger; import com.google.security.zynamics.binnavi.debug.models.trace.ModuleTraceProvider; import com.google.security.zynamics.binnavi.debug.models.trace.interfaces.ITraceListProvider; import com.google.security.zynamics.binnavi.disassembly.UnrelocatedAddress; import com.google.security.zynamics.binnavi.disassembly.ICallgraphView; import com.google.security.zynamics.binnavi.disassembly.IFlowgraphView; import com.google.security.zynamics.binnavi.disassembly.INaviAddressSpace; import com.google.security.zynamics.binnavi.disassembly.INaviFunction; import com.google.security.zynamics.binnavi.disassembly.INaviModule; import com.google.security.zynamics.binnavi.disassembly.views.CViewFilter; import com.google.security.zynamics.binnavi.disassembly.views.INaviView; import com.google.security.zynamics.binnavi.disassembly.views.IViewContainer; import com.google.security.zynamics.binnavi.disassembly.views.IViewContainerListener; import com.google.security.zynamics.zylib.general.ListenerProvider; import com.google.security.zynamics.zylib.general.Pair; import java.util.ArrayList; import java.util.List; /** * View container that encapsulates a module. */ public final class CModuleContainer implements IViewContainer { /** * Database the module belongs to. */ private final IDatabase m_database; /** * The encapsulated module. */ private final INaviModule m_module; /** * Trace provider of the container. */ private final ITraceListProvider m_provider; /** * Listeners that are notified about changes in the view container. */ private final ListenerProvider<IViewContainerListener> m_listeners = new ListenerProvider<IViewContainerListener>(); /** * Forwards module events to the view container listeners. */ private final InternalListener m_listener = new InternalListener(); /** * Provides the debuggers for the module container. */ private final DebuggerProvider m_debuggerProvider; /** * The active debugger. */ private IDebugger m_activeDebugger; /** * Creates a new container object. * * @param database Database the module belongs to. * @param module The encapsulated module. */ public CModuleContainer(final IDatabase database, final INaviModule module) { m_database = Preconditions.checkNotNull(database, "IE02397: database argument can not be null"); m_module = Preconditions.checkNotNull(module, "IE02398: module argument can not be null"); m_debuggerProvider = new DebuggerProvider(new ModuleTargetSettings(m_module)); final IDebugger debugger = m_module.getConfiguration().getDebugger(); if (debugger != null) { m_activeDebugger = debugger; m_debuggerProvider.addDebugger(debugger); } m_module.addListener(m_listener); m_provider = new ModuleTraceProvider(m_module); } @Override public Object getNative() { return m_module; } @Override public void addListener(final IViewContainerListener listener) { m_listeners.addListener(listener); } @Override public boolean containsModule(final INaviModule module) { return module.equals(m_module); } @Override public INaviView createView(final String name, final String description) { return m_module.getContent().getViewContainer().createView(name, description); } @Override public void deleteView(final INaviView view) throws CouldntDeleteException { m_module.getContent().getViewContainer().deleteView(view); } @Override public void dispose() { m_module.removeListener(m_listener); } @Override public List<INaviAddressSpace> getAddressSpaces() { return null; } @Override public IDatabase getDatabase() { return m_database; } @Override public DebuggerProvider getDebuggerProvider() { return m_debuggerProvider; } @Override public INaviFunction getFunction(final INaviView view) { return m_module.getContent().getViewContainer().getFunction(view); } @Override public List<INaviFunction> getFunctions() { return m_module.getContent().getFunctionContainer().getFunctions(); } @Override public List<INaviModule> getModules() { return Lists.newArrayList(m_module); } @Override public String getName() { return m_module.getConfiguration().getName(); } @Override public List<Pair<INaviView, CTag>> getTaggedViews() { return CViewFilter.getTaggedViews(m_module.getContent().getViewContainer().getViews()); } @Override public List<INaviView> getTaggedViews(final CTag object) { return CViewFilter.getTaggedViews(m_module.getContent().getViewContainer().getViews(), object); } @Override public ITraceListProvider getTraceProvider() { return m_provider; } @Override public List<INaviView> getUserViews() { return m_module.getContent().getViewContainer().getUserViews(); } @Override public INaviView getView(final INaviFunction function) { for (final INaviView view : m_module.getContent().getViewContainer().getViews()) { if (m_module.getContent().getViewContainer().getFunction(view) == function) { return view; } } return null; } @Override public int getViewCount() { return m_module.getCustomViewCount(); } @Override public List<INaviView> getViews() { return m_module.getContent().getViewContainer().getViews(); } @Override public List<INaviView> getViewsWithAddresses(final List<UnrelocatedAddress> address, final boolean all) throws CouldntLoadDataException { return m_module.getViewsWithAddresses(address, all); } @Override public boolean isLoaded() { return m_module.isLoaded(); } @Override public void removeListener(final IViewContainerListener listener) { m_listeners.removeListener(listener); } /** * Forwards module events to the view container listeners. */ private class InternalListener extends CModuleListenerAdapter { @Override public void addedView(final INaviModule module, final INaviView view) { for (final IViewContainerListener listener : m_listeners) { try { listener.addedView(CModuleContainer.this, view); } catch (final Exception exception) { CUtilityFunctions.logException(exception); } } } @Override public void changedDebugger(final INaviModule module, final IDebugger debugger) { if (m_activeDebugger != null) { m_debuggerProvider.removeDebugger(m_activeDebugger); } if (debugger != null) { m_activeDebugger = debugger; m_debuggerProvider.addDebugger(debugger); } } @Override public void closedModule(final CModule module, final ICallgraphView callgraphView, final List<IFlowgraphView> flowgraphs) { final List<INaviView> views = new ArrayList<INaviView>(flowgraphs); views.add(callgraphView); for (final IViewContainerListener listener : m_listeners) { try { listener.closedContainer(CModuleContainer.this, views); } catch (final Exception exception) { CUtilityFunctions.logException(exception); } } } @Override public void deletedView(final INaviModule module, final INaviView view) { for (final IViewContainerListener listener : m_listeners) { try { listener.deletedView(CModuleContainer.this, view); } catch (final Exception exception) { CUtilityFunctions.logException(exception); } } } @Override public void loadedModule(final INaviModule module) { for (final IViewContainerListener listener : m_listeners) { try { listener.loaded(CModuleContainer.this); } catch (final Exception exception) { CUtilityFunctions.logException(exception); } } } } }