mirror of
https://github.com/SabreTools/SabreTools.Serialization.git
synced 2026-07-08 18:06:41 +00:00
More granular locks
This commit is contained in:
@@ -36,7 +36,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_sourceDataLock)
|
||||
lock (_overlayAddressLock)
|
||||
{
|
||||
// Use the cached data if possible
|
||||
if (_overlayAddress != null)
|
||||
@@ -51,52 +51,59 @@ namespace SabreTools.Serialization.Wrappers
|
||||
if (Header == null || SegmentTable == null || ResourceTable?.ResourceTypes == null)
|
||||
return -1;
|
||||
|
||||
// Search through the segments table to find the furthest
|
||||
long endOfSectionData = -1;
|
||||
foreach (var entry in SegmentTable)
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
// Get end of segment data
|
||||
long offset = (entry.Offset * (1 << Header.SegmentAlignmentShiftCount)) + entry.Length;
|
||||
// Search through the segments table to find the furthest
|
||||
long endOfSectionData = -1;
|
||||
foreach (var entry in SegmentTable)
|
||||
{
|
||||
// Get end of segment data
|
||||
long offset = (entry.Offset * (1 << Header.SegmentAlignmentShiftCount)) + entry.Length;
|
||||
|
||||
// Read and find the end of the relocation data
|
||||
// Read and find the end of the relocation data
|
||||
#if NET20 || NET35
|
||||
if ((entry.FlagWord & SegmentTableEntryFlag.RELOCINFO) != 0)
|
||||
#else
|
||||
if (entry.FlagWord.HasFlag(SegmentTableEntryFlag.RELOCINFO))
|
||||
if (entry.FlagWord.HasFlag(SegmentTableEntryFlag.RELOCINFO))
|
||||
#endif
|
||||
{
|
||||
_dataSource.Seek(offset, SeekOrigin.Begin);
|
||||
var relocationData = Deserializers.NewExecutable.ParsePerSegmentData(_dataSource);
|
||||
{
|
||||
_dataSource.Seek(offset, SeekOrigin.Begin);
|
||||
var relocationData = Deserializers.NewExecutable.ParsePerSegmentData(_dataSource);
|
||||
|
||||
offset = _dataSource.Position;
|
||||
}
|
||||
offset = _dataSource.Position;
|
||||
}
|
||||
|
||||
if (offset > endOfSectionData)
|
||||
endOfSectionData = offset;
|
||||
}
|
||||
|
||||
// Search through the resources table to find the furthest
|
||||
foreach (var entry in ResourceTable.ResourceTypes)
|
||||
{
|
||||
// Skip invalid entries
|
||||
if (entry.ResourceCount == 0 || entry.Resources == null || entry.Resources.Length == 0)
|
||||
continue;
|
||||
|
||||
foreach (var resource in entry.Resources)
|
||||
{
|
||||
int offset = (resource.Offset << ResourceTable.AlignmentShiftCount) + resource.Length;
|
||||
if (offset > endOfSectionData)
|
||||
endOfSectionData = offset;
|
||||
}
|
||||
|
||||
// Search through the resources table to find the furthest
|
||||
foreach (var entry in ResourceTable.ResourceTypes)
|
||||
{
|
||||
// Skip invalid entries
|
||||
if (entry.ResourceCount == 0 || entry.Resources == null || entry.Resources.Length == 0)
|
||||
continue;
|
||||
|
||||
foreach (var resource in entry.Resources)
|
||||
{
|
||||
int offset = (resource.Offset << ResourceTable.AlignmentShiftCount) + resource.Length;
|
||||
if (offset > endOfSectionData)
|
||||
endOfSectionData = offset;
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't find the end of section data
|
||||
if (endOfSectionData <= 0)
|
||||
endOfSectionData = -1;
|
||||
|
||||
// Adjust the position of the data by 705 bytes
|
||||
// TODO: Investigate what the byte data is
|
||||
endOfSectionData += 705;
|
||||
|
||||
// Cache and return the position
|
||||
_overlayAddress = endOfSectionData;
|
||||
return _overlayAddress.Value;
|
||||
}
|
||||
|
||||
// If we didn't find the end of section data
|
||||
if (endOfSectionData <= 0)
|
||||
endOfSectionData = -1;
|
||||
|
||||
// Cache and return the position
|
||||
_overlayAddress = endOfSectionData;
|
||||
return _overlayAddress.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -109,7 +116,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_sourceDataLock)
|
||||
lock (_overlayDataLock)
|
||||
{
|
||||
// Use the cached data if possible
|
||||
if (_overlayData != null)
|
||||
@@ -124,44 +131,8 @@ namespace SabreTools.Serialization.Wrappers
|
||||
if (Header == null || SegmentTable == null || ResourceTable?.ResourceTypes == null)
|
||||
return null;
|
||||
|
||||
// Search through the segments table to find the furthest
|
||||
long endOfSectionData = -1;
|
||||
foreach (var entry in SegmentTable)
|
||||
{
|
||||
// Get end of segment data
|
||||
long offset = (entry.Offset * (1 << Header.SegmentAlignmentShiftCount)) + entry.Length;
|
||||
|
||||
// Read and find the end of the relocation data
|
||||
#if NET20 || NET35
|
||||
if ((entry.FlagWord & SegmentTableEntryFlag.RELOCINFO) != 0)
|
||||
#else
|
||||
if (entry.FlagWord.HasFlag(SegmentTableEntryFlag.RELOCINFO))
|
||||
#endif
|
||||
{
|
||||
_dataSource.Seek(offset, SeekOrigin.Begin);
|
||||
var relocationData = Deserializers.NewExecutable.ParsePerSegmentData(_dataSource);
|
||||
|
||||
offset = _dataSource.Position;
|
||||
}
|
||||
|
||||
if (offset > endOfSectionData)
|
||||
endOfSectionData = offset;
|
||||
}
|
||||
|
||||
// Search through the resources table to find the furthest
|
||||
foreach (var entry in ResourceTable.ResourceTypes)
|
||||
{
|
||||
// Skip invalid entries
|
||||
if (entry.ResourceCount == 0 || entry.Resources == null || entry.Resources.Length == 0)
|
||||
continue;
|
||||
|
||||
foreach (var resource in entry.Resources)
|
||||
{
|
||||
int offset = (resource.Offset << ResourceTable.AlignmentShiftCount) + resource.Length;
|
||||
if (offset > endOfSectionData)
|
||||
endOfSectionData = offset;
|
||||
}
|
||||
}
|
||||
// Get the overlay address if possible
|
||||
long endOfSectionData = OverlayAddress;
|
||||
|
||||
// If we didn't find the end of section data
|
||||
if (endOfSectionData <= 0)
|
||||
@@ -175,9 +146,12 @@ namespace SabreTools.Serialization.Wrappers
|
||||
}
|
||||
|
||||
// Otherwise, cache and return the data
|
||||
long overlayLength = dataLength - endOfSectionData;
|
||||
_overlayData = _dataSource.ReadFrom((int)endOfSectionData, (int)overlayLength, retainPosition: true);
|
||||
return _overlayData;
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
long overlayLength = dataLength - endOfSectionData;
|
||||
_overlayData = _dataSource.ReadFrom((int)endOfSectionData, (int)overlayLength, retainPosition: true);
|
||||
return _overlayData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -189,7 +163,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_sourceDataLock)
|
||||
lock (_overlayStringsLock)
|
||||
{
|
||||
// Use the cached data if possible
|
||||
if (_overlayStrings != null)
|
||||
@@ -204,52 +178,30 @@ namespace SabreTools.Serialization.Wrappers
|
||||
if (Header == null || SegmentTable == null || ResourceTable?.ResourceTypes == null)
|
||||
return null;
|
||||
|
||||
// Search through the segments table to find the furthest
|
||||
int endOfSectionData = -1;
|
||||
foreach (var entry in SegmentTable)
|
||||
{
|
||||
int offset = (entry.Offset << Header.SegmentAlignmentShiftCount) + entry.Length;
|
||||
if (offset > endOfSectionData)
|
||||
endOfSectionData = offset;
|
||||
}
|
||||
|
||||
// Search through the resources table to find the furthest
|
||||
foreach (var entry in ResourceTable.ResourceTypes)
|
||||
{
|
||||
// Skip invalid entries
|
||||
if (entry.ResourceCount == 0 || entry.Resources == null || entry.Resources.Length == 0)
|
||||
continue;
|
||||
|
||||
foreach (var resource in entry.Resources)
|
||||
{
|
||||
int offset = (resource.Offset << ResourceTable.AlignmentShiftCount) + resource.Length;
|
||||
if (offset > endOfSectionData)
|
||||
endOfSectionData = offset;
|
||||
}
|
||||
}
|
||||
// Get the overlay address if possible
|
||||
long endOfSectionData = OverlayAddress;
|
||||
|
||||
// If we didn't find the end of section data
|
||||
if (endOfSectionData <= 0)
|
||||
return null;
|
||||
|
||||
// Adjust the position of the data by 705 bytes
|
||||
// TODO: Investigate what the byte data is
|
||||
endOfSectionData += 705;
|
||||
|
||||
// If we're at the end of the file, cache an empty list
|
||||
// If we're at the end of the file, cache an empty byte array
|
||||
if (endOfSectionData >= dataLength)
|
||||
{
|
||||
_overlayStrings = [];
|
||||
return _overlayStrings;
|
||||
}
|
||||
|
||||
// TODO: Revisit the 16 MiB limit
|
||||
// Cap the check for overlay strings to 16 MiB (arbitrary)
|
||||
long overlayLength = Math.Min(dataLength - endOfSectionData, 16 * 1024 * 1024);
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
// TODO: Revisit the 16 MiB limit
|
||||
// Cap the check for overlay strings to 16 MiB (arbitrary)
|
||||
long overlayLength = Math.Min(dataLength - endOfSectionData, 16 * 1024 * 1024);
|
||||
|
||||
// Otherwise, cache and return the strings
|
||||
_overlayStrings = _dataSource.ReadStringsFrom(endOfSectionData, (int)overlayLength, charLimit: 3);
|
||||
return _overlayStrings;
|
||||
// Otherwise, cache and return the strings
|
||||
_overlayStrings = _dataSource.ReadStringsFrom((int)endOfSectionData, (int)overlayLength, charLimit: 3);
|
||||
return _overlayStrings;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -273,7 +225,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_sourceDataLock)
|
||||
lock (_stubExecutableDataLock)
|
||||
{
|
||||
// If we already have cached data, just use that immediately
|
||||
if (_stubExecutableData != null)
|
||||
@@ -282,13 +234,16 @@ namespace SabreTools.Serialization.Wrappers
|
||||
if (Stub?.Header?.NewExeHeaderAddr == null)
|
||||
return null;
|
||||
|
||||
// Populate the raw stub executable data based on the source
|
||||
int endOfStubHeader = 0x40;
|
||||
int lengthOfStubExecutableData = (int)Stub.Header.NewExeHeaderAddr - endOfStubHeader;
|
||||
_stubExecutableData = _dataSource.ReadFrom(endOfStubHeader, lengthOfStubExecutableData, retainPosition: true);
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
// Populate the raw stub executable data based on the source
|
||||
int endOfStubHeader = 0x40;
|
||||
int lengthOfStubExecutableData = (int)Stub.Header.NewExeHeaderAddr - endOfStubHeader;
|
||||
_stubExecutableData = _dataSource.ReadFrom(endOfStubHeader, lengthOfStubExecutableData, retainPosition: true);
|
||||
|
||||
// Cache and return the stub executable data, even if null
|
||||
return _stubExecutableData;
|
||||
// Cache and return the stub executable data, even if null
|
||||
return _stubExecutableData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -302,21 +257,41 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// </summary>
|
||||
private long? _overlayAddress = null;
|
||||
|
||||
/// <summary>
|
||||
/// Lock object for <see cref="_overlayAddress"/>
|
||||
/// </summary>
|
||||
private readonly object _overlayAddressLock = new();
|
||||
|
||||
/// <summary>
|
||||
/// Overlay data, if it exists
|
||||
/// </summary>
|
||||
private byte[]? _overlayData = null;
|
||||
|
||||
/// <summary>
|
||||
/// Lock object for <see cref="_overlayData"/>
|
||||
/// </summary>
|
||||
private readonly object _overlayDataLock = new();
|
||||
|
||||
/// <summary>
|
||||
/// Overlay strings, if they exist
|
||||
/// </summary>
|
||||
private List<string>? _overlayStrings = null;
|
||||
|
||||
/// <summary>
|
||||
/// Lock object for <see cref="_overlayStrings"/>
|
||||
/// </summary>
|
||||
private readonly object _overlayStringsLock = new();
|
||||
|
||||
/// <summary>
|
||||
/// Stub executable data, if it exists
|
||||
/// </summary>
|
||||
private byte[]? _stubExecutableData = null;
|
||||
|
||||
/// <summary>
|
||||
/// Lock object for <see cref="_stubExecutableData"/>
|
||||
/// </summary>
|
||||
private readonly object _stubExecutableDataLock = new();
|
||||
|
||||
/// <summary>
|
||||
/// Lock object for reading from the source
|
||||
/// </summary>
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_sourceDataLock)
|
||||
lock (_debugDataLock)
|
||||
{
|
||||
// Use the cached data if possible
|
||||
if (_debugData != null && _debugData.Count != 0)
|
||||
@@ -42,8 +42,11 @@ namespace SabreTools.Serialization.Wrappers
|
||||
return null;
|
||||
|
||||
// Otherwise, build and return the cached dictionary
|
||||
ParseDebugTable();
|
||||
return _debugData;
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
ParseDebugTable();
|
||||
return _debugData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,8 +62,12 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_sourceDataLock)
|
||||
lock (_entryPointDataLock)
|
||||
{
|
||||
// If we already have cached data, just use that immediately
|
||||
if (_entryPointData != null)
|
||||
return _entryPointData;
|
||||
|
||||
// If the section table is missing
|
||||
if (SectionTable == null)
|
||||
return null;
|
||||
@@ -77,17 +84,17 @@ namespace SabreTools.Serialization.Wrappers
|
||||
// If the entry point matches with the start of a section, use that
|
||||
int entryPointSection = FindEntryPointSectionIndex();
|
||||
if (entryPointSection >= 0 && OptionalHeader.AddressOfEntryPoint == SectionTable[entryPointSection]?.VirtualAddress)
|
||||
return GetSectionData(entryPointSection);
|
||||
|
||||
// If we already have cached data, just use that immediately
|
||||
if (_entryPointData != null)
|
||||
{
|
||||
_entryPointData = GetSectionData(entryPointSection);
|
||||
return _entryPointData;
|
||||
}
|
||||
|
||||
// Read the first 128 bytes of the entry point
|
||||
_entryPointData = _dataSource.ReadFrom(entryPointAddress, length: 128, retainPosition: true);
|
||||
|
||||
// Cache and return the entry point padding data, even if null
|
||||
return _entryPointData;
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
_entryPointData = _dataSource.ReadFrom(entryPointAddress, length: 128, retainPosition: true);
|
||||
return _entryPointData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -102,7 +109,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_sourceDataLock)
|
||||
lock (_headerPaddingDataLock)
|
||||
{
|
||||
// If we already have cached data, just use that immediately
|
||||
if (_headerPaddingData != null)
|
||||
@@ -133,12 +140,16 @@ namespace SabreTools.Serialization.Wrappers
|
||||
// Check if the header length is more than 0 before reading data
|
||||
int headerLength = (int)(firstSectionAddress - headerStartAddress);
|
||||
if (headerLength <= 0)
|
||||
{
|
||||
_headerPaddingData = [];
|
||||
else
|
||||
_headerPaddingData = _dataSource.ReadFrom((int)headerStartAddress, headerLength, retainPosition: true);
|
||||
return _headerPaddingData;
|
||||
}
|
||||
|
||||
// Cache and return the header padding data, even if null
|
||||
return _headerPaddingData;
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
_headerPaddingData = _dataSource.ReadFrom((int)headerStartAddress, headerLength, retainPosition: true);
|
||||
return _headerPaddingData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -150,7 +161,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_sourceDataLock)
|
||||
lock (_headerPaddingStringsLock)
|
||||
{
|
||||
// If we already have cached data, just use that immediately
|
||||
if (_headerPaddingStrings != null)
|
||||
@@ -181,12 +192,16 @@ namespace SabreTools.Serialization.Wrappers
|
||||
// Check if the header length is more than 0 before reading strings
|
||||
int headerLength = (int)(firstSectionAddress - headerStartAddress);
|
||||
if (headerLength <= 0)
|
||||
{
|
||||
_headerPaddingStrings = [];
|
||||
else
|
||||
_headerPaddingStrings = _dataSource.ReadStringsFrom((int)headerStartAddress, headerLength, charLimit: 3);
|
||||
return _headerPaddingStrings;
|
||||
}
|
||||
|
||||
// Cache and return the header padding data, even if null
|
||||
return _headerPaddingStrings;
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
_headerPaddingStrings = _dataSource.ReadStringsFrom((int)headerStartAddress, headerLength, charLimit: 3);
|
||||
return _headerPaddingStrings;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -205,7 +220,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_sourceDataLock)
|
||||
lock (_overlayAddressLock)
|
||||
{
|
||||
// Use the cached data if possible
|
||||
if (_overlayAddress != null)
|
||||
@@ -257,6 +272,10 @@ namespace SabreTools.Serialization.Wrappers
|
||||
if (endOfSectionData <= 0)
|
||||
endOfSectionData = -1;
|
||||
|
||||
// If the section data is followed by the end of the data
|
||||
if (endOfSectionData >= dataLength)
|
||||
endOfSectionData = -1;
|
||||
|
||||
// Cache and return the position
|
||||
_overlayAddress = endOfSectionData;
|
||||
return _overlayAddress.Value;
|
||||
@@ -272,7 +291,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_sourceDataLock)
|
||||
lock (_overlayDataLock)
|
||||
{
|
||||
// Use the cached data if possible
|
||||
if (_overlayData != null)
|
||||
@@ -287,38 +306,8 @@ namespace SabreTools.Serialization.Wrappers
|
||||
if (SectionTable == null)
|
||||
return null;
|
||||
|
||||
// If we have certificate data, use that as the end
|
||||
if (OptionalHeader?.CertificateTable != null)
|
||||
{
|
||||
int certificateTableAddress = (int)OptionalHeader.CertificateTable.VirtualAddress.ConvertVirtualAddress(SectionTable);
|
||||
if (certificateTableAddress != 0 && certificateTableAddress < dataLength)
|
||||
dataLength = certificateTableAddress;
|
||||
}
|
||||
|
||||
// Search through all sections and find the furthest a section goes
|
||||
int endOfSectionData = -1;
|
||||
foreach (var section in SectionTable)
|
||||
{
|
||||
// If we have an invalid section
|
||||
if (section == null)
|
||||
continue;
|
||||
|
||||
// If we have an invalid section address
|
||||
int sectionAddress = (int)section.VirtualAddress.ConvertVirtualAddress(SectionTable);
|
||||
if (sectionAddress == 0)
|
||||
continue;
|
||||
|
||||
// If we have an invalid section size
|
||||
if (section.SizeOfRawData == 0 && section.VirtualSize == 0)
|
||||
continue;
|
||||
|
||||
// Get the real section size
|
||||
int sectionSize = (int)section.SizeOfRawData;
|
||||
|
||||
// Compare and set the end of section data
|
||||
if (sectionAddress + sectionSize > endOfSectionData)
|
||||
endOfSectionData = sectionAddress + sectionSize;
|
||||
}
|
||||
// Get the overlay address if possible
|
||||
long endOfSectionData = OverlayAddress;
|
||||
|
||||
// If we didn't find the end of section data
|
||||
if (endOfSectionData <= 0)
|
||||
@@ -332,9 +321,12 @@ namespace SabreTools.Serialization.Wrappers
|
||||
}
|
||||
|
||||
// Otherwise, cache and return the data
|
||||
long overlayLength = dataLength - endOfSectionData;
|
||||
_overlayData = _dataSource.ReadFrom(endOfSectionData, (int)overlayLength, retainPosition: true);
|
||||
return _overlayData;
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
long overlayLength = dataLength - endOfSectionData;
|
||||
_overlayData = _dataSource.ReadFrom(endOfSectionData, (int)overlayLength, retainPosition: true);
|
||||
return _overlayData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -346,7 +338,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_sourceDataLock)
|
||||
lock (_overlayStringsLock)
|
||||
{
|
||||
// Use the cached data if possible
|
||||
if (_overlayStrings != null)
|
||||
@@ -361,61 +353,30 @@ namespace SabreTools.Serialization.Wrappers
|
||||
if (SectionTable == null)
|
||||
return null;
|
||||
|
||||
// If we have certificate data, use that as the end
|
||||
if (OptionalHeader?.CertificateTable != null)
|
||||
{
|
||||
int certificateTableAddress = (int)OptionalHeader.CertificateTable.VirtualAddress.ConvertVirtualAddress(SectionTable);
|
||||
if (certificateTableAddress != 0 && certificateTableAddress < dataLength)
|
||||
dataLength = certificateTableAddress;
|
||||
}
|
||||
|
||||
// Search through all sections and find the furthest a section goes
|
||||
int endOfSectionData = -1;
|
||||
foreach (var section in SectionTable)
|
||||
{
|
||||
// If we have an invalid section
|
||||
if (section == null)
|
||||
continue;
|
||||
|
||||
// If we have an invalid section address
|
||||
int sectionAddress = (int)section.VirtualAddress.ConvertVirtualAddress(SectionTable);
|
||||
if (sectionAddress == 0)
|
||||
continue;
|
||||
|
||||
// If we have an invalid section size
|
||||
if (section.SizeOfRawData == 0 && section.VirtualSize == 0)
|
||||
continue;
|
||||
|
||||
// Get the real section size
|
||||
int sectionSize;
|
||||
if (section.SizeOfRawData < section.VirtualSize)
|
||||
sectionSize = (int)section.VirtualSize;
|
||||
else
|
||||
sectionSize = (int)section.SizeOfRawData;
|
||||
|
||||
// Compare and set the end of section data
|
||||
if (sectionAddress + sectionSize > endOfSectionData)
|
||||
endOfSectionData = sectionAddress + sectionSize;
|
||||
}
|
||||
// Get the overlay address if possible
|
||||
long endOfSectionData = OverlayAddress;
|
||||
|
||||
// If we didn't find the end of section data
|
||||
if (endOfSectionData <= 0)
|
||||
return null;
|
||||
|
||||
// If we're at the end of the file, cache an empty list
|
||||
// If we're at the end of the file, cache an empty byte array
|
||||
if (endOfSectionData >= dataLength)
|
||||
{
|
||||
_overlayStrings = [];
|
||||
return _overlayStrings;
|
||||
}
|
||||
|
||||
// TODO: Revisit the 16 MiB limit
|
||||
// Cap the check for overlay strings to 16 MiB (arbitrary)
|
||||
long overlayLength = Math.Min(dataLength - endOfSectionData, 16 * 1024 * 1024);
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
// TODO: Revisit the 16 MiB limit
|
||||
// Cap the check for overlay strings to 16 MiB (arbitrary)
|
||||
long overlayLength = Math.Min(dataLength - endOfSectionData, 16 * 1024 * 1024);
|
||||
|
||||
// Otherwise, cache and return the strings
|
||||
_overlayStrings = _dataSource.ReadStringsFrom(endOfSectionData, (int)overlayLength, charLimit: 3);
|
||||
return _overlayStrings;
|
||||
// Otherwise, cache and return the strings
|
||||
_overlayStrings = _dataSource.ReadStringsFrom((int)endOfSectionData, (int)overlayLength, charLimit: 3);
|
||||
return _overlayStrings;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -430,7 +391,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_sourceDataLock)
|
||||
lock (_sectionNamesLock)
|
||||
{
|
||||
// Use the cached data if possible
|
||||
if (_sectionNames != null)
|
||||
@@ -475,7 +436,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_sourceDataLock)
|
||||
lock (_stubExecutableDataLock)
|
||||
{
|
||||
// If we already have cached data, just use that immediately
|
||||
if (_stubExecutableData != null)
|
||||
@@ -484,13 +445,16 @@ namespace SabreTools.Serialization.Wrappers
|
||||
if (Stub?.Header?.NewExeHeaderAddr == null)
|
||||
return null;
|
||||
|
||||
// Populate the raw stub executable data based on the source
|
||||
int endOfStubHeader = 0x40;
|
||||
int lengthOfStubExecutableData = (int)Stub.Header.NewExeHeaderAddr - endOfStubHeader;
|
||||
_stubExecutableData = _dataSource.ReadFrom(endOfStubHeader, lengthOfStubExecutableData, retainPosition: true);
|
||||
lock (_sourceDataLock)
|
||||
{
|
||||
// Populate the raw stub executable data based on the source
|
||||
int endOfStubHeader = 0x40;
|
||||
int lengthOfStubExecutableData = (int)Stub.Header.NewExeHeaderAddr - endOfStubHeader;
|
||||
_stubExecutableData = _dataSource.ReadFrom(endOfStubHeader, lengthOfStubExecutableData, retainPosition: true);
|
||||
|
||||
// Cache and return the stub executable data, even if null
|
||||
return _stubExecutableData;
|
||||
// Cache and return the stub executable data, even if null
|
||||
return _stubExecutableData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -502,7 +466,7 @@ namespace SabreTools.Serialization.Wrappers
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_sourceDataLock)
|
||||
lock (_resourceDataLock)
|
||||
{
|
||||
// Use the cached data if possible
|
||||
if (_resourceData != null && _resourceData.Count != 0)
|
||||
@@ -692,45 +656,95 @@ namespace SabreTools.Serialization.Wrappers
|
||||
#region Instance Variables
|
||||
|
||||
/// <summary>
|
||||
/// Header padding data, if it exists
|
||||
/// Cached debug data
|
||||
/// </summary>
|
||||
private byte[]? _headerPaddingData = null;
|
||||
private readonly Dictionary<int, object> _debugData = [];
|
||||
|
||||
/// <summary>
|
||||
/// Header padding strings, if they exist
|
||||
/// Lock object for <see cref="_debugData"/>
|
||||
/// </summary>
|
||||
private List<string>? _headerPaddingStrings = null;
|
||||
private readonly object _debugDataLock = new();
|
||||
|
||||
/// <summary>
|
||||
/// Entry point data, if it exists and isn't aligned to a section
|
||||
/// </summary>
|
||||
private byte[]? _entryPointData = null;
|
||||
|
||||
/// <summary>
|
||||
/// Lock object for <see cref="_entryPointData"/>
|
||||
/// </summary>
|
||||
private readonly object _entryPointDataLock = new();
|
||||
|
||||
/// <summary>
|
||||
/// Header padding data, if it exists
|
||||
/// </summary>
|
||||
private byte[]? _headerPaddingData = null;
|
||||
|
||||
/// <summary>
|
||||
/// Lock object for <see cref="_headerPaddingData"/>
|
||||
/// </summary>
|
||||
private readonly object _headerPaddingDataLock = new();
|
||||
|
||||
/// <summary>
|
||||
/// Header padding strings, if they exist
|
||||
/// </summary>
|
||||
private List<string>? _headerPaddingStrings = null;
|
||||
|
||||
/// <summary>
|
||||
/// Lock object for <see cref="_headerPaddingStrings"/>
|
||||
/// </summary>
|
||||
private readonly object _headerPaddingStringsLock = new();
|
||||
|
||||
/// <summary>
|
||||
/// Address of the overlay, if it exists
|
||||
/// </summary>
|
||||
private int? _overlayAddress = null;
|
||||
|
||||
/// <summary>
|
||||
/// Lock object for <see cref="_overlayAddress"/>
|
||||
/// </summary>
|
||||
private readonly object _overlayAddressLock = new();
|
||||
|
||||
/// <summary>
|
||||
/// Overlay data, if it exists
|
||||
/// </summary>
|
||||
private byte[]? _overlayData = null;
|
||||
|
||||
/// <summary>
|
||||
/// Lock object for <see cref="_overlayData"/>
|
||||
/// </summary>
|
||||
private readonly object _overlayDataLock = new();
|
||||
|
||||
/// <summary>
|
||||
/// Overlay strings, if they exist
|
||||
/// </summary>
|
||||
private List<string>? _overlayStrings = null;
|
||||
|
||||
/// <summary>
|
||||
/// Stub executable data, if it exists
|
||||
/// Lock object for <see cref="_overlayStrings"/>
|
||||
/// </summary>
|
||||
private byte[]? _stubExecutableData = null;
|
||||
private readonly object _overlayStringsLock = new();
|
||||
|
||||
/// <summary>
|
||||
/// Cached resource data
|
||||
/// </summary>
|
||||
private readonly Dictionary<string, object?> _resourceData = [];
|
||||
|
||||
/// <summary>
|
||||
/// Lock object for <see cref="_resourceData"/>
|
||||
/// </summary>
|
||||
private readonly object _resourceDataLock = new();
|
||||
|
||||
/// <summary>
|
||||
/// Sanitized section names
|
||||
/// </summary>
|
||||
private string[]? _sectionNames = null;
|
||||
|
||||
/// <summary>
|
||||
/// Lock object for <see cref="_sectionNames"/>
|
||||
/// </summary>
|
||||
private readonly object _sectionNamesLock = new();
|
||||
|
||||
/// <summary>
|
||||
/// Cached raw section data
|
||||
/// </summary>
|
||||
@@ -741,6 +755,16 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// </summary>
|
||||
private List<string>[]? _sectionStringData = null;
|
||||
|
||||
/// <summary>
|
||||
/// Stub executable data, if it exists
|
||||
/// </summary>
|
||||
private byte[]? _stubExecutableData = null;
|
||||
|
||||
/// <summary>
|
||||
/// Lock object for <see cref="_stubExecutableData"/>
|
||||
/// </summary>
|
||||
private readonly object _stubExecutableDataLock = new();
|
||||
|
||||
/// <summary>
|
||||
/// Cached raw table data
|
||||
/// </summary>
|
||||
@@ -751,16 +775,6 @@ namespace SabreTools.Serialization.Wrappers
|
||||
/// </summary>
|
||||
private List<string>[]? _tableStringData = null;
|
||||
|
||||
/// <summary>
|
||||
/// Cached debug data
|
||||
/// </summary>
|
||||
private readonly Dictionary<int, object> _debugData = [];
|
||||
|
||||
/// <summary>
|
||||
/// Cached resource data
|
||||
/// </summary>
|
||||
private readonly Dictionary<string, object?> _resourceData = [];
|
||||
|
||||
/// <summary>
|
||||
/// Cached version info data
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user