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