cprover
hybrid_binary.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Create hybrid binary with goto-binary section
4 
5 Author: Michael Tautschnig, 2018
6 
7 \*******************************************************************/
8 
11 
12 #include "hybrid_binary.h"
13 
14 #include <util/file_util.h>
15 #include <util/run.h>
16 #include <util/suffix.h>
17 
18 #include <cstring>
19 
20 #if defined(__APPLE__)
21 # include <sys/stat.h>
22 #endif
23 
25  const std::string &compiler_or_linker,
26  const std::string &goto_binary_file,
27  const std::string &output_file,
28  bool building_executable,
29  message_handlert &message_handler)
30 {
31  messaget message(message_handler);
32 
33  int result;
34 
35 #if defined(__linux__) || defined(__FreeBSD_kernel__)
36  // we can use objcopy for both object files and executables
37  (void)building_executable;
38 
39  std::string objcopy_cmd;
40 
41  if(has_suffix(compiler_or_linker, "-ld"))
42  {
43  objcopy_cmd = compiler_or_linker;
44  objcopy_cmd.erase(objcopy_cmd.size() - 2);
45  objcopy_cmd += "objcopy";
46  }
47  else
48  objcopy_cmd = "objcopy";
49 
50  // merge output from gcc or ld with goto-binary using objcopy
51 
52  message.debug() << "merging " << output_file << " and " << goto_binary_file
53  << " using " << objcopy_cmd
54  << messaget::eom;
55 
56  {
57  // Now add goto-binary as goto-cc section.
58  // Remove if it exists before, or otherwise adding fails.
59  std::vector<std::string> objcopy_argv = {
60  objcopy_cmd,
61  "--remove-section", "goto-cc",
62  "--add-section", "goto-cc=" + goto_binary_file, output_file};
63 
64  result = run(objcopy_argv[0], objcopy_argv);
65  }
66 
67  // delete the goto binary
68  bool remove_result = file_remove(goto_binary_file);
69  if(!remove_result)
70  {
71  message.error() << "Remove failed: " << std::strerror(errno)
72  << messaget::eom;
73  if(result == 0)
74  result = remove_result;
75  }
76 
77 #elif defined(__APPLE__)
78  // Mac
79 
80  message.debug() << "merging " << output_file << " and " << goto_binary_file
81  << " using " << (building_executable ? "lipo" : "ld")
82  << messaget::eom;
83 
84  if(building_executable)
85  {
86  // Add goto-binary as hppa7100LC section.
87  // This overwrites if there's already one.
88  std::vector<std::string> lipo_argv = {
89  "lipo", output_file, "-create", "-arch", "hppa7100LC", goto_binary_file,
90  "-output", output_file };
91 
92  result = run(lipo_argv[0], lipo_argv);
93 
94  if(result == 0)
95  {
96  // lipo creates an output file, but it does not set execute permissions,
97  // so the user is unable to directly execute the output file until its
98  // chmod +x
99  mode_t current_umask = umask(0);
100  umask(current_umask);
101  int chmod_result = chmod(
102  output_file.c_str(), (S_IRWXU | S_IRWXG | S_IRWXO) & ~current_umask);
103  if(chmod_result != 0)
104  {
105  message.error() << "Setting execute permissions failed: "
106  << std::strerror(errno) << messaget::eom;
107  result = chmod_result;
108  }
109  }
110  }
111  else
112  {
113  // This fails if there's already one.
114  std::vector<std::string> ld_argv = {"ld",
115  "-r",
116  "-sectcreate",
117  "__TEXT",
118  "goto-cc",
119  goto_binary_file,
120  output_file,
121  "-o",
122  output_file};
123 
124  result = run(ld_argv[0], ld_argv);
125  }
126 
127  // delete the goto binary
128  bool remove_result = file_remove(goto_binary_file);
129  if(!remove_result)
130  {
131  message.error() << "Remove failed: " << std::strerror(errno)
132  << messaget::eom;
133  if(result == 0)
134  result = remove_result;
135  }
136 
137 #else
138  // unused parameters
139  (void)compiler_or_linker;
140  (void)goto_binary_file;
141  (void)output_file;
142  (void)building_executable;
143  message.error() << "binary merging not implemented for this platform"
144  << messaget::eom;
145  result = 1;
146 #endif
147 
148  return result;
149 }
messaget
Class that provides messages with a built-in verbosity 'level'.
Definition: message.h:155
file_util.h
file_remove
bool file_remove(const std::string &path)
C++17 will allow us to use std::filesystem::remove.
Definition: file_util.cpp:231
run
int run(const std::string &what, const std::vector< std::string > &argv)
Definition: run.cpp:49
messaget::eom
static eomt eom
Definition: message.h:297
run.h
has_suffix
bool has_suffix(const std::string &s, const std::string &suffix)
Definition: suffix.h:17
mode_t
unsigned int mode_t
Definition: kdev_t.h:12
message
static const char * message(const static_verifier_resultt::statust &status)
Makes a status message string from a status.
Definition: static_verifier.cpp:74
hybrid_binary
int hybrid_binary(const std::string &compiler_or_linker, const std::string &goto_binary_file, const std::string &output_file, bool building_executable, message_handlert &message_handler)
Merges a goto binary into an object file (e.g.
Definition: hybrid_binary.cpp:24
message_handlert
Definition: message.h:28
hybrid_binary.h
Create hybrid binary with goto-binary section.
suffix.h