Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- % touch helloworld.not
- % ./nothing --help
- usage: ./nothing [OPTIONS] <input-file>...
- Allowed options:
- --help produce help message
- --silent suppress error messages
- --output-file arg (=a.out) output file
- --input-file arg input file
- % ./nothing helloworld.not
- % objdump -d ./a.out
- ./a.out: file format elf32-i386
- Disassembly of section .text:
- 08048000 <.text>:
- 8048000: bb 00 00 00 00 mov $0x0,%ebx
- 8048005: b8 01 00 00 00 mov $0x1,%eax
- 804800a: cd 80 int $0x80
- % ./nothing asdf
- nothing: error: asdf: No such file or directory
- nothing: fatal error: no input files
- compilation terminated.
- % ./nothing --silent asdf
- %
- /*
- * A 'Nothing' compiler
- * <http://www.turtle.dds.nl/nothing/>
- * September 2010, RoPe Development Inc.
- *
- * Author: authorname
- */
- #include <boost/program_options.hpp>
- #include <elfio/elfio.hpp>
- #include <iostream>
- #include <exception>
- #include <fstream>
- #include <cerrno>
- #include <cstdlib> // EXIT_FAILURE
- #include <cstring> // std::strerror
- #include <string> // std::char_traits<char>::eof
- /* Using the ELFIO library, we will create an ELF executable that
- * consists of the following (equivalent) assembly program:
- *
- * .section text
- *
- * global _start
- *
- * _start:
- * ; syscall for exit
- * mov ebx, 0
- * mov eax, 1
- * int 0x80
- *
- * To quote the documentation "3.4 ELF File Writer",
- *
- * "The executable will be created and run on i386 Linux OS platform. It
- * is supposed to run well on both 32 and 64 - bit Linux platforms. The
- * file will be created without invoking the compiler or assembler tools
- * in the usual way (i.e. translating high level source code that makes
- * use of the standard library functions). Instead, using the ELFIO
- * writer, all the necessary sections and segments of the file will be
- * created and filled explicitly, each, with its appropriate data. The
- * physical file would then be created by the ELFIO library."
- */
- void create_executable(std::string filename)
- {
- using namespace ELFIO;
- elfio writer;
- /* Initialize empty 'elfio' object. This should be done as the first
- * step when creating a new 'elfio' object as other API is relying
- * on parameters provided – ELF file 32-bits/64-bits and little/big
- * endianness
- */
- writer.create( ELFCLASS32, ELFDATA2LSB );
- /* Other attributes of the file. Linux OS loader does not require
- * full set of the attributes, but they are provided when a regular
- * linker used for creation of ELF files
- */
- writer.set_os_abi( ELFOSABI_LINUX );
- writer.set_type( ET_EXEC );
- writer.set_machine( EM_386 );
- // Create code section
- section* text_sec = writer.sections.add( ".text" );
- /* Set section’s attributes. Section type, flags and alignment have
- * a big significance and controls how this section is treated by a
- * linker or OS loader
- */
- text_sec->set_type( SHT_PROGBITS );
- text_sec->set_flags( SHF_ALLOC | SHF_EXECINSTR );
- text_sec->set_addr_align( 0x10 );
- // Add data into it
- char text[] = { 'xbb', 'x00', 'x00', 'x00', 'x00', // mov ebx, 0
- 'xB8', 'x01', 'x00', 'x00', 'x00', // mov eax, 1
- 'xCD', 'x80' // int 0x80
- };
- text_sec->set_data( text, sizeof( text ) );
- // Create a loadable segment
- segment* text_seg = writer.segments.add();
- text_seg->set_type( PT_LOAD );
- text_seg->set_virtual_address( 0x08048000 );
- text_seg->set_physical_address( 0x08048000 );
- text_seg->set_flags( PF_X | PF_R );
- text_seg->set_align( 0x1000 );
- // Add code section into program segment
- text_seg->add_section_index( text_sec->get_index(), text_sec->get_addr_align() );
- // Setup entry point
- writer.set_entry( 0x08048000 );
- // Create ELF file
- writer.save( filename );
- }
- int main(int argc, char* argv[])
- {
- namespace po = boost::program_options;
- try
- {
- bool silent = false;
- if (argc < 2)
- {
- std::cerr << "nothing: fatal error: no input filesn";
- std::cerr << "compilation terminated.n";
- return EXIT_FAILURE;
- }
- po::options_description options("Allowed options");
- options.add_options()
- ("help", "produce help message")
- ("silent", "suppress error messages")
- ("output-file", po::value<std::string>()->default_value("a.out"),
- "output file")
- ("input-file", po::value<std::vector<std::string>>(), "input file")
- ;
- po::positional_options_description positional_options;
- // The second parameter specifies the "max count". -1 means
- // unlimited
- positional_options.add("input-file", -1);
- po::variables_map variables_map;
- po::store(po::command_line_parser(argc, argv).
- options(options).positional(positional_options).run(),
- variables_map);
- po::notify(variables_map);
- if (variables_map.count("help"))
- {
- std::cout << "usage: ./nothing [OPTIONS] <input-file>...n";
- std::cout << options;
- std::cout.flush();
- return EXIT_SUCCESS;
- }
- if (variables_map.count("silent"))
- {
- silent = true;
- }
- auto input_files = variables_map["input-file"].as<std::vector<std::string>>();
- for (auto&& input_file : input_files)
- {
- std::ifstream program(input_file);
- if (!program)
- {
- if (!silent)
- {
- /* "errno uses thread-local storage on modern operating systems.
- * However, there's no guarantee that the fstream functions will
- * not clobber errno after an errno occurs. The underlying
- * functions may not set errno at all (direct system calls on
- * Linux, or Win32). This doesn't work on many real world
- * implementations."
- * - strcat,
- * <https://stackoverflow.com/questions/17337602/how-to-get-error-message-when-ifstream-open-fails/17338934#comment33958980_17338934>
- */
- std::cerr << "nothing: error: " << argv[1] << ": " << std::strerror(errno) << "n";
- std::cerr << "nothing: fatal error: no input filesn";
- std::cerr << "compilation terminated.n";
- return EXIT_FAILURE;
- }
- }
- if (program.peek() != std::char_traits<char>::eof())
- {
- if (!silent)
- {
- std::cerr << "nothing: fatal error: program is not emptyn";
- std::cerr << "compilation terminated.n";
- }
- return EXIT_FAILURE;
- }
- }
- create_executable(variables_map["output-file"].as<std::string>());
- } catch(std::exception& e) {
- std::cerr << "nothing: error: " << e.what() << "n";
- return EXIT_FAILURE;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement