summaryrefslogtreecommitdiffstats
path: root/tools/frr-llvm-debuginfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--tools/frr-llvm-debuginfo.cpp89
1 files changed, 89 insertions, 0 deletions
diff --git a/tools/frr-llvm-debuginfo.cpp b/tools/frr-llvm-debuginfo.cpp
new file mode 100644
index 0000000..16ad18b
--- /dev/null
+++ b/tools/frr-llvm-debuginfo.cpp
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: Unlicense
+
+#include <llvm-c/BitReader.h>
+#include <llvm-c/BitWriter.h>
+#include <llvm-c/Core.h>
+#include <llvm-c/DebugInfo.h>
+
+#include <llvm/IR/Module.h>
+#include <llvm/IR/Value.h>
+#include <llvm/IR/Type.h>
+#include <llvm/IR/DebugInfo.h>
+#include <llvm/IR/DebugInfoMetadata.h>
+#include <llvm/Support/raw_ostream.h>
+
+#include <map>
+
+#include "frr-llvm-debuginfo.h"
+
+/* llvm::DebugInfoFinder is unfortunately not exposed in the llvm-c API... */
+
+struct dbginfo {
+ llvm::DebugInfoFinder finder;
+ std::map<std::string, llvm::DICompositeType *> tab;
+};
+
+struct dbginfo *dbginfo_load(LLVMModuleRef _mod)
+{
+ llvm::Module *mod = llvm::unwrap(_mod);
+ struct dbginfo *info = new dbginfo();
+
+ info->finder.processModule(*mod);
+
+ for (auto ty : info->finder.types()) {
+ if (ty->getMetadataID() != llvm::Metadata::DICompositeTypeKind)
+ continue;
+
+ llvm::DICompositeType *cty = (llvm::DICompositeType *)ty;
+ /* empty forward declarations aka "struct foobar;" */
+ if (cty->getElements().size() == 0)
+ continue;
+
+ info->tab.emplace(std::move(ty->getName().str()), cty);
+ }
+
+ return info;
+}
+
+bool dbginfo_struct_member(struct dbginfo *info, LLVMTypeRef _typ,
+ unsigned long long idx, char **struct_name,
+ char **member_name)
+{
+ *struct_name = NULL;
+ *member_name = NULL;
+
+ llvm::Type *typ = llvm::unwrap(_typ);
+
+ if (!typ->isStructTy())
+ return false;
+
+ llvm::StructType *styp = (llvm::StructType *)typ;
+ auto sname = styp->getStructName();
+
+ if (!sname.startswith("struct."))
+ return false;
+ sname = sname.drop_front(7);
+
+ size_t dot = sname.find_last_of(".");
+ if (dot != sname.npos)
+ sname = sname.take_front(dot);
+
+ auto item = info->tab.find(sname.str());
+ if (item == info->tab.end())
+ return false;
+
+ auto elements = item->second->getElements();
+ if (idx >= elements.size())
+ return false;
+
+ auto elem = elements[idx];
+
+ if (elem->getMetadataID() != llvm::Metadata::DIDerivedTypeKind)
+ return false;
+
+ llvm::DIDerivedType *dtyp = (llvm::DIDerivedType *)elem;
+
+ *struct_name = strdup(sname.str().c_str());
+ *member_name = strdup(dtyp->getName().str().c_str());
+ return true;
+}