void Initialize() { if (initialized) { return; } initialized = true; var buffer = Span.Buffer; var pos = Span.Span.Start; reserved1 = buffer.ReadUInt32(pos); majorVersion = buffer.ReadByte(pos + 4); minorVersion = buffer.ReadByte(pos + 5); flags = (MDStreamFlags)buffer.ReadByte(pos + 6); log2Rid = buffer.ReadByte(pos + 7); validMask = buffer.ReadUInt64(pos + 8); sortedMask = buffer.ReadUInt64(pos + 0x10); pos += 0x18; Debug.Assert(Span.Span.Start + MinimumSize == pos); Debug.Assert(Span.Span.Contains(pos - 1), "Creator should've verified this"); var dnTableSizes = new DotNetTableSizes(); var tableInfos = dnTableSizes.CreateTables(majorVersion, minorVersion, out int maxPresentTables); var rowsCount = new uint[tableInfos.Length]; ulong valid = validMask; var sizes = new uint[64]; int rowsFieldCount = 0; for (int i = 0; i < 64; valid >>= 1, i++) { uint rows; if ((valid & 1) == 0 || !Span.Span.Contains(pos + 3)) { rows = 0; } else { rowsFieldCount++; rows = buffer.ReadUInt32(pos); pos += 4; } if (i >= maxPresentTables) { rows = 0; } // Mono ignores the high byte rows &= 0x00FFFFFF; sizes[i] = rows; if (i < rowsCount.Length) { rowsCount[i] = rows; } } bool hasExtraData = false; if ((flags & MDStreamFlags.ExtraData) != 0 && Span.Span.Contains(pos + 3)) { hasExtraData = true; extraData = buffer.ReadUInt32(pos); pos += 4; } headerSpan = HexSpan.FromBounds(Span.Span.Start, pos); dnTableSizes.InitializeSizes((flags & MDStreamFlags.BigStrings) != 0, (flags & MDStreamFlags.BigGUID) != 0, (flags & MDStreamFlags.BigBlob) != 0, sizes); mdTables = new MDTable[tableInfos.Length]; mdTablesReadOnly = new ReadOnlyCollection <MDTable>(mdTables); tableRecordDataFactories = new TableRecordDataFactory[tableInfos.Length]; var tablesStartPos = pos; bool bad = !Span.Span.Contains(pos); for (int i = 0; i < rowsCount.Length; i++) { var rows = rowsCount[i]; var mdTable = new MDTable(pos, (Table)i, rows, tableInfos[i]); if (bad || mdTable.Span.End > Span.End.Position) { mdTable = new MDTable(pos, (Table)i, 0, tableInfos[i]); bad = true; } pos = mdTable.Span.End; mdTables[i] = mdTable; tableRecordDataFactories[i] = CreateFactory(mdTable); } tablesSpan = HexSpan.FromBounds(HexPosition.Min(Span.End.Position, tablesStartPos), HexPosition.Min(Span.End.Position, pos)); tablesHeaderData = new TablesHeaderDataImpl(new HexBufferSpan(buffer, headerSpan), hasExtraData, rowsFieldCount); }
void AddImportScopeIndexes(Dictionary <uint, BlobDataInfoPosition> dict, TablesHeap tables, Table table, int column) { var mdTable = tables.MDTables[(int)table]; if (mdTable.Rows == 0) { return; } var heapStart = Span.Span.Start; var heapEnd = Span.Span.End; var buffer = Span.Buffer; var recPos = mdTable.Span.Start; var rows = mdTable.Rows; var colInfo = mdTable.Columns[column]; uint recSize = mdTable.RowSize; bool bigBlob = colInfo.Size == 4; for (uint rid = 1; rid <= rows; rid++, recPos += recSize) { uint offs = bigBlob ? buffer.ReadUInt32(recPos + colInfo.Offset) : buffer.ReadUInt16(recPos + colInfo.Offset); if (offs == 0) { continue; } var pos = heapStart + offs; int len = ReadCompressedUInt32(ref pos) ?? -1; if (len <= 0) { continue; } var end = HexPosition.Min(heapEnd, pos + len); while (pos < end) { var kind = ReadCompressedUInt32(ref pos); if (kind == null || pos > end) { break; } var flags = GetImportFlags(kind.Value); Debug.Assert(flags != 0); if (flags == 0) { break; } if ((flags & ImportFlags.Alias) != 0) { var valueTmp = ReadCompressedUInt32(ref pos); if (valueTmp == null || pos > end) { break; } var value = valueTmp.Value; if (value != 0 && !dict.ContainsKey((uint)value)) { var namePos = heapStart + value; if (namePos < heapEnd) { dict[(uint)value] = new BlobDataInfoPosition(namePos, BlobDataKind.Utf8Name); } } } if ((flags & ImportFlags.TargetAssembly) != 0) { var valueTmp = ReadCompressedUInt32(ref pos); if (valueTmp == null || pos > end) { break; } } if ((flags & ImportFlags.TargetNamespace) != 0) { var valueTmp = ReadCompressedUInt32(ref pos); if (valueTmp == null || pos > end) { break; } var value = valueTmp.Value; if (value != 0 && !dict.ContainsKey((uint)value)) { var namePos = heapStart + value; if (namePos < heapEnd) { dict[(uint)value] = new BlobDataInfoPosition(namePos, BlobDataKind.Utf8Name); } } } if ((flags & ImportFlags.TargetType) != 0) { var valueTmp = ReadCompressedUInt32(ref pos); if (valueTmp == null || pos > end) { break; } } } } }
public override HexBufferLine GetLineFromPosition(HexBufferPoint position) { position = FilterAndVerify(position); ResetBuilderFields(); var linePosition = startPosition + (position.Position - startPosition).ToUInt64() / bytesPerLine * bytesPerLine; var lineEnd = HexPosition.Min(linePosition + bytesPerLine, endPosition); var lineSpan = HexSpan.FromBounds(linePosition, lineEnd); var logicalOffset = ToLogicalPosition(lineSpan.Start); var hexBytes = buffer.ReadHexBytes(lineSpan.Start, (long)lineSpan.Length.ToUInt64()); var offsetSpan = default(VST.Span); var fullValuesSpan = default(VST.Span); var visibleValuesSpan = default(VST.Span); var fullAsciiSpan = default(VST.Span); var visibleAsciiSpan = default(VST.Span); var valueCells = Array.Empty <HexCell>(); var asciiCells = Array.Empty <HexCell>(); bool needSep = false; foreach (var column in columnOrder) { switch (column) { case HexColumnType.Offset: if (showOffset) { if (needSep) { stringBuilder.Append(' '); } needSep = true; WriteOffset(logicalOffset, out offsetSpan); } break; case HexColumnType.Values: if (showValues) { if (needSep) { stringBuilder.Append(' '); } needSep = true; valueCells = WriteValues(hexBytes, lineSpan, out fullValuesSpan, out visibleValuesSpan); } break; case HexColumnType.Ascii: if (showAscii) { if (needSep) { stringBuilder.Append(' '); } needSep = true; asciiCells = WriteAscii(hexBytes, lineSpan, out fullAsciiSpan, out visibleAsciiSpan); } break; default: throw new InvalidOperationException(); } } var text = stringBuilder.ToString(); if (text.Length != CharsPerLine) { throw new InvalidOperationException(); } var valueCellColl = valueCells.Length == 0 ? HexCellCollection.Empty : new HexCellCollection(valueCells); var asciiCellColl = asciiCells.Length == 0 ? HexCellCollection.Empty : new HexCellCollection(asciiCells); var lineNumber = GetLineNumberFromPosition(new HexBufferPoint(Buffer, lineSpan.Start)); var res = new HexBufferLineImpl(this, lineNumber, columnOrder, new HexBufferSpan(buffer, lineSpan), hexBytes, text, showOffset, showValues, showAscii, logicalOffset, valueCellColl, asciiCellColl, offsetSpan, fullValuesSpan, visibleValuesSpan, fullAsciiSpan, visibleAsciiSpan); ResetBuilderFields(); return(res); }
/// <summary> /// Returns the span the field value references or null. The span can be empty. /// </summary> /// <param name="file">File</param> /// <returns></returns> public override HexSpan?GetFieldReferenceSpan(HexBufferFile file) { var offset = ReadValue(); if (offset == 0) { return(null); } var pos = file.GetHeaders <PeHeaders>()?.FilePositionToBufferPosition(offset) ?? HexPosition.Min(HexPosition.MaxEndPosition - 1, file.Span.Start + offset); return(new HexSpan(pos, 0)); }
HexCell[] WriteValues(HexBytes hexBytes, HexSpan visibleBytesSpan, out VST.Span fullSpan, out VST.Span visibleSpan) { Debug.Assert(showValues); cellList.Clear(); int fullStart = CurrentTextIndex; ulong cellCount = bytesPerLine / (ulong)valueFormatter.ByteCount; var flags = valuesLowerCaseHex ? HexValueFormatterFlags.LowerCaseHex : HexValueFormatterFlags.None; var pos = visibleBytesSpan.Start; var end = visibleBytesSpan.Start + bytesPerLine; int? visStart = null; int? visEnd = null; int cellPos = 0; for (ulong i = 0; i < cellCount; i++) { if (i != 0) { stringBuilder.Append(' '); } int groupIndex = (cellPos / groupSizeInBytes) & 1; HexBufferSpan bufferSpan; int cellStart = CurrentTextIndex; int spaces; if (visibleBytesSpan.Contains(pos)) { if (visStart == null) { visStart = CurrentTextIndex; } long valueIndex = (long)(pos - visibleBytesSpan.Start).ToUInt64(); spaces = valueFormatter.FormatValue(stringBuilder, hexBytes, valueIndex, flags); var endPos = HexPosition.Min(endPosition, pos + (ulong)valueFormatter.ByteCount); bufferSpan = new HexBufferSpan(new HexBufferPoint(buffer, pos), new HexBufferPoint(buffer, endPos)); } else { if (visStart != null && visEnd == null) { visEnd = CurrentTextIndex; } stringBuilder.Append(' ', valueFormatter.FormattedLength); spaces = valueFormatter.FormattedLength; bufferSpan = default; } if (cellStart + valueFormatter.FormattedLength != CurrentTextIndex) { throw new InvalidOperationException(); } var textSpan = VST.Span.FromBounds(cellStart + spaces, CurrentTextIndex); var cellSpan = VST.Span.FromBounds(cellStart, CurrentTextIndex); VST.Span separatorSpan; if (i + 1 < cellCount) { separatorSpan = new VST.Span(CurrentTextIndex, 1); } else { separatorSpan = new VST.Span(CurrentTextIndex, 0); } var cellFullSpan = VST.Span.FromBounds(cellStart, separatorSpan.End); cellList.Add(new HexCell((int)i, groupIndex, bufferSpan, textSpan, cellSpan, separatorSpan, cellFullSpan)); pos += (ulong)valueFormatter.ByteCount; cellPos += valueFormatter.ByteCount; } if (pos != end) { throw new InvalidOperationException(); } if (visStart != null && visEnd == null) { visEnd = CurrentTextIndex; } visibleSpan = visStart == null ? default : VST.Span.FromBounds(visStart.Value, visEnd.Value); fullSpan = VST.Span.FromBounds(fullStart, CurrentTextIndex); if (ValuesSpan != fullSpan) { throw new InvalidOperationException(); } return(cellList.ToArray()); }