protected CodeBlock getAddressSetContaining(Address addr, TaskMonitor monitor)
			throws CancelledException {

		if (addr.isExternalAddress()) {
			if (includeExternals) {
				CodeBlock block = new ExtCodeBlockImpl(this, addr);
				foundMSubs.addObject(block, addr, addr);
				return block;
			}
			return null;
		}

		// create a holder for the blockSet
		AddressSet addrSet = new AddressSet();

		// Use a new block model each time, so that only the current
		//  function basic blocks will get saved.
		bbModel = new SimpleBlockModel(program, includeExternals);

		// Create the todoStack and initialize it with instr; also initialize the list for entryPts.
		ArrayList<Address> entryPtList = new ArrayList<Address>();
		LinkedList<Address> todoList = new LinkedList<Address>();   // list of address destinations to follow
		LinkedList<CodeBlock> srcList = new LinkedList<CodeBlock>();    // list of blocks to process for possible sources
		todoList.addFirst(addr);

		// Build model-M subroutine from basic blocks
		while (!todoList.isEmpty() || !srcList.isEmpty()) {

			if (monitor != null && monitor.isCancelled()) {
				throw new CancelledException();
			}

			// if todoList is empty
			//      process any blocks for sources that we put off to analyze later
			//   It is easier/efficient to follow flow in the forward direction.
			if (todoList.isEmpty()) {
				while (todoList.isEmpty() && !srcList.isEmpty()) {
					CodeBlock bblock = srcList.removeFirst();
					// Process all block source references
					addSources(monitor, entryPtList, todoList, bblock);
				}
				continue;
			}

			// get the next address to process
			Address a = null;
			a = todoList.removeFirst();

			// Get basic block at the specified address
			if (addrSet.contains(a)) {
				continue; // already processed this block  
			}

			CodeBlock bblock = bbModel.getFirstCodeBlockContaining(a, monitor);
			if (bblock == null) {
				continue;
			}

			// Verify that the block contains instructions
			if (listing.getInstructionAt(bblock.getMinAddress()) == null) {
				continue;
			}

			// Add basic block to subroutine address set
			addrSet.add(bblock);

			// Process all destination references
			addDestinations(monitor, todoList, bblock);

			// add block to list of block to process later
			srcList.addLast(bblock);
		}

		if (addrSet.isEmpty()) {
			return null;
		}

		// Check for failure to find entry point
		if (entryPtList.size() == 0) {
			Msg.warn(this, "Failed to find entry point for subroutine containing " + addr);
			entryPtList.add(addrSet.getMinAddress());
		}
		Address[] entryPts = new Address[entryPtList.size()];
		entryPtList.toArray(entryPts);

		CodeBlock block = new CodeBlockImpl(this, entryPts, addrSet);
		foundMSubs.addObject(block, addrSet);

		return block;
	}
Get the M-Model subroutine address set which contains the specified address.
This method also identifies the entry points and caches the resulting CodeBlock.

@param   addr    Address inside the subroutine that we are seeking
@param monitor task monitor which allows user to cancel operation.
@return          The <CODE>CodeBlock</CODE> for a
                 <CODE>MultEntSubModel</CODE> Subroutine.
					Null is returned if there is no instruction at addr.
@throws CancelledException if the monitor cancels the operation.
Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/block/MultEntSubModel.java