Java Code Examples for ghidra.util.task.TaskMonitor#setProgress()

The following examples show how to use ghidra.util.task.TaskMonitor#setProgress() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: AddMemRefsCmd.java    From ghidra with Apache License 2.0 6 votes vote down vote up
@Override
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {

	Program p = (Program) obj;
	ReferenceManager refMgr = p.getReferenceManager();
	Listing listing = p.getListing();

	monitor.initialize(toSet.getNumAddresses());
	monitor.setMessage("Adding memory references...");

	int cnt = 0;
	AddressIterator iter = toSet.getAddresses(true);
	CodeUnit prevCodeUnit = null;
	while (!monitor.isCancelled() && iter.hasNext()) {
		Address toAddr = iter.next();
		if (prevCodeUnit == null || !prevCodeUnit.contains(toAddr)) {
			CodeUnit cu = getSmallestCodeUnitAt(listing, toAddr);
			if (cu != null) {
				prevCodeUnit = cu;
				refMgr.addMemoryReference(fromAddr, toAddr, refType, source, opIndex);
			}
		}
		monitor.setProgress(++cnt);
	}
	return true;
}
 
Example 2
Source File: SymbolMerger.java    From ghidra with Apache License 2.0 6 votes vote down vote up
private long[] getNonMatchingIDsInFirst(long[] first, long[] second, TaskMonitor monitor)
		throws CancelledException {
	long[] uniqueIDs = new long[first.length];
	int u = 0;
	for (long element : first) {
		monitor.checkCanceled();
		monitor.setProgress(monitor.getProgress() + 1);
		boolean matched = false;
		for (long element2 : second) {
			if (element2 == element) {
				matched = true;
				break;
			}
		}
		if (!matched) {
			uniqueIDs[u++] = element;
		}
	}
	long[] results = new long[u];
	System.arraycopy(uniqueIDs, 0, results, 0, u);
	return results;
}
 
Example 3
Source File: AbstractLibrarySupportLoader.java    From ghidra with Apache License 2.0 6 votes vote down vote up
private void apply(List<Program> programs, List<Option> options, MessageLog log,
		TaskMonitor monitor) throws CancelledException {
	monitor.initialize(programs.size());

	for (int i = 0; i < programs.size() && isCreateExportSymbolFiles(options); ++i) {
		Program p = programs.get(i);

		monitor.checkCanceled();
		monitor.setProgress(i);

		int id = p.startTransaction("apply");
		boolean success = false;
		try {
			applyLibrarySymbols(p, log, monitor);
			applyImports(p, log, monitor);

			success = true;
		}
		finally {
			p.endTransaction(id, success);
		}
	}

	LibraryLookupTable.cleanup();
}
 
Example 4
Source File: LocalManagedBufferFile.java    From ghidra with Apache License 2.0 6 votes vote down vote up
void waitForTask(TaskMonitor taskMonitor) throws CancelledException {
	if (taskThread.isAlive()) {
		if (taskMonitor != null) {
			synchronized (preSaveLock) {
				taskMonitor.initialize(maxIndex);
				taskMonitor.setProgress(curIndex);
				this.monitor = taskMonitor;
				this.monitorThread = Thread.currentThread();
			}
		}
		try {
			taskThread.join();
		}
		catch (InterruptedException e) {
			// ignore
		}
		if (taskMonitor != null) {
			taskMonitor.checkCanceled();
		}
	}
}
 
Example 5
Source File: GTreeLoadChildrenTask.java    From ghidra with Apache License 2.0 6 votes vote down vote up
@Override
public void run(TaskMonitor monitor) {
	long progressValue = monitor.getProgress();
	long maxValue = monitor.getMaximum();
	monitor.setMessage("Loading children");
	try {
		node.setChildren(node.generateChildren(monitor));
	}
	catch (CancelledException e) {
		if (!tree.isDisposed()) {
			runOnSwingThread(new Runnable() {
				@Override
				public void run() {
					tree.collapseAll(tree.getViewRoot());
				}
			});
		}
		node.unloadChildren();
	}
	finally {
		monitor.initialize(maxValue);
		monitor.setProgress(progressValue);

	}
}
 
Example 6
Source File: SymbolMerger.java    From ghidra with Apache License 2.0 6 votes vote down vote up
private void processRemoves(TaskMonitor monitor) throws CancelledException {
	updateProgressMessage("Processing removed symbols...");
	monitor.setMessage("Symbol Merge: Processing removed symbols...");

	int len = myRemoveIDs.length;
	monitor.initialize(len);
	for (int i = 0; i < len; i++) {
		monitor.setProgress(i);
		monitor.checkCanceled();
		long id = myRemoveIDs[i];
		Symbol originalSym = originalSymTab.getSymbol(id);
		SymbolType originalType = originalSym.getSymbolType();
		// CODE, CLASS, EXTERNAL, FUNCTION, GLOBAL, GLOBAL_VAR, LIBRARY,
		// LOCAL_VAR, NAMESPACE, PARAMETER
		if ((originalType == SymbolType.LABEL && !originalSym.isExternal()) ||
			(originalType == SymbolType.CLASS) || (originalType == SymbolType.NAMESPACE)) {
			processSingleRemove(id, originalSym);
		}
	}
	monitor.setProgress(len);
}
 
Example 7
Source File: FunctionMerger.java    From ghidra with Apache License 2.0 6 votes vote down vote up
private void getLatestChangeTypes(TaskMonitor monitor) throws CancelledException {
	AddressIterator latestIter = latestDetailSet.getAddresses(true);
	long max = latestDetailSet.getNumAddresses();
	monitor.initialize(max);
	int count = 0;
	while (latestIter.hasNext()) {
		monitor.setProgress(count++);
		monitor.checkCanceled();
		Address entry = latestIter.next();
		Function originalFunc = functionManagers[ORIGINAL].getFunctionAt(entry);
		Function latestFunc = functionManagers[LATEST].getFunctionAt(entry);
		if (originalFunc == null) {
			addLatest.addRange(entry, entry);
		}
		else if (latestFunc == null) {
			removeLatest.addRange(entry, entry);
		}
		else {
			changeLatest.addRange(entry, entry);
		}
	}
	monitor.setProgress(max);
}
 
Example 8
Source File: SymbolMerger.java    From ghidra with Apache License 2.0 5 votes vote down vote up
private void getEntryPtChanges(TaskMonitor monitor) throws CancelledException {
	AddressIterator originalIter = originalSymTab.getExternalEntryPointIterator();
	AddressIterator latestIter = latestSymTab.getExternalEntryPointIterator();
	AddressIterator myIter = mySymTab.getExternalEntryPointIterator();

	updateProgressMessage("Finding entry point changes...");
	monitor.setMessage("Symbol Merge: Finding entry point changes...");
	monitor.setProgress(0);

	MultiAddressIterator multiIter =
		new MultiAddressIterator(new AddressIterator[] { originalIter, latestIter, myIter });
	while (multiIter.hasNext()) {
		monitor.checkCanceled();
		Address[] addrs = multiIter.nextAddresses();
		if (addrs[0] != null) {
			if (addrs[1] == null || addrs[2] == null) {
				removeEntryPts.addRange(addrs[0], addrs[0]);
			}
		}
		else {
			if (addrs[1] != null) {
				addEntryPts.addRange(addrs[1], addrs[1]);
			}
			else if (addrs[2] != null) {
				addEntryPts.addRange(addrs[2], addrs[2]);
			}
		}
	}
}
 
Example 9
Source File: ApplyBlockedMatchTask.java    From ghidra with Apache License 2.0 5 votes vote down vote up
private void clearAndApplyMatch(TaskMonitor monitor)
		throws CancelledException, VersionTrackingApplyException {
	monitor.setMessage("Applying a blocked match");
	monitor.initialize(2);
	monitor.checkCanceled();
	VTAssociation association = match.getAssociation();
	VTAssociationStatus status = association.getStatus();
	if (status != VTAssociationStatus.BLOCKED) {
		return;
	}

	monitor.setMessage("Clearing conflicts...");
	clearConflicts(monitor);

	monitor.setMessage("Applying match...");
	acceptMatch();

	MatchInfo matchInfo = controller.getMatchInfo(match);
	Collection<VTMarkupItem> markupItems = matchInfo.getAppliableMarkupItems(monitor);
	if (markupItems == null || markupItems.size() == 0) {
		monitor.setProgress(2);
		return; // No markup items to apply.
	}

	applyMarkupItems(monitor, markupItems);

	monitor.setProgress(2);
}
 
Example 10
Source File: FunctionGraphFactory.java    From ghidra with Apache License 2.0 5 votes vote down vote up
private static BidiMap<CodeBlock, FGVertex> createVertices(Function function,
		final FGController controller, TaskMonitor monitor) throws CancelledException {

	BidiMap<CodeBlock, FGVertex> vertices = new DualHashBidiMap<>();
	CodeBlockModel blockModel = new BasicBlockModel(controller.getProgram());

	AddressSetView addresses = function.getBody();
	CodeBlockIterator iterator = blockModel.getCodeBlocksContaining(addresses, monitor);
	monitor.initialize(addresses.getNumAddresses());

	for (; iterator.hasNext();) {
		CodeBlock codeBlock = iterator.next();

		FlowType flowType = codeBlock.getFlowType();
		boolean isEntry = isEntry(codeBlock);
		Address cbStart = codeBlock.getFirstStartAddress();
		if (cbStart.equals(function.getEntryPoint())) {
			isEntry = true;
		}

		FGVertex vertex =
			new ListingFunctionGraphVertex(controller, codeBlock, flowType, isEntry);
		vertices.put(codeBlock, vertex);

		long blockAddressCount = codeBlock.getNumAddresses();
		long currentProgress = monitor.getProgress();
		monitor.setProgress(currentProgress + blockAddressCount);
	}

	return vertices;
}
 
Example 11
Source File: RttiAnalyzer.java    From ghidra with Apache License 2.0 5 votes vote down vote up
private void processRtti0(Collection<Address> possibleRtti0Addresses, Program program,
		TaskMonitor monitor) throws CancelledException {

	monitor.setMaximum(possibleRtti0Addresses.size());
	monitor.setMessage("Creating RTTI Data...");

	ArrayList<Address> rtti0Locations = new ArrayList<Address>();
	int count = 0;
	for (Address rtti0Address : possibleRtti0Addresses) {
		monitor.checkCanceled();
		monitor.setProgress(count++);

		// Validate
		TypeDescriptorModel typeModel =
			new TypeDescriptorModel(program, rtti0Address, validationOptions);
		try {
			// Check that name matches the expected format.
			String typeName = typeModel.getTypeName(); // can be null.
			if (typeName == null || !typeName.startsWith(CLASS_PREFIX_CHARS)) {
				continue; // Invalid so don't create.
			}
		}
		catch (InvalidDataTypeException e) {
			continue; // Invalid so don't create.
		}

		// Create the TypeDescriptor (RTTI 0) regardless of the other RTTI structures.
		CreateTypeDescriptorBackgroundCmd typeDescCmd = new CreateTypeDescriptorBackgroundCmd(
			rtti0Address, validationOptions, applyOptions);
		typeDescCmd.applyTo(program, monitor);

		rtti0Locations.add(rtti0Address);
	}

	// Create any valid RTTI4s for this TypeDescriptor
	processRtti4sForRtti0(program, rtti0Locations, monitor);
}
 
Example 12
Source File: ObjectiveC1_MessageAnalyzer.java    From ghidra with Apache License 2.0 5 votes vote down vote up
@Override
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
		throws CancelledException {
	CurrentState state = new CurrentState(program);

	monitor.initialize(set.getNumAddresses());
	int progress = 0;

	AddressIterator iterator = set.getAddresses(true);
	while (iterator.hasNext()) {
		if (monitor.isCancelled()) {
			break;
		}

		monitor.setProgress(++progress);
		Address address = iterator.next();

		Function function = program.getListing().getFunctionAt(address);

		try {
			inspectFunction(program, function, state, monitor);
		}
		catch (Exception e) {
		}
	}

	return true;
}
 
Example 13
Source File: DexHeaderFormatAnalyzer.java    From ghidra with Apache License 2.0 5 votes vote down vote up
private void processFields(Program program, DexHeader header, TaskMonitor monitor,
		MessageLog log) throws Exception {
	monitor.setMessage("DEX: processing fields");
	monitor.setMaximum(header.getFieldIdsSize());
	monitor.setProgress(0);
	Address address = toAddr(program, header.getFieldIdsOffset());
	int index = 0;
	for (FieldIDItem item : header.getFields()) {
		monitor.checkCanceled();
		monitor.incrementProgress(1);
		DataType dataType = item.toDataType();
		createData(program, address, dataType);
		createFragment(program, "fields", address, address.add(dataType.getLength()));

		StringBuilder builder = new StringBuilder();
		builder.append("Field Index: 0x" + Integer.toHexString(index) + "\n");
		builder.append(
			"Class: " + DexUtil.convertTypeIndexToString(header, item.getClassIndex()) + "\n");
		builder.append(
			"Type: " + DexUtil.convertTypeIndexToString(header, item.getTypeIndex()) + "\n");
		builder.append("Name: " + DexUtil.convertToString(header, item.getNameIndex()) + "\n");
		setPlateComment(program, address, builder.toString());

		++index;

		address = address.add(dataType.getLength());
	}
}
 
Example 14
Source File: FunctionSymbol.java    From ghidra with Apache License 2.0 5 votes vote down vote up
@Override
public Reference[] getReferences(TaskMonitor monitor) {
	lock.acquire();
	try {
		checkIsValid();
		Reference[] refs = super.getReferences(monitor);
		if (monitor == null) {
			monitor = TaskMonitor.DUMMY;
		}
		if (monitor.isCancelled()) {
			return refs;
		}
		List<Long> thunkIds = functionMgr.getThunkFunctionIds(key);
		if (thunkIds == null) {
			return refs;
		}
		int thunkCnt = thunkIds.size();
		Reference[] newRefs = new Reference[refs.length + thunkCnt];
		System.arraycopy(refs, 0, newRefs, thunkCnt, refs.length);
		for (int i = 0; i < thunkCnt; i++) {
			if (monitor.isCancelled()) {
				return refs;
			}
			Symbol s = symbolMgr.getSymbol(thunkIds.get(i));
			newRefs[i] = new ThunkReference(s.getAddress(), getAddress());
			monitor.setProgress(refs.length + i);
		}
		return newRefs;
	}
	finally {
		lock.release();
	}
}
 
Example 15
Source File: SampleProgramTreePlugin.java    From ghidra with Apache License 2.0 4 votes vote down vote up
@Override
public boolean applyTo(DomainObject obj, TaskMonitor monitor) {
	Program program = (Program) obj;

	listing = program.getListing();

	createDefaultTreeView(program, programTreeName);

	Memory mem = program.getMemory();

	ProgramModule root_module = listing.getRootModule(programTreeName);

	AddressSet set = new AddressSet(mem);

	try {
		root_module.createModule("Fragments");
	}
	catch (DuplicateNameException e) {
		// don't care???
	}
	ProgramModule frags = listing.getModule(programTreeName, "Fragments");

	long startCount = set.getNumAddresses();
	monitor.initialize(startCount);
	while (!monitor.isCancelled() && !set.isEmpty()) {
		MemoryBlock block = mem.getBlock(set.getMinAddress());
		Address start = block.getStart();
		Address end = block.getEnd();

		set.deleteRange(block.getStart(), block.getEnd());

		long numLeft = set.getNumAddresses();
		monitor.setProgress(startCount - numLeft);

		String mod_name = block.getName();

		monitor.setMessage("Module " + start + " : " + mod_name);

		ProgramModule mod = make_module(mod_name, frags);
		makeFragment(start, end, "frag_" + fragment_count, mod);
		fragment_count++;
	}

	return true;
}
 
Example 16
Source File: ConstantPropagationAnalyzer.java    From ghidra with Apache License 2.0 4 votes vote down vote up
protected AddressSetView findLocations(Program program, AddressSetView set,
		Set<Address> locations, TaskMonitor monitor) throws CancelledException {

	monitor.setMessage("Finding function locations...");
	long total = set.getNumAddresses();
	monitor.initialize(total);

	// iterate over functions in program
	// add each defined function start to the list
	// return the address set that is minus the bodies of each function
	AddressSet inBodySet = new AddressSet();
	Iterator<Function> fiter = program.getFunctionManager().getFunctionsOverlapping(set);
	while (fiter.hasNext()) {
		monitor.checkCanceled();
		Function function = fiter.next();
		locations.add(function.getEntryPoint());
		inBodySet.add(function.getBody());
	}

	monitor.setProgress(total - inBodySet.getNumAddresses());
	set = set.subtract(inBodySet);

	// set now has Stuff in it that isn't in a recorded function body
	ReferenceManager referenceManager = program.getReferenceManager();
	AddressIterator referenceDestinationIterator =
		referenceManager.getReferenceDestinationIterator(set, true);

	AddressSet outOfBodySet = new AddressSet();
	while (referenceDestinationIterator.hasNext()) {
		monitor.checkCanceled();
		Address address = referenceDestinationIterator.next();
		ReferenceIterator referencesTo = referenceManager.getReferencesTo(address);
		while (referencesTo.hasNext()) {
			Reference reference = referencesTo.next();
			if (reference.getReferenceType().isCall()) {
				locations.add(address);
				outOfBodySet.add(address);
				// could subtract all local non-call flows from the set, but
				// might be extra work...
				break;
			}
		}
	}

	monitor.incrementProgress(outOfBodySet.getNumAddresses());
	set = set.subtract(outOfBodySet);

	// now iterate over individual address ranges, and use first address as a start
	outOfBodySet = new AddressSet();
	AddressRangeIterator addressRanges = set.getAddressRanges();
	while (addressRanges.hasNext()) {
		monitor.checkCanceled();
		AddressRange addressRange = addressRanges.next();
		locations.add(addressRange.getMinAddress());
		outOfBodySet.add(addressRange.getMinAddress());
	}

	monitor.incrementProgress(outOfBodySet.getNumAddresses());
	set = set.subtract(outOfBodySet);

	return set;
}
 
Example 17
Source File: SymbolManager.java    From ghidra with Apache License 2.0 4 votes vote down vote up
/**
 * Add old local symbols
 * @param table
 * @throws IOException
 * @throws CancelledException
 */
private void processOldLocalSymbols(TaskMonitor monitor)
		throws IOException, CancelledException {
	Table table = program.getDBHandle().getScratchPad().getTable(OLD_LOCAL_SYMBOLS_TABLE);
	if (table == null) {
		return;
	}

	AddressMap oldAddrMap = addrMap.getOldAddressMap();

	monitor.setMessage("Upgrading Local Symbols...");
	monitor.initialize(table.getRecordCount());
	int cnt = 0;

	RecordIterator iter = table.iterator();
	while (iter.hasNext()) {
		monitor.checkCanceled();
		Record rec = iter.next();
		Address addr = oldAddrMap.decodeAddress(rec.getLongValue(OLD_SYMBOL_ADDR_COL));
		Namespace namespace = namespaceMgr.getNamespaceContaining(addr);
		if (namespace.getID() != Namespace.GLOBAL_NAMESPACE_ID) {
			// Add symbol to function namespace
			String name = rec.getString(OLD_SYMBOL_NAME_COL);
			if (SymbolUtilities.startsWithDefaultDynamicPrefix(name)) {
				name = "_" + name; // dynamic prefix is reserved
			}
			boolean success = false;
			while (!success) {
				try {
					addSymbolRecord(rec.getKey(), addr, namespace, name,
						rec.getBooleanValue(OLD_SYMBOL_IS_PRIMARY_COL), SymbolType.LABEL,
						SourceType.USER_DEFINED);
					success = true;
				}
				catch (DuplicateNameException e) {
					name = rec.getString(OLD_SYMBOL_NAME_COL) + (++cnt);
				}
			}
		}
		monitor.setProgress(++cnt);
	}
}
 
Example 18
Source File: NewExt4Analyzer.java    From ghidra with Apache License 2.0 4 votes vote down vote up
private void createInodeTables( Program program, 
								BinaryReader reader, 
								Ext4SuperBlock superBlock, 
								Ext4GroupDescriptor [] groupDescriptors, 
								boolean is64Bit, 
								TaskMonitor monitor ) throws DuplicateNameException, Exception {
	
	int inodeCount = superBlock.getS_inodes_count( );
	Ext4Inode [] inodes = new Ext4Inode [ inodeCount ];
	int inodeIndex = 0;

	for ( int i = 0; i < groupDescriptors.length; i++ ) {
		monitor.checkCanceled( );
		long inodeTableBlockOffset = groupDescriptors[ i ].getBg_inode_table_lo( ) & 0xffffffffL;
		if ( is64Bit ) {
			inodeTableBlockOffset = ( groupDescriptors[ i ].getBg_inode_table_hi( ) << 32 ) | inodeTableBlockOffset;
		}
		long offset = inodeTableBlockOffset * blockSize;
		reader.setPointerIndex( offset );
		Address address = null;
		try {
			address = toAddr( program, offset );
		}
		catch ( Exception e ) {
			throw new IOException( "offset " + offset + " not in program." );
		}

		int inodesPerGroup = superBlock.getS_inodes_per_group( );
		monitor.setMessage( "Creating inode table " + i + " of " + ( groupDescriptors.length - 1 ) + "..." );
		monitor.setMaximum( inodesPerGroup );
		monitor.setProgress( 0 );
		for ( int j = 0; j < inodesPerGroup; j++ ) {
			monitor.checkCanceled( );

			Ext4Inode inode = new Ext4Inode( reader );
			DataType dataType = inode.toDataType( );
			createData( program, address, dataType );

			String comment = "Inode: 0x" + Integer.toHexString( inodeIndex + 1 ) + "\n";
			comment += "Group Descriptor ID: 0x" + Integer.toHexString( i ) + "\n";
			comment += "Inode Offset Into Group: 0x" + Integer.toHexString( j ) + "\n";

			Ext4IBlock iBlock = inode.getI_block( );
			if ( iBlock != null ) {
				for ( Ext4Extent extent : iBlock.getExtentEntries( ) ) {
					monitor.checkCanceled( );
					long lo = extent.getEe_start_lo( ) & 0xffffffffL;
					long hi = extent.getEe_start_hi( ) & 0xffffffffL;
					long value = ( hi << 32 ) | lo;
					long destination = value * blockSize;
					comment += "Extent: 0x" + Long.toHexString( destination ) + "\n";
				}
			}

			setPlateComment( program, address, comment );
			createLabel( program, address, "INODE_" + "0x" + Integer.toHexString( inodeIndex + 1 ) );
			address = address.add( superBlock.getS_inode_size( ) );
			reader.setPointerIndex( address.getOffset( ) );
			monitor.incrementProgress( 1 );
			inodes[ inodeIndex++ ] = inode; //inodes[ inodesPerGroup * i + j ] = inode;
		}
	}

	processInodes( program, reader, superBlock, inodes, monitor );
}
 
Example 19
Source File: AARCH64PltThunkAnalyzer.java    From ghidra with Apache License 2.0 4 votes vote down vote up
@Override
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
		throws CancelledException {
	
	Memory memory = program.getMemory();
	MemoryBlock block = memory.getBlock(".plt");
	if (block == null) {
		return true;
	}
	
	set = set.intersectRange(block.getStart(), block.getEnd());
	set = removeFunctionBodies(program, set, monitor);
	if (set.isEmpty()) {
		return true;
	}

	SequenceSearchState sequenceSearchState = SequenceSearchState.buildStateMachine(
			leThunkPatterns);
	
	monitor.setIndeterminate(true);
	monitor.setProgress(0);
	
	ArrayList<Match> matches = new ArrayList<>();
	
	try {
		for (AddressRange range : set.getAddressRanges()) {
			
			byte[] bytes = new byte[(int)range.getLength()];
			if (block.getBytes(range.getMinAddress(), bytes, 0, bytes.length) != bytes.length) {
				log.appendMsg("Expected initialized .plt section block");
				return false;
			}
			
			matches.clear();
			sequenceSearchState.apply(bytes, matches);
			
			for (Match match : matches) {
				Address addr = range.getMinAddress().add(match.getMarkOffset());
				analyzePltThunk(program, addr, match.getSequenceSize(), monitor);
			}
			
		}
	} catch (MemoryAccessException | AddressOutOfBoundsException e) {
		log.appendMsg("Expected initialized .plt section block: " + e.getMessage());
	}
	
	return true;
}
 
Example 20
Source File: CodeUnitMerger.java    From ghidra with Apache License 2.0 4 votes vote down vote up
private void mergeCodeUnits(Program fromPgm, AddressSetView addrSet, boolean copyBytes,
		TaskMonitor monitor) throws MemoryAccessException, CancelledException {
	if (addrSet.isEmpty()) {
		return;
	}
	adjustCodeUnitPicked(fromPgm, addrSet);

	Listing resultListing = resultPgm.getListing();

	ProgramContext originContext = fromPgm.getProgramContext();
	ProgramContext resultContext = resultPgm.getProgramContext();
	Register contextReg = originContext.getBaseContextRegister();

	for (AddressRange range : addrSet) {

		// Clear any existing code units in the merged program
		// where this code unit needs to go.
		// May cause the merge code unit to lose info attached to it, such as references.
		resultListing.clearCodeUnits(range.getMinAddress(), range.getMaxAddress(), false);

		if (contextReg != null) {
			// Copy context register value
			mergeProgramContext(resultContext, originContext,
				originContext.getBaseContextRegister(), range, monitor);
		}
	}

	CodeUnitIterator sourceCodeUnits = fromPgm.getListing().getCodeUnits(addrSet, true);
	long totalAddresses = addrSet.getNumAddresses();
	long granularity = (totalAddresses / 100) + 1;
	int mergeProgress = 0;
	int mergeCount = 0;
	monitor.initialize(totalAddresses);
	// Get each code unit out of the iterator and set it in the merged
	// program if it is an instruction.
	while (sourceCodeUnits.hasNext()) {
		monitor.checkCanceled();
		CodeUnit cu = sourceCodeUnits.next();
		if (mergeCount > granularity) {
			monitor.setProgress(mergeProgress);
			incrementProgress(1);
			mergeCount = 0;
		}
		//monitor.setMessage("Replacing Code Unit @ " + cu.getMinAddress().toString());
		try {
			// create a new instruction or data.
			if (cu instanceof Instruction) {
				performMergeInstruction((Instruction) cu, true);
			}
			else if (cu instanceof Data) {
				performMergeData((Data) cu, copyBytes);
			}
		}
		catch (CodeUnitInsertionException exc) {
		}
		int increment =
			(int) (cu.getMaxAddress().getOffset() - cu.getMinAddress().getOffset() + 1);
		mergeProgress += increment;
		mergeCount += increment;
	}
}