private bool IsFloatingPointEmulatorFixup(Fixup fixup) { ExternalSymbol symbol = fixup.Target.Referent as ExternalSymbol; if (symbol == null) { return(false); } switch (symbol.Name) { case "FIARQQ": case "FICRQQ": case "FIDRQQ": case "FIERQQ": case "FISRQQ": case "FIWRQQ": case "FJARQQ": case "FJCRQQ": case "FJSRQQ": return(true); default: return(false); } }
private static Fixup ConvertFixupDefinition( FixupDefinition def, Dictionary <object, object> objectMap) { Fixup fixup = new Fixup(); fixup.StartIndex = def.DataOffset; switch (def.Location) { case FixupLocation.LowByte: fixup.LocationType = FixupLocationType.LowByte; break; case FixupLocation.Offset: case FixupLocation.LoaderResolvedOffset: fixup.LocationType = FixupLocationType.Offset; break; case FixupLocation.Base: fixup.LocationType = FixupLocationType.Base; break; case FixupLocation.Pointer: fixup.LocationType = FixupLocationType.Pointer; break; default: throw new InvalidDataException("The fixup location is not supported."); } fixup.Mode = def.Mode; IAddressReferent referent; if (def.Target.Referent is UInt16) { referent = new PhysicalAddress((UInt16)def.Target.Referent, 0); } else { referent = (IAddressReferent)objectMap[def.Target.Referent]; } fixup.Target = new SymbolicTarget { Referent = (IAddressReferent)referent, Displacement = def.Target.Displacement }; //f.Frame = null; return(fixup); }
protected override Instruction DecodeInstruction(Address address) { Instruction instruction = base.DecodeInstruction(address); if (instruction == null) { return(instruction); } // Find the first fixup that covers the instruction. If no // fix-up covers the instruction, find the closest fix-up // that comes after. FixupCollection fixups = library.Image.GetSegment(address.Segment).Segment.Fixups; int fixupIndex = fixups.BinarySearch(address.Offset); // If there's a fixup right at the beginning of the instruction, // it is likely that the location is actually data, unless the // fixup is a floating point emulator which use a trick to change // the opcode. if (fixupIndex >= 0 && fixups[fixupIndex].StartIndex == address.Offset) { if (!IsFloatingPointEmulatorFixup(fixups[fixupIndex])) { AddError(address, ErrorCode.BrokenFixup, "Cannot decode instruction at a fix-up location: {0}", fixups[fixupIndex]); return(null); } } if (fixupIndex < 0) { fixupIndex = ~fixupIndex; } for (int i = 0; i < instruction.Operands.Length; i++) { if (fixupIndex >= fixups.Count) // no more fixups { break; } Fixup fixup = fixups[fixupIndex]; if (fixup.StartIndex >= address.Offset + instruction.EncodedLength) // past end { break; } Operand operand = instruction.Operands[i]; if (operand.FixableLocation.Length > 0) { int start = address.Offset + operand.FixableLocation.StartOffset; int end = start + operand.FixableLocation.Length; if (fixup.StartIndex >= end) { continue; } if (fixup.StartIndex != start || fixup.EndIndex != end) { // throw new BrokenFixupException(fixup); if (IsFloatingPointEmulatorFixup(fixup)) { AddError(new Address(address.Segment, fixup.StartIndex), ErrorCode.FixupDiscarded, "Floating point emulator fix-up discarded: {0}", fixup); } else { AddError(new Address(address.Segment, fixup.StartIndex), ErrorCode.BrokenFixup, "Broken fix-up: {0}", fixup); } continue; } instruction.Operands[i].Tag = fixup.Target; ++fixupIndex; } } if (fixupIndex < fixups.Count) { Fixup fixup = fixups[fixupIndex]; if (fixup.StartIndex < address.Offset + instruction.EncodedLength) { if (IsFloatingPointEmulatorFixup(fixup)) { AddError(new Address(address.Segment, fixup.StartIndex), ErrorCode.FixupDiscarded, "Floating point emulator fix-up discarded: {0}", fixup); } else { AddError(new Address(address.Segment, fixup.StartIndex), ErrorCode.BrokenFixup, "Broken fix-up: {0}", fixup); } } } return(instruction); }
public BrokenFixupException(Fixup fixup) { this.Fixup = fixup; }