| 67 | } |
| 68 | |
| 69 | void CodegenSymbolEmitter::NotifyObjectEmitted(const llvm::object::ObjectFile& obj, |
| 70 | const llvm::RuntimeDyld::LoadedObjectInfo& loaded_obj) { |
| 71 | non_freed_objects_++; |
| 72 | vector<PerfMapEntry> perf_map_entries; |
| 73 | |
| 74 | ofstream asm_file; |
| 75 | if (!asm_path_.empty()) { |
| 76 | asm_file.open(asm_path_, fstream::out | fstream::trunc); |
| 77 | if (asm_file.fail()) { |
| 78 | // Log error and continue if we can't write the disassembly to a file. Note that |
| 79 | // fstream operations don't throw exceptions by default unless configured to do so. |
| 80 | LOG(ERROR) << "Could not save disassembly to: " << asm_path_; |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | llvm::object::OwningBinary<llvm::object::ObjectFile> debug_obj_owner = |
| 85 | loaded_obj.getObjectForDebug(obj); |
| 86 | const llvm::object::ObjectFile& debug_obj = *debug_obj_owner.getBinary(); |
| 87 | llvm::DWARFContextInMemory dwarf_ctx(debug_obj); |
| 88 | |
| 89 | // Use symbol info to iterate functions in the object. |
| 90 | for (const std::pair<llvm::object::SymbolRef, uint64_t>& pair : |
| 91 | computeSymbolSizes(debug_obj)) { |
| 92 | ProcessSymbol(&dwarf_ctx, pair.first, pair.second, &perf_map_entries, asm_file); |
| 93 | } |
| 94 | |
| 95 | if (asm_file.is_open()) { |
| 96 | asm_file.close(); |
| 97 | LOG(INFO) << "Saved disassembly to " << asm_path_; |
| 98 | } |
| 99 | |
| 100 | ofstream perf_map_file; |
| 101 | if (emit_perf_map_) { |
| 102 | lock_guard<SpinLock> perf_map_lock(perf_map_lock_); |
| 103 | DCHECK(perf_map_.find(obj.getData().data()) == perf_map_.end()); |
| 104 | perf_map_[obj.getData().data()] = std::move(perf_map_entries); |
| 105 | WritePerfMapLocked(); |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | void CodegenSymbolEmitter::NotifyFreeingObject(const llvm::object::ObjectFile& obj) { |
| 110 | non_freed_objects_--; |