Java Code Examples for ghidra.program.model.address.Address#add()

The following examples show how to use ghidra.program.model.address.Address#add() . 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: EhFrameHeaderSection.java    From ghidra with Apache License 2.0 6 votes vote down vote up
/**
 * Create the data field for the number of entries in the FDE table 
 * and add an identifying comment.
 * 
 * @param curAddress address of the FDE count field
 * @param fdeDecoder decoder to use in determining data type for this field
 * @return the next address after the FDE count field
 */
private Address processEncodedFdeCount(Address curAddress, DwarfEHDecoder fdeDecoder) {

	/* Create the Encoded FDE count member */
	DataType encDataType = fdeDecoder.getDataType(program);

	CreateDataCmd dataCmd = new CreateDataCmd(curAddress, encDataType);
	dataCmd.applyTo(program);

	SetCommentCmd commentCmd =
		new SetCommentCmd(curAddress, CodeUnit.EOL_COMMENT, "Encoded FDE count");
	commentCmd.applyTo(program);

	curAddress = curAddress.add(encDataType.getLength());
	return curAddress;
}
 
Example 2
Source File: DataTypeMarkupItemTest.java    From ghidra with Apache License 2.0 6 votes vote down vote up
@Test
public void testReplaceWithLargerWhenBlockedByInstruction() throws Exception {

	Address sourceAddress = addr("0x010074e6", sourceProgram); // LoadCursorW
	TerminatedStringDataType sourceDataType = new TerminatedStringDataType();
	Data sourceData = setDataType(sourceProgram, sourceAddress, sourceDataType, -1); // Get "LoadCursorW".

	Address destinationAddress = addr("0x010074e6", destinationProgram); // LoadCursorW
	StringDataType destinationDataType = new StringDataType();
	Data destinationData =
		setDataType(destinationProgram, destinationAddress, destinationDataType, 4); // Get "Load".
	Address instructionAddress = destinationAddress.add(4);
	Instruction instruction = createInstruction(destinationProgram, instructionAddress);
	assertNotNull(instruction);
	Listing listing = destinationProgram.getListing();
	Instruction instructionAt = listing.getInstructionAt(instructionAddress);
	assertNotNull(instructionAt);

	DataTypeValidator validator = new DataTypeValidator(sourceData, destinationData,
		ReplaceDataChoices.REPLACE_FIRST_DATA_ONLY);
	doTestFindAndApplyMarkupItem_ApplyFails(validator);
}
 
Example 3
Source File: DexHeaderFormatAnalyzer.java    From ghidra with Apache License 2.0 6 votes vote down vote up
private void processCodeItemHandlers(Program program, CodeItem codeItem, Address tempAddress)
		throws DuplicateNameException, IOException, Exception {
	EncodedCatchHandlerList handlerList = codeItem.getHandlerList();
	if (handlerList == null) {
		return;
	}

	DataType handlerDataType = handlerList.toDataType();
	createData(program, tempAddress, handlerDataType);
	createFragment(program, "handlers", tempAddress,
		tempAddress.add(handlerDataType.getLength()));
	tempAddress = tempAddress.add(handlerDataType.getLength());

	for (EncodedCatchHandler handler : handlerList.getHandlers()) {
		DataType dataType = handler.toDataType();
		createData(program, tempAddress, dataType);
		createFragment(program, "handlers", tempAddress, tempAddress.add(dataType.getLength()));
		tempAddress = tempAddress.add(dataType.getLength());
	}
}
 
Example 4
Source File: CoffBinaryAnalysisCommand.java    From ghidra with Apache License 2.0 6 votes vote down vote up
private void processSectionLineNumbers(CoffSectionHeader section) throws Exception {
	monitor.setMessage("Processing section line numbers...");
	if (section.getLineNumberCount() == 0) {
		return;
	}
	Address start = toAddr(section.getPointerToLineNumbers());
	long length = section.getLineNumberCount() * CoffLineNumber.SIZEOF;
	Address address = start;
	List<CoffLineNumber> lineNumbers = section.getLineNumbers();
	for (CoffLineNumber lineNumber : lineNumbers) {
		if (monitor.isCancelled()) {
			break;
		}
		DataType dt = lineNumber.toDataType();
		createData(address, dt);
		address = address.add(dt.getLength());
	}
	createFragment(section.getName() + "-LineNumbers", start, length);
}
 
Example 5
Source File: PreboundDynamicLibraryCommand.java    From ghidra with Apache License 2.0 6 votes vote down vote up
@Override
public void markup(MachHeader header, FlatProgramAPI api, Address baseAddress, boolean isBinary,
		ProgramModule parentModule, TaskMonitor monitor, MessageLog log) {
	updateMonitor(monitor);
	try {
		if (isBinary) {
			createFragment(api, baseAddress, parentModule);
			Address addr = baseAddress.getNewAddress(getStartIndex());
			api.createData(addr, toDataType());

			int nameLen = getCommandSize() - name.getOffset();
			Address nameAddr = addr.add(name.getOffset());
			api.createAsciiString(nameAddr, nameLen);
		}
	}
	catch (Exception e) {
		log.appendMsg("Unable to create " + getCommandName() + " - " + e.getMessage());
	}
}
 
Example 6
Source File: ObjectiveC2_ClassAnalyzer.java    From ghidra with Apache License 2.0 6 votes vote down vote up
private void processSelectorReferences(ObjectiveC2_State state) throws Exception {
	state.monitor.setMessage("Objective-C 2.0 Selector References...");

	MemoryBlock block =
		state.program.getMemory().getBlock(ObjectiveC2_Constants.OBJC2_SELECTOR_REFS);
	if (block == null) {
		return;
	}
	ObjectiveC1_Utilities.clear(state, block);

	long count = block.getSize() / state.pointerSize;

	state.monitor.initialize((int) count);

	Address address = block.getStart();

	for (int i = 0; i < count; ++i) {
		if (state.monitor.isCancelled()) {
			break;
		}
		state.monitor.setProgress(i);
		ObjectiveC1_Utilities.createPointerAndReturnAddressBeingReferenced(state.program,
			address);
		address = address.add(state.pointerSize);
	}
}
 
Example 7
Source File: Cie.java    From ghidra with Apache License 2.0 5 votes vote down vote up
/**
 * Reads the CIE Augmentation Data and holds it in this class. This block of data is
 * defined by the contents of the Augmentation String and is only present if
 * the Augmentation string contains the character 'z'. Length of this string
 * is given by the Augmentation length.
 * 
 * @param addr Address at which the Augmentation Data array should be created.
 * @return Address immediately following the Augmentation Data
 * @throws MemoryAccessException if memory for the CIE couldn't be read.
 */
private Address grabAugmentationData(Address addr) throws MemoryAccessException {

	/*
	 * Copies the Augmentation Data at the specified address into <code>augmentationData</code>
	 * so it can be processed.
	 */
	augmentationData = new byte[augmentationDataLength];
	int numBytesRead = program.getMemory().getBytes(addr, augmentationData);

	curSize += numBytesRead;

	return addr.add(numBytesRead);
}
 
Example 8
Source File: Cie.java    From ghidra with Apache License 2.0 5 votes vote down vote up
/**
	 * Creates the initial set of Call Frame instructions. The
	 * number of instructions is determined by the remaining space in the CIE
	 * record.
	 * 
	 * @param addr Address at which the initial instructions array should be created.
	 * @return Address immediately following the initial instructions array
	 * @throws MemoryAccessException if memory for the CIE couldn't be read.
	 */
	private Address processInitialInstructions(Address addr) throws MemoryAccessException {
		CreateArrayCmd arrayCmd = null;

		// Create initial instructions array with remaining bytes
		initialInstructionCount = intLength - curSize;
		arrayCmd = new CreateArrayCmd(addr, initialInstructionCount, new ByteDataType(), BYTE_LEN);
		arrayCmd.applyTo(program);
		SetCommentCmd.createComment(program, addr, "(CIE) Initial Instructions",
			CodeUnit.EOL_COMMENT);

		initialInstructions = new byte[initialInstructionCount];
		int numBytesRead = program.getMemory().getBytes(addr, initialInstructions);

		// *** The following commented out code is for debugging purposes. ***
//		DwarfCallFrameOpcodeParser parser =
//			new DwarfCallFrameOpcodeParser(program, addr, numBytesRead);
//		parser.parse();

		curSize += numBytesRead;

		try {
			return addr.add(numBytesRead);
		}
		catch (AddressOutOfBoundsException e) {
			return null; // reached end of block
		}
	}
 
Example 9
Source File: RTTI1DataType.java    From ghidra with Apache License 2.0 5 votes vote down vote up
@Override
public boolean isValid(Program program, Address startAddress,
		DataValidationOptions validationOptions) {

	Memory memory = program.getMemory();
	Listing listing = program.getListing();

	if (!memory.contains(startAddress)) {
		return false;
	}

	Address endAddress = startAddress.add(LENGTH - 1);
	try {
		MSDataTypeUtils.getBytes(memory, startAddress, LENGTH);
	}
	catch (InvalidDataTypeException e) {
		return false; // Couldn't get enough bytes from memory for an RTTI1.
	}

	if (!validationOptions.shouldIgnoreInstructions() &&
		containsInstruction(listing, startAddress, endAddress)) {
		return false;
	}

	if (!validationOptions.shouldIgnoreDefinedData() &&
		containsDefinedData(listing, startAddress, endAddress)) {
		return false;
	}

	// RTTI1 should start on 4 byte boundary.
	if (startAddress.getOffset() % 4 != 0) {
		return false;
	}

	return validateComponents(program, startAddress, validationOptions);
}
 
Example 10
Source File: VfTableModel.java    From ghidra with Apache License 2.0 5 votes vote down vote up
/**
 * Gets the address of the virtual function pointed to by the vf table element at the index 
 * specified by <code>tableElementIndex</code>.
 * @param tableElementIndex index of the vf table element
 * @return the virtual function's address or null
 */
public Address getVirtualFunctionPointer(int tableElementIndex) {
	Address tableAddress = getAddress();
	int defaultPointerSize = getDefaultPointerSize();
	Address address = tableAddress.add(defaultPointerSize * tableElementIndex);
	return getAbsoluteAddress(getProgram(), address);
}
 
Example 11
Source File: VariableImpl.java    From ghidra with Apache License 2.0 5 votes vote down vote up
private Varnode expandVarnode(Varnode varnode, int sizeIncrease, VariableStorage curStorage,
		int newSize, DataType type) throws InvalidInputException {

	Address addr = varnode.getAddress();
	if (addr.isStackAddress()) {
		return resizeStackVarnode(varnode, varnode.getSize() + sizeIncrease, curStorage,
			newSize, type);
	}
	int size = varnode.getSize() + sizeIncrease;
	boolean bigEndian = program.getMemory().isBigEndian();
	Register reg = program.getRegister(varnode);
	Address vnAddr = varnode.getAddress();
	if (reg != null) {
		// Register expansion
		Register newReg = reg;
		while ((newReg.getMinimumByteSize() < size)) {
			newReg = newReg.getParentRegister();
			if (newReg == null) {
				throw new InvalidInputException("Current storage can't be expanded to " +
					newSize + " bytes: " + curStorage.toString());
			}
		}
		if (bigEndian) {
			vnAddr = vnAddr.add(newReg.getMinimumByteSize() - size);
			return new Varnode(vnAddr, size);
		}
	}
	boolean complexDt = (type instanceof Composite) || (type instanceof Array);
	if (bigEndian && !complexDt) {
		return new Varnode(vnAddr.subtract(sizeIncrease), size);
	}
	return new Varnode(vnAddr, size);
}
 
Example 12
Source File: RttiUtil.java    From ghidra with Apache License 2.0 5 votes vote down vote up
/**
 * Determines the number of vf addresses in the vf table that begins at the specified base 
 * address.
 * @param program the program whose memory is providing their addresses
 * @param vfTableBaseAddress the base address in the program for the vf table
 * @return the number of virtual function addresses in the vf table
 */
static int getVfTableCount(Program program, Address vfTableBaseAddress) {

	Memory memory = program.getMemory();
	MemoryBlock textBlock = memory.getBlock(".text");
	AddressSetView initializedAddresses = memory.getLoadedAndInitializedAddressSet();
	PseudoDisassembler pseudoDisassembler = new PseudoDisassembler(program);

	// Create pointers starting at the address until reaching a 0 pointer.
	// Terminate the possible table at any entry containing a cross reference that 
	// is beyond the first table entry and don't include it.
	int tableSize = 0;
	Address currentVfPointerAddress = vfTableBaseAddress;
	int defaultPointerSize = program.getDefaultPointerSize();
	while (true) {
		Address referencedAddress = getAbsoluteAddress(program, currentVfPointerAddress);
		if (referencedAddress == null) {
			break; // Cannot get a virtual function address.
		}
		if (referencedAddress.getOffset() == 0) {
			break; // Encountered 0 entry.
		}
		if (!initializedAddresses.contains(referencedAddress)) {
			break; // Not pointing to initialized memory.
		}
		if ((textBlock != null) ? !textBlock.equals(memory.getBlock(referencedAddress))
				: false) {
			break; // Not pointing to text section.
		}
		if (!pseudoDisassembler.isValidSubroutine(referencedAddress, true)) {
			break; // Not pointing to possible function.
		}

		tableSize++; // Count this entry in the table.

		// Advance to the next table entry address.
		currentVfPointerAddress = currentVfPointerAddress.add(defaultPointerSize);
	}
	return tableSize;
}
 
Example 13
Source File: PropertyManagerPluginScreenShots.java    From ghidra with Apache License 2.0 5 votes vote down vote up
@Override
public void setUp() throws Exception {
	super.setUp();

	// create some properties
	int id = program.startTransaction("test");
	PropertyMapManager pm = program.getUsrPropertyManager();
	pm.createIntPropertyMap("Foo Property");
	IntPropertyMap map1 = pm.createIntPropertyMap("Bar Property");
	Memory memory = program.getMemory();
	MemoryBlock block = memory.getBlock(".text");
	Address addr = block.getStart();
	for (int i = 0; i < 5000; i++) {
		map1.add(addr, i);
		addr = addr.add(10);
	}

	program.endTransaction(id, true);
	loadPlugin(PropertyManagerPlugin.class);
	showProvider(PropertyManagerProvider.class);
	PropertyManagerProvider provider = getProvider(PropertyManagerProvider.class);
	goToListing(0x00401082);
	final JTable table = (JTable) getInstanceField("table", provider);
	runSwing(new Runnable() {

		@Override
		public void run() {
			table.setRowSelectionInterval(0, 0);
		}
	});
}
 
Example 14
Source File: Img3Analyzer.java    From ghidra with Apache License 2.0 5 votes vote down vote up
private void applyTags(Program program, Img3 header, Address tagAddress, TaskMonitor monitor)
		throws Exception {
	List<AbstractImg3Tag> tags = header.getTags();
	for (AbstractImg3Tag tag : tags) {
		if (monitor.isCancelled()) {
			break;
		}
		DataType dt = tag.toDataType();
		setPlateComment(program, tagAddress, tag.getMagic());
		createData(program, tagAddress, dt);
		createFragment(program, tag.getMagic(), tagAddress,
			tagAddress.add(tag.getTotalLength()));
		tagAddress = tagAddress.add(tag.getTotalLength());
	}
}
 
Example 15
Source File: DexHeaderFormatAnalyzer.java    From ghidra with Apache License 2.0 4 votes vote down vote up
private void processPrototypes(Program program, DexHeader header, TaskMonitor monitor,
		MessageLog log) throws Exception {
	monitor.setMessage("DEX: processing prototypes");
	monitor.setMaximum(header.getProtoIdsSize());
	monitor.setProgress(0);
	Address address = toAddr(program, header.getProtoIdsOffset());
	int index = 0;
	for (PrototypesIDItem item : header.getPrototypes()) {
		monitor.checkCanceled();
		monitor.incrementProgress(1);
		DataType dataType = item.toDataType();
		createData(program, address, dataType);
		createFragment(program, "prototypes", address, address.add(dataType.getLength()));

		StringBuilder builder = new StringBuilder();
		builder.append("Prototype Index: 0x" + Integer.toHexString(index) + "\n");
		builder.append(
			"Shorty: " + DexUtil.convertToString(header, item.getShortyIndex()) + "\n");
		builder.append("Return Type: " +
			DexUtil.convertTypeIndexToString(header, item.getReturnTypeIndex()) + "\n");

		if (item.getParametersOffset() > 0) {
			builder.append("Parameters: " + "\n");
			TypeList parameters = item.getParameters();
			for (TypeItem parameter : parameters.getItems()) {
				monitor.checkCanceled();
				builder.append(
					DexUtil.convertTypeIndexToString(header, parameter.getType()) + " ");
			}

			DataType parametersDT = parameters.toDataType();
			Address parametersAddress = toAddr(program, item.getParametersOffset());
			createData(program, parametersAddress, parametersDT);
		}

		setPlateComment(program, address, builder.toString());

		++index;

		address = address.add(dataType.getLength());
	}
}
 
Example 16
Source File: LSDATable.java    From ghidra with Apache License 2.0 4 votes vote down vote up
/**
 * Create a LSDA Table from the bytes at <code>addr</code>. Parses the header, call site table,
 * action table, and type table.
 * <br>Note: This method must get called before any of the "get..." methods.
 * @param tableAddr the start (minimum address) of this LSDA table.
 * @param region the region of the program associated with this table
 * @throws MemoryAccessException if memory couldn't be accessed for the LSDA table
 */
public void create(Address tableAddr, RegionDescriptor region)
		throws MemoryAccessException {

	region.setLSDATable(this);

	Address baseAdress = tableAddr;

	header = new LSDAHeader(monitor, program, region);
	header.create(tableAddr);

	tableAddr = header.getNextAddress();

	callSiteTable = new LSDACallSiteTable(monitor, program, region);
	callSiteTable.create(tableAddr);

	tableAddr = callSiteTable.getNextAddress();

	int maxActionOffset = 0;
	boolean generateActionTable = false;
	for (LSDACallSiteRecord cs : callSiteTable.getCallSiteRecords()) {
		maxActionOffset = Math.max(maxActionOffset, cs.getActionOffset());
		if (cs.getActionOffset() != LSDAActionRecord.NO_ACTION) {
			generateActionTable = true;
		}
	}

	if (generateActionTable) {

		Address maxTableAddr = tableAddr.add(maxActionOffset);

		actionTable = new LSDAActionTable(monitor, program, region);
		actionTable.create(tableAddr, maxTableAddr);

		tableAddr = actionTable.getNextAddress();
	}

	if (header.getTTypeEncoding() != LSDAHeader.OMITTED_ENCODING_TYPE) {

		// NOTICE: This builds from the bottom (TTypeBaseAddress) to top
		// (tableAddr)
		Address tTypeBaseAddress = header.getTTypeBaseAddress();
		if (tTypeBaseAddress != Address.NO_ADDRESS) {
			typeTable = new LSDATypeTable(monitor, program, region);
			typeTable.create(tTypeBaseAddress, tableAddr);
		}
	}

	SetCommentCmd commentCmd = new SetCommentCmd(baseAdress, CodeUnit.PLATE_COMMENT, "Language-Specific Data Area");
	commentCmd.applyTo(program);

}
 
Example 17
Source File: EditBytesScriptTest.java    From ghidra with Apache License 2.0 4 votes vote down vote up
@Test
public void testInstWithoutUndefinedDisassemble() throws Exception {

	Address instAddr = addr("01001103");
	assertInstruction(instAddr, 2, "00 00", "ADD");

	Address undefAddr = instAddr.add(2);
	assertUndefined(undefAddr, undefAddr, 1, "00");

	goTo(tool, program, instAddr);
	ScriptTaskListener scriptID = env.runScript(script);

	giveUserInputBytes("5f 5f 5f");

	waitForScript(scriptID);

	assertInstruction(instAddr, 1, "5f", "POP");

	assertInstruction(instAddr.add(1), 1, "5f", "POP");

	assertUndefined(undefAddr, undefAddr, 1, "5f");
}
 
Example 18
Source File: FunctionGraphPlugin1Test.java    From ghidra with Apache License 2.0 4 votes vote down vote up
@Test
public void testCopyKeyBinding() throws Exception {
	//
	// Make a program selection and test that executing the copy keybinding will copy the 
	// selection (across vertices).
	//

	// 
	// Initialize the clipboard with known data
	//
	Clipboard systemClipboard = tool.getToolFrame().getToolkit().getSystemClipboard();
	systemClipboard.setContents(DUMMY_TRANSFERABLE, null);
	waitForSwing();

	//
	// Verify our initial state
	FGData graphData = getFunctionGraphData();
	assertNotNull(graphData);
	assertTrue("Unexpectedly received an empty FunctionGraphData", graphData.hasResults());
	ProgramLocation location = getLocationForAddressString(startAddressString);
	assertTrue(graphData.containsLocation(location));
	FunctionGraph functionGraph = graphData.getFunctionGraph();

	// locate vertex with cursor
	FGVertex focusedVertex = getFocusVertex(functionGraph);
	assertNotNull("We did not start with a focused vertex", focusedVertex);

	//
	// Create a selection that we will copy from the executing the action 
	//
	AddressSetView addresses = focusedVertex.getAddresses();
	Address address = addresses.getMinAddress();
	ProgramSelection selection =
		new ProgramSelection(program.getAddressFactory(), address, address.add(8));
	tool.firePluginEvent(new ProgramSelectionPluginEvent("Test", selection, program));

	//
	// Validate and execute the action
	//
	DockingAction copyAction = getCopyAction();
	FGController controller = getFunctionGraphController();
	ComponentProvider provider = controller.getProvider();
	assertTrue(copyAction.isEnabledForContext(provider.getActionContext(null)));

	performAction(copyAction, provider, false);

	waitForTasks();

	Transferable contents = systemClipboard.getContents(systemClipboard);
	assertNotNull(contents);
	assertTrue("Contents not copied into system clipboard", (contents != DUMMY_TRANSFERABLE));
}
 
Example 19
Source File: DyldCacheProgramBuilder.java    From ghidra with Apache License 2.0 4 votes vote down vote up
/**
 * Fixes up any chained pointers, starting at the given address.
 * 
 * @param unchainedLocList list of locations that were unchained
 * @param page within data pages that has pointers to be unchained
 * @param nextOff offset within the page that is the chain start
 * @param deltaMask delta offset mask for each value
 * @param deltaShift shift needed for the deltaMask to extract the next offset
 * @param valueAdd value to be added to each chain pointer
 * 
 * @throws MemoryAccessException IO problem reading file
 * @throws CancelledException user cancels
 */
private void processPointerChain(List<Address> unchainedLocList, long page, long nextOff,
		long deltaMask, long deltaShift, long valueAdd)
		throws MemoryAccessException, CancelledException {

	// TODO: should the image base be used to perform the ASLR slide on the pointers.
	//        currently image is kept at it's initial location with no ASLR.
	Address chainStart = memory.getProgram().getLanguage().getDefaultSpace().getAddress(page);

	byte origBytes[] = new byte[8];

	long valueMask = 0xffffffffffffffffL >>> (64 - deltaShift);

	long delta = -1;
	while (delta != 0) {
		monitor.checkCanceled();

		Address chainLoc = chainStart.add(nextOff);
		long chainValue = memory.getLong(chainLoc);

		delta = (chainValue & deltaMask) >> deltaShift;
		chainValue = chainValue & valueMask;
		if (chainValue != 0) {
			chainValue += valueAdd;
		}

		if (shouldAddRelocationEntries) {
			// Add entry to relocation table for the pointer fixup
			memory.getBytes(chainLoc, origBytes);
			program.getRelocationTable().add(chainLoc, 1, new long[] { chainValue }, origBytes,
				null);
		}

		memory.setLong(chainLoc, chainValue);

		// delay creating data until after memory has been changed
		unchainedLocList.add(chainLoc);

		nextOff += (delta * 4);
	}
}
 
Example 20
Source File: AppleSingleDoubleBinaryAnalysisCommand.java    From ghidra with Apache License 2.0 4 votes vote down vote up
@Override
public boolean analysisWorkerCallback(Program program, Object workerContext,
		TaskMonitor monitor) throws CancelledException, Exception {
	try {
		ByteProvider provider = new MemoryByteProvider(currentProgram.getMemory(),
			currentProgram.getAddressFactory().getDefaultAddressSpace());

		AppleSingleDouble header = new AppleSingleDouble(provider);
		Address address = toAddr(0);
		DataType headerDT = header.toDataType();
		createData(address, headerDT);
		setPlateComment(address, headerDT.getName());
		createFragment(headerDT.getName(), address, headerDT.getLength());
		address = address.add(headerDT.getLength());

		List<EntryDescriptor> entryList = header.getEntryList();
		for (EntryDescriptor descriptor : entryList) {
			if (monitor.isCancelled()) {
				break;
			}

			DataType descriptorDT = descriptor.toDataType();
			createData(address, descriptorDT);
			setPlateComment(address, descriptorDT.getName());
			createFragment(descriptorDT.getName(), address, descriptorDT.getLength());
			address = address.add(descriptorDT.getLength());

			String name = EntryDescriptorID.convertEntryIdToName(descriptor.getEntryID());
			createFragment(name, toAddr(descriptor.getOffset()), descriptor.getLength());

			Object entryObject = descriptor.getEntry();

			if (descriptor.getEntryID() == EntryDescriptorID.ENTRY_RESOURCE_FORK) {
				markup((ResourceHeader) entryObject, descriptor);
			}
		}

		removeEmptyFragments();

		return true;
	}
	catch (MacException e) {
		messages.appendMsg(
			"Not a binary AppleSingleDouble program: AppleSingleDouble header not found.");
		return false;
	}
}