diff --git a/doc/build.sh b/doc/build.sh new file mode 100644 index 0000000..274e7a5 --- /dev/null +++ b/doc/build.sh @@ -0,0 +1,2 @@ +xsltproc -o elfio.fo /usr/share/xml/docbook/stylesheet/docbook-xsl/fo/docbook.xsl elfio.docbook +fop -fo elfio.fo -pdf elfio.pdf diff --git a/doc/elfio.html b/doc/elfio.html deleted file mode 100644 index 14089da..0000000 --- a/doc/elfio.html +++ /dev/null @@ -1,428 +0,0 @@ -
Table of Contents
List of Tables
- ELFIO is a C++ library for reading and generating files in ELF binary - format. This library is independent and does not require any other product. - It is also cross-platform - the library uses standard ANSI C++ constructions - and runs on wide variety of architectures. -
- While the library's implementation does make your work much easier: basic - knowledge of the ELF binary format is required. Information about ELF - format can be found widely on the web. -
- The ELFIO library is a header only library. No preparatory compilation
- steps are required. To make your application be aware about the
- ELFIO classes and types declarations, just include elfio.hpp
header file.
- All ELFIO library declarations reside in ELFIO namespace.
- So, this tutorial code starts from the following code:
-
-#include <iostream> -#include <elfio.hpp> - -using namespace ELFIO; - -int main( int argc, char** argv ) -{ - if ( argc != 2 ) { - std::cout << "Usage: tutorial <elf_file>" << std::endl; - return 1; - } -
- Include | |
- The ELFIO namespace usage - |
- This chapter will explain how to work with the reader portion
- of the ELFIO library. The first step would be creation of the elfio
- class instance. The elfio
constructor does not
- receive any parameters. After creation of a class object, we initialize
- the instance by invoking load
function
- passing ELF file name as a parameter.
-
- // Create an elfio reader - elfio reader; - - // Load ELF data - if ( !reader.load( argv[1] ) ) { - std::cout << "Can't find or process ELF file " << argv[1] << std::endl; - return 2; - } -
- Create | |
- Initialize the instance by loading ELF file. The function
- |
-
- From here, ELF header properties are accessible. This makes it possible - to request file parameters such as encoding, machine type, - entry point, etc. To get the class and the encoding of the file use: -
- // Print ELF file properties - std::cout << "ELF file class : "; - if ( reader.get_class() == ELFCLASS32 ) - std::cout << "ELF32" << std::endl; - else - std::cout << "ELF64" << std::endl; - - std::cout << "ELF file encoding : "; - if ( reader.get_encoding() == ELFDATA2LSB ) - std::cout << "Little endian" << std::endl; - else - std::cout << "Big endian" << std::endl; -
- Member function | |
- Member function |
-
- Standard ELF types, flags and constants
- are defined in the elf_types.hpp
header file.
- This file is included automatically into the project.
- For example: ELFCLASS32
,
- ELFCLASS64
constants define a value for 32/64 bit
- architectures. ELFDATA2LSB
and
- ELFDATA2MSB
constants define value
- for little and big endian encoding.
-
- ELF binary files may consist of several sections. Each section has it's own - responsibility: some contain executable code; others describe program - dependencies; others symbol tables and so on. See ELF binary format - documentation for a full description of each section. -
- The following code demonstrates how to find out the amount of sections - the ELF file contains. The code also presents how to access particular - section properties like names and sizes: -
- // Print ELF file sections info - Elf_Half sec_num = reader.sections.size(); - std::cout << "Number of sections: " << sec_num << std::endl; - for ( int i = 0; i < sec_num; ++i ) { - const section* psec = reader.sections[i]; - std::cout << " [" << i << "] " - << psec->get_name() - << "\t" - << psec->get_size() - << std::endl; - // Access to section's data - // const char* p = reader.sections[i]->get_data() - } -
-
- sections
member of reader
- object permits to obtain number of sections the ELF file contains. It
- also serves for getting access to individual section by using
- operator[]
, which returns a pointer to
- corresponding section's interface.
-
- Similarly, segments of the ELF file can be processed: -
- // Print ELF file segments info - Elf_Half seg_num = reader.segments.size(); - std::cout << "Number of segments: " << seg_num << std::endl; - for ( int i = 0; i < seg_num; ++i ) { - const segment* pseg = reader.segments[i]; - std::cout << " [" << i << "] 0x" << std::hex - << pseg->get_flags() - << "\t0x" - << pseg->get_virtual_address() - << "\t0x" - << pseg->get_file_size() - << "\t0x" - << pseg->get_memory_size() - << std::endl; - // Access to segments's data - // const char* p = reader.segments[i]->get_data() - } -
- In this case, segments' attributes and data are obtained by using
- segments
member of the reader
.
-
- The full text of this example comes together with ELFIO library - distribution. -
- To simplify creation and interpretation of the ELF sections' data, - the ELFIO library comes with auxiliary classes - accessors. To the moment - of this document writing, the following accessors are available: -
- string_section_accessor
-
- symbol_section_accessor
-
- relocation_section_accessor
-
- note_section_accessor
-
- Definitely, it is possible to extend the library by implementing additional - accessors serving particular purposes. -
- Let's see how the accessors can be used with the previous ELF file reader - example. For this example purposes, we will print out all symbols in a - symbol section. -
- if ( psec->get_type() == SHT_SYMTAB ) { - const symbol_section_accessor symbols( reader, psec ); - for ( unsigned int j = 0; j < symbols.get_symbols_num(); ++j ) { - std::string name; - Elf64_Addr value; - Elf_Xword size; - unsigned char bind; - unsigned char type; - Elf_Half section_index; - unsigned char other; - - symbols.get_symbol( j, name, value, size, bind, - type, section_index, other ); - std::cout << j << " " << name << std::endl; - } - } -
- We create symbol_section_accessor
instance first.
- Usually, accessors receive the elfio
and
- section*
parameters for their constructors.
- get_symbol
is used to retrieve a particular entry
- in the symbol table.
-
- The source code for the ELF Dumping Utility can be found in - the "examples" directory; there also located more examples on how - to use different ELFIO reader interfaces. -
Table of Contents
- The ELFIO library's main class is elfio
. The class
- contains the following two public data members: sections and segments:
-
-
Table 2.1. Class elfio
member functions
Data member | Description |
---|---|
- sections - | - The container stores ELFIO library section instances. - Implements operator[] and size(). operator[] permits access to - individual ELF file section according to its index. - |
- segments - | - The container stores ELFIO library segment instances. - Implements operator[] and size(). operator[] permits access to - individual ELF file segment according to its index. - |
-
-
- Here is the list of elfio
public member functions.
- Most of the functions permit to retrieve or set ELF file properties.
-
-
Table 2.2. Class elfio
member functions
Function | Description | ||||||
---|---|---|---|---|---|---|---|
-
| - The constructor. - | ||||||
-
| - The destructor. - | ||||||
-
unsigned char file_class
- ;unsigned char encoding
- ; |
- Cleans and initializes empty elfio object.
- file_class is either ELFCLASS32 or ELFCLASS64.
- file_class is either ELFDATA2LSB or ELFDATA2MSB.
- | ||||||
-
const std::string& file_name
- ; |
- Initializes elfio object by loading data
- from ELF binary file. File name provided in file_name .
- Returns true if the file was processed successfully.
- | ||||||
-
const std::string& file_name
- ; |
- Creates a file in ELF binary format. File name provided in file_name .
- Returns true if the file was created successfully.
- | ||||||
-
| - Returns ELF file class. Possible values are ELFCLASS32 or ELFCLASS64. - | ||||||
-
| - Returns ELF file format version. - | ||||||
-
| - Returns ELF file format encoding. Possible values are ELFDATA2LSB and - ELFDATA2MSB. - | ||||||
-
| - Identifies the object file version. - | ||||||
-
| - Returns the ELF header's size in bytes. - | ||||||
-
| - Returns a section's entry size in ELF file header section table. - | ||||||
-
| - Returns a segment's entry size in ELF file header program table. - | ||||||
-
| - Returns operating system ABI identification. - | ||||||
-
unsigned char value
- ; | - Sets operating system ABI identification. - | ||||||
-
| - Returns ABI version. - | ||||||
-
unsigned char value
- ; | - Sets ABI version. - | ||||||
-
| - Returns the object file type. - | ||||||
-
Elf_Half value
- ; | - Sets the object file type. - | ||||||
-
| - Returns the object file's architecture. - | ||||||
-
Elf_Half value
- ; | - Sets the object file's architecture. - | ||||||
-
| - Returns processor-specific flags associated with the file. - | ||||||
-
Elf_Word value
- ; | - Sets processor-specific flags associated with the file. - |
-
-
-
Table 2.3. Class elfio
member functions (continue)
Function | Description | |||
---|---|---|---|---|
-
| - Returns the virtual address to which the system first transfers control. - | |||
-
Elf64_Addr value
- ; | - Sets the virtual address to which the system first transfers control. - | |||
-
| - Returns the section header table's file offset in bytes. - | |||
-
Elf64_Off value
- ; | - Sets the section header table's file offset. Attention! - The value can be overridden by the library, when it creates new ELF - file layout. - | |||
-
| - Returns the program header table's file offset. - | |||
-
Elf64_Off value
- ; | - Sets the program header table's file offset. Attention! - The value can be overridden by the library, when it creates new ELF - file layout. - | |||
-
| - Returns the section header table index of the entry associated with - the section name string table. - | |||
-
Elf_Half value
- ; | - Sets the section header table index of the entry associated with - the section name string table. - | |||
-
|
- Returns endianess convertor reference for the specific
- elfio object instance.
- | |||
-
Elf_Word section_type
- ; | - Returns default entry size for known section types having different values - on 32 and 64 bit architectures. At the moment, only SHT_RELA, SHT_REL, - SHT_SYMTAB and SHT_DYNAMIC are 'known' section types. The function - returns 0 for other section types. - |
-
-
- Class section
has no public data members.
-
The ELFIO library consists of two independent parts: ELF File Reader - (IELFI) - and ELF Producer (IELFO). - Each is represented by its own set of interfaces. - The library does not contain any classes that need to be explicitly - instantiated. ELFIO itself provides the interfaces that - are used to access the library's functionality. -
-To make the program recognize all ELFIO interface classes, the ELFIO.h - header file is needed. This header file defines all - standard definitions from the TIS documentation. -
#include <ELFIO.h>- -
This chapter will explain how to work with the reader component - of the ELFIO library. The first step is to get a pointer - onto the ELF File Reader: -
IELFI* pReader; - ELFIO::GetInstance()->CreateELFI( &pReader );- -
Now, that there is a pointer on the IELFI - interface: initialize the object by loading the ELF file: -
char* filename = "file.o"; - pReader->Load( filename );- -
From here, there is access to the ELF header. This makes it possible to request file - parameters such as encoding, machine type, entry point, etc. - To get the encoding of the file use: -
unsigned char encoding = pReader->GetEncoding();- -
Please note: standard types and constants from the TIS document are defined - in the ELFTypes.h header file. This file is included automatically into the - project. For example: ELFDATA2LSB and ELFDATA2MSB constants - define a value for little and big endian encoding. -
-The source code for the ELF Dumping Utility can be found in the "Examples" - directory; included there are more examples on how to use different ELFIO - reader interfaces. -
-ELFIO: Tutorial | ||
---|---|---|
Prev |
The ELFIO library can help you build a very short ELF executable file. - This chapter shows how to build an executable file that will run on - x86 Linux machines and print "Hello World!" on your console. -
-Just as with the reader, the first step is to get - a pointer onto the ELF File Writer (Producer): -
IELFO* pELFO; - ELFIO::GetInstance()->CreateELFO( &pELFO );- -
Before continuing, the library must be informed about the main - attributes of the executable file to be built. To do this, declare - that the executable ELF file will run on a 32 bit x86 machine; has little - endian encoding and uses the current version of the ELF file format: -
// You can't proceed without this function call! - pELFO->SetAttr( ELFCLASS32, ELFDATA2LSB, EV_CURRENT, - ET_EXEC, EM_386, EV_CURRENT, 0 );- -
Some sections of an ELF executable file should reside in the program - segments. To create this loadable segment call the - AddSegment() function. -
// Create a loadable segment - IELFOSegment* pSegment = pELFO->AddSegment( PT_LOAD, - 0x08040000, - 0x08040000, - PF_X | PF_R, - 0x1000 );- -
The following segment serves as a placeholder for our code section. To create - this code section call the AddSection() function: -
// Create code section - IELFOSection* pTextSec = pELFO->AddSection( ".text", - SHT_PROGBITS, - SHF_ALLOC | SHF_EXECINSTR, - 0, - 0x10, - 0 );- -
Then, add the executable code for the section: -
char text[] = - { '\xB8', '\x04', '\x00', '\x00', '\x00', // mov eax, 4 - '\xBB', '\x01', '\x00', '\x00', '\x00', // mov ebx, 1 - '\xB9', '\xFD', '\x00', '\x04', '\x08', // mov ecx, msg - '\xBA', '\x0E', '\x00', '\x00', '\x00', // mov edx, 14 - '\xCD', '\x80', // int 0x80 - '\xB8', '\x01', '\x00', '\x00', '\x00', // mov eax, 1 - '\xCD', '\x80', // int 0x80 - '\x48', '\x65', '\x6C', '\x6C', '\x6F', // db 'Hello' - '\x2C', '\x20', '\x57', '\x6F', '\x72', // db ', Wor' - '\x6C', '\x64', '\x21', '\x0A' // db 'ld!', 10 - }; - pTextSec->SetData( text, sizeof( text ) );- -
Next, this code section is put into the loadable segment: -
// Add code section into program segment - pSegment->AddSection( pTextSec ); - pTextSec->Release(); - pSegment->Release();- -
Finally, define the start address of the program - and create the result file: -
// Set program entry point - pELFO->SetEntry( 0x08040000 ); - // Create ELF file - pELFO->Save( "test.elf" ); - pELFO->Release();- -
Please note: Call the Release() functions - for each interface you have used. - This will free all resources the ELFIO library has created. -
-Now compile the program and run it. The result is a new ELF file - called "test.elf". The size of this working executable file is only - 267 bytes! Run it on your Linux machine with the following commands: -
[Writer]$ ./Writer - [Writer]$ chmod +x test.elf - [Writer]$ ./test.elf - Hello, World!- -
The full text for this program can be found in the "Writer" directory. - Also, in the "Examples" directory, two other programs "WriteObj" - and "WriteObj2" demonstrate the creation of ELF object files. -
-ELFIO is a C++ library for reading and generating files - in the ELF binary format. This library is unique and not based on - any other product. It is also platform independent. - The library uses standard ANSI C++ constructions and - runs on a wide variety of architectures. -
-While the library's implementation does make your work easier: - a basic knowledge of the ELF binary format is required. Information about ELF - is included in the TIS (Tool Interface Standards) documentation you received - with the library's source code. -
-Next | ||
Introduction |
ELF binary files consist of several sections. Each section has it's own - responsibility: some contain executable code; others describe program dependencies; - others symbol tables and so on. See the TIS documentation for a full description of each section. -
-To see how many sections the ELF file contains, including their - names and sizes, is demonstated in the following code: -
int nSecNo = pReader->GetSectionsNum(); - for ( int i = 0; i < nSecNo; ++i ) { // For all sections - const IELFISection* pSec = pReader->GetSection( i ); - std::cout << pSec->GetName() << '' '' - << pSec->GetSize() << std::endl; - pSec->Release(); - }- -
First, the number of sections are received; next, a pointer - on the IELFISection interface. Using this interface, - access is gained to the different section attributes: size, type, flags and address. - To get a buffer that contains the section's bytes use the - GetData() member function of this interface. - See the IELFISection declaration for a full - description of the IELFISection interface. -
-After the section data is received through the GetData() - function call, the data can be manipulated. - There are special sections - that provide information in predefined forms. The ELFIO library - processes these sections. The library provides a set of - section readers that understand these predefined formats and how to process their data. - The ELFIO.h header file currently defines the types of readers as: -
enum ReaderType { - ELFI_STRING, // Strings reader - ELFI_SYMBOL, // Symbol table reader - ELFI_RELOCATION, // Relocation table reader - ELFI_NOTE, // Notes reader - ELFI_DYNAMIC, // Dynamic section reader - ELFI_HASH // Hash - };- -
How to use the symbol table reader will be demonstated in the following example: -
-First, get the symbol section: -
const IELFISection* pSec = pReader->GetSection( ''.symtab'' );- -
Second, create a symbol section reader: -
IELFISymbolTable* pSymTbl = 0; - pReader->CreateSectionReader( IELFI::ELFI_SYMBOL, - pSec, - (void**)&pSymTbl );- -
And finally, use the section reader to process all entries - (print operations are omitted): -
std::string name; - Elf32_Addr value; - Elf32_Word size; - unsigned char bind; - unsigned char type; - Elf32_Half section; - int nSymNo = pSymTbl->GetSymbolNum(); - if ( 0 < nSymNo ) { - for ( int i = 0; i < nSymNo; ++i ) { - pSymTbl->GetSymbol( i, name, value, size, - bind, type, section ); - } - } - pSymTbl->Release(); - pSec->Release();- -
All interfaces from the ELFIO library should be freed after - use. Each interface has a Release() function. - It is not enough to only free the high level interface because - one of the sections or readers will still be held and its resources will not be cleared. -
-The interfaces are freed immediately after their use, in this - example we will free only the pReader object: -
pReader->Release();- -