165042b18Sopenharmony_ci/*
265042b18Sopenharmony_ciCopyright (C) 2001-present by Serge Lamikhov-Center
365042b18Sopenharmony_ci
465042b18Sopenharmony_ciPermission is hereby granted, free of charge, to any person obtaining a copy
565042b18Sopenharmony_ciof this software and associated documentation files (the "Software"), to deal
665042b18Sopenharmony_ciin the Software without restriction, including without limitation the rights
765042b18Sopenharmony_cito use, copy, modify, merge, publish, distribute, sublicense, and/or sell
865042b18Sopenharmony_cicopies of the Software, and to permit persons to whom the Software is
965042b18Sopenharmony_cifurnished to do so, subject to the following conditions:
1065042b18Sopenharmony_ci
1165042b18Sopenharmony_ciThe above copyright notice and this permission notice shall be included in
1265042b18Sopenharmony_ciall copies or substantial portions of the Software.
1365042b18Sopenharmony_ci
1465042b18Sopenharmony_ciTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1565042b18Sopenharmony_ciIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1665042b18Sopenharmony_ciFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1765042b18Sopenharmony_ciAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1865042b18Sopenharmony_ciLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1965042b18Sopenharmony_ciOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2065042b18Sopenharmony_ciTHE SOFTWARE.
2165042b18Sopenharmony_ci*/
2265042b18Sopenharmony_ci
2365042b18Sopenharmony_ci/*
2465042b18Sopenharmony_ci * This example shows how to create ELF executable file for Linux on x86-64
2565042b18Sopenharmony_ci *
2665042b18Sopenharmony_ci * Instructions:
2765042b18Sopenharmony_ci * 1. Compile and link this file with ELFIO library
2865042b18Sopenharmony_ci *    g++ writer.cpp -o writer
2965042b18Sopenharmony_ci * 2. Execute result file writer
3065042b18Sopenharmony_ci *    ./writer
3165042b18Sopenharmony_ci * 3. Add executable flag for the output file
3265042b18Sopenharmony_ci *    chmod +x hello_x86_64
3365042b18Sopenharmony_ci * 4. Run the result file:
3465042b18Sopenharmony_ci *    ./hello_x86_64
3565042b18Sopenharmony_ci */
3665042b18Sopenharmony_ci
3765042b18Sopenharmony_ci#include <elfio/elfio.hpp>
3865042b18Sopenharmony_ci
3965042b18Sopenharmony_ciusing namespace ELFIO;
4065042b18Sopenharmony_ci
4165042b18Sopenharmony_ciconst Elf64_Addr CODE_ADDR = 0x00401000;
4265042b18Sopenharmony_ciconst Elf_Xword  PAGE_SIZE = 0x1000;
4365042b18Sopenharmony_ciconst Elf64_Addr DATA_ADDR = CODE_ADDR + PAGE_SIZE;
4465042b18Sopenharmony_ci
4565042b18Sopenharmony_ciint main( void )
4665042b18Sopenharmony_ci{
4765042b18Sopenharmony_ci    elfio writer;
4865042b18Sopenharmony_ci
4965042b18Sopenharmony_ci    // You can't proceed without this function call!
5065042b18Sopenharmony_ci    writer.create( ELFCLASS64, ELFDATA2LSB );
5165042b18Sopenharmony_ci
5265042b18Sopenharmony_ci    writer.set_os_abi( ELFOSABI_LINUX );
5365042b18Sopenharmony_ci    writer.set_type( ET_EXEC );
5465042b18Sopenharmony_ci    writer.set_machine( EM_X86_64 );
5565042b18Sopenharmony_ci
5665042b18Sopenharmony_ci    // Create code section
5765042b18Sopenharmony_ci    section* text_sec = writer.sections.add( ".text" );
5865042b18Sopenharmony_ci    text_sec->set_type( SHT_PROGBITS );
5965042b18Sopenharmony_ci    text_sec->set_flags( SHF_ALLOC | SHF_EXECINSTR );
6065042b18Sopenharmony_ci    text_sec->set_addr_align( 0x10 );
6165042b18Sopenharmony_ci
6265042b18Sopenharmony_ci    // Add data into it
6365042b18Sopenharmony_ci    char text[] = {
6465042b18Sopenharmony_ci        '\xB8', '\x04', '\x00', '\x00', '\x00', // mov eax, 4
6565042b18Sopenharmony_ci        '\xBB', '\x01', '\x00', '\x00', '\x00', // mov ebx, 1
6665042b18Sopenharmony_ci        '\xB9', '\x00', '\x00', '\x00', '\x00', // mov ecx, msg
6765042b18Sopenharmony_ci        '\xBA', '\x0E', '\x00', '\x00', '\x00', // mov edx, 14
6865042b18Sopenharmony_ci        '\xCD', '\x80',                         // int 0x80
6965042b18Sopenharmony_ci        '\xB8', '\x01', '\x00', '\x00', '\x00', // mov eax, 1
7065042b18Sopenharmony_ci        '\xCD', '\x80'                          // int 0x80
7165042b18Sopenharmony_ci    };
7265042b18Sopenharmony_ci    // Adjust data address for 'msg'
7365042b18Sopenharmony_ci    *(uint32_t*)( text + 11 ) = DATA_ADDR;
7465042b18Sopenharmony_ci
7565042b18Sopenharmony_ci    text_sec->set_data( text, sizeof( text ) );
7665042b18Sopenharmony_ci
7765042b18Sopenharmony_ci    // Create a loadable segment
7865042b18Sopenharmony_ci    segment* text_seg = writer.segments.add();
7965042b18Sopenharmony_ci    text_seg->set_type( PT_LOAD );
8065042b18Sopenharmony_ci    text_seg->set_virtual_address( CODE_ADDR );
8165042b18Sopenharmony_ci    text_seg->set_physical_address( CODE_ADDR );
8265042b18Sopenharmony_ci    text_seg->set_flags( PF_X | PF_R );
8365042b18Sopenharmony_ci    text_seg->set_align( PAGE_SIZE );
8465042b18Sopenharmony_ci
8565042b18Sopenharmony_ci    // Add code section into program segment
8665042b18Sopenharmony_ci    text_seg->add_section( text_sec, text_sec->get_addr_align() );
8765042b18Sopenharmony_ci
8865042b18Sopenharmony_ci    // Create data section
8965042b18Sopenharmony_ci    section* data_sec = writer.sections.add( ".data" );
9065042b18Sopenharmony_ci    data_sec->set_type( SHT_PROGBITS );
9165042b18Sopenharmony_ci    data_sec->set_flags( SHF_ALLOC | SHF_WRITE );
9265042b18Sopenharmony_ci    data_sec->set_addr_align( 0x4 );
9365042b18Sopenharmony_ci
9465042b18Sopenharmony_ci    char data[] = {
9565042b18Sopenharmony_ci        '\x48', '\x65', '\x6C', '\x6C', '\x6F', // msg: db   'Hello, World!', 10
9665042b18Sopenharmony_ci        '\x2C', '\x20', '\x57', '\x6F', '\x72',
9765042b18Sopenharmony_ci        '\x6C', '\x64', '\x21', '\x0A' };
9865042b18Sopenharmony_ci    data_sec->set_data( data, sizeof( data ) );
9965042b18Sopenharmony_ci
10065042b18Sopenharmony_ci    // Create a read/write segment
10165042b18Sopenharmony_ci    segment* data_seg = writer.segments.add();
10265042b18Sopenharmony_ci    data_seg->set_type( PT_LOAD );
10365042b18Sopenharmony_ci    data_seg->set_virtual_address( DATA_ADDR );
10465042b18Sopenharmony_ci    data_seg->set_physical_address( DATA_ADDR );
10565042b18Sopenharmony_ci    data_seg->set_flags( PF_W | PF_R );
10665042b18Sopenharmony_ci    data_seg->set_align( PAGE_SIZE );
10765042b18Sopenharmony_ci
10865042b18Sopenharmony_ci    // Add code section into program segment
10965042b18Sopenharmony_ci    data_seg->add_section( data_sec, data_sec->get_addr_align() );
11065042b18Sopenharmony_ci
11165042b18Sopenharmony_ci    // Add optional signature for the file producer
11265042b18Sopenharmony_ci    section* note_sec = writer.sections.add( ".note" );
11365042b18Sopenharmony_ci    note_sec->set_type( SHT_NOTE );
11465042b18Sopenharmony_ci    note_sec->set_addr_align( 1 );
11565042b18Sopenharmony_ci
11665042b18Sopenharmony_ci    note_section_accessor note_writer( writer, note_sec );
11765042b18Sopenharmony_ci    note_writer.add_note( 0x01, "Created by ELFIO", 0, 0 );
11865042b18Sopenharmony_ci    char descr[6] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 };
11965042b18Sopenharmony_ci    note_writer.add_note( 0x01, "Never easier!", descr, sizeof( descr ) );
12065042b18Sopenharmony_ci
12165042b18Sopenharmony_ci    // Setup entry point. Usually, a linker sets this address on base of
12265042b18Sopenharmony_ci    // ‘_start’ label.
12365042b18Sopenharmony_ci    // In this example, the code starts at the first address of the
12465042b18Sopenharmony_ci    // 'text_seg' segment. Therefore, the start address is set
12565042b18Sopenharmony_ci    // to be equal to the segment location
12665042b18Sopenharmony_ci    writer.set_entry( text_seg->get_virtual_address() );
12765042b18Sopenharmony_ci
12865042b18Sopenharmony_ci    // Create ELF file
12965042b18Sopenharmony_ci    writer.save( "hello_x86_64" );
13065042b18Sopenharmony_ci
13165042b18Sopenharmony_ci    return 0;
13265042b18Sopenharmony_ci}
133