public RawFlowGraph readFlowGraph(final Diff diff, final IAddress functionAddress) {
    final RawFunction function = diff.getCallGraph(side).getFunction(functionAddress);

    BinExport2.FlowGraph flowGraph = null;
    // TODO(cblichmann): Binary search!
    for (final BinExport2.FlowGraph curFlowGraph : binexport.getFlowGraphList()) {
      final BinExport2.BasicBlock entryBasicBlock =
          binexport.getBasicBlock(curFlowGraph.getEntryBasicBlockIndex());
      final BinExport2.Instruction firstInstruction =
          binexport.getInstruction(entryBasicBlock.getInstructionIndex(0).getBeginIndex());
      if (functionAddress.toLong() == firstInstruction.getAddress()) {
        flowGraph = curFlowGraph;
        break;
      }
    }

    final Map<Integer, RawBasicBlock> basicBlocks = new TreeMap<>();
    final List<RawJump> jumps = new ArrayList<>();

    if (flowGraph != null) {
      for (final Integer basicBlockIndex : flowGraph.getBasicBlockIndexList()) {
        final BinExport2.BasicBlock basicBlock = binexport.getBasicBlock(basicBlockIndex);
        final CAddress basicBlockAddress =
            new CAddress(getInstructionAddress(basicBlock.getInstructionIndex(0).getBeginIndex()));

        final EMatchState matchState;
        final FunctionMatchData match = function.getFunctionMatch();
        if (match != null && match.getBasicBlockMatch(basicBlockAddress, side) != null) {
          matchState = EMatchState.MATCHED;
        } else {
          matchState =
              side == ESide.PRIMARY
                  ? EMatchState.PRIMARY_UNMATCHED
                  : EMatchState.SECONDRAY_UNMATCHED;
        }

        final SortedMap<IAddress, RawInstruction> instructions = new TreeMap<>();
        for (final BinExport2.BasicBlock.IndexRange range : basicBlock.getInstructionIndexList()) {
          int endIndex = !range.hasEndIndex() ? range.getBeginIndex() + 1 : range.getEndIndex();
          for (int i = range.getBeginIndex(); i < endIndex; i++) {
            final BinExport2.Instruction instruction = binexport.getInstruction(i);
            final IAddress instructionAddress = new CAddress(getInstructionAddress(i));

            final long[] callTargets = new long[instruction.getCallTargetCount()];
            for (int j = 0; j < callTargets.length; j++) {
              callTargets[j] = instruction.getCallTarget(j);
            }

            final List<RawInstructionComment> instructionComments = new ArrayList<>();
            final RawInstructionComment comment = comments.get(instructionAddress);
            if (comment != null) {
              instructionComments.add(comment);
            }

            final RawInstruction rawInstruction =
                new RawInstruction(
                    instructionAddress,
                    binexport.getMnemonic(instruction.getMnemonicIndex()).getName(),
                    maxMnemonicLen,
                    renderInstructionOperands(binexport, instruction).getBytes(UTF_8),
                    callTargets,
                    instructionComments);
            instructions.put(instructionAddress, rawInstruction);
          }
        }

        final RawBasicBlock rawBasicBlock =
            new RawBasicBlock(
                functionAddress,
                function.getName(),
                basicBlockAddress,
                instructions,
                side,
                matchState);
        basicBlocks.put(basicBlockIndex, rawBasicBlock);
      }

      for (final BinExport2.FlowGraph.Edge edge : flowGraph.getEdgeList()) {
        final int sourceIndex = edge.getSourceBasicBlockIndex();
        final RawBasicBlock source = basicBlocks.get(sourceIndex);
        final int targetIndex = edge.getTargetBasicBlockIndex();
        final RawBasicBlock target = basicBlocks.get(targetIndex);
        if (source == null || target == null) {
          logger.atWarning().log(
              "Incomplete %s flow graph edge (source %d%s, target %d%s)",
              side == ESide.PRIMARY ? "primary" : "secondary",
              sourceIndex,
              source == null ? " missing" : "",
              targetIndex,
              target == null ? " missing" : "");
          continue;
        }
        jumps.add(new RawJump(source, target, toJumpType(edge.getType())));
      }
    }

    final List<RawBasicBlock> bbs = new ArrayList<>(basicBlocks.values());
    return new RawFlowGraph(
        functionAddress, function.getName(), function.getFunctionType(), bbs, jumps, side);
  }
Reads data from BinExport2 files and renders disassemblies.
java/ui/src/main/java/com/google/security/zynamics/bindiff/io/BinExport2Reader.java