[llvm] [llvm][object][GOFF] refine Global flag conditions (PR #211632)

David Tenty via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 7 09:55:01 PDT 2026


https://github.com/daltenty updated https://github.com/llvm/llvm-project/pull/211632

>From 85ff941be5a22ad775623d9a2de8dd3dee063338 Mon Sep 17 00:00:00 2001
From: David Tenty <daltenty at ibm.com>
Date: Thu, 23 Jul 2026 00:15:56 -0400
Subject: [PATCH 01/12] [llvm][object][GOFF] refine Global flag conditions

---
 llvm/lib/Object/GOFFObjectFile.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Object/GOFFObjectFile.cpp b/llvm/lib/Object/GOFFObjectFile.cpp
index 057d3fc208c9b..59b94208b38d5 100644
--- a/llvm/lib/Object/GOFFObjectFile.cpp
+++ b/llvm/lib/Object/GOFFObjectFile.cpp
@@ -279,7 +279,8 @@ Expected<uint32_t> GOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
   GOFF::ESDBindingScope BindingScope;
   ESDRecord::getBindingScope(Record, BindingScope);
 
-  if (BindingScope != GOFF::ESD_BSC_Section) {
+  if (BindingScope != GOFF::ESD_BSC_Section &&
+      BindingScope != GOFF::ESD_BSC_Module) {
     Expected<StringRef> Name = getSymbolName(Symb);
     if (Name && *Name != " ") { // Blank name is local.
       Flags |= SymbolRef::SF_Global;

>From d82a9483ca5c6f3e075d924111dcea412a8fccd4 Mon Sep 17 00:00:00 2001
From: David Tenty <daltenty at ibm.com>
Date: Thu, 23 Jul 2026 13:48:07 -0400
Subject: [PATCH 02/12] Add test

---
 llvm/unittests/Object/GOFFObjectFileTest.cpp | 139 +++++++++++++++++++
 1 file changed, 139 insertions(+)

diff --git a/llvm/unittests/Object/GOFFObjectFileTest.cpp b/llvm/unittests/Object/GOFFObjectFileTest.cpp
index 09fa1c2f63938..dc8a4f30119ec 100644
--- a/llvm/unittests/Object/GOFFObjectFileTest.cpp
+++ b/llvm/unittests/Object/GOFFObjectFileTest.cpp
@@ -633,3 +633,142 @@ TEST_F(GOFFObjectFileTest, TXTConstruct) {
   StringRef Contents = SectionContent.get();
   EXPECT_EQ(Contents, "\x12\x34\x56\x78\x9a\xbc\xde\xf0");
 }
+
+TEST(GOFFObjectFileTest, GlobalSymbols) {
+  char GOFFData[GOFF::RecordLength * 12] = {0x00};
+
+  // HDR record.
+  GOFFData[0] = (char)0x03;
+  GOFFData[1] = (char)0xF0;
+
+  // ESD record 1: type SD
+  GOFFData[GOFF::RecordLength] = (char)0x03;
+  GOFFData[GOFF::RecordLength + 3] = (char)0x00;  // Type: SD
+  GOFFData[GOFF::RecordLength + 7] = (char)0x01;  // ESDID.
+  GOFFData[GOFF::RecordLength + 71] = (char)0x01; // Size of symbol name.
+  GOFFData[GOFF::RecordLength + 72] = (char)0xC1; // Symbol name is A.
+
+  // ESD record 2: type ED
+  GOFFData[GOFF::RecordLength * 2] = (char)0x03;
+  GOFFData[GOFF::RecordLength * 2 + 3] = (char)0x01;  // Type: ED
+  GOFFData[GOFF::RecordLength * 2 + 7] = (char)0x02;  // ESDID.
+  GOFFData[GOFF::RecordLength * 2 + 11] = (char)0x01; // Parent ESDID.
+  GOFFData[GOFF::RecordLength * 2 + 71] = (char)0x01; // Size of symbol name.
+  GOFFData[GOFF::RecordLength * 2 + 72] = (char)0xC2; // Symbol name is B.
+
+  // ESD record 3: type LD
+  GOFFData[GOFF::RecordLength * 3] = (char)0x03;
+  GOFFData[GOFF::RecordLength * 3 + 3] = (char)0x02;  // Type: LD
+  GOFFData[GOFF::RecordLength * 3 + 7] = (char)0x03;  // ESDID.
+  GOFFData[GOFF::RecordLength * 3 + 11] = (char)0x02; // Parent ESDID.
+  GOFFData[GOFF::RecordLength * 3 + 71] = (char)0x01; // Size of symbol name.
+  GOFFData[GOFF::RecordLength * 3 + 72] = (char)0xC3; // Symbol name is C.
+
+  // ESD record 4: type PR
+  GOFFData[GOFF::RecordLength * 4] = (char)0x03;
+  GOFFData[GOFF::RecordLength * 4 + 3] = (char)0x03;  // Type: PR
+  GOFFData[GOFF::RecordLength * 4 + 7] = (char)0x04;  // ESDID.
+  GOFFData[GOFF::RecordLength * 4 + 11] = (char)0x02; // Parent ESDID.
+  GOFFData[GOFF::RecordLength * 4 + 71] = (char)0x01; // Size of symbol name.
+  GOFFData[GOFF::RecordLength * 4 + 72] = (char)0xC4; // Symbol name is D.
+
+  // ESD record 5: type ErWx
+  GOFFData[GOFF::RecordLength * 5] = (char)0x03;
+  GOFFData[GOFF::RecordLength * 5 + 3] = (char)0x04;  // Type: ErWx
+  GOFFData[GOFF::RecordLength * 5 + 7] = (char)0x05;  // ESDID.
+  GOFFData[GOFF::RecordLength * 5 + 71] = (char)0x01; // Size of symbol name.
+  GOFFData[GOFF::RecordLength * 5 + 72] = (char)0xC5; // Symbol name is E.
+
+  // ESD record 6: type LD + Section binding scope
+  GOFFData[GOFF::RecordLength * 6] = (char)0x03;
+  GOFFData[GOFF::RecordLength * 6 + 3] = (char)0x02;  // Type: LD
+  GOFFData[GOFF::RecordLength * 6 + 7] = (char)0x06;  // ESDID.
+  GOFFData[GOFF::RecordLength * 6 + 11] = (char)0x02; // Parent ESDID.
+  GOFFData[GOFF::RecordLength * 6 + 65] = (char)0x01; // Binding Scope: Section.
+  GOFFData[GOFF::RecordLength * 6 + 71] = (char)0x01; // Size of symbol name.
+  GOFFData[GOFF::RecordLength * 6 + 72] = (char)0xC6; // Symbol name is F.
+
+  // ESD record 7: type LD + Module binding scope
+  GOFFData[GOFF::RecordLength * 7] = (char)0x03;
+  GOFFData[GOFF::RecordLength * 7 + 3] = (char)0x02;  // Type: LD
+  GOFFData[GOFF::RecordLength * 7 + 7] = (char)0x07;  // ESDID.
+  GOFFData[GOFF::RecordLength * 7 + 11] = (char)0x02; // Parent ESDID.
+  GOFFData[GOFF::RecordLength * 7 + 65] = (char)0x02; // Binding Scope: Module.
+  GOFFData[GOFF::RecordLength * 7 + 71] = (char)0x01; // Size of symbol name.
+  GOFFData[GOFF::RecordLength * 7 + 72] = (char)0xC7; // Symbol name is G.
+
+  // ESD record 8: type LD + Library binding scope
+  GOFFData[GOFF::RecordLength * 8] = (char)0x03;
+  GOFFData[GOFF::RecordLength * 8 + 3] = (char)0x02;  // Type: LD
+  GOFFData[GOFF::RecordLength * 8 + 7] = (char)0x08;  // ESDID.
+  GOFFData[GOFF::RecordLength * 8 + 11] = (char)0x02; // Parent ESDID.
+  GOFFData[GOFF::RecordLength * 8 + 65] = (char)0x03; // Binding Scope: Library.
+  GOFFData[GOFF::RecordLength * 8 + 71] = (char)0x01; // Size of symbol name.
+  GOFFData[GOFF::RecordLength * 8 + 72] = (char)0xC8; // Symbol name is H.
+
+ // ESD record 9: type LD + Import-Export binding scope
+  GOFFData[GOFF::RecordLength * 9] = (char)0x03;
+  GOFFData[GOFF::RecordLength * 9 + 3] = (char)0x02;  // Type: LD
+  GOFFData[GOFF::RecordLength * 9 + 7] = (char)0x09;  // ESDID.
+  GOFFData[GOFF::RecordLength * 9 + 11] = (char)0x02; // Parent ESDID.
+  GOFFData[GOFF::RecordLength * 9 + 65] = (char)0x04; // Binding Scope: ImportExport.
+  GOFFData[GOFF::RecordLength * 9 + 71] = (char)0x01; // Size of symbol name.
+  GOFFData[GOFF::RecordLength * 9 + 72] = (char)0xC9; // Symbol name is I.
+
+   // ESD record 10: type LD + blank name
+  GOFFData[GOFF::RecordLength * 10] = (char)0x03;
+  GOFFData[GOFF::RecordLength * 10 + 3] = (char)0x02;  // Type: LD
+  GOFFData[GOFF::RecordLength * 10 + 7] = (char)0x0A;  // ESDID.
+  GOFFData[GOFF::RecordLength * 10 + 11] = (char)0x02; // Parent ESDID.
+  GOFFData[GOFF::RecordLength * 10 + 71] = (char)0x01; // Size of symbol name.
+  GOFFData[GOFF::RecordLength * 10 + 72] = (char)0x40; // Symbol name is ' '.
+
+  // END record.
+  GOFFData[GOFF::RecordLength * 11] = (char)0x03;
+  GOFFData[GOFF::RecordLength * 11 + 1] = (char)0x40;
+
+  StringRef Data(GOFFData, GOFF::RecordLength * 12);
+
+  Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
+      object::ObjectFile::createGOFFObjectFile(
+          MemoryBufferRef(Data, "dummyGOFF"));
+
+  ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded());
+
+  GOFFObjectFile *GOFFObj = dyn_cast<GOFFObjectFile>((*GOFFObjOrErr).get());
+
+
+  auto SymbolRange = GOFFObj->symbols();
+  auto Symbol = SymbolRange.begin();
+  auto ValidateGlobal = [&](StringRef Name, bool IsGlobal) {
+    ASSERT_TRUE(Symbol != SymbolRange.end());
+
+    // Check Name.
+    Expected<StringRef> SymbolNameOrErr = GOFFObj->getSymbolName(*Symbol);
+    ASSERT_THAT_EXPECTED(SymbolNameOrErr, Succeeded());
+    StringRef SymbolName = SymbolNameOrErr.get();
+    EXPECT_EQ(SymbolName, Name);
+
+    // Check flags.
+    Expected<uint32_t> SymbolFlagsOrErr = Symbol->getFlags();
+    ASSERT_THAT_EXPECTED(SymbolFlagsOrErr, Succeeded());
+    uint32_t SymbolFlags = SymbolFlagsOrErr.get();
+    if (IsGlobal){
+      EXPECT_TRUE(SymbolFlags & SymbolRef::SF_Global);
+    } else {
+      EXPECT_FALSE(SymbolFlags & SymbolRef::SF_Global);
+    }
+
+    ++Symbol;
+  };
+
+  // ESD records 'A' and 'B' shouldn't be considered symbols.
+  ValidateGlobal("C", true);
+  ValidateGlobal("D", true);
+  ValidateGlobal("E", true);
+  ValidateGlobal("F", false);
+  ValidateGlobal("G", false);
+  ValidateGlobal("H", true);
+  ValidateGlobal("I", true);
+  ValidateGlobal(" ", false);
+}

>From f61f2826df894fa0aa3d30bf3f43d54703a6374c Mon Sep 17 00:00:00 2001
From: David Tenty <daltenty at ibm.com>
Date: Fri, 24 Jul 2026 10:44:22 -0400
Subject: [PATCH 03/12] clang-format

---
 llvm/unittests/Object/GOFFObjectFileTest.cpp | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/llvm/unittests/Object/GOFFObjectFileTest.cpp b/llvm/unittests/Object/GOFFObjectFileTest.cpp
index dc8a4f30119ec..538fbfc22eb0b 100644
--- a/llvm/unittests/Object/GOFFObjectFileTest.cpp
+++ b/llvm/unittests/Object/GOFFObjectFileTest.cpp
@@ -706,16 +706,17 @@ TEST(GOFFObjectFileTest, GlobalSymbols) {
   GOFFData[GOFF::RecordLength * 8 + 71] = (char)0x01; // Size of symbol name.
   GOFFData[GOFF::RecordLength * 8 + 72] = (char)0xC8; // Symbol name is H.
 
- // ESD record 9: type LD + Import-Export binding scope
+  // ESD record 9: type LD + Import-Export binding scope
   GOFFData[GOFF::RecordLength * 9] = (char)0x03;
   GOFFData[GOFF::RecordLength * 9 + 3] = (char)0x02;  // Type: LD
   GOFFData[GOFF::RecordLength * 9 + 7] = (char)0x09;  // ESDID.
   GOFFData[GOFF::RecordLength * 9 + 11] = (char)0x02; // Parent ESDID.
-  GOFFData[GOFF::RecordLength * 9 + 65] = (char)0x04; // Binding Scope: ImportExport.
+  GOFFData[GOFF::RecordLength * 9 + 65] =
+      (char)0x04; // Binding Scope: ImportExport.
   GOFFData[GOFF::RecordLength * 9 + 71] = (char)0x01; // Size of symbol name.
   GOFFData[GOFF::RecordLength * 9 + 72] = (char)0xC9; // Symbol name is I.
 
-   // ESD record 10: type LD + blank name
+  // ESD record 10: type LD + blank name
   GOFFData[GOFF::RecordLength * 10] = (char)0x03;
   GOFFData[GOFF::RecordLength * 10 + 3] = (char)0x02;  // Type: LD
   GOFFData[GOFF::RecordLength * 10 + 7] = (char)0x0A;  // ESDID.
@@ -737,7 +738,6 @@ TEST(GOFFObjectFileTest, GlobalSymbols) {
 
   GOFFObjectFile *GOFFObj = dyn_cast<GOFFObjectFile>((*GOFFObjOrErr).get());
 
-
   auto SymbolRange = GOFFObj->symbols();
   auto Symbol = SymbolRange.begin();
   auto ValidateGlobal = [&](StringRef Name, bool IsGlobal) {
@@ -753,7 +753,7 @@ TEST(GOFFObjectFileTest, GlobalSymbols) {
     Expected<uint32_t> SymbolFlagsOrErr = Symbol->getFlags();
     ASSERT_THAT_EXPECTED(SymbolFlagsOrErr, Succeeded());
     uint32_t SymbolFlags = SymbolFlagsOrErr.get();
-    if (IsGlobal){
+    if (IsGlobal) {
       EXPECT_TRUE(SymbolFlags & SymbolRef::SF_Global);
     } else {
       EXPECT_FALSE(SymbolFlags & SymbolRef::SF_Global);

>From 11630d3fe7ad929173854a1bfc9d9bac2ebfc61e Mon Sep 17 00:00:00 2001
From: David Tenty <daltenty at ibm.com>
Date: Fri, 24 Jul 2026 16:42:18 -0400
Subject: [PATCH 04/12] Update cast

---
 llvm/unittests/Object/GOFFObjectFileTest.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/unittests/Object/GOFFObjectFileTest.cpp b/llvm/unittests/Object/GOFFObjectFileTest.cpp
index 538fbfc22eb0b..62fdbe58de6d1 100644
--- a/llvm/unittests/Object/GOFFObjectFileTest.cpp
+++ b/llvm/unittests/Object/GOFFObjectFileTest.cpp
@@ -736,7 +736,7 @@ TEST(GOFFObjectFileTest, GlobalSymbols) {
 
   ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded());
 
-  GOFFObjectFile *GOFFObj = dyn_cast<GOFFObjectFile>((*GOFFObjOrErr).get());
+  GOFFObjectFile *GOFFObj = static_cast<GOFFObjectFile*>((*GOFFObjOrErr).get());
 
   auto SymbolRange = GOFFObj->symbols();
   auto Symbol = SymbolRange.begin();

>From 876ccacdee43a6100786ff958c88128924e67088 Mon Sep 17 00:00:00 2001
From: David Tenty <daltenty at ibm.com>
Date: Wed, 5 Aug 2026 17:11:08 -0400
Subject: [PATCH 05/12] Adopt new record helpers

---
 llvm/unittests/Object/GOFFObjectFileTest.cpp | 101 +++++--------------
 1 file changed, 25 insertions(+), 76 deletions(-)

diff --git a/llvm/unittests/Object/GOFFObjectFileTest.cpp b/llvm/unittests/Object/GOFFObjectFileTest.cpp
index 62fdbe58de6d1..9b8c74103f941 100644
--- a/llvm/unittests/Object/GOFFObjectFileTest.cpp
+++ b/llvm/unittests/Object/GOFFObjectFileTest.cpp
@@ -634,101 +634,49 @@ TEST_F(GOFFObjectFileTest, TXTConstruct) {
   EXPECT_EQ(Contents, "\x12\x34\x56\x78\x9a\xbc\xde\xf0");
 }
 
-TEST(GOFFObjectFileTest, GlobalSymbols) {
-  char GOFFData[GOFF::RecordLength * 12] = {0x00};
-
+TEST_F(GOFFObjectFileTest, GlobalSymbols) {
   // HDR record.
-  GOFFData[0] = (char)0x03;
-  GOFFData[1] = (char)0xF0;
+  addHdrRecord();
 
   // ESD record 1: type SD
-  GOFFData[GOFF::RecordLength] = (char)0x03;
-  GOFFData[GOFF::RecordLength + 3] = (char)0x00;  // Type: SD
-  GOFFData[GOFF::RecordLength + 7] = (char)0x01;  // ESDID.
-  GOFFData[GOFF::RecordLength + 71] = (char)0x01; // Size of symbol name.
-  GOFFData[GOFF::RecordLength + 72] = (char)0xC1; // Symbol name is A.
+  addEsdRecord(0x00, 0x01, {0xC1}); // A
 
   // ESD record 2: type ED
-  GOFFData[GOFF::RecordLength * 2] = (char)0x03;
-  GOFFData[GOFF::RecordLength * 2 + 3] = (char)0x01;  // Type: ED
-  GOFFData[GOFF::RecordLength * 2 + 7] = (char)0x02;  // ESDID.
-  GOFFData[GOFF::RecordLength * 2 + 11] = (char)0x01; // Parent ESDID.
-  GOFFData[GOFF::RecordLength * 2 + 71] = (char)0x01; // Size of symbol name.
-  GOFFData[GOFF::RecordLength * 2 + 72] = (char)0xC2; // Symbol name is B.
-
-  // ESD record 3: type LD
-  GOFFData[GOFF::RecordLength * 3] = (char)0x03;
-  GOFFData[GOFF::RecordLength * 3 + 3] = (char)0x02;  // Type: LD
-  GOFFData[GOFF::RecordLength * 3 + 7] = (char)0x03;  // ESDID.
-  GOFFData[GOFF::RecordLength * 3 + 11] = (char)0x02; // Parent ESDID.
-  GOFFData[GOFF::RecordLength * 3 + 71] = (char)0x01; // Size of symbol name.
-  GOFFData[GOFF::RecordLength * 3 + 72] = (char)0xC3; // Symbol name is C.
+  addEsdRecord(0x01, 0x02, {0xC2}, 0x01); // B, parent=1
+
+  // ESD record 3: type LD (default binding scope = global)
+  addEsdRecord(0x02, 0x03, {0xC3}, 0x02); // C, parent=2
 
   // ESD record 4: type PR
-  GOFFData[GOFF::RecordLength * 4] = (char)0x03;
-  GOFFData[GOFF::RecordLength * 4 + 3] = (char)0x03;  // Type: PR
-  GOFFData[GOFF::RecordLength * 4 + 7] = (char)0x04;  // ESDID.
-  GOFFData[GOFF::RecordLength * 4 + 11] = (char)0x02; // Parent ESDID.
-  GOFFData[GOFF::RecordLength * 4 + 71] = (char)0x01; // Size of symbol name.
-  GOFFData[GOFF::RecordLength * 4 + 72] = (char)0xC4; // Symbol name is D.
+  addEsdRecord(0x03, 0x04, {0xC4}, 0x02); // D, parent=2
 
   // ESD record 5: type ErWx
-  GOFFData[GOFF::RecordLength * 5] = (char)0x03;
-  GOFFData[GOFF::RecordLength * 5 + 3] = (char)0x04;  // Type: ErWx
-  GOFFData[GOFF::RecordLength * 5 + 7] = (char)0x05;  // ESDID.
-  GOFFData[GOFF::RecordLength * 5 + 71] = (char)0x01; // Size of symbol name.
-  GOFFData[GOFF::RecordLength * 5 + 72] = (char)0xC5; // Symbol name is E.
-
-  // ESD record 6: type LD + Section binding scope
-  GOFFData[GOFF::RecordLength * 6] = (char)0x03;
-  GOFFData[GOFF::RecordLength * 6 + 3] = (char)0x02;  // Type: LD
-  GOFFData[GOFF::RecordLength * 6 + 7] = (char)0x06;  // ESDID.
-  GOFFData[GOFF::RecordLength * 6 + 11] = (char)0x02; // Parent ESDID.
-  GOFFData[GOFF::RecordLength * 6 + 65] = (char)0x01; // Binding Scope: Section.
-  GOFFData[GOFF::RecordLength * 6 + 71] = (char)0x01; // Size of symbol name.
-  GOFFData[GOFF::RecordLength * 6 + 72] = (char)0xC6; // Symbol name is F.
+  addEsdRecord(0x04, 0x05, {0xC5}); // E
+
+  // ESD record 6: type LD + Section binding scope (BindingScope=1 -> lower
+  // nibble of BehavioralAttributes[5])
+  addEsdRecord(0x02, 0x06, {0xC6}, 0x02, 0x00, 0x00, 0x00,
+               {0, 0, 0, 0, 0, 0x01, 0, 0, 0, 0}); // F, parent=2
 
   // ESD record 7: type LD + Module binding scope
-  GOFFData[GOFF::RecordLength * 7] = (char)0x03;
-  GOFFData[GOFF::RecordLength * 7 + 3] = (char)0x02;  // Type: LD
-  GOFFData[GOFF::RecordLength * 7 + 7] = (char)0x07;  // ESDID.
-  GOFFData[GOFF::RecordLength * 7 + 11] = (char)0x02; // Parent ESDID.
-  GOFFData[GOFF::RecordLength * 7 + 65] = (char)0x02; // Binding Scope: Module.
-  GOFFData[GOFF::RecordLength * 7 + 71] = (char)0x01; // Size of symbol name.
-  GOFFData[GOFF::RecordLength * 7 + 72] = (char)0xC7; // Symbol name is G.
+  addEsdRecord(0x02, 0x07, {0xC7}, 0x02, 0x00, 0x00, 0x00,
+               {0, 0, 0, 0, 0, 0x02, 0, 0, 0, 0}); // G, parent=2
 
   // ESD record 8: type LD + Library binding scope
-  GOFFData[GOFF::RecordLength * 8] = (char)0x03;
-  GOFFData[GOFF::RecordLength * 8 + 3] = (char)0x02;  // Type: LD
-  GOFFData[GOFF::RecordLength * 8 + 7] = (char)0x08;  // ESDID.
-  GOFFData[GOFF::RecordLength * 8 + 11] = (char)0x02; // Parent ESDID.
-  GOFFData[GOFF::RecordLength * 8 + 65] = (char)0x03; // Binding Scope: Library.
-  GOFFData[GOFF::RecordLength * 8 + 71] = (char)0x01; // Size of symbol name.
-  GOFFData[GOFF::RecordLength * 8 + 72] = (char)0xC8; // Symbol name is H.
+  addEsdRecord(0x02, 0x08, {0xC8}, 0x02, 0x00, 0x00, 0x00,
+               {0, 0, 0, 0, 0, 0x03, 0, 0, 0, 0}); // H, parent=2
 
   // ESD record 9: type LD + Import-Export binding scope
-  GOFFData[GOFF::RecordLength * 9] = (char)0x03;
-  GOFFData[GOFF::RecordLength * 9 + 3] = (char)0x02;  // Type: LD
-  GOFFData[GOFF::RecordLength * 9 + 7] = (char)0x09;  // ESDID.
-  GOFFData[GOFF::RecordLength * 9 + 11] = (char)0x02; // Parent ESDID.
-  GOFFData[GOFF::RecordLength * 9 + 65] =
-      (char)0x04; // Binding Scope: ImportExport.
-  GOFFData[GOFF::RecordLength * 9 + 71] = (char)0x01; // Size of symbol name.
-  GOFFData[GOFF::RecordLength * 9 + 72] = (char)0xC9; // Symbol name is I.
+  addEsdRecord(0x02, 0x09, {0xC9}, 0x02, 0x00, 0x00, 0x00,
+               {0, 0, 0, 0, 0, 0x04, 0, 0, 0, 0}); // I, parent=2
 
   // ESD record 10: type LD + blank name
-  GOFFData[GOFF::RecordLength * 10] = (char)0x03;
-  GOFFData[GOFF::RecordLength * 10 + 3] = (char)0x02;  // Type: LD
-  GOFFData[GOFF::RecordLength * 10 + 7] = (char)0x0A;  // ESDID.
-  GOFFData[GOFF::RecordLength * 10 + 11] = (char)0x02; // Parent ESDID.
-  GOFFData[GOFF::RecordLength * 10 + 71] = (char)0x01; // Size of symbol name.
-  GOFFData[GOFF::RecordLength * 10 + 72] = (char)0x40; // Symbol name is ' '.
+  addEsdRecord(0x02, 0x0A, {0x40}, 0x02); // ' ', parent=2
 
   // END record.
-  GOFFData[GOFF::RecordLength * 11] = (char)0x03;
-  GOFFData[GOFF::RecordLength * 11 + 1] = (char)0x40;
+  addEndRecord();
 
-  StringRef Data(GOFFData, GOFF::RecordLength * 12);
+  StringRef Data(GOFFData.data(), GOFFData.size());
 
   Expected<std::unique_ptr<ObjectFile>> GOFFObjOrErr =
       object::ObjectFile::createGOFFObjectFile(
@@ -736,7 +684,8 @@ TEST(GOFFObjectFileTest, GlobalSymbols) {
 
   ASSERT_THAT_EXPECTED(GOFFObjOrErr, Succeeded());
 
-  GOFFObjectFile *GOFFObj = static_cast<GOFFObjectFile*>((*GOFFObjOrErr).get());
+  GOFFObjectFile *GOFFObj =
+      static_cast<GOFFObjectFile *>((*GOFFObjOrErr).get());
 
   auto SymbolRange = GOFFObj->symbols();
   auto Symbol = SymbolRange.begin();

>From 4c9195e17af0fc6d54cec77d643c5c540e83e897 Mon Sep 17 00:00:00 2001
From: David Tenty <daltenty at ibm.com>
Date: Wed, 5 Aug 2026 17:15:44 -0400
Subject: [PATCH 06/12] Add FIXME for missing ESD records

---
 llvm/unittests/Object/GOFFObjectFileTest.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/unittests/Object/GOFFObjectFileTest.cpp b/llvm/unittests/Object/GOFFObjectFileTest.cpp
index 9b8c74103f941..02124b2b2a176 100644
--- a/llvm/unittests/Object/GOFFObjectFileTest.cpp
+++ b/llvm/unittests/Object/GOFFObjectFileTest.cpp
@@ -711,7 +711,7 @@ TEST_F(GOFFObjectFileTest, GlobalSymbols) {
     ++Symbol;
   };
 
-  // ESD records 'A' and 'B' shouldn't be considered symbols.
+  // FIXME: ESD records 'A' and 'B' should be considered symbols, but aren't returned iteration.
   ValidateGlobal("C", true);
   ValidateGlobal("D", true);
   ValidateGlobal("E", true);

>From 82c2ec152720034d77cddbd2131132ff7f834d04 Mon Sep 17 00:00:00 2001
From: David Tenty <daltenty at ibm.com>
Date: Wed, 5 Aug 2026 17:25:18 -0400
Subject: [PATCH 07/12] Add explicit type checks

---
 llvm/lib/Object/GOFFObjectFile.cpp | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Object/GOFFObjectFile.cpp b/llvm/lib/Object/GOFFObjectFile.cpp
index 59b94208b38d5..d00ad71105fd5 100644
--- a/llvm/lib/Object/GOFFObjectFile.cpp
+++ b/llvm/lib/Object/GOFFObjectFile.cpp
@@ -279,7 +279,12 @@ Expected<uint32_t> GOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const {
   GOFF::ESDBindingScope BindingScope;
   ESDRecord::getBindingScope(Record, BindingScope);
 
-  if (BindingScope != GOFF::ESD_BSC_Section &&
+  GOFF::ESDSymbolType Type;
+  ESDRecord::getSymbolType(Record, Type);
+
+  if (Type != GOFF::ESD_ST_SectionDefinition &&
+      Type != GOFF::ESD_ST_ElementDefinition &&
+      BindingScope != GOFF::ESD_BSC_Section &&
       BindingScope != GOFF::ESD_BSC_Module) {
     Expected<StringRef> Name = getSymbolName(Symb);
     if (Name && *Name != " ") { // Blank name is local.

>From 6205ea4f65e83bb33b873b502ac6fafbacedc029 Mon Sep 17 00:00:00 2001
From: David Tenty <daltenty at ibm.com>
Date: Wed, 5 Aug 2026 17:32:21 -0400
Subject: [PATCH 08/12] clang-format

---
 llvm/unittests/Object/GOFFObjectFileTest.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/unittests/Object/GOFFObjectFileTest.cpp b/llvm/unittests/Object/GOFFObjectFileTest.cpp
index 02124b2b2a176..142666a6da077 100644
--- a/llvm/unittests/Object/GOFFObjectFileTest.cpp
+++ b/llvm/unittests/Object/GOFFObjectFileTest.cpp
@@ -711,7 +711,8 @@ TEST_F(GOFFObjectFileTest, GlobalSymbols) {
     ++Symbol;
   };
 
-  // FIXME: ESD records 'A' and 'B' should be considered symbols, but aren't returned iteration.
+  // FIXME: ESD records 'A' and 'B' should be considered symbols, but aren't
+  // returned iteration.
   ValidateGlobal("C", true);
   ValidateGlobal("D", true);
   ValidateGlobal("E", true);

>From 18b36ec707a81707927181558beb3be5a714d2bd Mon Sep 17 00:00:00 2001
From: David Tenty <daltenty.dev at gmail.com>
Date: Thu, 6 Aug 2026 13:13:31 -0400
Subject: [PATCH 09/12] Fix comment

---
 llvm/unittests/Object/GOFFObjectFileTest.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/unittests/Object/GOFFObjectFileTest.cpp b/llvm/unittests/Object/GOFFObjectFileTest.cpp
index 142666a6da077..acb8511be9851 100644
--- a/llvm/unittests/Object/GOFFObjectFileTest.cpp
+++ b/llvm/unittests/Object/GOFFObjectFileTest.cpp
@@ -711,8 +711,8 @@ TEST_F(GOFFObjectFileTest, GlobalSymbols) {
     ++Symbol;
   };
 
-  // FIXME: ESD records 'A' and 'B' should be considered symbols, but aren't
-  // returned iteration.
+  // FIXME: ESD records 'A' and 'B' should be considered symbols, but are
+  // currently skipped by the iterators.
   ValidateGlobal("C", true);
   ValidateGlobal("D", true);
   ValidateGlobal("E", true);

>From cd1908cd5c1dcd6f89a11a5cd1cade4a7ffc67a1 Mon Sep 17 00:00:00 2001
From: David Tenty <daltenty at ibm.com>
Date: Thu, 6 Aug 2026 21:09:47 -0400
Subject: [PATCH 10/12] Address comments

---
 llvm/unittests/Object/GOFFObjectFileTest.cpp | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/llvm/unittests/Object/GOFFObjectFileTest.cpp b/llvm/unittests/Object/GOFFObjectFileTest.cpp
index acb8511be9851..996cf8de703f5 100644
--- a/llvm/unittests/Object/GOFFObjectFileTest.cpp
+++ b/llvm/unittests/Object/GOFFObjectFileTest.cpp
@@ -687,7 +687,7 @@ TEST_F(GOFFObjectFileTest, GlobalSymbols) {
   GOFFObjectFile *GOFFObj =
       static_cast<GOFFObjectFile *>((*GOFFObjOrErr).get());
 
-  auto SymbolRange = GOFFObj->symbols();
+  object::GOFFObjectFile::symbol_iterator_range SymbolRange = GOFFObj->symbols();
   auto Symbol = SymbolRange.begin();
   auto ValidateGlobal = [&](StringRef Name, bool IsGlobal) {
     ASSERT_TRUE(Symbol != SymbolRange.end());
@@ -695,18 +695,13 @@ TEST_F(GOFFObjectFileTest, GlobalSymbols) {
     // Check Name.
     Expected<StringRef> SymbolNameOrErr = GOFFObj->getSymbolName(*Symbol);
     ASSERT_THAT_EXPECTED(SymbolNameOrErr, Succeeded());
-    StringRef SymbolName = SymbolNameOrErr.get();
-    EXPECT_EQ(SymbolName, Name);
+    EXPECT_EQ(*SymbolNameOrErr, Name);
 
     // Check flags.
     Expected<uint32_t> SymbolFlagsOrErr = Symbol->getFlags();
     ASSERT_THAT_EXPECTED(SymbolFlagsOrErr, Succeeded());
     uint32_t SymbolFlags = SymbolFlagsOrErr.get();
-    if (IsGlobal) {
-      EXPECT_TRUE(SymbolFlags & SymbolRef::SF_Global);
-    } else {
-      EXPECT_FALSE(SymbolFlags & SymbolRef::SF_Global);
-    }
+    EXPECT_EQ((SymbolFlags & SymbolRef::SF_Global) != 0, IsGlobal);
 
     ++Symbol;
   };

>From 0150a0cefa25186da52d5d346cbeb63139159eb3 Mon Sep 17 00:00:00 2001
From: David Tenty <daltenty at ibm.com>
Date: Thu, 6 Aug 2026 21:40:27 -0400
Subject: [PATCH 11/12] clang-format

---
 llvm/unittests/Object/GOFFObjectFileTest.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/unittests/Object/GOFFObjectFileTest.cpp b/llvm/unittests/Object/GOFFObjectFileTest.cpp
index 996cf8de703f5..1982222fc34e4 100644
--- a/llvm/unittests/Object/GOFFObjectFileTest.cpp
+++ b/llvm/unittests/Object/GOFFObjectFileTest.cpp
@@ -687,7 +687,8 @@ TEST_F(GOFFObjectFileTest, GlobalSymbols) {
   GOFFObjectFile *GOFFObj =
       static_cast<GOFFObjectFile *>((*GOFFObjOrErr).get());
 
-  object::GOFFObjectFile::symbol_iterator_range SymbolRange = GOFFObj->symbols();
+  object::GOFFObjectFile::symbol_iterator_range SymbolRange =
+      GOFFObj->symbols();
   auto Symbol = SymbolRange.begin();
   auto ValidateGlobal = [&](StringRef Name, bool IsGlobal) {
     ASSERT_TRUE(Symbol != SymbolRange.end());

>From aab44562560adbb8a04bc7b61126556814de9b41 Mon Sep 17 00:00:00 2001
From: David Tenty <daltenty at ibm.com>
Date: Fri, 7 Aug 2026 12:54:38 -0400
Subject: [PATCH 12/12] Address remaining nit

---
 llvm/unittests/Object/GOFFObjectFileTest.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/llvm/unittests/Object/GOFFObjectFileTest.cpp b/llvm/unittests/Object/GOFFObjectFileTest.cpp
index 1982222fc34e4..89096a87618cc 100644
--- a/llvm/unittests/Object/GOFFObjectFileTest.cpp
+++ b/llvm/unittests/Object/GOFFObjectFileTest.cpp
@@ -701,8 +701,7 @@ TEST_F(GOFFObjectFileTest, GlobalSymbols) {
     // Check flags.
     Expected<uint32_t> SymbolFlagsOrErr = Symbol->getFlags();
     ASSERT_THAT_EXPECTED(SymbolFlagsOrErr, Succeeded());
-    uint32_t SymbolFlags = SymbolFlagsOrErr.get();
-    EXPECT_EQ((SymbolFlags & SymbolRef::SF_Global) != 0, IsGlobal);
+    EXPECT_EQ((*SymbolFlagsOrErr & SymbolRef::SF_Global) != 0, IsGlobal);
 
     ++Symbol;
   };



More information about the llvm-commits mailing list