| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| |
| |
| #ifndef IMPALA_CODEGEN_JIT_SYMBOL_EMITTER_H |
| #define IMPALA_CODEGEN_JIT_SYMBOL_EMITTER_H |
| |
| #include <boost/thread/locks.hpp> |
| #include <boost/unordered_map.hpp> |
| #include <iosfwd> |
| #include <llvm/ExecutionEngine/JITEventListener.h> |
| |
| #include "util/spinlock.h" |
| |
| namespace llvm { |
| class DIContext; |
| namespace object { |
| class SymbolRef; |
| } |
| } |
| |
| namespace impala { |
| |
| /// Class to emit debug symbols and associated info from jitted object files. |
| /// The methods of this listener are called whenever the query fragment emits |
| /// a compiled machine code object. We can then process any debug symbols |
| /// associated with the code object and emit useful information such as disassembly |
| /// and symbols for perf profiling. |
| class CodegenSymbolEmitter : public llvm::JITEventListener { |
| public: |
| CodegenSymbolEmitter(std::string id) : id_(id), emit_perf_map_(false) { } |
| |
| ~CodegenSymbolEmitter() { } |
| |
| /// Write the current contents of 'perf_map_' to /tmp/perf-<pid>.map |
| /// Atomically updates the current map by writing to a temporary file then moving it. |
| static void WritePerfMap(); |
| |
| /// Called whenever MCJIT module code is emitted. |
| void NotifyObjectEmitted(const llvm::object::ObjectFile &obj, |
| const llvm::RuntimeDyld::LoadedObjectInfo &loaded_obj) override; |
| |
| /// Called whenever MCJIT module code is freed. |
| void NotifyFreeingObject(const llvm::object::ObjectFile &obj) override; |
| |
| void set_emit_perf_map(bool emit_perf_map) { emit_perf_map_ = emit_perf_map; } |
| |
| void set_asm_path(const std::string& asm_path) { asm_path_ = asm_path; } |
| |
| private: |
| struct PerfMapEntry { |
| std::string symbol; |
| uint64_t addr; |
| uint64_t size; |
| }; |
| |
| /// Process the given 'symbol' with 'size'. For function symbols, append to |
| /// 'perf_map_entries' if 'emit_perf_map_' is true and write disassembly to 'asm_file' |
| /// if it is open. |
| void ProcessSymbol(llvm::DIContext* debug_ctx, const llvm::object::SymbolRef& symbol, |
| uint64_t size, std::vector<PerfMapEntry>* perf_map_entries, |
| std::ofstream& asm_file); |
| |
| /// Implementation of WritePerfMap(). 'perf_map_lock_' must be held by caller. |
| static void WritePerfMapLocked(); |
| |
| /// Emit disassembly for the function. If symbols are present for the code object, |
| /// the symbols will be interleaved with the disassembly. |
| void EmitFunctionAsm(llvm::DIContext* debug_ctx, const std::string& fn_symbol, |
| uint64_t addr, uint64_t size, std::ofstream& asm_file); |
| |
| /// Identifier to append to symbols, e.g. a fragment instance id. The identifier is |
| /// passed by the caller when the CodegenSymbolEmitter is constructed. Without this |
| /// identifier, many distinct codegen'd functions will have the same symbol. |
| std::string id_; |
| |
| /// If true, emit perf map info to /tmp/perf-<pid>.map. |
| bool emit_perf_map_; |
| |
| /// File to emit disassembly to. If empty string, don't emit. |
| std::string asm_path_; |
| |
| /// Global lock to protect 'perf_map_' and writes to /tmp/perf-<pid>.map. |
| static SpinLock perf_map_lock_; |
| |
| /// All current entries that should be emitted into the perf map file. |
| /// Maps the address of each ObjectFile's data to the symbols in the object. |
| static boost::unordered_map<const void*, std::vector<PerfMapEntry>> perf_map_; |
| }; |
| |
| } |
| |
| #endif |