in src/BinaryParsers/PEBinary/ProgramDatabase/TruncatedCompilandRecordList.cs [76:175]
public string CreateTruncatedObjectList()
{
this.EnsureSorted();
if (this.rawRecords.Count <= this.maxRecords)
{
// No truncation necessary.
// (Avoids unnecessary calulation and prevents infinite loops;
// since remainingSize must eventually reach 0)
return this.CreateAllObjectList();
}
var blockStarts = new List<int>();
var blockDisplaySizes = new List<int>();
// Size of [ blockStarts[n], blockStarts[n + 1] ) is in blockSizes[n]
// Build `blockStarts` and `blockDisplaySizes` by trying to give each library
// `targetLibraryBlockSize` space
int remainingSpace = this.TryRoughFitOfBlocksOfTargetLibraryBlockSize(blockStarts, blockDisplaySizes, this.maxRecords - 1 /* -1 for total truncated records message */);
bool anyLibrariesAreCompletelyTruncated = blockStarts[blockStarts.Count - 1] != this.rawRecords.Count;
if (anyLibrariesAreCompletelyTruncated)
{
// There will be a "completely removed libraries" block; recalculate with 1 less remainingSpace
// to allow for that message
remainingSpace = this.TryRoughFitOfBlocksOfTargetLibraryBlockSize(blockStarts, blockDisplaySizes, this.maxRecords - 2);
}
ExpandDisplayedBlockSizesToConsumeRemainingSpace(blockStarts, blockDisplaySizes, remainingSpace);
var sb = new StringBuilder();
int totalTruncatedLibrariesCount = 0;
int totalTruncatedObjectsCount = 0;
for (int idx = 0; idx < blockDisplaySizes.Count; ++idx)
{
int blockStart = blockStarts[idx];
int blockSize = blockStarts[idx + 1] - blockStart;
int blockSizeDisplay = blockDisplaySizes[idx];
if (blockSizeDisplay == blockSize)
{
// No truncation
this.AppendRecords(sb, blockStart, blockStart + blockSizeDisplay);
}
else
{
// Truncation
int truncatedRecords = blockSize - blockSizeDisplay + 1; // +1 for truncation message
this.AppendRecords(sb, blockStart, blockStart + blockSize - truncatedRecords);
// (X object files truncated from Y)
sb.Append('(');
sb.Append(truncatedRecords.ToString(CultureInfo.InvariantCulture));
sb.Append(" object files truncated");
string library = this.rawRecords[blockStart].Library;
if (library != null)
{
sb.Append(" from ");
sb.Append(library);
}
sb.AppendLine(")");
totalTruncatedObjectsCount += truncatedRecords;
++totalTruncatedLibrariesCount;
}
}
if (anyLibrariesAreCompletelyTruncated)
{
int ptr = blockStarts[blockStarts.Count - 1];
int totallyTruncatedObjects = this.rawRecords.Count - ptr;
int totallyTruncatedLibraries = 0;
while (ptr != this.rawRecords.Count)
{
++totallyTruncatedLibraries;
ptr = this.FindNextLibraryTransition(ptr);
}
// (X entire libraries truncated containing Y object files)
sb.Append('(');
sb.Append(totallyTruncatedLibraries.ToString(CultureInfo.InvariantCulture));
sb.Append(" entire libraries truncated containing ");
sb.Append(totallyTruncatedObjects.ToString(CultureInfo.InvariantCulture));
sb.AppendLine(" object files)");
totalTruncatedObjectsCount += totallyTruncatedObjects;
totalTruncatedLibrariesCount += totallyTruncatedLibraries;
}
if (totalTruncatedObjectsCount != 0)
{
// (X total objects truncated from Y total libraries, use pdbinfo.exe to list all objects)
sb.Append('(');
sb.Append(totalTruncatedObjectsCount.ToString(CultureInfo.InvariantCulture));
sb.Append(" total objects truncated from ");
sb.Append(totalTruncatedLibrariesCount.ToString(CultureInfo.InvariantCulture));
sb.AppendLine(" total libraries, use pdbinfo.exe to list all objects)");
}
string result = sb.ToString();
Debug.Assert(result.Count(ch => ch == Environment.NewLine[0]) == this.maxRecords);
return result;
}