Skip to content

Commit 0c43341

Browse files
committed
goto-ld: handle EFI binaries gracefully
Running objcopy on EFI binaries does not work, hence we need to give up on the goto-cc sections in a graceful manner.
1 parent d3612cc commit 0c43341

File tree

3 files changed

+88
-15
lines changed

3 files changed

+88
-15
lines changed

src/goto-cc/hybrid_binary.cpp

+27-13
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,33 @@ Author: Michael Tautschnig, 2018
1616

1717
#include <cstring>
1818

19+
std::string objcopy_command(const std::string &compiler_or_linker)
20+
{
21+
if(has_suffix(compiler_or_linker, "-ld"))
22+
{
23+
std::string objcopy_cmd = compiler_or_linker;
24+
objcopy_cmd.erase(objcopy_cmd.size() - 2);
25+
objcopy_cmd += "objcopy";
26+
27+
return objcopy_cmd;
28+
}
29+
else
30+
return "objcopy";
31+
}
32+
1933
int hybrid_binary(
2034
const std::string &compiler_or_linker,
2135
const std::string &goto_binary_file,
2236
const std::string &output_file,
23-
message_handlert &message_handler)
37+
message_handlert &message_handler,
38+
bool linking_efi)
2439
{
2540
messaget message(message_handler);
2641

27-
int result;
42+
int result = 0;
2843

2944
#if defined(__linux__) || defined(__FreeBSD_kernel__)
30-
std::string objcopy_cmd;
31-
32-
if(has_suffix(compiler_or_linker, "-ld"))
33-
{
34-
objcopy_cmd = compiler_or_linker;
35-
objcopy_cmd.erase(objcopy_cmd.size() - 2);
36-
objcopy_cmd += "objcopy";
37-
}
38-
else
39-
objcopy_cmd = "objcopy";
45+
const std::string objcopy_cmd = objcopy_command(compiler_or_linker);
4046

4147
// merge output from gcc or ld with goto-binary using objcopy
4248

@@ -52,7 +58,15 @@ int hybrid_binary(
5258
"--remove-section", "goto-cc",
5359
"--add-section", "goto-cc=" + goto_binary_file, output_file};
5460

55-
result = run(objcopy_argv[0], objcopy_argv);
61+
const int add_section_result = run(objcopy_argv[0], objcopy_argv);
62+
if(add_section_result != 0)
63+
{
64+
if(linking_efi)
65+
message.warning() << "cannot merge EFI binaries: goto-cc section lost"
66+
<< messaget::eom;
67+
else
68+
result = add_section_result;
69+
}
5670
}
5771

5872
// delete the goto binary

src/goto-cc/hybrid_binary.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,18 @@ Date: May 2018
2424
/// \param goto_binary_file The file name of the goto binary
2525
/// \param output_file The name of the object file; the result is
2626
/// stored here.
27+
/// \param linking_efi Set to true if linking x86 EFI binaries to relax error
28+
/// checking.
2729
int hybrid_binary(
2830
const std::string &compiler_or_linker,
2931
const std::string &goto_binary_file,
3032
const std::string &output_file,
31-
message_handlert &);
33+
message_handlert &,
34+
bool linking_efi = false);
35+
36+
/// Return the name of the objcopy tool matching the chosen compiler or linker
37+
/// command.
38+
/// \param compiler_or_linker Compiler or linker commmand
39+
std::string objcopy_command(const std::string &compiler_or_linker);
3240

3341
#endif // CPROVER_GOTO_CC_HYBRID_BINARY_H

src/goto-cc/ld_mode.cpp

+52-1
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,38 @@ int ld_modet::ld_hybrid_binary(compilet &compiler)
195195
return result;
196196
}
197197

198+
const bool linking_efi = cmdline.get_value('m') == "i386pep";
199+
200+
#ifdef __linux__
201+
if(linking_efi)
202+
{
203+
const std::string objcopy_cmd = objcopy_command(native_tool_name);
204+
205+
for(const auto &object_file : compiler.object_files)
206+
{
207+
debug() << "stripping goto-cc sections before building EFI binary" << eom;
208+
// create a backup copy
209+
const std::string bin_name = object_file + goto_binary_tmp_suffix;
210+
211+
std::ifstream in(object_file, std::ios::binary);
212+
std::ofstream out(bin_name, std::ios::binary);
213+
out << in.rdbuf();
214+
215+
// remove any existing goto-cc section
216+
std::vector<std::string> objcopy_argv;
217+
218+
objcopy_argv.push_back(objcopy_cmd);
219+
objcopy_argv.push_back("--remove-section=goto-cc");
220+
objcopy_argv.push_back(object_file);
221+
222+
result = run(objcopy_argv[0], objcopy_argv);
223+
if(result != 0)
224+
debug() << "EFI binary preparation: removing goto-cc section failed"
225+
<< eom;
226+
}
227+
}
228+
#endif
229+
198230
result = run_ld();
199231

200232
if(result == 0 && cmdline.isset('T'))
@@ -204,12 +236,31 @@ int ld_modet::ld_hybrid_binary(compilet &compiler)
204236
result = ls_merge.add_linker_script_definitions();
205237
}
206238

239+
#ifdef __linux__
240+
if(linking_efi)
241+
{
242+
debug() << "arch set with " << compiler.object_files.size() << eom;
243+
for(const auto &object_file : compiler.object_files)
244+
{
245+
debug() << "EFI binary preparation: restoring object files" << eom;
246+
const std::string bin_name = object_file + goto_binary_tmp_suffix;
247+
const int mv_result = rename(bin_name.c_str(), object_file.c_str());
248+
if(mv_result != 0)
249+
debug() << "Rename failed: " << std::strerror(errno) << eom;
250+
}
251+
}
252+
#endif
253+
207254
if(result == 0)
208255
{
209256
std::string native_linker = linker_name(cmdline, base_name);
210257

211258
result = hybrid_binary(
212-
native_linker, goto_binary, output_file, get_message_handler());
259+
native_linker,
260+
goto_binary,
261+
output_file,
262+
get_message_handler(),
263+
linking_efi);
213264
}
214265

215266
return result;

0 commit comments

Comments
 (0)