summaryrefslogtreecommitdiff
path: root/utils/mapsorter
diff options
context:
space:
mode:
Diffstat (limited to 'utils/mapsorter')
-rw-r--r--utils/mapsorter/Class1.cs30
-rw-r--r--utils/mapsorter/MapFileLoader.cs248
-rw-r--r--utils/mapsorter/MapSorter.csproj100
-rw-r--r--utils/mapsorter/MapSorter.exebin0 -> 20480 bytes
-rw-r--r--utils/mapsorter/MapSorter.sln21
5 files changed, 399 insertions, 0 deletions
diff --git a/utils/mapsorter/Class1.cs b/utils/mapsorter/Class1.cs
new file mode 100644
index 0000000..40005d5
--- /dev/null
+++ b/utils/mapsorter/Class1.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Text.RegularExpressions;
+using System.Collections;
+using System.IO;
+
+namespace MapSorter
+{
+
+
+ /// <summary>
+ /// Summary description for Class1.
+ /// </summary>
+ class Class1
+ {
+ /// <summary>
+ /// The main entry point for the application.
+ /// </summary>
+ [STAThread]
+ static void Main(string[] args)
+ {
+ if( args.Length != 1 )
+ {
+ Console.WriteLine("Usage: MapSorter <filename.map>");
+ return;
+ }
+
+ new MapFileLoader(args[0]).DumpReport();
+ }
+ }
+}
diff --git a/utils/mapsorter/MapFileLoader.cs b/utils/mapsorter/MapFileLoader.cs
new file mode 100644
index 0000000..a77b194
--- /dev/null
+++ b/utils/mapsorter/MapFileLoader.cs
@@ -0,0 +1,248 @@
+using System;
+using System.Text.RegularExpressions;
+using System.Collections;
+using System.IO;
+
+namespace MapSorter
+{
+ public class Element : IComparable
+ {
+ /// <summary>
+ /// Segment this element is in.
+ /// </summary>
+ public int Segment;
+
+ /// <summary>
+ /// Base or virtual file address.
+ /// </summary>
+ public int Address;
+
+ /// <summary>
+ /// Adjusted relative virtual address.
+ /// </summary>
+ public int RVA;
+
+ /// <summary>
+ /// Name of this element.
+ /// </summary>
+ public string Text;
+
+ /// <summary>
+ /// Object file this element is located in.
+ /// </summary>
+ public string Obj;
+
+ /// <summary>
+ /// Size of this element, or -1.
+ /// </summary>
+ public int Size = -1;
+
+ /// <summary>
+ /// True if this is the last element in an object file.
+ /// </summary>
+ public bool bCrossObj = false;
+
+ public Element( int Segment, int Address, string Text, int RVA, string Obj )
+ {
+ this.Segment = Segment;
+ this.Address = Address;
+ this.RVA = RVA;
+ this.Text = Text;
+ this.Obj = Obj;
+ }
+
+ // Comparable interface:
+ int System.IComparable.CompareTo( object o )
+ {
+ // HACK HACK - sorts according to size if size field is non negative, otherwise sorts by segment then address
+ Element other = (Element)o;
+
+ // Sort by size:
+ if( other.Size != -1 || Size != -1 )
+ {
+ if( Size < other.Size )
+ return -1;
+
+ if( Size > other.Size )
+ return 1;
+
+ return 0;
+ }
+
+ // Sizes aren't defined, sort by Segment then Address:
+ if( Segment != other.Segment )
+ {
+ if( Segment < other.Segment )
+ return -1;
+ else
+ return 0;
+ }
+
+ if( Address < other.Address )
+ return -1;
+ else if( Address > other.Address )
+ return 1;
+
+ return 0;
+ }
+ }
+
+ public class Module : IComparable
+ {
+ public string Name;
+ public int Size;
+
+ public Module(string Name, int Size)
+ {
+ this.Name = Name;
+ this.Size = Size;
+ }
+
+ int System.IComparable.CompareTo( object o )
+ {
+ Module m = (Module)o;
+ if( Size < m.Size )
+ return -1;
+
+ if( Size > m.Size )
+ return 1;
+ return 0;
+ }
+ }
+
+ /// <summary>
+ /// An atomic class that loads and parses a given map file.
+ /// </summary>
+ public class MapFileLoader
+ {
+ ArrayList Elements;
+ ArrayList Modules;
+
+ /// <summary>
+ /// Regular expression to break mapfile elements up:
+ /// </summary>
+ protected static Regex ElementRegex = new Regex(@"([0-9a-fA-F]{4})\:([0-9a-fA-F]{8})\s+([^\s]*)\s+([0-9a-fA-F]{8})\s(f\s)?(i\s)?\s+(.*\.obj)",RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.IgnoreCase );
+
+
+ public MapFileLoader( string filename )
+ {
+ // Load the element data from the mapfile:
+ LoadElements( new StreamReader(filename).ReadToEnd() );
+
+ // Compute modules and their sizes:
+ ComputeModules();
+ }
+
+ public void DumpReport()
+ {
+ Console.WriteLine("***** Elements by size ascending. (*) = element straddles an .obj file boundary, so the size may not be correct.");
+ Console.WriteLine();
+
+ foreach (Element e in Elements )
+ {
+ if( e.Size < 1024 )
+ continue;
+
+ if( e.bCrossObj )
+ Console.Write("(*)");
+
+ Console.WriteLine( e.Size / 1024 + "k : " +e.Obj + " : " + e.Text );
+ }
+
+ Console.WriteLine();
+ Console.WriteLine();
+ Console.WriteLine("***** Modules by size, ascending. This is estimated based on elements that don't straddle .obj boundaries.");
+ Console.WriteLine();
+
+ foreach(Module m in Modules )
+ {
+ if( m.Size < 1024 )
+ continue;
+
+ Console.WriteLine( m.Size / 1024 + "k : " + m.Name );
+ }
+
+
+ }
+
+ protected void LoadElements( string mapfile )
+ {
+ // Match each appropriate line in the map file. The summary entries at the top of each map file are NOT matched by this regex.
+ MatchCollection matches = ElementRegex.Matches(mapfile);
+
+
+ Elements = new ArrayList();
+
+ // Convert each match to an Element type and add them to an array list.
+ foreach( Match m in matches )
+ {
+
+ Element e = new Element(int.Parse(m.Groups[1].Value,System.Globalization.NumberStyles.AllowHexSpecifier),
+ int.Parse(m.Groups[2].Value,System.Globalization.NumberStyles.AllowHexSpecifier),
+ m.Groups[3].Value,
+ int.Parse(m.Groups[4].Value,System.Globalization.NumberStyles.AllowHexSpecifier),
+ m.Groups[7].Value);
+
+ Elements.Add(e);
+
+ }
+
+ // Sort the list by address:
+ Elements.Sort();
+
+ Element previous = null;
+
+ // Compute estimated sizes for each element in the list:
+ foreach( Element e in Elements )
+ {
+ if( previous != null )
+ {
+ if( e.Segment == previous.Segment )
+ {
+ previous.Size = e.Address- previous.Address;
+
+ // Take note of the symbols that cross object file boundaries:
+ if( !previous.Obj.Equals(e.Obj) )
+ {
+ previous.bCrossObj = true;
+ }
+ }
+ }
+
+ previous = e;
+ }
+
+ // Sort the list by size
+ Elements.Sort();
+
+
+ }
+
+ protected void ComputeModules()
+ {
+ // Estimate the size of each object file:
+ Hashtable h = new Hashtable();
+
+ foreach(Element e in Elements )
+ {
+ if( !h.ContainsKey(e.Obj) )
+ h.Add(e.Obj,0);
+
+ if( !e.bCrossObj )
+ {
+ h[e.Obj] = (int)h[e.Obj] + e.Size;
+ }
+ }
+
+ Modules = new ArrayList();
+
+ foreach( string key in h.Keys )
+ {
+ Modules.Add( new Module(key, (int)h[key] ));
+ }
+
+ Modules.Sort();
+ }
+
+ }
+}
diff --git a/utils/mapsorter/MapSorter.csproj b/utils/mapsorter/MapSorter.csproj
new file mode 100644
index 0000000..c3e48c6
--- /dev/null
+++ b/utils/mapsorter/MapSorter.csproj
@@ -0,0 +1,100 @@
+<VisualStudioProject>
+ <CSHARP
+ ProjectType = "Local"
+ ProductVersion = "7.10.3077"
+ SchemaVersion = "2.0"
+ ProjectGuid = "{296D6B2D-4FAD-48BE-AC61-CEF53B472983}"
+ >
+ <Build>
+ <Settings
+ ApplicationIcon = ""
+ AssemblyKeyContainerName = ""
+ AssemblyName = "MapSorter"
+ AssemblyOriginatorKeyFile = ""
+ DefaultClientScript = "JScript"
+ DefaultHTMLPageLayout = "Grid"
+ DefaultTargetSchema = "IE50"
+ DelaySign = "false"
+ OutputType = "Exe"
+ PreBuildEvent = ""
+ PostBuildEvent = ""
+ RootNamespace = "MapSorter"
+ RunPostBuildEvent = "OnBuildSuccess"
+ StartupObject = ""
+ >
+ <Config
+ Name = "Debug"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "DEBUG;TRACE"
+ DocumentationFile = ""
+ DebugSymbols = "true"
+ FileAlignment = "4096"
+ IncrementalBuild = "false"
+ NoStdLib = "false"
+ NoWarn = ""
+ Optimize = "false"
+ OutputPath = "bin\Debug\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ <Config
+ Name = "Release"
+ AllowUnsafeBlocks = "false"
+ BaseAddress = "285212672"
+ CheckForOverflowUnderflow = "false"
+ ConfigurationOverrideFile = ""
+ DefineConstants = "TRACE"
+ DocumentationFile = ""
+ DebugSymbols = "false"
+ FileAlignment = "4096"
+ IncrementalBuild = "false"
+ NoStdLib = "false"
+ NoWarn = ""
+ Optimize = "true"
+ OutputPath = "bin\Release\"
+ RegisterForComInterop = "false"
+ RemoveIntegerChecks = "false"
+ TreatWarningsAsErrors = "false"
+ WarningLevel = "4"
+ />
+ </Settings>
+ <References>
+ <Reference
+ Name = "System"
+ AssemblyName = "System"
+ HintPath = "..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll"
+ />
+ <Reference
+ Name = "System.Data"
+ AssemblyName = "System.Data"
+ HintPath = "..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll"
+ />
+ <Reference
+ Name = "System.XML"
+ AssemblyName = "System.Xml"
+ HintPath = "..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.XML.dll"
+ />
+ </References>
+ </Build>
+ <Files>
+ <Include>
+ <File
+ RelPath = "Class1.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
+ RelPath = "MapFileLoader.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ </Include>
+ </Files>
+ </CSHARP>
+</VisualStudioProject>
+
diff --git a/utils/mapsorter/MapSorter.exe b/utils/mapsorter/MapSorter.exe
new file mode 100644
index 0000000..d0b7e77
--- /dev/null
+++ b/utils/mapsorter/MapSorter.exe
Binary files differ
diff --git a/utils/mapsorter/MapSorter.sln b/utils/mapsorter/MapSorter.sln
new file mode 100644
index 0000000..be9b426
--- /dev/null
+++ b/utils/mapsorter/MapSorter.sln
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MapSorter", "MapSorter.csproj", "{296D6B2D-4FAD-48BE-AC61-CEF53B472983}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {296D6B2D-4FAD-48BE-AC61-CEF53B472983}.Debug.ActiveCfg = Debug|.NET
+ {296D6B2D-4FAD-48BE-AC61-CEF53B472983}.Debug.Build.0 = Debug|.NET
+ {296D6B2D-4FAD-48BE-AC61-CEF53B472983}.Release.ActiveCfg = Release|.NET
+ {296D6B2D-4FAD-48BE-AC61-CEF53B472983}.Release.Build.0 = Release|.NET
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal