public void Fold(int firstBlockSize) { if (firstBlockSize <= 0) { return; } // Repeatedly fold the last guess in the list until the key is less than firstBlockSize while (_guesses.Count > 0 && _guesses.Keys[_guesses.Count - 1] >= firstBlockSize) { // Grab the guess at the end and remove it along with its submap MetaValueGuess guess = _guesses.Values[_guesses.Count - 1]; _guesses.RemoveAt(_guesses.Count - 1); MetaMap subMap = GetSubMap(guess.Offset); if (subMap != null) { _submaps.Remove(guess.Offset); } // Wrap its offset guess.Offset %= firstBlockSize; // Add them back in if (AddGuess(guess)) { AssociateSubMap(guess.Offset, subMap); } } }
public bool AddGuess(MetaValueGuess guess) { // Don't overwrite good guesses with null pointers if (_guesses.ContainsKey(guess.Offset)) { if (guess.Pointer == 0 || guess.Pointer == 0xFFFFFFFF || guess.Pointer == 0xCDCDCDCD) return false; } /*if (_submaps.ContainsKey(guess.Offset)) return;*/ // Just store it _guesses[guess.Offset] = guess; return true; }
public bool AddGuess(MetaValueGuess guess) { // Don't overwrite good guesses with null pointers if (_guesses.ContainsKey(guess.Offset)) { if (guess.Pointer == 0 || guess.Pointer == 0xFFFFFFFF || guess.Pointer == 0xCDCDCDCD) { return(false); } } /*if (_submaps.ContainsKey(guess.Offset)) * return;*/ // Just store it _guesses[guess.Offset] = guess; return(true); }
public void AnalyzeArea(IReader reader, long startAddress, MetaMap resultMap) { // Right now, this method only searches for the signatures of a few complex meta values. // Reflexives: int32 entry count + uint32 address + 4 bytes of padding // Data references: int32 size + 8 bytes of padding + uint32 address // Tag references: int32 class id + 8 bytes of padding + uint32 datum index // ASCII strings: characters with the values 0 or 0x20 - 0x7F // End at the next-highest address long endAddress = _memMap.GetNextHighestAddress(startAddress); if (endAddress == 0xFFFFFFFF) { throw new InvalidOperationException("Invalid start address for area analysis"); } uint size = (uint)(endAddress - startAddress); // The size of the block of data int paddingLength = 0; // The number of 4-byte padding values that have been read uint prePadding = 0; // The last non-padding uint32 that was read MetaValueGuess pendingGuess = null; // If not null and padding is encountered, this guess is confirmed for (int offset = 0; offset < size; offset += 4) { uint value = reader.ReadUInt32(); long expValue = _expander.Expand(value); if (IsPadding(value)) { if (paddingLength == 0 && pendingGuess != null) { resultMap.AddGuess(pendingGuess); // Add the address to the memory map long address = pendingGuess.Pointer; _memMap.AddAddress(address, (int)reader.Position); } // More padding! :D paddingLength++; pendingGuess = null; } else { pendingGuess = null; if (offset <= size - 8 && prePadding > 0 && prePadding < 0x80000000 // && (value & 3) == 0 && IsValidAddress(expValue) && expValue + prePadding > value && IsValidAddress(expValue + prePadding - 1) && !_memMap.BlockCrossesBoundary(expValue, (int)prePadding)) { // Either a reflexive or a data reference // Check the padding to determine which (see the comments at the beginning of this method) if (paddingLength == 2 && offset >= 12 && (prePadding & 3) == 0) { // Found a data reference uint dataSize = prePadding; pendingGuess = new MetaValueGuess(offset - 12, MetaValueType.DataReference, expValue, dataSize); // Guess with Pointer = address, Data1 = data size } else if (paddingLength == 0 && offset >= 4) { // Found a reflexive! uint entryCount = prePadding; pendingGuess = new MetaValueGuess(offset - 4, MetaValueType.Reflexive, expValue, entryCount); // Guess with Pointer = address, Data1 = entry count } } if (paddingLength == 2 && offset >= 12 && (_classIds.Contains((int)prePadding) || (prePadding == 0xFFFFFFFF && value == 0xFFFFFFFF))) { // Found a tag reference uint classId = prePadding; uint datumIndex = value; var guess = new MetaValueGuess(offset - 12, MetaValueType.TagReference, datumIndex, classId); // Guess with Pointer = datum index, Data1 = class id resultMap.AddGuess(guess); } // This obviously isn't a padding value because IsPadding returned false, // so update padding run information accordingly prePadding = value; paddingLength = 0; } } }
public void AnalyzeArea(IReader reader, uint startAddress, MetaMap resultMap) { // Right now, this method only searches for the signatures of a few complex meta values. // Reflexives: int32 entry count + uint32 address + 4 bytes of padding // Data references: int32 size + 8 bytes of padding + uint32 address // Tag references: int32 class id + 8 bytes of padding + uint32 datum index // ASCII strings: characters with the values 0 or 0x20 - 0x7F // End at the next-highest address uint endAddress = _memMap.GetNextHighestAddress(startAddress); if (endAddress == 0xFFFFFFFF) throw new InvalidOperationException("Invalid start address for area analysis"); uint size = endAddress - startAddress; // The size of the block of data int paddingLength = 0; // The number of 4-byte padding values that have been read uint prePadding = 0; // The last non-padding uint32 that was read MetaValueGuess pendingGuess = null; // If not null and padding is encountered, this guess is confirmed for (int offset = 0; offset < size; offset += 4) { uint value = reader.ReadUInt32(); if (IsPadding(value)) { if (paddingLength == 0 && pendingGuess != null) { resultMap.AddGuess(pendingGuess); // Add the address to the memory map uint address = pendingGuess.Pointer; _memMap.AddAddress(address, (int) reader.Position); } // More padding! :D paddingLength++; pendingGuess = null; } else { pendingGuess = null; if (offset <= size - 8 && prePadding > 0 && prePadding < 0x80000000 && (value & 3) == 0 && IsValidAddress(value) && value + prePadding > value && IsValidAddress(value + prePadding - 1) && !_memMap.BlockCrossesBoundary(value, (int) prePadding)) { // Either a reflexive or a data reference // Check the padding to determine which (see the comments at the beginning of this method) if (paddingLength == 2 && offset >= 12 && (prePadding & 3) == 0) { // Found a data reference uint dataSize = prePadding; uint address = value; pendingGuess = new MetaValueGuess(offset - 12, MetaValueType.DataReference, address, dataSize); // Guess with Pointer = address, Data1 = data size } else if (paddingLength == 0 && offset >= 4) { // Found a reflexive! uint entryCount = prePadding; uint address = value; pendingGuess = new MetaValueGuess(offset - 4, MetaValueType.Reflexive, address, entryCount); // Guess with Pointer = address, Data1 = entry count } } if (paddingLength == 2 && offset >= 12 && (_classIds.Contains((int) prePadding) || (prePadding == 0xFFFFFFFF && value == 0xFFFFFFFF))) { // Found a tag reference uint classId = prePadding; uint datumIndex = value; var guess = new MetaValueGuess(offset - 12, MetaValueType.TagReference, datumIndex, classId); // Guess with Pointer = datum index, Data1 = class id resultMap.AddGuess(guess); } // This obviously isn't a padding value because IsPadding returned false, // so update padding run information accordingly prePadding = value; paddingLength = 0; } } }