Skip to content

Conversation

@clayborg
Copy link
Collaborator

@clayborg clayborg commented Mar 5, 2025

Sections now support specifying:

  • user IDs
  • file offset/size
  • alignment
  • flags
  • bool values for fake, encrypted and thread specific sections

Sections now support specifying:
- user IDs
- file offset/size
- alignment
- flags
- bool values for fake, encrypted and thread specific sections
@clayborg clayborg requested a review from JDevlieghere as a code owner March 5, 2025 19:23
@llvmbot llvmbot added the lldb label Mar 5, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 5, 2025

@llvm/pr-subscribers-lldb

Author: Greg Clayton (clayborg)

Changes

Sections now support specifying:

  • user IDs
  • file offset/size
  • alignment
  • flags
  • bool values for fake, encrypted and thread specific sections

Full diff: https://github.com/llvm/llvm-project/pull/129916.diff

4 Files Affected:

  • (modified) lldb/include/lldb/Core/Section.h (+11)
  • (modified) lldb/source/Core/Section.cpp (+19-15)
  • (modified) lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.cpp (+21-22)
  • (modified) lldb/test/API/functionalities/json/object-file/TestObjectFileJSON.py (+69-6)
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)

Copy link
Member

@JDevlieghere JDevlieghere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you also update docs/use/symbolfilejson.rst? Doesn't need to be in this PR.

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) &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about just alignment instead of log2align?

Copy link
Member

@JDevlieghere JDevlieghere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@github-actions
Copy link

github-actions bot commented Mar 7, 2025

⚠️ Python code formatter, darker found issues in your code. ⚠️

You can test this locally with the following command:
darker --check --diff -r 024362f413dbfcf8188003762c9cc299f274d76e...48fec8f9fd6fd19426943f0daf3eb6fcaf6fe8f0 lldb/test/API/functionalities/json/object-file/TestObjectFileJSON.py
View the diff from darker here.
--- TestObjectFileJSON.py	2025-03-07 23:29:50.000000 +0000
+++ TestObjectFileJSON.py	2025-03-07 23:33:27.931147 +0000
@@ -78,13 +78,13 @@
                     "user_id": 0x100,
                     "name": "__PAGEZERO",
                     "type": "container",
                     "address": 0,
                     "size": 0x100000000,
-                    "flags": 0x101
-              },
-              {
+                    "flags": 0x101,
+                },
+                {
                     "user_id": 0x200,
                     "name": "__TEXT",
                     "type": "container",
                     "address": TEXT_file_addr,
                     "size": TEXT_size,
@@ -107,24 +107,24 @@
                         },
                         {
                             "name": "__fake",
                             "address": TEXT_file_addr + 1 * text_size,
                             "size": text_size,
-                            "fake": True
+                            "fake": True,
                         },
                         {
                             "name": "__encrypted",
                             "address": TEXT_file_addr + 2 * text_size,
                             "size": text_size,
-                            "encrypted": True
+                            "encrypted": True,
                         },
                         {
                             "name": "__tls",
                             "address": TEXT_file_addr + 2 * text_size,
                             "size": text_size,
-                            "thread_specific": True
-                        }
+                            "thread_specific": True,
+                        },
                     ],
                 },
                 {
                     "name": "__DATA",
                     "type": "data",
@@ -220,20 +220,22 @@
         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 = [
+        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"
-            ])
+                "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)
         self.assertSuccess(error)

@clayborg clayborg merged commit 8ac359b into llvm:main Mar 7, 2025
6 of 10 checks passed
@clayborg clayborg deleted the objfilejson-section-extras branch March 7, 2025 23:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants