CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
151 lines
4.7 KiB
C++
151 lines
4.7 KiB
C++
//===------- BacktraceTools.cpp - Backtrace symbolication tools ----------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/ExecutionEngine/Orc/BacktraceTools.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/ADT/StringMap.h"
|
|
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
|
|
#include "llvm/Support/FileSystem.h"
|
|
#include "llvm/Support/FormatVariadic.h"
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
|
|
namespace llvm::orc {
|
|
|
|
Expected<std::shared_ptr<SymbolTableDumpPlugin>>
|
|
SymbolTableDumpPlugin::Create(StringRef Path) {
|
|
std::error_code EC;
|
|
auto P = std::make_shared<SymbolTableDumpPlugin>(Path, EC);
|
|
if (EC)
|
|
return createFileError(Path, EC);
|
|
return P;
|
|
}
|
|
|
|
SymbolTableDumpPlugin::SymbolTableDumpPlugin(StringRef Path,
|
|
std::error_code &EC)
|
|
: OutputStream(Path, EC) {}
|
|
|
|
void SymbolTableDumpPlugin::modifyPassConfig(
|
|
MaterializationResponsibility &MR, jitlink::LinkGraph &G,
|
|
jitlink::PassConfiguration &Config) {
|
|
|
|
Config.PostAllocationPasses.push_back([this](jitlink::LinkGraph &G) -> Error {
|
|
std::scoped_lock<std::mutex> Lock(DumpMutex);
|
|
|
|
OutputStream << "\"" << G.getName() << "\"\n";
|
|
for (auto &Sec : G.sections()) {
|
|
// NoAlloc symbols don't exist in the executing process, so can't
|
|
// contribute to symbolication. (Note: We leave Finalize-liftime symbols
|
|
// in for now in case of crashes during finalization, but we should
|
|
// probably make this optional).
|
|
if (Sec.getMemLifetime() == MemLifetime::NoAlloc)
|
|
continue;
|
|
|
|
// Write out named symbols. Anonymous symbols are skipped, since they
|
|
// don't add any information for symbolication purposes.
|
|
for (auto *Sym : Sec.symbols()) {
|
|
if (Sym->hasName())
|
|
OutputStream << formatv("{0:x}", Sym->getAddress().getValue()) << " "
|
|
<< Sym->getName() << "\n";
|
|
}
|
|
}
|
|
|
|
OutputStream.flush();
|
|
return Error::success();
|
|
});
|
|
}
|
|
|
|
Expected<DumpedSymbolTable> DumpedSymbolTable::Create(StringRef Path) {
|
|
auto MB = MemoryBuffer::getFile(Path);
|
|
if (!MB)
|
|
return createFileError(Path, MB.getError());
|
|
|
|
return DumpedSymbolTable(std::move(*MB));
|
|
}
|
|
|
|
DumpedSymbolTable::DumpedSymbolTable(std::unique_ptr<MemoryBuffer> SymtabBuffer)
|
|
: SymtabBuffer(std::move(SymtabBuffer)) {
|
|
parseBuffer();
|
|
}
|
|
|
|
void DumpedSymbolTable::parseBuffer() {
|
|
// Read the symbol table file
|
|
SmallVector<StringRef, 0> Rows;
|
|
SymtabBuffer->getBuffer().split(Rows, '\n');
|
|
|
|
StringRef CurGraph = "<unidentified>";
|
|
for (auto Row : Rows) {
|
|
Row = Row.trim();
|
|
if (Row.empty())
|
|
continue;
|
|
|
|
// Check for graph name line (enclosed in quotes)
|
|
if (Row.starts_with("\"") && Row.ends_with("\"")) {
|
|
CurGraph = Row.trim('"');
|
|
continue;
|
|
}
|
|
|
|
// Parse "address symbol_name" lines, ignoring malformed lines.
|
|
size_t SpacePos = Row.find(' ');
|
|
if (SpacePos == StringRef::npos)
|
|
continue;
|
|
|
|
StringRef AddrStr = Row.substr(0, SpacePos);
|
|
StringRef SymName = Row.substr(SpacePos + 1);
|
|
|
|
uint64_t Addr;
|
|
if (AddrStr.starts_with("0x"))
|
|
AddrStr = AddrStr.drop_front(2);
|
|
if (AddrStr.getAsInteger(16, Addr))
|
|
continue; // Skip malformed lines
|
|
|
|
SymbolInfos[Addr] = {SymName, CurGraph};
|
|
}
|
|
}
|
|
|
|
std::string DumpedSymbolTable::symbolicate(StringRef Backtrace) {
|
|
// Symbolicate the backtrace by replacing rows with empty symbol names
|
|
SmallVector<StringRef, 0> BacktraceRows;
|
|
Backtrace.split(BacktraceRows, '\n');
|
|
|
|
std::string Result;
|
|
raw_string_ostream Out(Result);
|
|
for (auto Row : BacktraceRows) {
|
|
// Look for a row ending with a hex number. If there's only one column, or
|
|
// if the last column is not a hex number, then just reproduce the input
|
|
// row.
|
|
auto [RowStart, AddrCol] = Row.rtrim().rsplit(' ');
|
|
auto AddrStr = AddrCol.starts_with("0x") ? AddrCol.drop_front(2) : AddrCol;
|
|
|
|
uint64_t Addr;
|
|
if (AddrStr.empty() || AddrStr.getAsInteger(16, Addr)) {
|
|
Out << Row << "\n";
|
|
continue;
|
|
}
|
|
|
|
// Search for the address
|
|
auto I = SymbolInfos.upper_bound(Addr);
|
|
|
|
// If no JIT symbol entry within 2Gb then skip.
|
|
if (I == SymbolInfos.begin() || (Addr - std::prev(I)->first >= 1U << 31)) {
|
|
Out << Row << "\n";
|
|
continue;
|
|
}
|
|
|
|
// Found a symbol. Output modified line.
|
|
auto &[SymAddr, SymInfo] = *std::prev(I);
|
|
Out << RowStart << " " << AddrCol << " " << SymInfo.SymName;
|
|
if (auto Delta = Addr - SymAddr)
|
|
Out << " + " << formatv("{0}", Delta);
|
|
Out << " (" << SymInfo.GraphName << ")\n";
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
} // namespace llvm::orc
|