mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-16 16:56:35 +00:00
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
This commit is contained in:
parent
0ea52234fc
commit
8ac359ba0d
@ -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``,
|
||||
|
@ -101,14 +101,25 @@ protected:
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -64,6 +64,7 @@ class TestObjectFileJSON(TestBase):
|
||||
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 @@ class TestObjectFileJSON(TestBase):
|
||||
"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 @@ class TestObjectFileJSON(TestBase):
|
||||
"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 @@ class TestObjectFileJSON(TestBase):
|
||||
"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 @@ class TestObjectFileJSON(TestBase):
|
||||
|
||||
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 @@ class TestObjectFileJSON(TestBase):
|
||||
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 @@ class TestObjectFileJSON(TestBase):
|
||||
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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user