Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 51 additions & 4 deletions lldb/docs/use/symbolfilejson.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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``,
Expand Down
11 changes: 11 additions & 0 deletions lldb/include/lldb/Core/Section.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

Expand Down
34 changes: 19 additions & 15 deletions lldb/source/Core/Section.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,34 +160,33 @@ 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),
m_file_addr(file_addr), m_byte_size(byte_size),
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),
m_file_addr(file_addr), m_byte_size(byte_size),
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;
}
Expand Down Expand Up @@ -469,7 +468,6 @@ bool Section::ContainsOnlyDebugInfo() const {
return false;
}


#pragma mark SectionList

SectionList &SectionList::operator=(const SectionList &rhs) {
Expand Down Expand Up @@ -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()) {
Expand Down Expand Up @@ -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,
Expand Down
43 changes: 21 additions & 22 deletions lldb/source/Plugins/ObjectFile/JSON/ObjectFileJSON.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand All @@ -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
}
],
},
Expand All @@ -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": [
Expand All @@ -127,33 +162,48 @@ 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()
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)
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)
Expand All @@ -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)
Expand Down
Loading