[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:
Pavel Labath
2018-02-27 22:14:33 +00:00
parent 3acdc67734
commit 029fb69372
13 changed files with 505 additions and 23 deletions

View File

@@ -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);
}