[lldb] Use vFlash commands when writing to target's flash memory regions
Summary: When writing an object file over gdb-remote, use the vFlashErase, vFlashWrite, and vFlashDone commands if the write address is in a flash memory region. A bare metal target may have this kind of setup. - Update ObjectFileELF to set load addresses using physical addresses. A typical case may be a data section with a physical address in ROM and a virtual address in RAM, which should be loaded to the ROM address. - Add support for querying the target's qXfer:memory-map, which contains information about flash memory regions, leveraging MemoryRegionInfo data structures with minor modifications - Update ProcessGDBRemote to use vFlash commands in DoWriteMemory when the target address is in a flash region Original discussion at http://lists.llvm.org/pipermail/lldb-dev/2018-January/013093.html Reviewers: clayborg, labath Reviewed By: labath Subscribers: arichardson, emaste, mgorny, lldb-commits Differential Revision: https://reviews.llvm.org/D42145 Patch by Owen Shaw <llvm@owenpshaw.net> llvm-svn: 326261
This commit is contained in:
@@ -827,7 +827,7 @@ bool ObjectFileELF::SetLoadAddress(Target &target, lldb::addr_t value,
|
||||
// of the sections that have SHF_ALLOC in their flag bits.
|
||||
SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
|
||||
if (section_sp && section_sp->Test(SHF_ALLOC)) {
|
||||
lldb::addr_t load_addr = section_sp->GetFileAddress();
|
||||
lldb::addr_t load_addr = GetSectionPhysicalAddress(section_sp);
|
||||
// We don't want to update the load address of a section with type
|
||||
// eSectionTypeAbsoluteAddress as they already have the absolute load
|
||||
// address
|
||||
@@ -3470,3 +3470,40 @@ size_t ObjectFileELF::ReadSectionData(Section *section,
|
||||
section_data.SetData(buffer_sp);
|
||||
return buffer_sp->GetByteSize();
|
||||
}
|
||||
|
||||
bool ObjectFileELF::AnySegmentHasPhysicalAddress() {
|
||||
size_t header_count = ParseProgramHeaders();
|
||||
for (size_t i = 1; i <= header_count; ++i) {
|
||||
auto header = GetProgramHeaderByIndex(i);
|
||||
if (header->p_paddr != 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const elf::ELFProgramHeader *
|
||||
ObjectFileELF::GetSectionSegment(SectionSP section_sp) {
|
||||
auto section_size = section_sp->GetFileSize();
|
||||
if (section_size == 0)
|
||||
section_size = 1;
|
||||
size_t header_count = ParseProgramHeaders();
|
||||
for (size_t i = 1; i <= header_count; ++i) {
|
||||
auto header = GetProgramHeaderByIndex(i);
|
||||
if (section_sp->GetFileOffset() >= header->p_offset &&
|
||||
section_sp->GetFileOffset() + section_size <=
|
||||
header->p_offset + header->p_filesz)
|
||||
return header;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
addr_t ObjectFileELF::GetSectionPhysicalAddress(SectionSP section_sp) {
|
||||
auto segment = GetSectionSegment(section_sp);
|
||||
if (segment == nullptr)
|
||||
return section_sp->GetFileAddress();
|
||||
if (segment->p_type != PT_LOAD)
|
||||
return LLDB_INVALID_ADDRESS;
|
||||
auto base_address =
|
||||
AnySegmentHasPhysicalAddress() ? segment->p_paddr : segment->p_vaddr;
|
||||
return base_address + (section_sp->GetFileOffset() - segment->p_offset);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user