@@ -7109,20 +7109,30 @@ internal TraceModuleFile UniversalMapping(ProcessMappingTraceData data, ProcessM
71097109 int index;
71107110
71117111 // A loaded and managed modules depend on a module file, so get or create one.
7112+ // The key is the file name. For jitted code on Linux, this will be a memfd with a static name, which is OK
7113+ // because this path will use the StartAddress to ensure that we get the right one.
71127114 // TODO: We'll need to store FileOffset as well to handle elf images.
71137115 TraceModuleFile moduleFile = process.Log.ModuleFiles.GetOrCreateModuleFile(data.FileName, data.StartAddress);
7114- moduleFile.imageSize = (long)(data.EndAddress - data.StartAddress);
7116+ long newImageSize = (long)(data.EndAddress - data.StartAddress);
7117+
7118+ // New mappings will have an imageSize of 0 and will get set.
7119+ // Existing mappings that have the same StartAddress but increase in length will get updated here.
7120+ if (moduleFile.imageSize < newImageSize)
7121+ {
7122+ moduleFile.imageSize = newImageSize;
7123+ }
71157124
7116- // Get or create the loaded module.
7125+ // The loaded module is looked up by StartAddress and time to ensure that we don't use a module that hasn't been loaded yet.
7126+ // If the StartAddress or size don't match, then create a new one. This handles overlapping cases.
71177127 TraceLoadedModule loadedModule = FindModuleAndIndexContainingAddress(data.StartAddress, data.TimeStampQPC, out index);
7118- if (loadedModule == null)
7119- {
7128+ if (loadedModule == null || loadedModule.ImageBase != data.StartAddress || loadedModule.ModuleFile.imageSize != newImageSize )
7129+ {
71207130 // The module file is what is used when looking up the module for an arbitrary address, so it must save both the start address and image size.
71217131 loadedModule = new TraceLoadedModule(process, moduleFile, data.StartAddress);
7122-
7123- // All mappings are enumerated at the beginning of the trace.
7124- loadedModule.loadTimeQPC = process.Log.sessionStartTimeQPC ;
7125-
7132+
7133+ // Set the timestamp from the mapping data
7134+ loadedModule.loadTimeQPC = data.TimeStampQPC ;
7135+
71267136 InsertAndSetOverlap(index + 1, loadedModule);
71277137 }
71287138
@@ -7131,6 +7141,7 @@ internal TraceModuleFile UniversalMapping(ProcessMappingTraceData data, ProcessM
71317141 if (managedModule == null)
71327142 {
71337143 managedModule = new TraceManagedModule(process, moduleFile, (long)data.StartAddress);
7144+ managedModule.loadTimeQPC = data.TimeStampQPC;
71347145 modules.Insert(index + 1, managedModule);
71357146 }
71367147
@@ -8525,15 +8536,26 @@ internal void AddUniversalDynamicSymbol(ProcessSymbolTraceData data, TraceProces
85258536 {
85268537 int index;
85278538 TraceLoadedModule loadedModule = process.LoadedModules.FindModuleAndIndexContainingAddress(data.StartAddress, data.TimeStampQPC, out index);
8528- module = process.LoadedModules.GetOrCreateManagedModule(loadedModule.ModuleID, data.TimeStampQPC);
8529- moduleFileIndex = module.ModuleFile.ModuleFileIndex;
8530- methodIndex = methods.NewMethod(data.Name, moduleFileIndex, (int)data.Id);
8539+
8540+ // We should always get a loadedModule here because if we have a symbol, then we should have a module that contains it.
8541+ // Assert so that we can detect bugs here during development.
8542+ Debug.Assert(loadedModule != null, "loadedModule is missing for symbol");
8543+
8544+ if (loadedModule != null)
8545+ {
8546+ module = process.LoadedModules.GetOrCreateManagedModule(loadedModule.ModuleID, data.TimeStampQPC);
8547+ moduleFileIndex = module.ModuleFile.ModuleFileIndex;
8548+ methodIndex = methods.NewMethod(data.Name, moduleFileIndex, (int)data.Id);
8549+ }
85318550
85328551 // When universal traces support re-use of address space, we'll need to support it here.
85338552 }
85348553
8535- // Set the info
8536- info.SetMethodIndex(this, methodIndex);
8554+ // Set the info (only if we found a module)
8555+ if (module != null)
8556+ {
8557+ info.SetMethodIndex(this, methodIndex);
8558+ }
85378559 }
85388560 });
85398561 }
0 commit comments