| 170 | bool CoverageCatalog::isSampling() const { return mSampler && mSampler->isRunning(); } |
| 171 | |
| 172 | bool CoverageCatalog::buildForModule(ModuleInfo mod) { |
| 173 | auto symbolProvider = ISymbolProvider::createDefault(); |
| 174 | auto exportEnumerator = IExportEnumerator::createDefault(); |
| 175 | if (!symbolProvider || !exportEnumerator) { |
| 176 | return false; |
| 177 | } |
| 178 | |
| 179 | DiscoveredModule discovered{ |
| 180 | .moduleName = mod.moduleName, |
| 181 | .modulePath = mod.modulePath, |
| 182 | .baseAddress = mod.baseAddress, |
| 183 | .imageSize = mod.imageSize, |
| 184 | .hasDebugSymbols = mod.hasPdb, |
| 185 | }; |
| 186 | symbolProvider->prepareModule(discovered); |
| 187 | mod.hasPdb = discovered.hasDebugSymbols; |
| 188 | |
| 189 | auto& moduleData = mModules.emplace_back(); |
| 190 | moduleData.info = std::move(mod); |
| 191 | |
| 192 | auto& funcs = moduleData.functions; |
| 193 | auto& lines = moduleData.lines; |
| 194 | auto& addrs = moduleData.instrumentedAddresses; |
| 195 | auto& addrLns = moduleData.addressToLines; |
| 196 | auto& addrFns = moduleData.addressToFunctions; |
| 197 | auto& exports = moduleData.exportedAddresses; |
| 198 | |
| 199 | exports = exportEnumerator->collectExportedAddresses(discovered); |
| 200 | |
| 201 | auto functionRecords = symbolProvider->enumerateFunctions(discovered); |
| 202 | auto hasLineInfo = std::ranges::any_of(functionRecords, [](SymbolRecord const& record) { |
| 203 | return record.hasLineInfo; |
| 204 | }); |
| 205 | funcs.reserve(functionRecords.size()); |
| 206 | for (auto& record : functionRecords) { |
| 207 | FunctionInfo info; |
| 208 | info.name = std::move(record.name); |
| 209 | info.demangledName = std::move(record.demangledName); |
| 210 | info.start = record.start; |
| 211 | info.end = record.end; |
| 212 | info.sourceFile = normalizeSourcePath(record.sourceFile); |
| 213 | info.startLine = record.startLine; |
| 214 | info.endLine = record.endLine; |
| 215 | info.hasLineInfo = record.hasLineInfo; |
| 216 | funcs.push_back(std::move(info)); |
| 217 | } |
| 218 | |
| 219 | std::unordered_map<LineKey, std::vector<uintptr_t>, LineKeyHash> lineAddresses; |
| 220 | auto lineRecords = symbolProvider->enumerateLines(discovered); |
| 221 | if (!lineRecords.empty()) { |
| 222 | hasLineInfo = true; |
| 223 | } |
| 224 | if (hasLineInfo) { |
| 225 | moduleData.info.hasPdb = true; |
| 226 | } |
| 227 | for (auto& record : lineRecords) { |
| 228 | if (!isTargetSourceFile(record.file)) { |
| 229 | continue; |
nothing calls this directly
no test coverage detected