Files CCore/inc/Elf.h CCore/src/Elf.cpp
CCore has a simple ELF file parser. It is not comprehensive, but sufficient for the current purpose. The parser and related software entities are enclosed in the namespace Elf.
template <class Custom,class Dev>
void Parse(Dev &dev,PtrLen<const uint8> map);
The main parser function is called Parse. It is a template. The second parameter is a processing device type. Usually it is derived from the first argument type. But the first parameter is a Custom. It must be one of the LeOrder or BeOrder. This parameter specifies the byte-to-integer conversion method to be used by the parser during the ELF image processing. The first function argument is a processing device. The object methods are called with various piece of the image data. The second argument is a byte range, it is considered as an ELF image. An exception is thrown in case of error.
The type Dev must comply with the following pattern:
class Dev { public: void operator () (const Elf::Header &header); void operator () (ulen index,StrLen name,const Elf::SectHeader §); void operator () (ulen index,StrLen name,const Elf::SectHeader §,PtrLen<const uint8> data); void operator () (); };
The first operator is called first with a reference to the image header. This operator should check the expected image properties and throw an exception if they are not such.
The second and the third operators are called next per each image section. The first argument is the section index. The second argument is the section name. The third is a reference to the section header. Finally, if the section must be loaded the range of the section data is provided.
The last operator is called last to finish the processing.
Each of operators may throw an exception.
Header describes various properties of an ELF image.
enum BitType { BitType_32 = 1, BitType_64 = 2 }; enum EndianType { EndianType_LE = 1, EndianType_BE = 2 }; enum CPUType { CPUType_ARM = 40 }; struct Header { // +0 uint8 elf0; uint8 elf1; uint8 elf2; uint8 elf3; uint8 bit_type; uint8 endian_type; // +16 uint16 file_type; uint16 cpu_type; uint32 elf_version; uint32 entry_point; uint32 program_header_off; uint32 section_header_off; uint32 cpu_flags; uint16 header_size; uint16 program_header_size; uint16 program_header_count; uint16 section_header_size; uint16 section_header_count; uint16 section_name_section_index; bool check_id(uint8 bit_type_,uint8 endian_type_) const; bool check_cpu(uint16 cpu_type_) const; template <class P> void print(P &out) const; };
The most interesting properties are:
bit_type is the image bit type. It must be BitType_32 to proceed further.
endian_type is the image endian type.
cpu_type is the CPU type.
entry_point is the image entry point, if the image is executable.
check_id() can be used to check the expected bit type and the expected endian type.
check_cpu() can be used to check the expected CPU type.
SectHeader describes various properties of a section.
enum SectFlags { SectFlag_write = 1, SectFlag_alloc = 2, SectFlag_code = 4 }; struct SectHeader { uint32 name_off; uint32 type; uint32 flags; uint32 address; uint32 data_off; uint32 size; uint32 link; uint32 info; uint32 address_align; uint32 entry_size; template <class P> void print(P &out) const; };
The most interesting properties are:
flags is the section flags.
address is the section load address.
size is the section size.