mirror of
https://github.com/serge1/ELFIO.git
synced 2024-12-28 06:15:21 +00:00
483 lines
17 KiB
XML
483 lines
17 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
|
|
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
|
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
|
<!ENTITY elfio_data_members_table SYSTEM "elfio_data_members_table.docbook">
|
|
<!ENTITY elfio_members_table SYSTEM "elfio_members_table.docbook">
|
|
<!ENTITY section_members_table SYSTEM "section_members_table.docbook">
|
|
]>
|
|
|
|
<book>
|
|
<bookinfo>
|
|
<date>2002-5-25</date>
|
|
<title>ELFIO</title>
|
|
<subtitle>User's Guide</subtitle>
|
|
<authorgroup>
|
|
<author>
|
|
<firstname>Serge</firstname>
|
|
<surname>Lamikhov-Center</surname>
|
|
</author>
|
|
</authorgroup>
|
|
</bookinfo>
|
|
<toc/>
|
|
|
|
<preface id="introduction">
|
|
<title>Introduction</title>
|
|
<para>
|
|
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.
|
|
</para>
|
|
<para>
|
|
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.
|
|
</para>
|
|
</preface>
|
|
|
|
<chapter id="get-started">
|
|
<title>Getting Started With ELFIO</title>
|
|
|
|
<sect1>
|
|
<title>ELF File Reader</title>
|
|
<para>
|
|
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 <filename>elfio.hpp</filename> header file.
|
|
All ELFIO library declarations reside in ELFIO namespace.
|
|
So, this tutorial code starts from the following code:
|
|
</para>
|
|
<programlistingco>
|
|
<areaspec>
|
|
<area id="plco.include" coords='3 60'/>
|
|
<area id="plco.namespace" coords='5 60'/>
|
|
</areaspec>
|
|
<programlisting><![CDATA[
|
|
#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;
|
|
}
|
|
]]></programlisting>
|
|
<calloutlist>
|
|
<callout arearefs="plco.include">
|
|
<para>
|
|
Include <filename>elfio.hpp</filename> header file
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="plco.namespace">
|
|
<para>
|
|
The ELFIO namespace usage
|
|
</para>
|
|
</callout>
|
|
</calloutlist>
|
|
</programlistingco>
|
|
<para>
|
|
This chapter will explain how to work with the reader portion
|
|
of the ELFIO library. The first step would be creation of the <classname>elfio</classname>
|
|
class instance. The <classname>elfio</classname> constructor does not
|
|
receive any parameters. After that, we initialize the instance by
|
|
loading an ELF file with name passed as a parameter.
|
|
<programlistingco>
|
|
<areaspec>
|
|
<area id="plco.constructor" coords='3 60'/>
|
|
<area id="plco.load" coords='6 60'/>
|
|
</areaspec>
|
|
<programlisting><![CDATA[
|
|
// 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;
|
|
}
|
|
]]></programlisting>
|
|
<calloutlist>
|
|
<callout arearefs="plco.constructor">
|
|
<para>
|
|
Create <classname>elfio</classname> class instance
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="plco.load">
|
|
<para>
|
|
Initialize the instance by loading ELF file. The function
|
|
<function>load</function> returns
|
|
<returnvalue>true</returnvalue>
|
|
if the ELF file was found and processed successfully. It returns
|
|
<returnvalue>false</returnvalue> otherwise.
|
|
</para>
|
|
</callout>
|
|
</calloutlist>
|
|
</programlistingco>
|
|
</para>
|
|
|
|
<para>
|
|
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:
|
|
<programlistingco>
|
|
<areaspec>
|
|
<area id="plco.get_class" coords='4 60'/>
|
|
<area id="plco.get_encoding" coords='10 60'/>
|
|
</areaspec>
|
|
<programlisting><![CDATA[
|
|
// 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;
|
|
]]></programlisting>
|
|
<calloutlist>
|
|
<callout arearefs="plco.get_class">
|
|
<para>
|
|
Member function <function>get_class()</function> returns ELF file
|
|
class. Possible values are <constant>ELFCLASS32</constant> or
|
|
<constant>ELFCLASS64</constant>.
|
|
</para>
|
|
</callout>
|
|
<callout arearefs="plco.get_encoding">
|
|
<para>
|
|
Member function <function>get_encoding()</function> returns ELF file
|
|
format encoding. Possible values are <constant>ELFDATA2LSB</constant>
|
|
and <constant>ELFDATA2MSB</constant>.
|
|
</para>
|
|
</callout>
|
|
</calloutlist>
|
|
</programlistingco>
|
|
</para>
|
|
<note>
|
|
<para>
|
|
Standard ELF types, flags and constants
|
|
are defined in the <filename>elf_types.hpp</filename> header file.
|
|
This file is included automatically into the project.
|
|
For example: <constant>ELFCLASS32</constant>,
|
|
<constant>ELFCLASS64</constant> constants define a value for 32/64 bit
|
|
architectures. <constant>ELFDATA2LSB</constant> and
|
|
<constant>ELFDATA2MSB</constant> constants define value
|
|
for little and big endian encoding.
|
|
</para>
|
|
</note>
|
|
|
|
<para>
|
|
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.
|
|
</para>
|
|
<para>
|
|
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:
|
|
<programlisting><![CDATA[
|
|
// 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()
|
|
}
|
|
]]></programlisting>
|
|
</para>
|
|
<para>
|
|
<methodname>sections</methodname> member of <classname>reader</classname>
|
|
object permits to obtain number of sections the ELF file contains. It
|
|
also serves for getting access to individual section by using
|
|
<methodname>operator[]</methodname>, which returns a pointer to
|
|
corresponding section's interface.
|
|
</para>
|
|
|
|
<para>
|
|
Similarly, segments of the ELF file can be processed:
|
|
<programlisting><![CDATA[
|
|
// 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()
|
|
}
|
|
]]></programlisting>
|
|
In this case, segments' attributes and data are obtained by using
|
|
<methodname>segments</methodname> member of the <classname>reader</classname>.
|
|
</para>
|
|
<para>
|
|
The full text of this example comes together with ELFIO library
|
|
distribution.
|
|
</para>
|
|
</sect1>
|
|
|
|
<sect1>
|
|
<title>ELF Section Data Accessors</title>
|
|
<para>
|
|
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:
|
|
<itemizedlist mark='opencircle'>
|
|
<listitem><para>
|
|
<classname>string_section_accessor</classname>
|
|
</para></listitem>
|
|
<listitem><para>
|
|
<classname>symbol_section_accessor</classname>
|
|
</para></listitem>
|
|
<listitem><para>
|
|
<classname>relocation_section_accessor</classname>
|
|
</para></listitem>
|
|
<listitem><para>
|
|
<classname>note_section_accessor</classname>
|
|
</para></listitem>
|
|
</itemizedlist>
|
|
Definitely, it is possible to extend the library by implementing additional
|
|
accessors serving particular purposes.
|
|
</para>
|
|
<para>
|
|
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.
|
|
<programlisting><![CDATA[
|
|
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;
|
|
}
|
|
}
|
|
]]></programlisting>
|
|
We create <classname>symbol_section_accessor</classname> instance first.
|
|
Usually, accessors receive the <classname>elfio</classname> and
|
|
<classname>section*</classname> parameters for their constructors.
|
|
<methodname>get_symbol</methodname> is used to retrieve a particular entry
|
|
in the symbol table.
|
|
</para>
|
|
</sect1>
|
|
|
|
<sect1>
|
|
<title>ELFDump Utility</title>
|
|
<para>
|
|
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.
|
|
</para>
|
|
</sect1>
|
|
|
|
<sect1>
|
|
<title>ELF File Writer</title>
|
|
<para>
|
|
TODO
|
|
</para>
|
|
</sect1>
|
|
</chapter>
|
|
|
|
|
|
<chapter id="library-classes">
|
|
<title>ELFIO Library Classes</title>
|
|
|
|
<sect1>
|
|
<title>Class <classname>elfio</classname></title>
|
|
<sect2>
|
|
<title>Data members</title>
|
|
<para>
|
|
The ELFIO library's main class is <classname>elfio</classname>. The class
|
|
contains the following two public data members: sections and segments:
|
|
</para>
|
|
<para>
|
|
&elfio_data_members_table;
|
|
</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Member functions</title>
|
|
<para>
|
|
Here is the list of <classname>elfio</classname> public member functions.
|
|
Most of the functions permit to retrieve or set ELF file properties.
|
|
</para>
|
|
<para>
|
|
&elfio_members_table;
|
|
</para>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1>
|
|
<title>Class <classname>section</classname></title>
|
|
<para>
|
|
Class <classname>section</classname> has no public data members.
|
|
</para>
|
|
<sect2>
|
|
<title>Member functions</title>
|
|
<para>
|
|
Here is the list of <classname>section</classname> public member functions.
|
|
These functions permit to retrieve or set ELF file section properties.
|
|
</para>
|
|
<para>
|
|
§ion_members_table;
|
|
</para>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
</chapter>
|
|
|
|
<!--chapter id="ielfo">
|
|
<title>
|
|
<classname>IELFO</classname> - ELF File Producer Interface
|
|
</title>
|
|
<para>
|
|
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.
|
|
</para>
|
|
<para>
|
|
Just as with the reader, the first step is to get
|
|
a pointer onto the ELF File Writer (Producer):
|
|
<programlisting>
|
|
<![CDATA[
|
|
IELFO* pELFO;
|
|
ELFIO::GetInstance()->CreateELFO( &pELFO );
|
|
]]></programlisting>
|
|
</para>
|
|
<para>
|
|
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:
|
|
<programlisting>
|
|
<![CDATA[
|
|
// You can't proceed without this function call!
|
|
pELFO->SetAttr( ELFCLASS32, ELFDATA2LSB, EV_CURRENT,
|
|
ET_EXEC, EM_386, EV_CURRENT, 0 );
|
|
]]></programlisting>
|
|
</para>
|
|
<para>
|
|
Some sections of an ELF executable file should reside in the program
|
|
segments. To create this loadable segment call the
|
|
<methodname>AddSegment()</methodname> function.
|
|
<programlisting>
|
|
<![CDATA[
|
|
// Create a loadable segment
|
|
IELFOSegment* pSegment = pELFO->AddSegment( PT_LOAD,
|
|
0x08040000,
|
|
0x08040000,
|
|
PF_X | PF_R,
|
|
0x1000 );
|
|
]]></programlisting>
|
|
</para>
|
|
<para>
|
|
The following segment serves as a placeholder for our code section.
|
|
To create this code section call the AddSection() function:
|
|
<programlisting>
|
|
<![CDATA[
|
|
// Create code section
|
|
IELFOSection* pTextSec = pELFO->AddSection( ".text",
|
|
SHT_PROGBITS,
|
|
SHF_ALLOC | SHF_EXECINSTR,
|
|
0,
|
|
0x10,
|
|
0 );
|
|
]]></programlisting>
|
|
</para>
|
|
<para>
|
|
Then, add the executable code for the section:
|
|
<programlisting>
|
|
<![CDATA[
|
|
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 ) );
|
|
]]></programlisting>
|
|
</para>
|
|
<para>
|
|
Next, this code section is put into the loadable segment:
|
|
<programlisting>
|
|
<![CDATA[
|
|
// Add code section into program segment
|
|
pSegment->AddSection( pTextSec );
|
|
pTextSec->Release();
|
|
pSegment->Release();
|
|
]]></programlisting>
|
|
</para>
|
|
<para>
|
|
Finally, define the start address of the program
|
|
and create the result file:
|
|
<programlisting>
|
|
<![CDATA[
|
|
// Set program entry point
|
|
pELFO->SetEntry( 0x08040000 );
|
|
// Create ELF file
|
|
pELFO->Save( "test.elf" );
|
|
pELFO->Release();
|
|
]]></programlisting>
|
|
</para>
|
|
<para>
|
|
Please note: Call the <methodname>Release()</methodname> functions
|
|
for each interface you have used.
|
|
This will free all resources the ELFIO library has created.
|
|
</para>
|
|
<para>
|
|
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:
|
|
<programlisting>
|
|
<![CDATA[
|
|
[Writer]$ ./Writer
|
|
[Writer]$ chmod +x test.elf
|
|
[Writer]$ ./test.elf
|
|
Hello, World!
|
|
]]>
|
|
</programlisting>
|
|
</para>
|
|
<para>
|
|
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.
|
|
</para>
|
|
</chapter-->
|
|
|
|
</book>
|