[Lldb-commits] [lldb] Add complete ObjectFileJSON support for sections. (PR #129916)

Greg Clayton via lldb-commits lldb-commits at lists.llvm.org
Wed Mar 5 11:23:39 PST 2025


https://github.com/clayborg created https://github.com/llvm/llvm-project/pull/129916

Sections now support specifying:
- user IDs
- file offset/size
- alignment
- flags
- bool values for fake, encrypted and thread specific sections

>From 150bbe0d8c3e2fb4e2dd324a0d9080a462eda156 Mon Sep 17 00:00:00 2001
From: Greg Clayton <clayborg at gmail.com>
Date: Wed, 5 Mar 2025 11:21:40 -0800
Subject: [PATCH] Add complete ObjectFileJSON support for sections.

Sections now support specifying:
- user IDs
- file offset/size
- alignment
- flags
- bool values for fake, encrypted and thread specific sections
---
 lldb/include/lldb/Core/Section.h              | 11 +++
 lldb/source/Core/Section.cpp                  | 34 +++++----
 .../ObjectFile/JSON/ObjectFileJSON.cpp        | 43 ++++++-----
 .../json/object-file/TestObjectFileJSON.py    | 75 +++++++++++++++++--
 4 files changed, 120 insertions(+), 43 deletions(-)

diff --git a/lldb/include/lldb/Core/Section.h b/lldb/include/lldb/Core/Section.h
index 17b3cb454949f..f0f5a0b3499c0 100644
--- a/lldb/include/lldb/Core/Section.h
+++ b/lldb/include/lldb/Core/Section.h
@@ -101,14 +101,25 @@ class SectionList {
 };
 
 struct JSONSection {
+  std::optional<lldb::user_id_t> user_id;
   std::string name;
   std::optional<lldb::SectionType> type;
   std::optional<uint64_t> address;
   std::optional<uint64_t> size;
+  std::optional<uint64_t> file_offset;
+  std::optional<uint64_t> file_size;
+  std::optional<uint64_t> log2align;
+  std::optional<uint64_t> flags;
+
   // Section permissions;
   std::optional<bool> read;
   std::optional<bool> write;
   std::optional<bool> execute;
+
+  std::optional<bool> fake;
+  std::optional<bool> encrypted;
+  std::optional<bool> thread_specific;
+
   std::vector<JSONSection> subsections;
 };
 
diff --git a/lldb/source/Core/Section.cpp b/lldb/source/Core/Section.cpp
index 608e2a5fc3093..b3a0814750aa5 100644
--- a/lldb/source/Core/Section.cpp
+++ b/lldb/source/Core/Section.cpp
@@ -160,10 +160,9 @@ const char *Section::GetTypeAsCString() const {
 }
 
 Section::Section(const ModuleSP &module_sp, ObjectFile *obj_file,
-                 user_id_t sect_id, ConstString name,
-                 SectionType sect_type, addr_t file_addr, addr_t byte_size,
-                 lldb::offset_t file_offset, lldb::offset_t file_size,
-                 uint32_t log2align, uint32_t flags,
+                 user_id_t sect_id, ConstString name, SectionType sect_type,
+                 addr_t file_addr, addr_t byte_size, lldb::offset_t file_offset,
+                 lldb::offset_t file_size, uint32_t log2align, uint32_t flags,
                  uint32_t target_byte_size /*=1*/)
     : ModuleChild(module_sp), UserID(sect_id), Flags(flags),
       m_obj_file(obj_file), m_type(sect_type), m_parent_wp(), m_name(name),
@@ -171,15 +170,14 @@ Section::Section(const ModuleSP &module_sp, ObjectFile *obj_file,
       m_file_offset(file_offset), m_file_size(file_size),
       m_log2align(log2align), m_children(), m_fake(false), m_encrypted(false),
       m_thread_specific(false), m_readable(false), m_writable(false),
-      m_executable(false), m_relocated(false), m_target_byte_size(target_byte_size) {
-}
+      m_executable(false), m_relocated(false),
+      m_target_byte_size(target_byte_size) {}
 
 Section::Section(const lldb::SectionSP &parent_section_sp,
                  const ModuleSP &module_sp, ObjectFile *obj_file,
-                 user_id_t sect_id, ConstString name,
-                 SectionType sect_type, addr_t file_addr, addr_t byte_size,
-                 lldb::offset_t file_offset, lldb::offset_t file_size,
-                 uint32_t log2align, uint32_t flags,
+                 user_id_t sect_id, ConstString name, SectionType sect_type,
+                 addr_t file_addr, addr_t byte_size, lldb::offset_t file_offset,
+                 lldb::offset_t file_size, uint32_t log2align, uint32_t flags,
                  uint32_t target_byte_size /*=1*/)
     : ModuleChild(module_sp), UserID(sect_id), Flags(flags),
       m_obj_file(obj_file), m_type(sect_type), m_parent_wp(), m_name(name),
@@ -187,7 +185,8 @@ Section::Section(const lldb::SectionSP &parent_section_sp,
       m_file_offset(file_offset), m_file_size(file_size),
       m_log2align(log2align), m_children(), m_fake(false), m_encrypted(false),
       m_thread_specific(false), m_readable(false), m_writable(false),
-      m_executable(false), m_relocated(false), m_target_byte_size(target_byte_size) {
+      m_executable(false), m_relocated(false),
+      m_target_byte_size(target_byte_size) {
   if (parent_section_sp)
     m_parent_wp = parent_section_sp;
 }
@@ -469,7 +468,6 @@ bool Section::ContainsOnlyDebugInfo() const {
   return false;
 }
 
-
 #pragma mark SectionList
 
 SectionList &SectionList::operator=(const SectionList &rhs) {
@@ -554,8 +552,7 @@ SectionSP SectionList::GetSectionAtIndex(size_t idx) const {
   return sect_sp;
 }
 
-SectionSP
-SectionList::FindSectionByName(ConstString section_dstr) const {
+SectionSP SectionList::FindSectionByName(ConstString section_dstr) const {
   SectionSP sect_sp;
   // Check if we have a valid section string
   if (section_dstr && !m_sections.empty()) {
@@ -693,7 +690,14 @@ bool fromJSON(const llvm::json::Value &value,
          o.map("address", section.address) && o.map("size", section.size) &&
          o.map("read", section.read) && o.map("write", section.write) &&
          o.map("execute", section.execute) &&
-         o.mapOptional("subsections", section.subsections);
+         o.mapOptional("subsections", section.subsections) &&
+         o.map("user_id", section.user_id) &&
+         o.map("file_offset", section.file_offset) &&
+         o.map("file_size", section.file_size) &&
+         o.map("log2align", section.log2align) &&
+         o.map("flags", section.flags) && o.map("fake", section.fake) &&
+         o.map("encrypted", section.encrypted) &&
+         o.map("thread_specific", section.thread_specific);
 }
 
 bool fromJSON(const llvm::json::Value &value, lldb::SectionType &type,
diff --git a/lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.cpp b/lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.cpp
index 0f9676b836b50..cb8ba05d461d4 100644
--- a/lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.cpp
+++ b/lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.cpp
@@ -179,39 +179,35 @@ void ObjectFileJSON::CreateSections(SectionList &unified_section_list) {
     return;
   m_sections_up = std::make_unique<SectionList>();
 
-  lldb::user_id_t id = 1;
+  lldb::user_id_t id = 0;
   for (const auto &json_section : m_sections) {
     auto make_section = [this, &id](const JSONSection &section,
                                     SectionSP parent_section_sp =
                                         nullptr) -> SectionSP {
       SectionSP section_sp;
+      auto sect_id = section.user_id.value_or(id + 1);
+      if (!section.user_id.has_value())
+        ++id;
+      const auto name = ConstString(section.name);
+      const auto sect_type = section.type.value_or(eSectionTypeCode);
+      const auto vm_addr = section.address.value_or(0);
+      const auto vm_size = section.size.value_or(0);
+      const auto file_offset = section.file_offset.value_or(0);
+      const auto file_size = section.file_size.value_or(0);
+      const auto log2align = section.log2align.value_or(0);
+      const auto flags = section.flags.value_or(0);
       if (parent_section_sp) {
         section_sp = std::make_shared<Section>(
-            parent_section_sp, GetModule(), this,
-            /*sect_id=*/id++,
-            /*name=*/ConstString(section.name),
-            /*sect_type=*/section.type.value_or(eSectionTypeCode),
-            /*file_vm_addr=*/section.address.value_or(0) -
-                parent_section_sp->GetFileAddress(),
-            /*vm_size=*/section.size.value_or(0),
-            /*file_offset=*/0,
-            /*file_size=*/0,
-            /*log2align=*/0,
-            /*flags=*/0);
+            parent_section_sp, GetModule(), this, sect_id, name, sect_type,
+            vm_addr - parent_section_sp->GetFileAddress(), vm_size, file_offset,
+            file_size, log2align, flags);
 
       } else {
         section_sp = std::make_shared<Section>(
-            GetModule(), this,
-            /*sect_id=*/id++,
-            /*name=*/ConstString(section.name),
-            /*sect_type=*/section.type.value_or(eSectionTypeCode),
-            /*file_vm_addr=*/section.address.value_or(0),
-            /*vm_size=*/section.size.value_or(0),
-            /*file_offset=*/0,
-            /*file_size=*/0,
-            /*log2align=*/0,
-            /*flags=*/0);
+            GetModule(), this, sect_id, name, sect_type, vm_addr, vm_size,
+            file_offset, file_size, log2align, flags);
       }
+      // Set permissions
       uint32_t permissions = 0;
       if (section.read.value_or(0))
         permissions |= lldb::ePermissionsReadable;
@@ -221,6 +217,9 @@ void ObjectFileJSON::CreateSections(SectionList &unified_section_list) {
         permissions |= lldb::ePermissionsExecutable;
       if (permissions)
         section_sp->SetPermissions(permissions);
+      section_sp->SetIsFake(section.fake.value_or(false));
+      section_sp->SetIsEncrypted(section.encrypted.value_or(false));
+      section_sp->SetIsThreadSpecific(section.thread_specific.value_or(false));
       return section_sp;
     };
     auto section_sp = make_section(json_section);
diff --git a/lldb/test/API/functionalities/json/object-file/TestObjectFileJSON.py b/lldb/test/API/functionalities/json/object-file/TestObjectFileJSON.py
index 510788b43d0db..03c0d11a858a7 100644
--- a/lldb/test/API/functionalities/json/object-file/TestObjectFileJSON.py
+++ b/lldb/test/API/functionalities/json/object-file/TestObjectFileJSON.py
@@ -64,6 +64,7 @@ def test_module(self):
         foo_file_addr = TEXT_file_addr + 0x100
         bar_file_addr = DATA_file_addr + 0x10
         TEXT_size = 0x222
+        text_size = 0x20
         DATA_size = 0x333
         foo_size = 0x11
         bar_size = 0x22
@@ -74,10 +75,22 @@ def test_module(self):
             "type": "sharedlibrary",
             "sections": [
                 {
+                    "user_id": 0x100,
+                    "name": "__PAGEZERO",
+                    "type": "container",
+                    "address": 0,
+                    "size": 0x100000000,
+                    "flags": 0x101
+              },
+              {
+                    "user_id": 0x200,
                     "name": "__TEXT",
                     "type": "container",
                     "address": TEXT_file_addr,
                     "size": TEXT_size,
+                    "flags": 0x202,
+                    "file_offset": 0,
+                    "file_size": TEXT_size,
                     "read": True,
                     "write": False,
                     "execute": True,
@@ -86,10 +99,29 @@ def test_module(self):
                             "name": "__text",
                             "type": "code",
                             "address": TEXT_file_addr,
-                            "size": TEXT_size,
+                            "size": text_size,
+                            "log2align": 2,
                             "read": True,
                             "write": False,
                             "execute": True,
+                        },
+                        {
+                            "name": "__fake",
+                            "address": TEXT_file_addr + 1 * text_size,
+                            "size": text_size,
+                            "fake": True
+                        },
+                        {
+                            "name": "__encrypted",
+                            "address": TEXT_file_addr + 2 * text_size,
+                            "size": text_size,
+                            "encrypted": True
+                        },
+                        {
+                            "name": "__tls",
+                            "address": TEXT_file_addr + 2 * text_size,
+                            "size": text_size,
+                            "thread_specific": True
                         }
                     ],
                 },
@@ -101,6 +133,9 @@ def test_module(self):
                     "read": True,
                     "write": True,
                     "execute": False,
+                    "flags": 0x303,
+                    "file_offset": DATA_file_addr - TEXT_file_addr,
+                    "file_size": DATA_size,
                 },
             ],
             "symbols": [
@@ -127,21 +162,34 @@ def test_module(self):
 
         TEXT_section = module.GetSectionAtIndex(0)
         self.assertTrue(TEXT_section.IsValid())
+        self.assertEqual(TEXT_section.GetName(), "__PAGEZERO")
+        self.assertEqual(TEXT_section.file_addr, 0)
+        self.assertEqual(TEXT_section.size, 0x100000000)
+        self.assertEqual(TEXT_section.GetSectionType(), lldb.eSectionTypeContainer)
+        self.assertEqual(TEXT_section.GetNumSubSections(), 0)
+        text_permissions = TEXT_section.GetPermissions()
+        self.assertFalse((text_permissions & lldb.ePermissionsReadable) != 0)
+        self.assertFalse((text_permissions & lldb.ePermissionsWritable) != 0)
+        self.assertFalse((text_permissions & lldb.ePermissionsExecutable) != 0)
+
+        TEXT_section = module.GetSectionAtIndex(1)
+        self.assertTrue(TEXT_section.IsValid())
         self.assertEqual(TEXT_section.GetName(), "__TEXT")
         self.assertEqual(TEXT_section.file_addr, TEXT_file_addr)
         self.assertEqual(TEXT_section.size, TEXT_size)
+        self.assertEqual(TEXT_section.file_offset, 0)
+        self.assertEqual(TEXT_section.file_size, TEXT_size)
         self.assertEqual(TEXT_section.GetSectionType(), lldb.eSectionTypeContainer)
-        self.assertEqual(TEXT_section.GetNumSubSections(), 1)
+        self.assertEqual(TEXT_section.GetNumSubSections(), 4)
         text_permissions = TEXT_section.GetPermissions()
         self.assertTrue((text_permissions & lldb.ePermissionsReadable) != 0)
         self.assertFalse((text_permissions & lldb.ePermissionsWritable) != 0)
         self.assertTrue((text_permissions & lldb.ePermissionsExecutable) != 0)
 
         text_section = TEXT_section.GetSubSectionAtIndex(0)
-        self.assertTrue(text_section.IsValid())
         self.assertEqual(text_section.GetName(), "__text")
-        self.assertEqual(text_section.file_addr, TEXT_file_addr)
-        self.assertEqual(text_section.size, TEXT_size)
+        self.assertEqual(text_section.size, text_size)
+        self.assertEqual(text_section.GetAlignment(), 4)
         self.assertEqual(text_section.GetSectionType(), lldb.eSectionTypeCode)
         self.assertEqual(text_section.GetNumSubSections(), 0)
         text_permissions = text_section.GetPermissions()
@@ -149,11 +197,13 @@ def test_module(self):
         self.assertFalse((text_permissions & lldb.ePermissionsWritable) != 0)
         self.assertTrue((text_permissions & lldb.ePermissionsExecutable) != 0)
 
-        DATA_section = module.GetSectionAtIndex(1)
+        DATA_section = module.GetSectionAtIndex(2)
         self.assertTrue(DATA_section.IsValid())
         self.assertEqual(DATA_section.GetName(), "__DATA")
         self.assertEqual(DATA_section.file_addr, DATA_file_addr)
         self.assertEqual(DATA_section.size, DATA_size)
+        self.assertEqual(DATA_section.file_offset, DATA_file_addr - TEXT_file_addr)
+        self.assertEqual(DATA_section.file_size, DATA_size)
         self.assertEqual(DATA_section.GetSectionType(), lldb.eSectionTypeData)
         data_permissions = DATA_section.GetPermissions()
         self.assertTrue((data_permissions & lldb.ePermissionsReadable) != 0)
@@ -170,6 +220,19 @@ def test_module(self):
         self.assertEqual(bar_symbol.addr.GetFileAddress(), bar_file_addr)
         self.assertEqual(bar_symbol.GetSize(), bar_size)
 
+        # Verify the user_ids and flags are set correctly since there is no API
+        # for this on lldb.SBSection
+        self.expect("target modules dump sections c.json",
+            substrs = [
+                "0x0000000000000100 container              [0x0000000000000000-0x0000000100000000)  ---  0x00000000 0x00000000 0x00000101 c.json.__PAGEZERO",
+                "0x0000000000000200 container              [0x0000000100000000-0x0000000100000222)  r-x  0x00000000 0x00000222 0x00000202 c.json.__TEXT",
+                "0x0000000000000001 code                   [0x0000000100000000-0x0000000100000020)  r-x  0x00000000 0x00000000 0x00000000 c.json.__TEXT.__text",
+                "0x0000000000000002 code                   [0x0000000100000020-0x0000000100000040)  ---  0x00000000 0x00000000 0x00000000 c.json.__TEXT.__fake",
+                "0x0000000000000003 code                   [0x0000000100000040-0x0000000100000060)  ---  0x00000000 0x00000000 0x00000000 c.json.__TEXT.__encrypted",
+                "0x0000000000000004 code                   [0x0000000100000040-0x0000000100000060)  ---  0x00000000 0x00000000 0x00000000 c.json.__TEXT.__tls",
+                "0x0000000000000005 data                   [0x0000000100001000-0x0000000100001333)  rw-  0x00001000 0x00000333 0x00000303 c.json.__DATA"
+            ])
+
         error = target.SetSectionLoadAddress(TEXT_section, TEXT_file_addr + slide)
         self.assertSuccess(error)
         error = target.SetSectionLoadAddress(DATA_section, DATA_file_addr + slide)



More information about the lldb-commits mailing list