RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_PerfMapEnabled, W("PerfMapEnabled"), 0, "This flag is used on Linux to enable writing /tmp/perf-$pid.map. It is disabled by default", CLRConfig::REGUTIL_default)
RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_PerfMapIgnoreSignal, W("PerfMapIgnoreSignal"), 0, "When perf map is enabled, this option will configure the specified signal to be accepted and ignored as a marker in the perf logs. It is disabled by default", CLRConfig::REGUTIL_default)
RETAIL_CONFIG_DWORD_INFO(EXTERNAL_PerfMapShowOptimizationTiers, W("PerfMapShowOptimizationTiers"), 1, "Shows optimization tiers in the perf map for methods, as part of the symbol name. Useful for seeing separate stack frames for different optimization tiers of each method.")
+RETAIL_CONFIG_STRING_INFO(EXTERNAL_NativeImagePerfMapFormat, W("NativeImagePerfMapFormat"), "Specifies the format of native image perfmap files generated by crossgen. Valid options are RVA or OFFSET.")
#endif
RETAIL_CONFIG_STRING_INFO(EXTERNAL_StartupDelayMS, W("StartupDelayMS"), "")
SString value;
const SString& path = pFile->GetPath();
- value.Printf("%S%c%S", path.GetUnicode(), sDelimiter, guid);
+ PEImageLayout *pLoadedLayout = pFile->GetLoaded();
+ SIZE_T baseAddr = (SIZE_T)pLoadedLayout->GetBase();
+ value.Printf("%S%c%S%c%p", path.GetUnicode(), sDelimiter, guid, sDelimiter, baseAddr);
SString command;
command.Printf("%s", "ImageLoad");
// Open the perf map file.
OpenFile(sDestPerfMapPath);
+
+ // Determine whether to emit RVAs or file offsets based on the specified configuration.
+ m_EmitRVAs = true;
+ CLRConfigStringHolder wszFormat(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_NativeImagePerfMapFormat));
+ if(wszFormat != NULL && (wcsncmp(wszFormat, strOFFSET, wcslen(strOFFSET)) == 0))
+ {
+ m_EmitRVAs = false;
+ }
}
// Log data to the perfmap for the specified module.
}
// Log a pre-compiled method to the perfmap.
-void NativeImagePerfMap::LogPreCompiledMethod(MethodDesc * pMethod, PCODE pCode, PEImageLayout * pLoadedLayout, const char *optimizationTier)
+void NativeImagePerfMap::LogPreCompiledMethod(MethodDesc * pMethod, PCODE pCode, PEImageLayout *pLoadedLayout, const char *optimizationTier)
{
STANDARD_VM_CONTRACT;
// NGEN can split code between hot and cold sections which are separate in memory.
// Emit an entry for each section if it is used.
+ PCODE addr;
if (methodRegionInfo.hotSize > 0)
{
- LogMethod(pMethod, pLoadedLayout->RvaToOffset((PCODE)methodRegionInfo.hotStartAddress - baseAddr), methodRegionInfo.hotSize, optimizationTier);
+ addr = (PCODE)methodRegionInfo.hotStartAddress - baseAddr;
+ if (!m_EmitRVAs)
+ {
+ addr = pLoadedLayout->RvaToOffset(addr);
+ }
+ LogMethod(pMethod, addr, methodRegionInfo.hotSize, optimizationTier);
}
if (methodRegionInfo.coldSize > 0)
{
- LogMethod(pMethod, pLoadedLayout->RvaToOffset((PCODE)methodRegionInfo.coldStartAddress - baseAddr), methodRegionInfo.coldSize, optimizationTier);
+ addr = (PCODE)methodRegionInfo.coldStartAddress - baseAddr;
+ if (!m_EmitRVAs)
+ {
+ addr = pLoadedLayout->RvaToOffset(addr);
+ }
+ LogMethod(pMethod, addr, methodRegionInfo.coldSize, optimizationTier);
}
}
class NativeImagePerfMap : PerfMap
{
private:
+ const WCHAR *strOFFSET = W("OFFSET");
+
+ // Specify the address format since it's now possible for 'perf script' to output file offsets or RVAs.
+ bool m_EmitRVAs;
+
// Log a pre-compiled method to the map.
- void LogPreCompiledMethod(MethodDesc * pMethod, PCODE pCode, PEImageLayout * pLoadedLayout, const char *optimizationTier);
+ void LogPreCompiledMethod(MethodDesc * pMethod, PCODE pCode, PEImageLayout *pLoadedLayout, const char *optimizationTier);
public:
// Construct a new map for a native image.