Skip to content

Commit 87572ed

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 b19ba69 commit 87572ed

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
@@ -23,10 +23,18 @@ Date: May 2018
2323
/// deduce the name of objcopy
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 stored here.
26+
/// \param linking_efi: Set to true if linking x86 EFI binaries to relax error
27+
/// checking.
2628
int hybrid_binary(
2729
const std::string &compiler_or_linker,
2830
const std::string &goto_binary_file,
2931
const std::string &output_file,
30-
message_handlert &);
32+
message_handlert &,
33+
bool linking_efi = false);
34+
35+
/// Return the name of the objcopy tool matching the chosen compiler or linker
36+
/// command.
37+
/// \param compiler_or_linker Compiler or linker commmand
38+
std::string objcopy_command(const std::string &compiler_or_linker);
3139

3240
#endif // CPROVER_GOTO_CC_HYBRID_BINARY_H

src/goto-cc/ld_mode.cpp

+52-1
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,38 @@ int ld_modet::ld_hybrid_binary(compilet &compiler)
198198
return result;
199199
}
200200

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

203235
if(result == 0 && cmdline.isset('T'))
@@ -207,12 +239,31 @@ int ld_modet::ld_hybrid_binary(compilet &compiler)
207239
result = ls_merge.add_linker_script_definitions();
208240
}
209241

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

214261
result = hybrid_binary(
215-
native_linker, goto_binary, output_file, get_message_handler());
262+
native_linker,
263+
goto_binary,
264+
output_file,
265+
get_message_handler(),
266+
linking_efi);
216267
}
217268

218269
return result;

0 commit comments

Comments
 (0)