[llvm] [llvm-readobj] Dump callgraph section info for ELF (PR #157499)

Paul Kirth via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 22 14:06:11 PDT 2025


================
@@ -5260,6 +5307,247 @@ template <class ELFT> void GNUELFDumper<ELFT>::printCGProfile() {
   OS << "GNUStyle::printCGProfile not implemented\n";
 }
 
+template <class ELFT>
+static std::optional<object::SectionRef>
+getCallGraphSection(const object::ELFObjectFile<ELFT> &ObjF) {
+  // Get the .callgraph section.
+  StringRef CallGraphSectionName(".callgraph");
+  std::optional<object::SectionRef> CallGraphSection;
+  for (auto Sec : ObjF.sections()) {
+    StringRef Name;
+    if (Expected<StringRef> NameOrErr = Sec.getName())
+      Name = *NameOrErr;
+    else
+      consumeError(NameOrErr.takeError());
+
+    if (Name == CallGraphSectionName)
+      return Sec;
+  }
+  return CallGraphSection;
+}
+
+template <class ELFT> bool ELFDumper<ELFT>::processCallGraphSection() {
+  const Elf_Shdr *CGSection = findSectionByName(".callgraph");
+  if (!CGSection) {
+    Error NoSectionErr = createError("No .callgraph section found.");
+    reportError(std::move(NoSectionErr), "Missing section");
+  }
+
+  Expected<ArrayRef<uint8_t>> SectionBytesOrErr =
+      Obj.getSectionContents(*CGSection);
+  if (!SectionBytesOrErr) {
+    Error SectionReadErr = SectionBytesOrErr.takeError();
+    reportError(std::move(SectionReadErr),
+                "Unable to read the .callgraph section");
+  }
+
+  auto PrintMalformedError = [&](Error &E, Twine FuncPC, StringRef Component) {
+    // auto Msg = llvm::Twine("Malformed callgraph section while reading [") +
+    // Component + llvm::Twine("] .\n");
+    std::string Msg =
+        (StringRef("While reading call graph info's [") + Component +
+         StringRef("] for function at [0x") + StringRef(FuncPC.str()) + "]")
+            .str();
+    reportError(std::move(E), StringRef(Msg));
+  };
+
+  DataExtractor Data(SectionBytesOrErr.get(), Obj.isLE(),
+                     ObjF.getBytesInAddress());
+
+  uint64_t NotListedCount = 0;
+  uint64_t UnknownCount = 0;
+
+  uint64_t Offset = 0;
+  while (Offset < CGSection->sh_size) {
+    Error CGSectionErr = Error::success();
+    // Format version number.
+    uint64_t FormatVersionNumber = Data.getU64(&Offset, &CGSectionErr);
+
+    if (CGSectionErr)
+      reportError(std::move(CGSectionErr),
+                  "While reading call graph info FormatVersionNumber");
+
+    if (FormatVersionNumber != 0) {
+      Error FormatErr = createError("Unknown format version value [" +
+                                    std::to_string(FormatVersionNumber) +
+                                    "] in .callgraph section.");
+      reportError(std::move(FormatErr), "Unknown value");
----------------
ilovepi wrote:

```suggestion
      reportError(createError("Unknown format version value [" +
                                    std::to_string(FormatVersionNumber) +
                                    "] in .callgraph section."), "Unknown value");
```

What you have is fine. I just think this is a bit more typical of what I see in the codebase. either way is OK, so I'd just follow whatever convention this file/library uses.

https://github.com/llvm/llvm-project/pull/157499


More information about the llvm-commits mailing list