Advertisement
Guest User

Untitled

a guest
Sep 3rd, 2015
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.06 KB | None | 0 0
  1. % touch helloworld.not
  2. % ./nothing --help
  3. usage: ./nothing [OPTIONS] <input-file>...
  4. Allowed options:
  5. --help produce help message
  6. --silent suppress error messages
  7. --output-file arg (=a.out) output file
  8. --input-file arg input file
  9. % ./nothing helloworld.not
  10. % objdump -d ./a.out
  11.  
  12. ./a.out: file format elf32-i386
  13.  
  14.  
  15. Disassembly of section .text:
  16.  
  17. 08048000 <.text>:
  18. 8048000: bb 00 00 00 00 mov $0x0,%ebx
  19. 8048005: b8 01 00 00 00 mov $0x1,%eax
  20. 804800a: cd 80 int $0x80
  21. % ./nothing asdf
  22. nothing: error: asdf: No such file or directory
  23. nothing: fatal error: no input files
  24. compilation terminated.
  25. % ./nothing --silent asdf
  26. %
  27.  
  28. /*
  29. * A 'Nothing' compiler
  30. * <http://www.turtle.dds.nl/nothing/>
  31. * September 2010, RoPe Development Inc.
  32. *
  33. * Author: authorname
  34. */
  35. #include <boost/program_options.hpp>
  36. #include <elfio/elfio.hpp>
  37.  
  38. #include <iostream>
  39. #include <exception>
  40. #include <fstream>
  41. #include <cerrno>
  42. #include <cstdlib> // EXIT_FAILURE
  43. #include <cstring> // std::strerror
  44. #include <string> // std::char_traits<char>::eof
  45.  
  46. /* Using the ELFIO library, we will create an ELF executable that
  47. * consists of the following (equivalent) assembly program:
  48. *
  49. * .section text
  50. *
  51. * global _start
  52. *
  53. * _start:
  54. * ; syscall for exit
  55. * mov ebx, 0
  56. * mov eax, 1
  57. * int 0x80
  58. *
  59. * To quote the documentation "3.4 ELF File Writer",
  60. *
  61. * "The executable will be created and run on i386 Linux OS platform. It
  62. * is supposed to run well on both 32 and 64 - bit Linux platforms. The
  63. * file will be created without invoking the compiler or assembler tools
  64. * in the usual way (i.e. translating high level source code that makes
  65. * use of the standard library functions). Instead, using the ELFIO
  66. * writer, all the necessary sections and segments of the file will be
  67. * created and filled explicitly, each, with its appropriate data. The
  68. * physical file would then be created by the ELFIO library."
  69. */
  70. void create_executable(std::string filename)
  71. {
  72. using namespace ELFIO;
  73.  
  74. elfio writer;
  75.  
  76. /* Initialize empty 'elfio' object. This should be done as the first
  77. * step when creating a new 'elfio' object as other API is relying
  78. * on parameters provided – ELF file 32-bits/64-bits and little/big
  79. * endianness
  80. */
  81. writer.create( ELFCLASS32, ELFDATA2LSB );
  82.  
  83. /* Other attributes of the file. Linux OS loader does not require
  84. * full set of the attributes, but they are provided when a regular
  85. * linker used for creation of ELF files
  86. */
  87. writer.set_os_abi( ELFOSABI_LINUX );
  88. writer.set_type( ET_EXEC );
  89. writer.set_machine( EM_386 );
  90.  
  91. // Create code section
  92. section* text_sec = writer.sections.add( ".text" );
  93.  
  94. /* Set section’s attributes. Section type, flags and alignment have
  95. * a big significance and controls how this section is treated by a
  96. * linker or OS loader
  97. */
  98. text_sec->set_type( SHT_PROGBITS );
  99. text_sec->set_flags( SHF_ALLOC | SHF_EXECINSTR );
  100. text_sec->set_addr_align( 0x10 );
  101.  
  102. // Add data into it
  103. char text[] = { 'xbb', 'x00', 'x00', 'x00', 'x00', // mov ebx, 0
  104. 'xB8', 'x01', 'x00', 'x00', 'x00', // mov eax, 1
  105. 'xCD', 'x80' // int 0x80
  106. };
  107. text_sec->set_data( text, sizeof( text ) );
  108.  
  109. // Create a loadable segment
  110. segment* text_seg = writer.segments.add();
  111. text_seg->set_type( PT_LOAD );
  112. text_seg->set_virtual_address( 0x08048000 );
  113. text_seg->set_physical_address( 0x08048000 );
  114. text_seg->set_flags( PF_X | PF_R );
  115. text_seg->set_align( 0x1000 );
  116.  
  117. // Add code section into program segment
  118. text_seg->add_section_index( text_sec->get_index(), text_sec->get_addr_align() );
  119.  
  120. // Setup entry point
  121. writer.set_entry( 0x08048000 );
  122.  
  123. // Create ELF file
  124. writer.save( filename );
  125. }
  126.  
  127. int main(int argc, char* argv[])
  128. {
  129. namespace po = boost::program_options;
  130.  
  131. try
  132. {
  133. bool silent = false;
  134. if (argc < 2)
  135. {
  136. std::cerr << "nothing: fatal error: no input filesn";
  137. std::cerr << "compilation terminated.n";
  138. return EXIT_FAILURE;
  139. }
  140.  
  141. po::options_description options("Allowed options");
  142. options.add_options()
  143. ("help", "produce help message")
  144. ("silent", "suppress error messages")
  145. ("output-file", po::value<std::string>()->default_value("a.out"),
  146. "output file")
  147. ("input-file", po::value<std::vector<std::string>>(), "input file")
  148. ;
  149.  
  150. po::positional_options_description positional_options;
  151.  
  152. // The second parameter specifies the "max count". -1 means
  153. // unlimited
  154. positional_options.add("input-file", -1);
  155.  
  156. po::variables_map variables_map;
  157. po::store(po::command_line_parser(argc, argv).
  158. options(options).positional(positional_options).run(),
  159. variables_map);
  160. po::notify(variables_map);
  161.  
  162. if (variables_map.count("help"))
  163. {
  164. std::cout << "usage: ./nothing [OPTIONS] <input-file>...n";
  165. std::cout << options;
  166. std::cout.flush();
  167. return EXIT_SUCCESS;
  168. }
  169.  
  170. if (variables_map.count("silent"))
  171. {
  172. silent = true;
  173. }
  174.  
  175. auto input_files = variables_map["input-file"].as<std::vector<std::string>>();
  176.  
  177. for (auto&& input_file : input_files)
  178. {
  179. std::ifstream program(input_file);
  180.  
  181. if (!program)
  182. {
  183. if (!silent)
  184. {
  185. /* "errno uses thread-local storage on modern operating systems.
  186. * However, there's no guarantee that the fstream functions will
  187. * not clobber errno after an errno occurs. The underlying
  188. * functions may not set errno at all (direct system calls on
  189. * Linux, or Win32). This doesn't work on many real world
  190. * implementations."
  191. * - strcat,
  192. * <https://stackoverflow.com/questions/17337602/how-to-get-error-message-when-ifstream-open-fails/17338934#comment33958980_17338934>
  193. */
  194. std::cerr << "nothing: error: " << argv[1] << ": " << std::strerror(errno) << "n";
  195. std::cerr << "nothing: fatal error: no input filesn";
  196. std::cerr << "compilation terminated.n";
  197. return EXIT_FAILURE;
  198. }
  199. }
  200.  
  201. if (program.peek() != std::char_traits<char>::eof())
  202. {
  203. if (!silent)
  204. {
  205. std::cerr << "nothing: fatal error: program is not emptyn";
  206. std::cerr << "compilation terminated.n";
  207. }
  208. return EXIT_FAILURE;
  209. }
  210. }
  211.  
  212. create_executable(variables_map["output-file"].as<std::string>());
  213. } catch(std::exception& e) {
  214. std::cerr << "nothing: error: " << e.what() << "n";
  215. return EXIT_FAILURE;
  216. }
  217. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement