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