[lld] [llvm] RFC: [llvm-readobj] Support FDO package metadata in readelf (PR #214375)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 6 05:14:57 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lld
@llvm/pr-subscribers-llvm-support
Author: Dan McGregor (dankm)
<details>
<summary>Changes</summary>
This adds initial support for displaying FDO package metadata and dlopen note types in readobj.
In the GNU display mode it mimicks GNU readelf, and simply displays the JSON string as-is. In the LLVM display mode it parses and pretty-prints the object. In the JSON mode it outputs it as a JSON object.
This still needs better tests, but I figure I should expose it to the community for comment.
---
Full diff: https://github.com/llvm/llvm-project/pull/214375.diff
5 Files Affected:
- (modified) lld/test/ELF/package-metadata.s (+3-3)
- (modified) llvm/include/llvm/BinaryFormat/ELF.h (+2-1)
- (modified) llvm/include/llvm/Support/JSON.h (+4-3)
- (modified) llvm/include/llvm/Support/ScopedPrinter.h (+13)
- (modified) llvm/tools/llvm-readobj/ELFDumper.cpp (+39)
``````````diff
diff --git a/lld/test/ELF/package-metadata.s b/lld/test/ELF/package-metadata.s
index a70a8940d7c68..c4ca2e169d3ec 100644
--- a/lld/test/ELF/package-metadata.s
+++ b/lld/test/ELF/package-metadata.s
@@ -13,9 +13,9 @@
# NOTE: .note.package
# NOTE-NEXT: Owner
-# NOTE-NEXT: FDO 0x{{.*}} Unknown note type: (0xcafe1a7e)
-# FIRST-NEXT: description data: 7b 7d 00
-# SECOND-NEXT: description data: 7b 22 61 62 63 22 3a 31 32 33 7d 00
+# NOTE-NEXT: FDO 0x{{.*}} FDO_PACKAGING_METADATA
+# FIRST-NEXT: Packaging Metadata: {}
+# SECOND-NEXT: Packaging Metadata: {"abc":123}
# RUN: not ld.lld a.o --package-metadata='%7b%' 2>&1 | FileCheck %s --check-prefix=ERR
# RUN: not ld.lld a.o --package-metadata='%7b%7' 2>&1 | FileCheck %s --check-prefix=ERR
diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index 823a08d7dd81b..b59532f3ddf4e 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -1812,12 +1812,13 @@ enum {
};
// GNU note types.
-enum {
+enum : unsigned {
NT_GNU_ABI_TAG = 1,
NT_GNU_HWCAP = 2,
NT_GNU_BUILD_ID = 3,
NT_GNU_GOLD_VERSION = 4,
NT_GNU_PROPERTY_TYPE_0 = 5,
+ NT_FDO_DLOPEN_METADATA = 0x407c0c0a,
FDO_PACKAGING_METADATA = 0xcafe1a7e,
};
diff --git a/llvm/include/llvm/Support/JSON.h b/llvm/include/llvm/Support/JSON.h
index 3b145a69c74cb..a0118ca883ce6 100644
--- a/llvm/include/llvm/Support/JSON.h
+++ b/llvm/include/llvm/Support/JSON.h
@@ -984,8 +984,9 @@ class OStream {
public:
using Block = llvm::function_ref<void()>;
// If IndentSize is nonzero, output is pretty-printed.
- explicit OStream(llvm::raw_ostream &OS, unsigned IndentSize = 0)
- : OS(OS), IndentSize(IndentSize) {
+ explicit OStream(llvm::raw_ostream &OS, unsigned IndentSize = 0,
+ unsigned IndentLevel = 0)
+ : OS(OS), IndentSize(IndentSize), Indent(IndentSize * IndentLevel) {
Stack.emplace_back();
}
~OStream() {
@@ -1084,7 +1085,7 @@ class OStream {
llvm::StringRef PendingComment;
llvm::raw_ostream &OS;
unsigned IndentSize;
- unsigned Indent = 0;
+ unsigned Indent;
};
/// Serializes this Value to JSON, writing it to the provided stream.
diff --git a/llvm/include/llvm/Support/ScopedPrinter.h b/llvm/include/llvm/Support/ScopedPrinter.h
index f6fd2671e812f..3da97c40ff466 100644
--- a/llvm/include/llvm/Support/ScopedPrinter.h
+++ b/llvm/include/llvm/Support/ScopedPrinter.h
@@ -399,6 +399,15 @@ class LLVM_ABI ScopedPrinter {
printString(Label, to_string(Value));
}
+ virtual void printObject(StringRef Label, const llvm::json::Value &Value) {
+ std::string prettyValue;
+ raw_string_ostream stream(prettyValue);
+ llvm::json::OStream(stream, 2, getIndentLevel()).value(Value);
+ startLine() << Label << ": "
+ << prettyValue.substr(prettyValue.find_first_not_of(" "))
+ << "\n";
+ }
+
virtual void objectBegin() { scopedBegin('{'); }
virtual void objectBegin(StringRef Label) { scopedBegin(Label, '{'); }
@@ -672,6 +681,10 @@ class JSONScopedPrinter : public ScopedPrinter {
JOS.attribute(Label, Value);
}
+ void printObject(StringRef Label, const llvm::json::Value &Value) override {
+ JOS.attribute(Label, Value);
+ }
+
void objectBegin() override {
scopedBegin({Scope::Object, ScopeKind::NoAttribute});
}
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index de0a97abb08ee..84aadbea4ceba 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -5934,6 +5934,24 @@ static bool printLLVMOMPOFFLOADNote(raw_ostream &OS, uint32_t NoteType,
return true;
}
+struct FDONote {
+ std::string Type;
+ std::string Value;
+};
+
+template <typename ELFT>
+static std::optional<FDONote> getFDONote(typename ELFT::Word NoteType,
+ ArrayRef<uint8_t> Desc) {
+ switch (NoteType) {
+ case ELF::FDO_PACKAGING_METADATA:
+ return FDONote{"Packaging Metadata", toStringRef(Desc).rtrim('\0').str()};
+ case ELF::NT_FDO_DLOPEN_METADATA:
+ return FDONote{"Dlopen Metadata", toStringRef(Desc).rtrim('\0').str()};
+ default:
+ return std::nullopt;
+ }
+}
+
constexpr EnumStringDef<unsigned> FreeBSDFeatureCtlFlagsDefs[] = {
{{"ASLR_DISABLE"}, NT_FREEBSD_FCTL_ASLR_DISABLE},
{{"PROTMAX_DISABLE"}, NT_FREEBSD_FCTL_PROTMAX_DISABLE},
@@ -6220,6 +6238,11 @@ const NoteType GNUNoteTypes[] = {
{ELF::NT_GNU_PROPERTY_TYPE_0, "NT_GNU_PROPERTY_TYPE_0 (property note)"},
};
+const NoteType FDONoteTypes[] = {
+ {ELF::FDO_PACKAGING_METADATA, "FDO_PACKAGING_METADATA"},
+ {ELF::NT_FDO_DLOPEN_METADATA, "FDO_DLOPEN_METADATA"},
+};
+
const NoteType FreeBSDCoreNoteTypes[] = {
{ELF::NT_FREEBSD_THRMISC, "NT_THRMISC (thrmisc structure)"},
{ELF::NT_FREEBSD_PROCSTAT_PROC, "NT_PROCSTAT_PROC (proc data)"},
@@ -6379,6 +6402,8 @@ StringRef getNoteTypeName(const typename ELFT::Note &Note, unsigned ELFType) {
StringRef Name = Note.getName();
if (Name == "GNU")
return FindNote(GNUNoteTypes);
+ if (Name == "FDO")
+ return FindNote(FDONoteTypes);
if (Name == "FreeBSD") {
if (ELFType == ELF::ET_CORE) {
// FreeBSD also places the generic core notes in the FreeBSD namespace.
@@ -6532,6 +6557,11 @@ template <class ELFT> void GNUELFDumper<ELFT>::printNotes() {
if (Name == "GNU") {
if (printGNUNote<ELFT>(OS, Type, Descriptor, EMachine))
return Error::success();
+ } else if (Name == "FDO") {
+ if (std::optional<FDONote> N = getFDONote<ELFT>(Type, Descriptor)) {
+ OS << " " << N->Type << ": " << N->Value << '\n';
+ return Error::success();
+ }
} else if (Name == "FreeBSD") {
if (std::optional<FreeBSDNote> N =
getFreeBSDNote<ELFT>(Type, Descriptor, IsCore)) {
@@ -8733,6 +8763,15 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printNotes() {
if (Name == "GNU") {
if (printGNUNoteLLVMStyle<ELFT>(Type, Descriptor, W, EMachine))
return Error::success();
+ } else if (Name == "FDO") {
+ if (std::optional<FDONote> N = getFDONote<ELFT>(Type, Descriptor)) {
+ auto f = llvm::json::parse(N->Value);
+ if (f)
+ W.printObject(N->Type, f.get());
+ else
+ W.printString(N->Type, N->Value);
+ return Error::success();
+ }
} else if (Name == "FreeBSD") {
if (std::optional<FreeBSDNote> N =
getFreeBSDNote<ELFT>(Type, Descriptor, IsCore)) {
``````````
</details>
https://github.com/llvm/llvm-project/pull/214375
More information about the llvm-commits
mailing list