Proof-of-concept Wise section caching

This commit is contained in:
Matt Nadareski
2025-09-18 09:40:15 -04:00
parent 5d2cf58477
commit 53af618fe4
2 changed files with 85 additions and 43 deletions

View File

@@ -397,9 +397,8 @@ namespace SabreTools.Serialization.Wrappers
return ExtractWiseOverlay(outputDirectory, includeDebug, source, offset);
// Try to find the section header
var section = FindWiseSection();
if (section != null)
return ExtractWiseSection(outputDirectory, includeDebug, source, section);
if (WiseSection != null)
return ExtractWiseSection(outputDirectory, includeDebug, source);
// Everything else could not extract
return false;
@@ -527,23 +526,10 @@ namespace SabreTools.Serialization.Wrappers
/// <param name="source">Potentially multi-part stream to read</param>
/// <param name="section">Wise section information</param>
/// <returns>True if extraction succeeded, false otherwise</returns>
private bool ExtractWiseSection(string outputDirectory, bool includeDebug, Stream source, Models.PortableExecutable.SectionHeader section)
private bool ExtractWiseSection(string outputDirectory, bool includeDebug, Stream source)
{
// Get the offset
long offset = section.VirtualAddress.ConvertVirtualAddress(SectionTable);
if (offset < 0 || offset >= source.Length)
return false;
// Read the section into a local array
int sectionLength = (int)section.VirtualSize;
byte[]? sectionData;
lock (source)
{
sectionData = source.ReadFrom(offset, sectionLength, retainPosition: true);
}
// Parse the section header
var header = WiseSectionHeader.Create(sectionData, 0);
// Get the section header
var header = WiseSection;
if (header == null)
{
if (includeDebug) Console.Error.WriteLine("Could not parse the section header");

View File

@@ -491,6 +491,71 @@ namespace SabreTools.Serialization.Wrappers
}
}
/// <summary>
/// Wise section wrapper, if it exists
/// </summary>
public WiseSectionHeader? WiseSection
{
get
{
lock (_wiseSectionHeaderLock)
{
// If we already have cached data, just use that immediately
if (_wiseSectionHeader != null)
return _wiseSectionHeader;
// If the header will not be found due to missing section data
if (_wiseSectionHeaderMissing)
return null;
// If the section table is invalid
if (SectionTable == null)
{
_wiseSectionHeaderMissing = true;
return null;
}
// Find the .WISE section
SectionHeader? wiseSection = null;
foreach (var section in SectionTable)
{
string sectionName = Encoding.ASCII.GetString(section.Name ?? []).TrimEnd('\0');
if (sectionName != ".WISE")
continue;
wiseSection = section;
break;
}
// If the section cannot be found
if (wiseSection == null)
{
_wiseSectionHeaderMissing = true;
return null;
}
// Get the physical offset of the section
long offset = wiseSection.VirtualAddress.ConvertVirtualAddress(SectionTable);
if (offset < 0 || offset >= Length)
{
_wiseSectionHeaderMissing = true;
return null;
}
// Read the section into a local array
int sectionLength = (int)wiseSection.VirtualSize;
byte[]? sectionData = ReadRangeFromSource(offset, sectionLength);
// Parse the section header
_wiseSectionHeader = WiseSectionHeader.Create(sectionData, 0);
if (_wiseSectionHeader == null)
_wiseSectionHeaderMissing = true;
return _wiseSectionHeader;
}
}
}
#region Version Information
/// <summary>
@@ -815,6 +880,21 @@ namespace SabreTools.Serialization.Wrappers
/// </summary>
private readonly List<string>?[] _tableStringData = new List<string>?[16];
/// <summary>
/// Wise section wrapper, if it exists
/// </summary>
private WiseSectionHeader? _wiseSectionHeader = null;
/// <summary>
/// Lock object for <see cref="_wiseSectionHeader"/>
/// </summary>
private readonly object _wiseSectionHeaderLock = new();
/// <summary>
/// Indicates if <see cref="_wiseSectionHeader"/> cannot be found
/// </summary>
private bool _wiseSectionHeaderMissing = false;
#region Version Information
/// <summary>
@@ -1446,30 +1526,6 @@ namespace SabreTools.Serialization.Wrappers
}
}
/// <summary>
/// Find the location of a Wise section, if it exists
/// </summary>
/// <returns>Wise section on success, null otherwise</returns>
public SectionHeader? FindWiseSection()
{
// If the section table is invalid
if (SectionTable == null)
return null;
// Find the .WISE section
foreach (var section in SectionTable)
{
string sectionName = Encoding.ASCII.GetString(section.Name ?? []).TrimEnd('\0');
if (sectionName != ".WISE")
continue;
return section;
}
// Otherwise, it could not be found
return null;
}
#endregion
#region Resource Parsing