AllocationData::DisplayId AllocationData::display = AllocationData::DisplayId::malloc;
bool AccumulatedTraceData::isHideUnmanagedStackParts = false;
+bool AccumulatedTraceData::isShowCoreCLRPartOption = false;
namespace {
TraceNode node;
reader >> node.ipIndex;
reader >> node.parentIndex;
+
+ AllocationData::CoreCLRType coreclrType;
+ if (isShowCoreCLRPartOption)
+ {
+ coreclrType = checkIsNodeCoreCLR(node.ipIndex);
+ }
+
// skip operator new and operator new[] at the beginning of traces
while (find(opNewIpIndices.begin(), opNewIpIndices.end(), node.ipIndex) != opNewIpIndices.end()) {
node = findTrace(node.parentIndex);
}
}
+ if (isShowCoreCLRPartOption)
+ {
+ coreclrType = combineTwoTypes(checkIsNodeCoreCLR(node.ipIndex), coreclrType);
+ if (coreclrType != AllocationData::CoreCLRType::CoreCLR)
+ {
+ coreclrType = combineTwoTypes(checkCallStackIsCoreCLR(node.parentIndex), coreclrType);
+ }
+ node.coreclrType = coreclrType;
+ }
+
traces.push_back(node);
} else if (reader.mode() == 'i') {
if (pass != FirstPass) {
}
} else if (reader.mode() == '*') {
uint64_t length, ptr;
- int prot, fd;
+ int prot, fd, isCoreclr;
TraceIndex traceIndex;
- if (AllocationData::display == AllocationData::DisplayId::malloc
- || AllocationData::display == AllocationData::DisplayId::managed) {
- // we don't need the mmap/munmap details information for malloc/managed statistics
- continue;
- }
-
if (!(reader >> length)
|| !(reader >> prot)
+ || !(reader >> isCoreclr)
|| !(reader >> fd)
|| !(reader >> traceIndex.index)
|| !(reader >> ptr)) {
rangeInfo.setProt(prot);
rangeInfo.setFd(fd);
+ rangeInfo.setIsCoreCLR(isCoreclr);
rangeInfo.setTraceIndex(traceIndex.index);
combineContiguousSimilarRanges();
} else if (reader.mode() == '/') {
uint64_t length, ptr;
- if (AllocationData::display == AllocationData::DisplayId::malloc
- || AllocationData::display == AllocationData::DisplayId::managed) {
- // we don't need the mmap/munmap details information for malloc/managed statistics
- continue;
- }
-
if (!(reader >> length)
|| !(reader >> ptr)) {
cerr << "failed to parse line: " << reader.line() << endl;
if(!addressRangeInfo.isPhysicalMemoryConsumptionSet) {
cerr << "Unknown range: 0x" << std::hex << addressRangeInfo.start << " (0x" << addressRangeInfo.size << " bytes)" << std::dec << endl;
+ continue;
}
totalCost.privateClean.allocated += addressRangeInfo.getPrivateClean();
allocation.shared.allocated += addressRangeInfo.getShared();
}
}
+
+ if (isShowCoreCLRPartOption)
+ {
+ if (pass == SecondPass && totalCost.privateClean.peak == lastPrivateCleanPeakCost && timeStamp == lastPrivateCleanPeakTime
+ && AllocationData::display == AllocationData::DisplayId::privateClean)
+ {
+ partCoreclrMMAP.peak = 0;
+ partNonCoreclrMMAP.peak = 0;
+ partUnknownMMAP.peak = 0;
+ partUntrackedMMAP.peak = 0;
+
+ calculatePeak(AllocationData::DisplayId::privateClean);
+ }
+
+ if (pass == SecondPass && totalCost.privateDirty.peak == lastPrivateDirtyPeakCost && timeStamp == lastPrivateDirtyPeakTime
+ && AllocationData::display == AllocationData::DisplayId::privateDirty)
+ {
+ partCoreclrMMAP.peak = 0;
+ partNonCoreclrMMAP.peak = 0;
+ partUnknownMMAP.peak = 0;
+ partUntrackedMMAP.peak = 0;
+
+ calculatePeak(AllocationData::DisplayId::privateDirty);
+ }
+
+ if (pass == SecondPass && totalCost.shared.peak == lastSharedPeakCost && timeStamp == lastSharedPeakTime
+ && AllocationData::display == AllocationData::DisplayId::shared)
+ {
+ partCoreclrMMAP.peak = 0;
+ partNonCoreclrMMAP.peak = 0;
+ partUnknownMMAP.peak = 0;
+ partUntrackedMMAP.peak = 0;
+
+ calculatePeak(AllocationData::DisplayId::shared);
+ }
+ }
}
handleTotalCostUpdate();
continue;
}
- if (AllocationData::display == AllocationData::DisplayId::malloc
- || AllocationData::display == AllocationData::DisplayId::managed) {
- // we don't need the physical memory consumption details information for malloc/managed statistics
- continue;
- }
-
uint64_t addr, diff, size, privateDirty, privateClean, sharedDirty, sharedClean;
int prot;
handleTimeStamp(timeStamp, totalTime);
}
+ if (isShowCoreCLRPartOption)
+ {
+ AllocationData::Stats totalCoreclr;
+ AllocationData::Stats totalNonCoreclr;
+ AllocationData::Stats totalUnknown;
+ AllocationData::Stats totalUntracked;
+
+ if (AllocationData::display == AllocationData::DisplayId::malloc)
+ {
+ for (auto it = allocations.begin(); it != allocations.end(); ++it)
+ {
+ if (!isValidTrace(it->traceIndex))
+ {
+ totalUnknown += *(it->getDisplay ());
+ continue;
+ }
+
+ AllocationData::CoreCLRType isCoreclr = findTrace(it->traceIndex).coreclrType;
+
+ if (isCoreclr == AllocationData::CoreCLRType::CoreCLR)
+ {
+ totalCoreclr += *(it->getDisplay ());
+ }
+ else if (isCoreclr == AllocationData::CoreCLRType::nonCoreCLR)
+ {
+ totalNonCoreclr += *(it->getDisplay ());
+ }
+ else if (isCoreclr == AllocationData::CoreCLRType::untracked)
+ {
+ totalUntracked += *(it->getDisplay ());
+ }
+ else if (isCoreclr == AllocationData::CoreCLRType::unknown)
+ {
+ totalUnknown += *(it->getDisplay ());
+ }
+ }
+
+ partCoreclr = totalCoreclr;
+ partNonCoreclr = totalNonCoreclr;
+ partUnknown = totalUnknown;
+ partUntracked = totalUntracked;
+ }
+ else if (AllocationData::display == AllocationData::DisplayId::privateDirty
+ || AllocationData::display == AllocationData::DisplayId::privateClean
+ || AllocationData::display == AllocationData::DisplayId::shared)
+ {
+ for (auto it = addressRangeInfos.begin(); it != addressRangeInfos.end(); ++it)
+ {
+ int64_t val = AllocationData::display == AllocationData::DisplayId::privateDirty
+ ? it->second.getPrivateDirty()
+ : AllocationData::display == AllocationData::DisplayId::privateClean
+ ? it->second.getPrivateClean()
+ : AllocationData::display == AllocationData::DisplayId::shared
+ ? it->second.getShared()
+ : 0;
+
+ if (!isValidTrace(it->second.traceIndex))
+ {
+ totalUnknown.leaked += val;
+ continue;
+ }
+
+ AllocationData::CoreCLRType coreclrType = AllocationData::CoreCLRType::unknown;
+ if (it->second.isCoreCLR == 0)
+ {
+ coreclrType = AllocationData::CoreCLRType::nonCoreCLR;
+ }
+ else if (it->second.isCoreCLR == 1)
+ {
+ coreclrType = AllocationData::CoreCLRType::CoreCLR;
+ }
+ else if (it->second.isCoreCLR == 2)
+ {
+ coreclrType = AllocationData::CoreCLRType::untracked;
+ }
+ assert(coreclrType != AllocationData::CoreCLRType::unknown);
+
+ AllocationData::CoreCLRType isCoreclr = combineTwoTypes(findTrace(it->second.traceIndex).coreclrType, coreclrType);
+
+ if (isCoreclr == AllocationData::CoreCLRType::CoreCLR)
+ {
+ totalCoreclr.leaked += val;
+ }
+ else if (isCoreclr == AllocationData::CoreCLRType::nonCoreCLR)
+ {
+ totalNonCoreclr.leaked += val;
+ }
+ else if (isCoreclr == AllocationData::CoreCLRType::untracked)
+ {
+ totalUntracked.leaked += val;
+ }
+ else if (isCoreclr == AllocationData::CoreCLRType::unknown)
+ {
+ totalUnknown.leaked += val;
+ }
+ }
+
+ partCoreclrMMAP.leaked = totalCoreclr.leaked;
+ partNonCoreclrMMAP.leaked = totalNonCoreclr.leaked;
+ partUnknownMMAP.leaked = totalUnknown.leaked;
+ partUntrackedMMAP.leaked = totalUntracked.leaked;
+ }
+ }
+
return true;
}
+void
+AccumulatedTraceData::calculatePeak(AllocationData::DisplayId type)
+{
+ for (auto i = addressRangeInfos.begin (); i != addressRangeInfos.end(); ++i)
+ {
+ const AddressRangeInfo& addressRangeInfo = i->second;
+
+ int64_t peak = 0;
+ switch (type)
+ {
+ case AllocationData::DisplayId::privateDirty:
+ {
+ peak = addressRangeInfo.getPrivateDirty();
+ break;
+ }
+ case AllocationData::DisplayId::privateClean:
+ {
+ peak = addressRangeInfo.getPrivateClean();
+ break;
+ }
+ case AllocationData::DisplayId::shared:
+ {
+ peak = addressRangeInfo.getShared();
+ break;
+ }
+ default:
+ {
+ assert(0);
+ }
+ }
+
+ if(!addressRangeInfo.isPhysicalMemoryConsumptionSet) {
+ continue;
+ }
+
+ if (!isValidTrace(addressRangeInfo.traceIndex))
+ {
+ partUnknownMMAP.peak += peak;
+ continue;
+ }
+
+ AllocationData::CoreCLRType coreclrType = AllocationData::CoreCLRType::unknown;
+ if (addressRangeInfo.isCoreCLR == 0)
+ {
+ coreclrType = AllocationData::CoreCLRType::nonCoreCLR;
+ }
+ else if (addressRangeInfo.isCoreCLR == 1)
+ {
+ coreclrType = AllocationData::CoreCLRType::CoreCLR;
+ }
+ else if (addressRangeInfo.isCoreCLR == 2)
+ {
+ coreclrType = AllocationData::CoreCLRType::untracked;
+ }
+
+ AllocationData::CoreCLRType isCoreclr = combineTwoTypes(findTrace(addressRangeInfo.traceIndex).coreclrType, coreclrType);
+
+ if (isCoreclr == AllocationData::CoreCLRType::CoreCLR)
+ {
+ partCoreclrMMAP.peak += peak;
+ }
+ else if (isCoreclr == AllocationData::CoreCLRType::nonCoreCLR)
+ {
+ partNonCoreclrMMAP.peak += peak;
+ }
+ else if (isCoreclr == AllocationData::CoreCLRType::untracked)
+ {
+ partUntrackedMMAP.peak += peak;
+ }
+ else if (isCoreclr == AllocationData::CoreCLRType::unknown)
+ {
+ partUnknownMMAP.peak += peak;
+ }
+ }
+}
+
+AllocationData::CoreCLRType
+AccumulatedTraceData::checkIsNodeCoreCLR(IpIndex ipindex)
+{
+ InstructionPointer ip = findIp(ipindex);
+ AllocationData::CoreCLRType coreclrType = AllocationData::CoreCLRType::unknown;
+
+ for (auto iter = addressRangeInfos.begin(); iter != addressRangeInfos.end(); ++iter)
+ {
+ if (iter->second.start <= ip.instructionPointer && iter->second.start + iter->second.size > ip.instructionPointer)
+ {
+ if (iter->second.isCoreCLR == 0)
+ {
+ coreclrType = AllocationData::CoreCLRType::nonCoreCLR;
+ }
+ else if (iter->second.isCoreCLR == 1)
+ {
+ coreclrType = AllocationData::CoreCLRType::CoreCLR;
+ }
+ else if (iter->second.isCoreCLR == 2)
+ {
+ coreclrType = AllocationData::CoreCLRType::untracked;
+ }
+ break;
+ }
+ }
+ if (coreclrType == AllocationData::CoreCLRType::unknown)
+ {
+ // warning here, address is not found in ranges
+ }
+
+ return coreclrType;
+}
+
+AllocationData::CoreCLRType
+AccumulatedTraceData::combineTwoTypes(AllocationData::CoreCLRType a, AllocationData::CoreCLRType b)
+{
+ if (a == AllocationData::CoreCLRType::CoreCLR
+ || b == AllocationData::CoreCLRType::CoreCLR)
+ {
+ return AllocationData::CoreCLRType::CoreCLR;
+ }
+
+ if (a == AllocationData::CoreCLRType::untracked
+ || b == AllocationData::CoreCLRType::untracked)
+ {
+ return AllocationData::CoreCLRType::untracked;
+ }
+
+ if (a == AllocationData::CoreCLRType::nonCoreCLR
+ || b == AllocationData::CoreCLRType::nonCoreCLR)
+ {
+ return AllocationData::CoreCLRType::nonCoreCLR;
+ }
+
+ return AllocationData::CoreCLRType::unknown;
+}
+
+AllocationData::CoreCLRType
+AccumulatedTraceData::checkCallStackIsCoreCLR(TraceIndex index)
+{
+ AllocationData::CoreCLRType isCoreclr = AllocationData::CoreCLRType::unknown;
+
+ while (isValidTrace(index))
+ {
+ TraceNode node = findTrace(index);
+ index = node.parentIndex;
+
+ if (node.coreclrType == AllocationData::CoreCLRType::CoreCLR)
+ {
+ return node.coreclrType;
+ }
+
+ isCoreclr = combineTwoTypes(isCoreclr, node.coreclrType);
+ }
+
+ return isCoreclr;
+}
+
namespace { // helpers for diffing
template <typename IndexT, typename SortF>
}
}
+bool AccumulatedTraceData::isValidTrace(const TraceIndex traceIndex) const
+{
+ return !(!traceIndex || traceIndex.index > traces.size());
+}
+
TraceNode AccumulatedTraceData::findPrevTrace(const TraceIndex traceIndex) const
{
TraceNode trace = findTrace(traceIndex);
{
IpIndex ipIndex;
TraceIndex parentIndex;
+ AllocationData::CoreCLRType coreclrType;
};
struct Allocation : public AllocationData
struct AddressRangeInfo
{
AddressRangeInfo(uint64_t vStart, uint64_t vSize)
- : start(vStart), size(vSize), isProtSet(false), isPhysicalMemoryConsumptionSet(false), isFdSet(false)
+ : start(vStart), size(vSize), isProtSet(false), isPhysicalMemoryConsumptionSet(false), isFdSet(false), isCoreCLRSet (false)
{
assert(!traceIndex);
}
mutable int prot;
mutable int fd;
+ mutable int isCoreCLR;
mutable bool isProtSet;
mutable bool isPhysicalMemoryConsumptionSet;
mutable bool isFdSet;
+ mutable bool isCoreCLRSet;
uint64_t getPrivateClean() const
{
isFdSet = true;
}
+ void setIsCoreCLR(int flag)
+ {
+ isCoreCLR = flag;
+ isCoreCLRSet = true;
+ }
+
void setPhysicalMemoryConsumption(uint64_t smapsRangeSize,
uint64_t vPrivateDirty,
uint64_t vPrivateClean,
void mapRemoveRanges(const uint64_t start, const uint64_t size);
void combineContiguousSimilarRanges();
+ AllocationData::CoreCLRType checkCallStackIsCoreCLR(TraceIndex traceIndex);
+ bool isValidTrace(const TraceIndex traceIndex) const;
+ AllocationData::CoreCLRType checkIsNodeCoreCLR(IpIndex ipindex);
+ AllocationData::CoreCLRType combineTwoTypes(AllocationData::CoreCLRType a, AllocationData::CoreCLRType b);
+ void calculatePeak(AllocationData::DisplayId type);
+
// indices of functions that should stop the backtrace, e.g. main or static
// initialization
std::vector<StringIndex> stopIndices;
AddressRangesMap addressRangeInfos;
static bool isHideUnmanagedStackParts;
+ static bool isShowCoreCLRPartOption;
+
+ AllocationData::Stats partCoreclr;
+ AllocationData::Stats partNonCoreclr;
+ AllocationData::Stats partUnknown;
+ AllocationData::Stats partUntracked;
+
+ AllocationData::Stats partCoreclrMMAP;
+ AllocationData::Stats partNonCoreclrMMAP;
+ AllocationData::Stats partUnknownMMAP;
+ AllocationData::Stats partUntrackedMMAP;
};
#endif // ACCUMULATEDTRACEDATA_H
shared
};
+ enum class CoreCLRType
+ {
+ unknown,
+ CoreCLR,
+ nonCoreCLR,
+ untracked
+ };
+
AllocationData()
: malloc(),
managed(),
QCommandLineOption hideUnmanagedStackPartsOption(QStringLiteral("hide-unmanaged-stacks"), QStringLiteral("Hide unmanaged parts of call stacks"));
parser.addOption(hideUnmanagedStackPartsOption);
+ QCommandLineOption showCoreCLRPartOption(QStringLiteral("show-coreclr"), QStringLiteral("Show CoreCLR/non-CoreCLR memory distribution"));
+ parser.addOption(showCoreCLRPartOption);
+
parser.process(app);
aboutData.processCommandLine(&parser);
bool isShowPrivateClean = parser.isSet(showPrivateCleanOption);
bool isShowShared = parser.isSet(showSharedOption);
bool isHideUnmanagedStackParts = parser.isSet(hideUnmanagedStackPartsOption);
+ bool isShowCoreCLRPartOption = parser.isSet(showCoreCLRPartOption);
if ((isShowMalloc ? 1 : 0)
+ (isShowManaged ? 1 : 0)
AccumulatedTraceData::isHideUnmanagedStackParts = true;
}
+ if (isShowCoreCLRPartOption) {
+ AccumulatedTraceData::isShowCoreCLRPartOption = true;
+ }
+
auto createWindow = []() -> MainWindow* {
auto window = new MainWindow;
window->setAttribute(Qt::WA_DeleteOnClose);
format.formatByteSize(data.cost.allocated / totalTimeS, 1, KFormat::MetricBinaryDialect))
<< "</dl></qt>";
}
+ if (AccumulatedTraceData::isShowCoreCLRPartOption)
+ {
+ QTextStream stream(&textRight);
+
+ if (AllocationData::display == AllocationData::DisplayId::malloc)
+ {
+ stream << "<qt><dl>" << i18n("<dt><b>peak heap memory consumption</b>:</dt><dd>%1 "
+ "after %2s</dd>"
+ "</dt><dd>%3 (CoreCLR), %4 (non-CoreCLR), %5 (unknown)</dd>",
+ format.formatByteSize(data.cost.peak, 1, KFormat::JEDECBinaryDialect),
+ peakTimeS,
+ format.formatByteSize(data.CoreCLRPart.peak, 1, KFormat::JEDECBinaryDialect),
+ format.formatByteSize(data.nonCoreCLRPart.peak, 1, KFormat::JEDECBinaryDialect),
+ format.formatByteSize(data.unknownPart.peak, 1, KFormat::JEDECBinaryDialect))
+ << i18n("<dt><b>peak RSS</b> (including heaptrack "
+ "overhead):</dt><dd>%1</dd>",
+ format.formatByteSize(data.peakRSS, 1, KFormat::JEDECBinaryDialect))
+ << i18n("<dt><b>total memory leaked</b>:</dt><dd>%1</dd>"
+ "</dt><dd>%2 (CoreCLR), %3 (non-CoreCLR), %4 (unknown)</dd>",
+ format.formatByteSize(data.cost.leaked, 1, KFormat::JEDECBinaryDialect),
+ format.formatByteSize(data.CoreCLRPart.leaked, 1, KFormat::JEDECBinaryDialect),
+ format.formatByteSize(data.nonCoreCLRPart.leaked, 1, KFormat::JEDECBinaryDialect),
+ format.formatByteSize(data.unknownPart.leaked, 1, KFormat::JEDECBinaryDialect))
+ << "</dl></qt>";
+ }
+ else
+ {
+ stream << "<qt><dl>" << i18n("<dt><b>peak heap memory consumption</b>:</dt><dd>%1 "
+ "after %2s</dd>"
+ "</dt><dd>%3 (CoreCLR), %4 (non-CoreCLR), %5 (sbrk heap), %6 (unknown)</dd>",
+ format.formatByteSize(data.cost.peak, 1, KFormat::JEDECBinaryDialect),
+ peakTimeS,
+ format.formatByteSize(data.CoreCLRPart.peak, 1, KFormat::JEDECBinaryDialect),
+ format.formatByteSize(data.nonCoreCLRPart.peak, 1, KFormat::JEDECBinaryDialect),
+ format.formatByteSize(data.untrackedPart.peak, 1, KFormat::JEDECBinaryDialect),
+ format.formatByteSize(data.unknownPart.peak, 1, KFormat::JEDECBinaryDialect))
+ << i18n("<dt><b>peak RSS</b> (including heaptrack "
+ "overhead):</dt><dd>%1</dd>",
+ format.formatByteSize(data.peakRSS, 1, KFormat::JEDECBinaryDialect))
+ << i18n("<dt><b>total memory leaked</b>:</dt><dd>%1</dd>"
+ "</dt><dd>%2 (CoreCLR), %3 (non-CoreCLR), %4 (sbrk heap), %5 (unknown)</dd>",
+ format.formatByteSize(data.cost.leaked, 1, KFormat::JEDECBinaryDialect),
+ format.formatByteSize(data.CoreCLRPart.leaked, 1, KFormat::JEDECBinaryDialect),
+ format.formatByteSize(data.nonCoreCLRPart.leaked, 1, KFormat::JEDECBinaryDialect),
+ format.formatByteSize(data.untrackedPart.leaked, 1, KFormat::JEDECBinaryDialect),
+ format.formatByteSize(data.unknownPart.leaked, 1, KFormat::JEDECBinaryDialect))
+ << "</dl></qt>";
+ }
+ }
+ else
{
QTextStream stream(&textRight);
stream << "<qt><dl>" << i18n("<dt><b>peak heap memory consumption</b>:</dt><dd>%1 "
data->updateStringCache();
+ AllocationData::Stats *partCoreclr;
+ AllocationData::Stats *partNonCoreclr;
+ AllocationData::Stats *partUntracked;
+ AllocationData::Stats *partUnknown;
+
+ if (AllocationData::display == AllocationData::DisplayId::malloc)
+ {
+ partCoreclr = &data->partCoreclr;
+ partNonCoreclr = &data->partNonCoreclr;
+ partUntracked = &data->partUntracked;
+ partUnknown = &data->partUnknown;
+ }
+ else
+ {
+ partCoreclr = &data->partCoreclrMMAP;
+ partNonCoreclr = &data->partNonCoreclrMMAP;
+ partUntracked = &data->partUntrackedMMAP;
+ partUnknown = &data->partUnknownMMAP;
+ }
+
emit summaryAvailable({QString::fromStdString(data->debuggee), *data->totalCost.getDisplay(), data->totalTime, data->getPeakTime(),
data->peakRSS * 1024,
- data->systemInfo.pages * data->systemInfo.pageSize, data->fromAttached});
+ data->systemInfo.pages * data->systemInfo.pageSize, data->fromAttached,
+ *partCoreclr, *partNonCoreclr, *partUntracked, *partUnknown});
emit progressMessageAvailable(i18n("merging allocations..."));
// merge allocations before modifying the data again
int64_t peakRSS;
int64_t totalSystemMemory;
bool fromAttached;
+
+ AllocationData::Stats CoreCLRPart;
+ AllocationData::Stats nonCoreCLRPart;
+ AllocationData::Stats untrackedPart;
+ AllocationData::Stats unknownPart;
};
Q_DECLARE_METATYPE(SummaryData)
__attribute__((weak)) extern void __freeres();
}
+static int isCoreCLR(const char *filename)
+{
+ const char *localFilename = strrchr(filename,'/');
+ if (!localFilename)
+ {
+ localFilename = filename;
+ }
+ else
+ {
+ ++localFilename;
+ }
+
+ if (strcmp(localFilename, "libclrjit.so") == 0
+ || strcmp(localFilename, "libcoreclr.so") == 0
+ || strcmp(localFilename, "libcoreclrtraceptprovider.so") == 0
+ || strcmp(localFilename, "libdbgshim.so") == 0
+ || strcmp(localFilename, "libmscordaccore.so") == 0
+ || strcmp(localFilename, "libmscordbi.so") == 0
+ || strcmp(localFilename, "libprotojit.so") == 0
+ || strcmp(localFilename, "libsosplugin.so") == 0
+ || strcmp(localFilename, "libsos.so") == 0
+ || strcmp(localFilename, "libsuperpmi-shim-collector.so") == 0
+ || strcmp(localFilename, "libsuperpmi-shim-counter.so") == 0
+ || strcmp(localFilename, "libsuperpmi-shim-simple.so") == 0
+ || strcmp(localFilename, "System.Globalization.Native.so") == 0
+ || strcmp(localFilename, "System.IO.Compression.Native.so") == 0
+ || strcmp(localFilename, "System.Native.so") == 0
+ || strcmp(localFilename, "System.Net.Http.Native.so") == 0
+ || strcmp(localFilename, "System.Net.Security.Native.so") == 0
+ || strcmp(localFilename, "System.Security.Cryptography.Native.OpenSsl.so") == 0
+ || strcmp(localFilename, "System.Security.Cryptography.Native.so") == 0)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
static bool isExiting = false;
static int dl_iterate_phdr_get_maps(struct dl_phdr_info* info, size_t /*size*/, void* data)
{
- auto maps = (map<void *, pair<size_t, int>> *) data;
+ auto maps = (map<void *, tuple<size_t, int, int>> *) data;
const char* fileName = info->dlpi_name;
if (!fileName || !fileName[0]) {
fileName = "x";
}
+ int isCoreclr = isCoreCLR(fileName);
+
debugLog<VerboseOutput>("dl_iterate_phdr_get_maps: %s %zx", fileName, info->dlpi_addr);
for (int i = 0; i < info->dlpi_phnum; i++) {
prot |= PROT_EXEC;
if (maps->find(addr) == maps->end()) {
- maps->insert(make_pair(addr, make_pair(size, prot)));
+ maps->insert(make_pair(addr, make_tuple(size, prot, isCoreclr)));
} else {
debugLog<VerboseOutput>("dl_iterate_phdr_get_maps: repeated section address %s %zx", fileName, info->dlpi_addr);
}
nullptr, nullptr);
{
- map<void *, pair<size_t, int>> map;
+ map<void *, tuple<size_t, int, int>> map;
dl_iterate_phdr(&dl_iterate_phdr_get_maps, &map);
- vector<pair<void *, pair<size_t, int>>> newMmaps;
+ vector<pair<void *, tuple<size_t, int, int>>> newMmaps;
for (const auto & section : map) {
newMmaps.push_back(section);
hooks::init();
}
- map<void *, pair<size_t, int>> map_before, map_after;
+ map<void *, tuple<size_t, int, int>> map_before, map_after;
if (!RecursionGuard::isActive) {
RecursionGuard guard;
if(map_after.size() < map_before.size()) {
debugLog<VerboseOutput>("dlopen: count of sections after dlopen is less than before: %p %s %x", ret, filename, flag);
} else if (map_after.size() != map_before.size()) {
- vector<pair<void *, pair<size_t, int>>> newMmaps;
+ vector<pair<void *, tuple<size_t, int, int>>> newMmaps;
if (!RecursionGuard::isActive) {
RecursionGuard guard;
hooks::init();
}
- map<void *, pair<size_t, int>> map_before, map_after;
+ map<void *, tuple<size_t, int, int>> map_before, map_after;
if (!isExiting) {
if (!RecursionGuard::isActive) {
for (const auto & section_before : map_before) {
if (map_after.find(section_before.first) == map_after.end()) {
- munmaps.push_back(make_pair(section_before.first, section_before.second.first));
+ munmaps.push_back(make_pair(section_before.first, get<0>(section_before.second)));
}
}
}
Trace trace;
trace.fill((void *) sbrk);
- heaptrack.handleMmap((void *) begin, end - begin, PROT_READ | PROT_WRITE, -1, trace);
+ heaptrack.handleMmap((void *) begin, end - begin, PROT_READ | PROT_WRITE, 2, -1, trace);
}
isHeap = false;
void handleMmap(void* ptr,
size_t length,
int prot,
+ int isCoreclr,
int fd,
const Trace& trace)
{
size_t alignedLength = ((length + k_pageSize - 1) / k_pageSize) * k_pageSize;
- if (fprintf(s_data->out, "* %zx %x %x %x %" PRIxPTR "\n",
- alignedLength, prot, fd, index, reinterpret_cast<uintptr_t>(ptr)) < 0) {
+ if (fprintf(s_data->out, "* %zx %x %x %x %x %" PRIxPTR "\n",
+ alignedLength, prot, isCoreclr, fd, index, reinterpret_cast<uintptr_t>(ptr)) < 0) {
writeError();
return;
}
}
__attribute__((noinline))
-void heaptrack_dlopen(const vector<pair<void *, pair<size_t, int>>> &newMmaps, bool isPreloaded, void *dlopenOriginal)
+void heaptrack_dlopen(const vector<pair<void *, tuple<size_t, int, int>>> &newMmaps, bool isPreloaded, void *dlopenOriginal)
{
if (!RecursionGuard::isActive) {
RecursionGuard guard;
HeapTrack heaptrack(guard);
for (const auto &mmapRecord : newMmaps) {
- heaptrack.handleMmap(mmapRecord.first, mmapRecord.second.first, mmapRecord.second.second, -2 /* FIXME: */, trace);
+ heaptrack.handleMmap(mmapRecord.first, get<0>(mmapRecord.second), get<1>(mmapRecord.second), get<2>(mmapRecord.second), -2 /* FIXME: */, trace);
}
}
}
trace.fill(2);
HeapTrack heaptrack(guard);
- heaptrack.handleMmap(ptr, length, prot, fd, trace);
+ heaptrack.handleMmap(ptr, length, prot, 0, fd, trace);
}
}
void heaptrack_stop();
-void heaptrack_dlopen(const std::vector<std::pair<void *, std::pair<size_t, int>>> &newMmaps, bool isPreloaded, void *dlopenOriginal);
+void heaptrack_dlopen(const std::vector<std::pair<void *, std::tuple<size_t, int, int>>> &newMmaps, bool isPreloaded, void *dlopenOriginal);
void heaptrack_dlclose(const std::vector<std::pair<void *, size_t>> &unmaps);
void heaptrack_malloc(void* ptr, size_t size);