Author: Greg Clayton Date: 2025-03-07T15:34:27-08:00 New Revision: 8ac359ba0d7ec1f1e7334a50405f0f20983b997a
URL: https://github.com/llvm/llvm-project/commit/8ac359ba0d7ec1f1e7334a50405f0f20983b997a DIFF: https://github.com/llvm/llvm-project/commit/8ac359ba0d7ec1f1e7334a50405f0f20983b997a.diff LOG: Add complete ObjectFileJSON support for sections. (#129916) Sections now support specifying: - user IDs - file offset/size - alignment - flags - bool values for fake, encrypted and thread specific sections Added: Modified: lldb/docs/use/symbolfilejson.rst lldb/include/lldb/Core/Section.h lldb/source/Core/Section.cpp lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.cpp lldb/test/API/functionalities/json/object-file/TestObjectFileJSON.py Removed: ################################################################################ diff --git a/lldb/docs/use/symbolfilejson.rst b/lldb/docs/use/symbolfilejson.rst index 9d15d704f3574..2ad28a14e9320 100644 --- a/lldb/docs/use/symbolfilejson.rst +++ b/lldb/docs/use/symbolfilejson.rst @@ -74,14 +74,61 @@ sections * ``type``: a string representing the section type (see below). * ``address``: a number representing the section file address. * ``size``: a number representing the section size in bytes. +* ``read``: a boolean value indicating if the section has read permissions. +* ``write``: a boolean value indicating if the section has write permissions. +* ``execute``: a boolean value indicating if the section has execute permissions. +* ``subsections``: An array of child sections in the same format. +* ``user_id``: a number representing the section identifier. +* ``file_offset``: a number that represents the offset in the file for this section's contents. +* ``file_size``: a number that represents the size in bytes in the file for this section's contents. +* ``alignment``: a boolean value indicating if the section has execute permissions. +* ``fake``: a boolean value indicating if the section is fake. +* ``encrypted``: a boolean value indicating if the section is encrypted. +* ``thread_specific``: a boolean value indicating if the section is thread specific. .. code-block:: JSON { - "name": "__TEXT", - "type": "code", - "address": 0, - "size": 546, + "user_id": 256, + "name": "__TEXT", + "type": "code", + "address": 0, + "size": 546, + "file_offset": 0, + "file_size": 4096, + "read": true, + "write": false, + "executable": true, + "subsections": [ + { + "name": "__text", + "type": "code", + "address": 0, + "size": 200, + "alignment": 2, + "read": true, + "write": false, + "execute": true + }, + { + "name": "__fake", + "address": 200, + "size": 10, + "fake": true + }, + { + "name": "__encrypted", + "address": 210, + "size": 20, + "encrypted": true + }, + { + "name": "__tls", + "address": 230, + "size": 30, + "thread_specific": true + } + ] } The ``type`` field accepts the following values: ``code``, ``container``, 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..27dcf987b0278 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("alignment", 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 §ion, 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..5145a6c0cd53a 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, + "alignment": 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) _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits