Open ELF core dumps with more than 64K sections
Summary: Problem: There are three filelds in the ELF header - e_phnum, e_shnum, and e_shstrndx - that could be bigger than 64K and therefore do not fit in 16 bits reserved for them in the header. If this happens, pretty often there is a special section at index 0 which contains their real values for these fields in the section header in the fields sh_info, sh_size, and sh_link respectively. Fix: - Rename original fields in the header declaration. We want to have them around just in case. - Reintroduce these fields as 32-bit members at the end of the header. By default they are initialized from the header in Parse() method. - In Parse(), detect the situation when the header might have been extended into section info #0 and try to read it from the same data source. - ObjectFileELF::GetModuleSpecifications accesses some of these fields but the original parse uses too small data source. Re-parse the header if necessary using bigger data source. - ProcessElfCore::CreateInstance uses header with potentially sentinel values, but it does not access these fields, so a comment here is enough. Reviewers: labath Reviewed By: labath Subscribers: davidb, lldb-commits, mgorny Differential Revision: https://reviews.llvm.org/D29095 Author: Eugene Birukov <eugenebi@hotmail.com> llvm-svn: 293714
This commit is contained in:
@@ -610,7 +610,8 @@ size_t ObjectFileELF::GetModuleSpecifications(
|
||||
DataExtractor data;
|
||||
data.SetData(data_sp);
|
||||
elf::ELFHeader header;
|
||||
if (header.Parse(data, &data_offset)) {
|
||||
lldb::offset_t header_offset = data_offset;
|
||||
if (header.Parse(data, &header_offset)) {
|
||||
if (data_sp) {
|
||||
ModuleSpec spec(file);
|
||||
|
||||
@@ -645,10 +646,24 @@ size_t ObjectFileELF::GetModuleSpecifications(
|
||||
__FUNCTION__, file.GetPath().c_str());
|
||||
}
|
||||
|
||||
// In case there is header extension in the section #0, the header
|
||||
// we parsed above could have sentinel values for e_phnum, e_shnum,
|
||||
// and e_shstrndx. In this case we need to reparse the header
|
||||
// with a bigger data source to get the actual values.
|
||||
size_t section_header_end = header.e_shoff + header.e_shentsize;
|
||||
if (header.HasHeaderExtension() &&
|
||||
section_header_end > data_sp->GetByteSize()) {
|
||||
data_sp = file.MemoryMapFileContentsIfLocal (file_offset,
|
||||
section_header_end);
|
||||
data.SetData(data_sp);
|
||||
lldb::offset_t header_offset = data_offset;
|
||||
header.Parse(data, &header_offset);
|
||||
}
|
||||
|
||||
// Try to get the UUID from the section list. Usually that's at the
|
||||
// end, so
|
||||
// map the file in if we don't have it already.
|
||||
size_t section_header_end =
|
||||
section_header_end =
|
||||
header.e_shoff + header.e_shnum * header.e_shentsize;
|
||||
if (section_header_end > data_sp->GetByteSize()) {
|
||||
data_sp = file.MemoryMapFileContentsIfLocal(file_offset,
|
||||
@@ -3067,10 +3082,10 @@ void ObjectFileELF::DumpELFHeader(Stream *s, const ELFHeader &header) {
|
||||
s->Printf("e_flags = 0x%8.8x\n", header.e_flags);
|
||||
s->Printf("e_ehsize = 0x%4.4x\n", header.e_ehsize);
|
||||
s->Printf("e_phentsize = 0x%4.4x\n", header.e_phentsize);
|
||||
s->Printf("e_phnum = 0x%4.4x\n", header.e_phnum);
|
||||
s->Printf("e_phnum = 0x%8.8x\n", header.e_phnum);
|
||||
s->Printf("e_shentsize = 0x%4.4x\n", header.e_shentsize);
|
||||
s->Printf("e_shnum = 0x%4.4x\n", header.e_shnum);
|
||||
s->Printf("e_shstrndx = 0x%4.4x\n", header.e_shstrndx);
|
||||
s->Printf("e_shnum = 0x%8.8x\n", header.e_shnum);
|
||||
s->Printf("e_shstrndx = 0x%8.8x\n", header.e_shstrndx);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user