-
Notifications
You must be signed in to change notification settings - Fork 14.3k
Add subsection and permissions support to ObjectFileJSON. #129801
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add subsection and permissions support to ObjectFileJSON. #129801
Conversation
This patch adds the ability to create subsections in a section and allows permissions to be specified.
@llvm/pr-subscribers-lldb Author: Greg Clayton (clayborg) ChangesThis patch adds the ability to create subsections in a section and allows permissions to be specified. Full diff: https://github.com/llvm/llvm-project/pull/129801.diff 4 Files Affected:
diff --git a/lldb/include/lldb/Core/Section.h b/lldb/include/lldb/Core/Section.h
index 4bf73e2e5a068..17b3cb454949f 100644
--- a/lldb/include/lldb/Core/Section.h
+++ b/lldb/include/lldb/Core/Section.h
@@ -105,6 +105,11 @@ struct JSONSection {
std::optional<lldb::SectionType> type;
std::optional<uint64_t> address;
std::optional<uint64_t> size;
+ // Section permissions;
+ std::optional<bool> read;
+ std::optional<bool> write;
+ std::optional<bool> execute;
+ std::vector<JSONSection> subsections;
};
class Section : public std::enable_shared_from_this<Section>,
diff --git a/lldb/source/Core/Section.cpp b/lldb/source/Core/Section.cpp
index 96410a1ad497c..72a466a9bed40 100644
--- a/lldb/source/Core/Section.cpp
+++ b/lldb/source/Core/Section.cpp
@@ -690,7 +690,11 @@ bool fromJSON(const llvm::json::Value &value,
lldb_private::JSONSection §ion, llvm::json::Path path) {
llvm::json::ObjectMapper o(value, path);
return o && o.map("name", section.name) && o.map("type", section.type) &&
- o.map("address", section.address) && o.map("size", section.size);
+ 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);
}
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 8e90fac46f348..de939fdefaebb 100644
--- a/lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.cpp
+++ b/lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.cpp
@@ -180,18 +180,53 @@ void ObjectFileJSON::CreateSections(SectionList &unified_section_list) {
m_sections_up = std::make_unique<SectionList>();
lldb::user_id_t id = 1;
- for (const auto §ion : m_sections) {
- auto 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);
+ for (const auto &json_section : m_sections) {
+ auto make_section = [this, &id](const JSONSection §ion,
+ SectionSP parent_section_sp = nullptr) -> SectionSP {
+ SectionSP section_sp;
+ 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);
+
+ } 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);
+ }
+ uint32_t permissions = 0;
+ if (section.read.value_or(0))
+ permissions |= lldb::ePermissionsReadable;
+ if (section.write.value_or(0))
+ permissions |= lldb::ePermissionsWritable;
+ if (section.execute.value_or(0))
+ permissions |= lldb::ePermissionsExecutable;
+ if (permissions)
+ section_sp->SetPermissions(permissions);
+ return section_sp;
+ };
+ auto section_sp = make_section(json_section);
+ for (const auto &subsection : json_section.subsections) {
+ SectionSP subsection_sp = make_section(subsection, section_sp);
+ section_sp->GetChildren().AddSection(subsection_sp);
+ }
+
m_sections_up->AddSection(section_sp);
unified_section_list.AddSection(section_sp);
}
diff --git a/lldb/test/API/functionalities/json/object-file/TestObjectFileJSON.py b/lldb/test/API/functionalities/json/object-file/TestObjectFileJSON.py
index eee0144ad5706..255704d6e159d 100644
--- a/lldb/test/API/functionalities/json/object-file/TestObjectFileJSON.py
+++ b/lldb/test/API/functionalities/json/object-file/TestObjectFileJSON.py
@@ -75,15 +75,32 @@ def test_module(self):
"sections": [
{
"name": "__TEXT",
- "type": "code",
+ "type": "container",
"address": TEXT_file_addr,
"size": TEXT_size,
+ "read": True,
+ "write": False,
+ "execute": True,
+ "subsections": [
+ {
+ "name": "__text",
+ "type": "code",
+ "address": TEXT_file_addr,
+ "size": TEXT_size,
+ "read": True,
+ "write": False,
+ "execute": True
+ }
+ ]
},
{
"name": "__DATA",
- "type": "code",
+ "type": "data",
"address": DATA_file_addr,
"size": DATA_size,
+ "read": True,
+ "write": True,
+ "execute": False
}
],
"symbols": [
@@ -108,17 +125,43 @@ def test_module(self):
module = target.AddModule(self.toModuleSpec(json_object_file_c))
self.assertTrue(module.IsValid())
- text_section = module.GetSectionAtIndex(0)
+ TEXT_section = module.GetSectionAtIndex(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.GetSectionType(),
+ lldb.eSectionTypeContainer)
+ self.assertEqual(TEXT_section.GetNumSubSections(), 1)
+ 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.GetName(), "__text")
self.assertEqual(text_section.file_addr, TEXT_file_addr)
self.assertEqual(text_section.size, TEXT_size)
-
- data_section = module.GetSectionAtIndex(1)
- 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(text_section.GetSectionType(),
+ lldb.eSectionTypeCode)
+ self.assertEqual(text_section.GetNumSubSections(), 0)
+ 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)
+
+ DATA_section = module.GetSectionAtIndex(1)
+ 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.GetSectionType(),
+ lldb.eSectionTypeData)
+ data_permissions = DATA_section.GetPermissions()
+ self.assertTrue((data_permissions & lldb.ePermissionsReadable) != 0)
+ self.assertTrue((data_permissions & lldb.ePermissionsWritable) != 0)
+ self.assertFalse((data_permissions & lldb.ePermissionsExecutable) != 0)
foo_symbol = module.FindSymbol("foo")
self.assertTrue(foo_symbol.IsValid())
@@ -130,9 +173,9 @@ def test_module(self):
self.assertEqual(bar_symbol.addr.GetFileAddress(), bar_file_addr)
self.assertEqual(bar_symbol.GetSize(), bar_size)
- error = target.SetSectionLoadAddress(text_section, TEXT_file_addr + slide)
+ error = target.SetSectionLoadAddress(TEXT_section, TEXT_file_addr + slide)
self.assertSuccess(error)
- error = target.SetSectionLoadAddress(data_section, DATA_file_addr + slide)
+ error = target.SetSectionLoadAddress(DATA_section, DATA_file_addr + slide)
self.assertSuccess(error)
self.assertEqual(foo_symbol.addr.GetLoadAddress(target), foo_file_addr + slide)
self.assertEqual(bar_symbol.addr.GetLoadAddress(target), bar_file_addr + slide)
|
You can test this locally with the following command:darker --check --diff -r 7b596ce362829281ea73b576774ce90bb212138d...bf7e4a6c6079262adec17134debf1022450e05f7 lldb/test/API/functionalities/json/object-file/TestObjectFileJSON.py View the diff from darker here.--- TestObjectFileJSON.py 2025-03-04 23:41:27.000000 +0000
+++ TestObjectFileJSON.py 2025-03-05 00:08:39.394202 +0000
@@ -87,23 +87,23 @@
"type": "code",
"address": TEXT_file_addr,
"size": TEXT_size,
"read": True,
"write": False,
- "execute": True
+ "execute": True,
}
- ]
+ ],
},
{
"name": "__DATA",
"type": "data",
"address": DATA_file_addr,
"size": DATA_size,
"read": True,
"write": True,
- "execute": False
- }
+ "execute": False,
+ },
],
"symbols": [
{
"name": "foo",
"type": "code",
@@ -128,12 +128,11 @@
TEXT_section = module.GetSectionAtIndex(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.GetSectionType(),
- lldb.eSectionTypeContainer)
+ self.assertEqual(TEXT_section.GetSectionType(), lldb.eSectionTypeContainer)
self.assertEqual(TEXT_section.GetNumSubSections(), 1)
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)
@@ -141,12 +140,11 @@
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.GetSectionType(),
- lldb.eSectionTypeCode)
+ self.assertEqual(text_section.GetSectionType(), lldb.eSectionTypeCode)
self.assertEqual(text_section.GetNumSubSections(), 0)
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)
@@ -154,12 +152,11 @@
DATA_section = module.GetSectionAtIndex(1)
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.GetSectionType(),
- lldb.eSectionTypeData)
+ self.assertEqual(DATA_section.GetSectionType(), lldb.eSectionTypeData)
data_permissions = DATA_section.GetPermissions()
self.assertTrue((data_permissions & lldb.ePermissionsReadable) != 0)
self.assertTrue((data_permissions & lldb.ePermissionsWritable) != 0)
self.assertFalse((data_permissions & lldb.ePermissionsExecutable) != 0)
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
This patch adds the ability to create subsections in a section and allows permissions to be specified.
This patch adds the ability to create subsections in a section and allows permissions to be specified.