BUG: A few more corrections for cmELF

- Add os-specific and processor-specific file types
  - Add more error strings for invalid files.
  - Byte order of header fields does not always match encoding
This commit is contained in:
Brad King 2008-03-02 16:19:40 -05:00
parent 34a338dcc1
commit f42c3de1d7
2 changed files with 74 additions and 11 deletions

View File

@ -77,7 +77,9 @@ public:
ByteOrder(order), ByteOrder(order),
ELFType(cmELF::FileTypeInvalid) ELFType(cmELF::FileTypeInvalid)
{ {
// Decide whether we need to byte swap fields. // In most cases the processor-specific byte order will match that
// of the target execution environment. If we choose wrong here
// it is fixed when the header is read.
#if cmsys_CPU_ENDIAN_ID == cmsys_CPU_ENDIAN_ID_LITTLE #if cmsys_CPU_ENDIAN_ID == cmsys_CPU_ENDIAN_ID_LITTLE
this->NeedSwap = (this->ByteOrder == ByteOrderMSB); this->NeedSwap = (this->ByteOrder == ByteOrderMSB);
#elif cmsys_CPU_ENDIAN_ID == cmsys_CPU_ENDIAN_ID_BIG #elif cmsys_CPU_ENDIAN_ID == cmsys_CPU_ENDIAN_ID_BIG
@ -231,6 +233,12 @@ public:
case cmELF::FileTypeCore: case cmELF::FileTypeCore:
os << " core file"; os << " core file";
break; break;
case cmELF::FileTypeSpecificOS:
os << " os-specific type";
break;
case cmELF::FileTypeSpecificProc:
os << " processor-specific type";
break;
} }
os << "\n"; os << "\n";
} }
@ -328,12 +336,46 @@ private:
bool Read(ELF_Ehdr& x) bool Read(ELF_Ehdr& x)
{ {
if(this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)) && // Read the header from the file.
this->NeedSwap) if(!this->Stream.read(reinterpret_cast<char*>(&x), sizeof(x)))
{
return false;
}
// The byte order of ELF header fields may not match that of the
// processor-specific data. The header fields are ordered to
// match the target execution environment, so we may need to
// memorize the order of all platforms based on the e_machine
// value. As a heuristic, if the type is invalid but its
// swapped value is okay then flip our swap mode.
ELF_Half et = x.e_type;
if(this->NeedSwap)
{
cmELFByteSwap(et);
}
unsigned int eti = static_cast<unsigned int>(et);
if(!(eti == ET_NONE || eti == ET_REL || eti == ET_EXEC ||
eti == ET_DYN || eti == ET_CORE ||
(eti >= ET_LOOS && eti <= ET_HIOS) ||
(eti >= ET_LOPROC && eti <= ET_HIPROC)))
{
cmELFByteSwap(et);
if(eti == ET_NONE || eti == ET_REL || eti == ET_EXEC ||
eti == ET_DYN || eti == ET_CORE ||
(eti >= ET_LOOS && eti <= ET_HIOS) ||
(eti >= ET_LOPROC && eti <= ET_HIPROC))
{
// The previous byte order guess was wrong. Flip it.
this->NeedSwap = !this->NeedSwap;
}
}
// Fix the byte order of the header.
if(this->NeedSwap)
{ {
ByteSwap(x); ByteSwap(x);
} }
return this->Stream? true:false; return true;
} }
bool Read(ELF_Shdr& x) bool Read(ELF_Shdr& x)
{ {
@ -395,26 +437,45 @@ cmELFInternalImpl<Types>
// Read the main header. // Read the main header.
if(!this->Read(this->ELFHeader)) if(!this->Read(this->ELFHeader))
{ {
this->SetErrorMessage("Failed to read main ELF header.");
return; return;
} }
// Determine the ELF file type. // Determine the ELF file type.
switch(this->ELFHeader.e_type) switch(this->ELFHeader.e_type)
{ {
case 1: case ET_NONE:
this->SetErrorMessage("No ELF file type.");
return;
case ET_REL:
this->ELFType = cmELF::FileTypeRelocatableObject; this->ELFType = cmELF::FileTypeRelocatableObject;
break; break;
case 2: case ET_EXEC:
this->ELFType = cmELF::FileTypeExecutable; this->ELFType = cmELF::FileTypeExecutable;
break; break;
case 3: case ET_DYN:
this->ELFType = cmELF::FileTypeSharedLibrary; this->ELFType = cmELF::FileTypeSharedLibrary;
break; break;
case 4: case ET_CORE:
this->ELFType = cmELF::FileTypeCore; this->ELFType = cmELF::FileTypeCore;
break; break;
default: default:
return; unsigned int et = static_cast<unsigned int>(this->ELFHeader.e_type);
if(et >= ET_LOOS && et <= ET_HIOS)
{
this->ELFType = cmELF::FileTypeSpecificOS;
break;
}
else if(et >= ET_LOPROC && et <= ET_HIPROC)
{
this->ELFType = cmELF::FileTypeSpecificProc;
break;
}
else
{
this->SetErrorMessage("Unknown ELF file type.");
return;
}
} }
// Load the section headers. // Load the section headers.
@ -423,7 +484,7 @@ cmELFInternalImpl<Types>
{ {
if(!this->LoadSectionHeader(i)) if(!this->LoadSectionHeader(i))
{ {
this->ELFType = cmELF::FileTypeInvalid; this->SetErrorMessage("Failed to load section headers.");
return; return;
} }
} }

View File

@ -51,7 +51,9 @@ public:
FileTypeRelocatableObject, FileTypeRelocatableObject,
FileTypeExecutable, FileTypeExecutable,
FileTypeSharedLibrary, FileTypeSharedLibrary,
FileTypeCore FileTypeCore,
FileTypeSpecificOS,
FileTypeSpecificProc
}; };
/** Represent string table entries. */ /** Represent string table entries. */