Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -111,16 +111,29 @@ public static bool GenerateManifest(ITracer tracer, DirectoryInfo dir, string ma

if (specialFilesRequireAdjacentRuntime)
{
FileInfo correlatedFile = new(Path.Combine(runtimeModule.DirectoryName, correlatedFileName));
return (FoundMultipleCandidates: false,
File: correlatedFile.Exists ? correlatedFile : default);
FileInfo[] adjacentCorrelatedFiles = runtimeModule.Directory?.GetFiles()
.Where(file => file.Name.Equals(correlatedFileName, StringComparison.OrdinalIgnoreCase))
.ToArray()
?? Array.Empty<FileInfo>();

if (adjacentCorrelatedFiles.Length > 1)
{
tracer.Error($"Multiple adjacent files '{correlatedFileName}' found for runtime '{runtimeModule.FullName}': {string.Join<FileInfo>(", ", adjacentCorrelatedFiles)}.");
}

return adjacentCorrelatedFiles.Length switch
{
0 => (FoundMultipleCandidates: false, default),
1 => (FoundMultipleCandidates: false, adjacentCorrelatedFiles[0]),
_ => (FoundMultipleCandidates: true, default)
};
}

FileInfo[] correlatedFiles = allFiles.Where(file => file.Name.Equals(correlatedFileName, StringComparison.OrdinalIgnoreCase)).ToArray();

if (correlatedFiles.Length > 1)
{
tracer.Error($"Multiple files '${correlatedFileName}' found for runtime '{runtimeModule.FullName}': {string.Join<FileInfo>(", ", correlatedFiles)}.");
tracer.Error($"Multiple files '{correlatedFileName}' found for runtime '{runtimeModule.FullName}': {string.Join<FileInfo>(", ", correlatedFiles)}.");
}

return correlatedFiles.Length switch
Expand Down
26 changes: 15 additions & 11 deletions src/Microsoft.SymbolStore/KeyGenerators/PEFileKeyGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ public override IEnumerable<SymbolStoreKey> GetKeys(KeyTypeFlags flags)
{
yield return GetKey(_path, _peFile.Timestamp, _peFile.SizeOfImage);
}
if ((flags & KeyTypeFlags.RuntimeKeys) != 0 && (GetFileName(_path) == CoreClrFileName || GetFileName(_path) == ClrFileName))
string runtimeFileName = GetFileName(_path);
if ((flags & KeyTypeFlags.RuntimeKeys) != 0 &&
(runtimeFileName.Equals(CoreClrFileName, StringComparison.OrdinalIgnoreCase) ||

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic is used on linux where we can't do case insensitive matching

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we only accept lower case coreclr.dll/clr.dll? or just have case insensitive matching on Windows?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whats the background for this PR? My understanding is that these code paths would only be running when trying to do special indexing of files the .NET team produces so is this occurring in our own .NET build or somewhere else?

runtimeFileName.Equals(ClrFileName, StringComparison.OrdinalIgnoreCase)))
{
yield return GetKey(_path, _peFile.Timestamp, _peFile.SizeOfImage);
}
Expand Down Expand Up @@ -107,10 +110,10 @@ public override IEnumerable<SymbolStoreKey> GetKeys(KeyTypeFlags flags)
if ((flags & KeyTypeFlags.ClrKeys) != 0)
{
string coreclrId = BuildId(_peFile.Timestamp, _peFile.SizeOfImage);
string[] sosFiles = GetSOSFiles(GetFileName(_path)).ToArray();
string[] sosFiles = GetSOSFiles(runtimeFileName).ToArray();
if (sosFiles.Length == 0)
{
Tracer.Verbose("PEFile `{0}`: no SOS special files generated for runtime file {1}. No SOS keys will be produced.", _path, GetFileName(_path));
Tracer.Verbose("PEFile `{0}`: no SOS special files generated for runtime file {1}. No SOS keys will be produced.", _path, runtimeFileName);
}
foreach (string specialFileName in sosFiles)
{
Expand All @@ -122,10 +125,10 @@ public override IEnumerable<SymbolStoreKey> GetKeys(KeyTypeFlags flags)
if ((flags & (KeyTypeFlags.ClrKeys | KeyTypeFlags.DacDbiKeys)) != 0)
{
string coreclrId = BuildId(_peFile.Timestamp, _peFile.SizeOfImage);
string[] dacFiles = GetDACFiles(GetFileName(_path)).ToArray();
string[] dacFiles = GetDACFiles(runtimeFileName).ToArray();
if (dacFiles.Length == 0)
{
Tracer.Verbose("PEFile `{0}`: no DAC/DBI special files generated for runtime file {1}. No DAC/DBI keys will be produced.", _path, GetFileName(_path));
Tracer.Verbose("PEFile `{0}`: no DAC/DBI special files generated for runtime file {1}. No DAC/DBI keys will be produced.", _path, runtimeFileName);
}
foreach (string specialFileName in dacFiles)
{
Expand Down Expand Up @@ -155,7 +158,7 @@ public override IEnumerable<SymbolStoreKey> GetKeys(KeyTypeFlags flags)

private IEnumerable<string> GetSOSFiles(string runtimeFileName)
{
if (runtimeFileName == ClrFileName)
if (runtimeFileName.Equals(ClrFileName, StringComparison.OrdinalIgnoreCase))
{
return GetFilesLongNameVariants(SosFileName);
}
Expand All @@ -165,14 +168,14 @@ private IEnumerable<string> GetSOSFiles(string runtimeFileName)

private IEnumerable<string> GetDACFiles(string runtimeFileName)
{
if (runtimeFileName == CoreClrFileName)
if (runtimeFileName.Equals(CoreClrFileName, StringComparison.OrdinalIgnoreCase))
{
string[] coreClrDACFiles = new string[] { CoreClrDACFileName, DbiFileName };
IEnumerable<string> longNameDACFiles = GetFilesLongNameVariants(CoreClrDACFileName);
return coreClrDACFiles.Concat(longNameDACFiles);
}

if (runtimeFileName == ClrFileName)
if (runtimeFileName.Equals(ClrFileName, StringComparison.OrdinalIgnoreCase))
{
string[] clrDACFiles = new string[] { ClrDACFileName, DbiFileName };
IEnumerable<string> longNameDACFiles = GetFilesLongNameVariants(ClrDACFileName);
Expand All @@ -184,7 +187,7 @@ private IEnumerable<string> GetDACFiles(string runtimeFileName)

private IEnumerable<string> GetFilesLongNameVariants(string fileWithLongNameVariant)
{
if (!s_knownFilesWithLongNameVariant.Contains(fileWithLongNameVariant))
if (!s_knownFilesWithLongNameVariant.Contains(fileWithLongNameVariant, StringComparer.OrdinalIgnoreCase))
{
Tracer.Warning("{0} is not a recognized file with a long name variant", fileWithLongNameVariant);
return Enumerable.Empty<string>();
Expand Down Expand Up @@ -251,8 +254,9 @@ public static SymbolStoreKey GetKey(string path, uint timestamp, uint sizeOfImag
// The clr special file flag can not be based on the GetSpecialFiles() list because
// that is only valid when "path" is the coreclr.dll.
string fileName = GetFileName(path);
bool clrSpecialFile = s_knownRuntimeSpecialFiles.Contains(fileName) ||
(s_knownFilesWithLongNameVariant.Any((file) => fileName.StartsWith(Path.GetFileNameWithoutExtension(file).ToLowerInvariant() + "_")) && Path.GetExtension(fileName) == ".dll");
bool clrSpecialFile = s_knownRuntimeSpecialFiles.Contains(fileName, StringComparer.OrdinalIgnoreCase) ||
(s_knownFilesWithLongNameVariant.Any((file) => fileName.StartsWith(Path.GetFileNameWithoutExtension(file) + "_", StringComparison.OrdinalIgnoreCase))
&& Path.GetExtension(fileName).Equals(".dll", StringComparison.OrdinalIgnoreCase));

string id = BuildId(timestamp, sizeOfImage);
return BuildKey(path, id, clrSpecialFile);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,5 +135,42 @@ public void PEFileGenerateRuntimeKeys(MockPEFile mockPEFile)
Assert.Empty(runtimeKeys);
}
}

[Fact]
public void PEFileGenerateRuntimeKeysCaseInsensitiveRuntimeName()
{
using var mockFileStream = new FileStream("TestBinaries/mockclr_amd64.dll", FileMode.Open, FileAccess.Read);
var mockSymbolStoreFile = new SymbolStoreFile(mockFileStream, "CLR.DLL");
var generator = new PEFileKeyGenerator(_tracer, mockSymbolStoreFile);

var runtimeKeys = generator.GetKeys(KeyTypeFlags.RuntimeKeys);
Assert.Single(runtimeKeys);
Assert.Equal("clr.dll/4D4F434B434c52/clr.dll", runtimeKeys.Single().Index);
}

[Fact]
public void PEFileGenerateClrKeysCaseInsensitiveRuntimeName()
{
using var mockFileStream = new FileStream("TestBinaries/mockclr_amd64.dll", FileMode.Open, FileAccess.Read);
var mockSymbolStoreFile = new SymbolStoreFile(mockFileStream, "CLR.DLL");
var generator = new PEFileKeyGenerator(_tracer, mockSymbolStoreFile);

var clrKeys = generator.GetKeys(KeyTypeFlags.ClrKeys).ToDictionary((key) => key.Index);
Assert.Contains("sos_amd64_amd64_1.2.3.45.dll/4D4F434B434c52/sos_amd64_amd64_1.2.3.45.dll", clrKeys.Keys);
Assert.Contains("mscordacwks.dll/4D4F434B434c52/mscordacwks.dll", clrKeys.Keys);
Assert.Contains("mscordbi.dll/4D4F434B434c52/mscordbi.dll", clrKeys.Keys);
}

[Fact]
public void PEFileGenerateIdentityKeysCaseInsensitiveSpecialName()
{
using var mockFileStream = new FileStream("TestBinaries/mockdac.dll", FileMode.Open, FileAccess.Read);
var mockSymbolStoreFile = new SymbolStoreFile(mockFileStream, "MSCORDACWKS.DLL");
var generator = new PEFileKeyGenerator(_tracer, mockSymbolStoreFile);

SymbolStoreKey identityKey = generator.GetKeys(KeyTypeFlags.IdentityKey).Single();
Assert.Equal("mscordacwks.dll/4D4F434B444143/mscordacwks.dll", identityKey.Index);
Assert.True(identityKey.IsClrSpecialFile);
}
}
}
Loading