Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mono] Save trimmed methods list to a file #97705

Closed
Closed
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
27 changes: 23 additions & 4 deletions src/tasks/MonoTargetsTasks/ILStrip/ILStrip.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,13 +164,15 @@ private bool TrimMethods(ITaskItem assemblyItem, string trimmedAssemblyFolder)
}

string trimmedAssemblyFilePath = ComputeTrimmedAssemblyPath(trimmedAssemblyFolder, assemblyFilePath);
string trimmedMethodListFilePath = trimmedAssemblyFilePath.Replace(".dll", ".txt");
if (File.Exists(trimmedAssemblyFilePath))
{
if (IsInputNewerThanOutput(assemblyFilePath, trimmedAssemblyFilePath))
{
Log.LogMessage(MessageImportance.Low, $"Re-trimming {assemblyFilePath} because {trimmedAssemblyFilePath} is older than {assemblyFilePath} .");
Log.LogMessage(MessageImportance.Low, $"Deleting {trimmedAssemblyFilePath} .");
File.Delete(trimmedAssemblyFilePath);
File.Delete(trimmedMethodListFilePath);
}
else
{
Expand All @@ -196,12 +198,13 @@ private bool TrimMethods(ITaskItem assemblyItem, string trimmedAssemblyFolder)
return true;
}

Dictionary<int, string> rvaToName = new();
string? line = sr.ReadLine();
if (!string.IsNullOrEmpty(line))
{
isTrimmed = true;
Dictionary<int, int> methodBodyUses = ComputeMethodBodyUsage(mr, sr, line, methodTokenFile);
CreateTrimmedAssembly(peReader, trimmedAssemblyFilePath, fs, methodBodyUses);
Dictionary<int, int> methodBodyUses = ComputeMethodBodyUsage(mr, sr, line, methodTokenFile, ref rvaToName);
CreateTrimmedAssembly(peReader, trimmedAssemblyFilePath, fs, methodBodyUses, rvaToName, trimmedMethodListFilePath);
}

var outAssemblyItem = isTrimmed ? GetTrimmedAssemblyItem(assemblyItem, trimmedAssemblyFilePath, assemblyFilePathArg) : assemblyItem;
Expand Down Expand Up @@ -237,7 +240,7 @@ private static string ComputeGuid(MetadataReader mr)
return mvid.ToString();
}

private Dictionary<int, int> ComputeMethodBodyUsage(MetadataReader mr, StreamReader sr, string? line, string methodTokenFile)
private Dictionary<int, int> ComputeMethodBodyUsage(MetadataReader mr, StreamReader sr, string? line, string methodTokenFile, ref Dictionary<int, string> rvaToName)
{
Dictionary<int, int> tokenToRva = new();
Dictionary<int, int> methodBodyUses = new();
Expand All @@ -247,6 +250,7 @@ private Dictionary<int, int> ComputeMethodBodyUsage(MetadataReader mr, StreamRea
int methodToken = MetadataTokens.GetToken(mr, mdefh);
MethodDefinition mdef = mr.GetMethodDefinition(mdefh);
int rva = mdef.RelativeVirtualAddress;
string methodName = mr.GetString(mdef.Name);
Copy link
Member

Choose a reason for hiding this comment

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

this isn't the full name of the method (ie: NameSpace.ClassName+NestedClassName<T,U>.SomeMethod<V,W>(Arg1 arg1, Arg2 arg2, ..., ArgN argN)). It's just SomeMethod. Is that what we want? The file might have 100 methods all named ToString or something.

Copy link
Member Author

Choose a reason for hiding this comment

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

You are right. Do you know how to get the method full signature?

Copy link
Member

Choose a reason for hiding this comment

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

There's not an easy way :-(

you need to get the mdef.GetDeclaringType() which will be a TypeDefinitionHandle. then you need to get the TypeDefinition using mr.GetTypeDefiniton() which will have a Namespace and a Name property. And also you have to get its GetDeclaringType if it's a nested type, and so on until there's no more enclosing types.

That will at least get you enough so you can print SomeNameSpace.SomeClass.SomeEnclosingType.SomeMethodName which is better. (it woudl be good to also print the method signature in case we need to care about overloads, but that's harder)


tokenToRva.Add(methodToken, rva);

Expand All @@ -258,6 +262,15 @@ private Dictionary<int, int> ComputeMethodBodyUsage(MetadataReader mr, StreamRea
{
methodBodyUses.Add(rva, 1);
}

if (rvaToName.TryGetValue(rva, out var _))
{
rvaToName[rva] = rvaToName[rva] + ", " + methodName;
}
else
{
rvaToName.Add(rva, methodName);
}
}

do
Expand All @@ -280,8 +293,10 @@ private Dictionary<int, int> ComputeMethodBodyUsage(MetadataReader mr, StreamRea
return methodBodyUses;
}

private void CreateTrimmedAssembly(PEReader peReader, string trimmedAssemblyFilePath, FileStream fs, Dictionary<int, int> methodBodyUses)
private void CreateTrimmedAssembly(PEReader peReader, string trimmedAssemblyFilePath, FileStream fs, Dictionary<int, int> methodBodyUses, Dictionary<int, string> rvaToName, string trimmedMethodListFilePath)
{
List<string> trimmedMethods = new();

using FileStream os = File.Open(trimmedAssemblyFilePath, FileMode.Create);
{
fs.Position = 0;
Expand All @@ -300,6 +315,7 @@ private void CreateTrimmedAssembly(PEReader peReader, string trimmedAssemblyFile
if (headerSize == 1) //Set code size to zero for TinyFormat
SetCodeSizeToZeroForTiny(ref memStream, actualLoc);
ZeroOutMethodBody(ref memStream, methodSize, actualLoc, headerSize);
trimmedMethods.Add(rvaToName[rva]);
}
else if (count < 0)
{
Expand All @@ -310,6 +326,9 @@ private void CreateTrimmedAssembly(PEReader peReader, string trimmedAssemblyFile
memStream.Position = 0;
memStream.CopyTo(os);
}

string trimmedMethodsStr = string.Join(Environment.NewLine, trimmedMethods.ToArray());
File.WriteAllText(trimmedMethodListFilePath, trimmedMethodsStr);
lambdageek marked this conversation as resolved.
Show resolved Hide resolved
}

private static int ComputeMethodSize(PEReader peReader, int rva) => peReader.GetMethodBody(rva).Size;
Expand Down
Loading