/// <summary>Gets an array of module infos for the specified process.</summary>
/// <param name="processId">The ID of the process whose modules should be enumerated.</param>
/// <returns>The array of modules.</returns>
internal static ProcessModuleCollection GetModules(int processId)
{
var modules = new ProcessModuleCollection(0);
// Process from the parsed maps file each entry representing a module
foreach (Interop.procfs.ParsedMapsModule entry in Interop.procfs.ParseMapsModules(processId))
{
int sizeOfImage = (int)(entry.AddressRange.Value - entry.AddressRange.Key);
// A single module may be split across multiple map entries; consolidate based on
// the name and address ranges of sequential entries.
if (modules.Count > 0)
{
ProcessModule module = modules[modules.Count - 1];
if (module.FileName == entry.FileName &&
((long)module.BaseAddress + module.ModuleMemorySize == entry.AddressRange.Key))
{
// Merge this entry with the previous one
module.ModuleMemorySize += sizeOfImage;
continue;
}
}
// It's not a continuation of a previous entry but a new one: add it.
unsafe
{
modules.Add(new ProcessModule()
{
FileName = entry.FileName,
ModuleName = Path.GetFileName(entry.FileName),
BaseAddress = new IntPtr(unchecked ((void *)entry.AddressRange.Key)),
ModuleMemorySize = sizeOfImage,
EntryPointAddress = IntPtr.Zero // unknown
});
}
}
// Move the main executable module to be the first in the list if it's not already
string exePath = Process.GetExePath(processId);
for (int i = 0; i < modules.Count; i++)
{
ProcessModule module = modules[i];
if (module.FileName == exePath)
{
if (i > 0)
{
modules.RemoveAt(i);
modules.Insert(0, module);
}
break;
}
}
// Return the set of modules found
return(modules);
}