public override Address ReadStub(Address addrStub, MemoryArea mem) { var offsetInSection = (uint)(addrStub - mem.BaseAddress); var opcode = mem.ReadBeUInt16(offsetInSection); // Expect move.l offset(pc),a0 if (opcode != 0x207B) { return(null); } var offsetToGotEntry = mem.ReadBeInt32(offsetInSection + 4); var addrGotEntry = addrStub + 2 + offsetToGotEntry; return(addrGotEntry); }
public void AddResourcesToImageMap( Address addrLoad, MemoryArea mem, SegmentMap segmentMap, List <ImageSymbol> entryPoints, SortedList <Address, ImageSymbol> symbols) { JumpTable jt = null; var codeSegs = new Dictionary <int, ImageSegment>(); foreach (ResourceType type in ResourceTypes) { foreach (ResourceReference rsrc in type.References) { uint uSegOffset = rsrc.DataOffset + rsrcDataOff; int segmentSize = mem.ReadBeInt32(uSegOffset); // Skip the size longword at the beginning of the segment, and an extra 4 // if it is a code segement other than CODE#0. int bytesToSkip = 4; if (type.Name == "CODE" && rsrc.ResourceID != 0) { bytesToSkip += 4; } var abSegment = new byte[segmentSize]; Array.Copy(mem.Bytes, uSegOffset + bytesToSkip, abSegment, 0, segmentSize); Address addrSegment = addrLoad + uSegOffset + bytesToSkip; //$TODO pad to 16-byte boundary? var memSeg = new MemoryArea(addrSegment, abSegment); var segment = segmentMap.AddSegment(new ImageSegment( ResourceDescriptiveName(type, rsrc), memSeg, AccessMode.Read)); if (type.Name == "CODE") { if (rsrc.ResourceID == 0) { jt = ProcessJumpTable(memSeg, symbols); } else { codeSegs.Add(rsrc.ResourceID, segment); var macsBug = new MacsBugSymbolScanner(arch, segment.MemoryArea); var mbSymbols = macsBug.ScanForSymbols(); foreach (var symbol in mbSymbols) { symbols[symbol.Address] = symbol; } } } } } // We have found a jump table, so we allocate an A5World. if (jt != null) { // Find an address beyond all known segments. var addr = segmentMap.Segments.Values.Max(s => s.Address + s.Size).Align(0x10); var a5world = LoadA5World(jt, addr, codeSegs, symbols); platform.A5World = a5world; platform.A5Offset = jt.BelowA5Size; segmentMap.AddSegment(a5world); // Find first (and only!) segment containing the name %A5Init. var a5dataSegment = segmentMap.Segments.Values.SingleOrDefault(SegmentNamedA5Init); if (a5dataSegment == null) { return; } // Get an image reader to the start of the data. var a5dr = GetA5InitImageReader(a5dataSegment); if (a5dr == null) { return; } var a5dbelow = a5dr.ReadBeUInt32(); var a5dbankSize = a5dr.ReadBeUInt32(); var a5doffset = a5dr.ReadBeUInt32(); var a5dreloc = a5dr.ReadBeUInt32(); var a5dhdrend = a5dr.ReadBeUInt32(); if (a5dbankSize != 0x00010000) { // bank size not supported for compressed global data return; } A5Expand(a5dr, a5dbelow); } }