You've already forked linux-packaging-mono
Imported Upstream version 5.12.0.220
Former-commit-id: c477e03582759447177c6d4bf412cd2355aad476
This commit is contained in:
parent
8bd104cef2
commit
8fc30896db
@@ -15,7 +15,7 @@ namespace LinkerAnalyzer
|
||||
{
|
||||
public class ConsoleDependencyGraph : DependencyGraph
|
||||
{
|
||||
public bool Tree = false;
|
||||
public bool Tree;
|
||||
public bool FlatDeps;
|
||||
|
||||
public void ShowDependencies (string raw, List<VertexData> verticesList, string searchString)
|
||||
@@ -48,16 +48,25 @@ namespace LinkerAnalyzer
|
||||
Console.WriteLine ();
|
||||
|
||||
foreach (var d in flatDeps) {
|
||||
var dSize = SpaceAnalyzer == null ? 0 : SpaceAnalyzer.GetSize (d.Item1);
|
||||
if (first) {
|
||||
Console.WriteLine ($"Distance | {d.Item1.value} [total deps: {flatDeps.Count}]");
|
||||
var sizeStr = dSize > 0 ? $" [size: {dSize}]" : "";
|
||||
Console.WriteLine ($"Distance | {d.Item1.value} [total deps: {flatDeps.Count}]{sizeStr}");
|
||||
Line ();
|
||||
first = false;
|
||||
continue;
|
||||
}
|
||||
Console.WriteLine ($"{string.Format ("{0,8}", d.Item2)} | {d.Item1.value}");
|
||||
var sizeStr2 = dSize > 0 ? $" [size: {dSize}]" : "";
|
||||
Console.WriteLine ($"{string.Format ("{0,8}", d.Item2)} | {d.Item1.value}{d.Item1.DepsCount}{sizeStr2}");
|
||||
}
|
||||
}
|
||||
|
||||
string SizeString (VertexData vertex)
|
||||
{
|
||||
return SpaceAnalyzer == null ?
|
||||
"" : string.Format (" size: {0}", SpaceAnalyzer.GetSize (vertex));
|
||||
}
|
||||
|
||||
public void ShowDependencies (VertexData vertex)
|
||||
{
|
||||
if (FlatDeps) {
|
||||
@@ -73,7 +82,7 @@ namespace LinkerAnalyzer
|
||||
int i = 0;
|
||||
foreach (int index in vertex.parentIndexes) {
|
||||
Console.WriteLine ("Dependency #{0}", ++i);
|
||||
Console.WriteLine ("\t{0}", vertex.value);
|
||||
Console.WriteLine ($"\t{vertex.value}{SizeString (vertex)}");
|
||||
var childVertex = Vertex (index);
|
||||
Console.WriteLine ("\t| {0}{1}", childVertex.value, childVertex.DepsCount);
|
||||
while (childVertex.parentIndexes != null) {
|
||||
@@ -166,7 +175,7 @@ namespace LinkerAnalyzer
|
||||
Console.WriteLine ();
|
||||
}
|
||||
|
||||
void Header (string header, params object[] values)
|
||||
static public void Header (string header, params object[] values)
|
||||
{
|
||||
string formatted = string.Format (header, values);
|
||||
Console.WriteLine ();
|
||||
|
||||
@@ -34,6 +34,7 @@ namespace LinkerAnalyzer.Core
|
||||
public List<VertexData> Types = new List<VertexData> ();
|
||||
Dictionary<string, int> indexes = new Dictionary<string, int> ();
|
||||
protected Dictionary<string, int> counts = new Dictionary<string, int> ();
|
||||
internal SpaceAnalyzer SpaceAnalyzer { get; set; }
|
||||
|
||||
public void Load (string filename)
|
||||
{
|
||||
|
||||
153
external/linker/analyzer/LinkerAnalyzerCore/SpaceAnalyzer.cs
vendored
Normal file
153
external/linker/analyzer/LinkerAnalyzerCore/SpaceAnalyzer.cs
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
// SpaceAnalyzer.cs
|
||||
//
|
||||
// Author:
|
||||
// Radek Doulik <radou@microsoft.com>
|
||||
//
|
||||
// Copyright (C) 2018 Microsoft Corporation (http://www.microsoft.com)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Mono.Cecil;
|
||||
|
||||
namespace LinkerAnalyzer.Core
|
||||
{
|
||||
public class SpaceAnalyzer
|
||||
{
|
||||
string assembliesDirectory;
|
||||
List<AssemblyDefinition> assemblies = new List<AssemblyDefinition> ();
|
||||
readonly Dictionary<string, int> sizes = new Dictionary<string, int> ();
|
||||
|
||||
public SpaceAnalyzer (string assembliesDirectory)
|
||||
{
|
||||
this.assembliesDirectory = assembliesDirectory;
|
||||
}
|
||||
|
||||
static bool IsAssemblyBound (TypeDefinition td)
|
||||
{
|
||||
do {
|
||||
if (td.IsNestedPrivate || td.IsNestedAssembly || td.IsNestedFamilyAndAssembly)
|
||||
return true;
|
||||
|
||||
td = td.DeclaringType;
|
||||
} while (td != null);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
string GetTypeKey (TypeDefinition td)
|
||||
{
|
||||
if (td == null)
|
||||
return "";
|
||||
|
||||
var addAssembly = td.IsNotPublic || IsAssemblyBound (td);
|
||||
|
||||
var addition = addAssembly ? $":{td.Module}" : "";
|
||||
return $"{td.MetadataToken.TokenType}:{td}{addition}";
|
||||
}
|
||||
|
||||
string GetKey (IMetadataTokenProvider provider)
|
||||
{
|
||||
return $"{provider.MetadataToken.TokenType}:{provider}";
|
||||
}
|
||||
|
||||
int GetMethodSize (MethodDefinition method)
|
||||
{
|
||||
var key = GetKey (method);
|
||||
|
||||
if (sizes.ContainsKey (key))
|
||||
return sizes [key];
|
||||
|
||||
var msize = method.Body.CodeSize;
|
||||
msize += method.Name.Length;
|
||||
|
||||
sizes.Add (key, msize);
|
||||
|
||||
return msize;
|
||||
}
|
||||
|
||||
int ProcessType (TypeDefinition type)
|
||||
{
|
||||
int size = type.Name.Length;
|
||||
|
||||
foreach (var field in type.Fields)
|
||||
size += field.Name.Length;
|
||||
|
||||
foreach (var method in type.Methods) {
|
||||
method.Resolve ();
|
||||
if (method.Body != null)
|
||||
size += GetMethodSize (method);
|
||||
}
|
||||
|
||||
var resolvedType = type.Resolve ();
|
||||
try {
|
||||
sizes.Add (GetTypeKey (type), size);
|
||||
} catch (ArgumentException e) {
|
||||
Console.WriteLine ($"\nWarning: duplicated type '{type}' scope '{type.Scope}'\n{e}");
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
public void LoadAssemblies (bool verbose = true)
|
||||
{
|
||||
if (verbose) {
|
||||
ConsoleDependencyGraph.Header ("Space analyzer");
|
||||
Console.WriteLine ("Load assemblies from {0}", assembliesDirectory);
|
||||
} else
|
||||
Console.Write ("Analyzing assemblies .");
|
||||
|
||||
var resolver = new DefaultAssemblyResolver ();
|
||||
resolver.AddSearchDirectory (assembliesDirectory);
|
||||
|
||||
int totalSize = 0;
|
||||
foreach (var file in System.IO.Directory.GetFiles (assembliesDirectory, "*.dll")) {
|
||||
if (verbose)
|
||||
Console.WriteLine ($"Analyzing {file}");
|
||||
else
|
||||
Console.Write (".");
|
||||
|
||||
ReaderParameters parameters = new ReaderParameters () { ReadingMode = ReadingMode.Immediate, AssemblyResolver = resolver};
|
||||
var assembly = AssemblyDefinition.ReadAssembly (file, parameters);
|
||||
assemblies.Add (assembly);
|
||||
foreach (var module in assembly.Modules) {
|
||||
foreach (var type in module.Types) {
|
||||
totalSize += ProcessType (type);
|
||||
foreach (var child in type.NestedTypes)
|
||||
totalSize += ProcessType (child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
Console.WriteLine ("Total known size: {0}", totalSize);
|
||||
else
|
||||
System.Console.WriteLine ();
|
||||
}
|
||||
|
||||
public int GetSize (VertexData vertex)
|
||||
{
|
||||
if (sizes.ContainsKey (vertex.value))
|
||||
return sizes [vertex.value];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
10
external/linker/analyzer/Main.cs
vendored
10
external/linker/analyzer/Main.cs
vendored
@@ -23,23 +23,23 @@ namespace LinkerAnalyzer
|
||||
bool showRawDeps = false;
|
||||
string rawName = null;
|
||||
bool showRoots = false;
|
||||
bool showSpaceUsage = false;
|
||||
bool showStat = false;
|
||||
bool showTypes = false;
|
||||
bool reduceToTree = false;
|
||||
bool verbose = false;
|
||||
bool flatDeps = false;
|
||||
string linkedPath = null;
|
||||
|
||||
var optionsParser = new OptionSet () {
|
||||
{ "a|alldeps", "show all dependencies", v => { showAllDeps = v != null; } },
|
||||
{ "h|help", "show this message and exit.", v => showUsage = v != null },
|
||||
{ "l|linkedpath=", "sets the linked assemblies directory path. Enables displaying size estimates.", v => { linkedPath = v; } },
|
||||
{ "r|rawdeps=", "show raw vertex dependencies. Raw vertex VALUE is in the raw format written by linker to the dependency XML file. VALUE can be regular expression", v => { showRawDeps = v != null; rawName = v; } },
|
||||
{ "roots", "show root dependencies.", v => showRoots = v != null },
|
||||
{ "stat", "show statistic of loaded dependencies.", v => showStat = v != null },
|
||||
{ "tree", "reduce the dependency graph to the tree.", v => reduceToTree = v != null },
|
||||
{ "types", "show all types dependencies.", v => showTypes = v != null },
|
||||
{ "t|typedeps=", "show type dependencies. The VALUE can be regular expression", v => { showTypeDeps = v != null; typeName = v; } },
|
||||
//{ "u|spaceusage", "show space analysis.", v => showSpaceUsage = v != null },
|
||||
{ "f|flat", "show all dependencies per vertex and their distance", v => flatDeps = v != null },
|
||||
{ "v|verbose", "be more verbose. Enables stat and roots options.", v => verbose = v != null },
|
||||
};
|
||||
@@ -61,9 +61,9 @@ namespace LinkerAnalyzer
|
||||
ConsoleDependencyGraph deps = new ConsoleDependencyGraph () { Tree = reduceToTree, FlatDeps = flatDeps };
|
||||
deps.Load (dependencyFile);
|
||||
|
||||
if (showSpaceUsage) {
|
||||
// SpaceAnalyzer sa = new SpaceAnalyzer (System.IO.Path.GetDirectoryName (dependencyFile));
|
||||
// sa.LoadAssemblies (verbose);
|
||||
if (linkedPath != null) {
|
||||
deps.SpaceAnalyzer = new SpaceAnalyzer (linkedPath);
|
||||
deps.SpaceAnalyzer.LoadAssemblies (verbose);
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
|
||||
21
external/linker/analyzer/README.md
vendored
21
external/linker/analyzer/README.md
vendored
@@ -1,3 +1,5 @@
|
||||
# Linker Analyzer
|
||||
|
||||
Linker analyzer is a command line tool to analyze dependencies, which
|
||||
were recorded during linker processing, and led linker to mark an item
|
||||
to keep it in the resulting linked assembly.
|
||||
@@ -7,8 +9,7 @@ dumped during the linker run. The vertices of this graph are the items
|
||||
of interest like assemblies, types, methods, fields, linker steps,
|
||||
etc. The edges represent the dependencies.
|
||||
|
||||
How to dump dependencies
|
||||
------------------------
|
||||
## How to dump dependencies
|
||||
|
||||
The linker analyzer needs a linker dependencies file as an input. It
|
||||
can be retrieved by enabling dependencies dumping during linking of a
|
||||
@@ -25,8 +26,7 @@ the project like this:
|
||||
After a successful build, there will be a linker-dependencies.xml.gz
|
||||
file created, containing the information for the analyzer.
|
||||
|
||||
How to use the analyzer
|
||||
-----------------------
|
||||
## How to use the analyzer
|
||||
|
||||
Let say you would like to know, why a type, Android.App.Activity for
|
||||
example, was marked by the linker. So run the analyzer like this:
|
||||
@@ -48,11 +48,7 @@ Dependency #1
|
||||
| Other:Mono.Linker.Steps.ResolveFromAssemblyStep
|
||||
```
|
||||
|
||||
The output contains dependencies string(s), starting with the type and
|
||||
continuing with the item of interest, which depends on the type. The
|
||||
dependency could be result of multiple reasons. For example the type
|
||||
was referenced from a method, or the type was listed in the linker xml
|
||||
file to be protected.
|
||||
The output contains dependencies string(s), starting with the type and continuing with the item of interest, which depends on the type. The dependency could be a result of multiple reasons. For example, the type was referenced from a method, or the type was listed in the linker XML descriptor file.
|
||||
|
||||
In our example there is only one dependency string called `Dependency
|
||||
#1`. It shows us that the type `Android.App.Activity` was marked
|
||||
@@ -91,8 +87,7 @@ Dependency #2
|
||||
| Other:Mono.Linker.Steps.ResolveFromAssemblyStep
|
||||
```
|
||||
|
||||
Known issues
|
||||
------------
|
||||
### Known issues
|
||||
|
||||
Sometimes the linker processing is not straight forward and the
|
||||
marking is postponed, like processing of some of the methods. They are
|
||||
@@ -100,8 +95,8 @@ queued to be processed later. In such case the dependencies are
|
||||
"interrupted" and the dependecy string for the method usually shows
|
||||
just dependency on the Mark step.
|
||||
|
||||
Command line help
|
||||
-----------------
|
||||
# Command line help
|
||||
|
||||
```
|
||||
Usage:
|
||||
|
||||
|
||||
5
external/linker/analyzer/analyzer.csproj
vendored
5
external/linker/analyzer/analyzer.csproj
vendored
@@ -31,11 +31,16 @@
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Xml" />
|
||||
<ProjectReference Include="../cecil/Mono.Cecil.csproj">
|
||||
<Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
|
||||
<Name>Mono.Cecil</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ConsoleDependencyGraph.cs" />
|
||||
<Compile Include="Main.cs" />
|
||||
<Compile Include="LinkerAnalyzerCore\DependencyGraph.cs" />
|
||||
<Compile Include="LinkerAnalyzerCore\SpaceAnalyzer.cs" />
|
||||
<Compile Include="..\common\Mono.Options\Options.cs">
|
||||
<Link>Options.cs</Link>
|
||||
</Compile>
|
||||
|
||||
Reference in New Issue
Block a user