Skip to content

Commit f3e7707

Browse files
author
Daniel Kroening
committed
add separate path for ld
1 parent caf4eca commit f3e7707

File tree

4 files changed

+350
-5
lines changed

4 files changed

+350
-5
lines changed

src/goto-cc/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ SRC = armcc_cmdline.cpp \
1313
goto_cc_main.cpp \
1414
goto_cc_mode.cpp \
1515
ld_cmdline.cpp \
16+
ld_mode.cpp \
1617
linker_script_merge.cpp \
1718
ms_cl_cmdline.cpp \
1819
ms_cl_mode.cpp \

src/goto-cc/goto_cc_main.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,12 @@ Date: May 2006
2525
#include "as_cmdline.h"
2626
#include "as86_cmdline.h"
2727

28-
#include "gcc_mode.h"
29-
#include "cw_mode.h"
30-
#include "ms_cl_mode.h"
3128
#include "armcc_mode.h"
3229
#include "as_mode.h"
30+
#include "cw_mode.h"
31+
#include "gcc_mode.h"
32+
#include "ld_mode.h"
33+
#include "ms_cl_mode.h"
3334

3435
std::string to_lower_string(const std::string &s)
3536
{
@@ -106,8 +107,8 @@ int main(int argc, const char **argv)
106107
{
107108
// this simulates "ld" for linking
108109
ld_cmdlinet cmdline;
109-
gcc_modet gcc_mode(cmdline, base_name, true);
110-
return gcc_mode.main(argc, argv);
110+
ld_modet ld_mode(cmdline, base_name);
111+
return ld_mode.main(argc, argv);
111112
}
112113
else if(base_name.find("goto-bcc")!=std::string::npos)
113114
{

src/goto-cc/ld_mode.cpp

Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
/*******************************************************************\
2+
3+
Module: LD Mode
4+
5+
Author: CM Wintersteiger, 2006
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// LD Mode
11+
12+
#include "ld_mode.h"
13+
14+
#ifdef _WIN32
15+
#define EX_OK 0
16+
#define EX_USAGE 64
17+
#define EX_SOFTWARE 70
18+
#else
19+
#include <sysexits.h>
20+
#endif
21+
22+
#include <algorithm>
23+
#include <cstddef>
24+
#include <cstdio>
25+
#include <cstring>
26+
#include <fstream>
27+
#include <iostream>
28+
#include <iterator>
29+
#include <numeric>
30+
#include <sstream>
31+
32+
#include <json/json_parser.h>
33+
34+
#include <util/arith_tools.h>
35+
#include <util/c_types.h>
36+
#include <util/config.h>
37+
#include <util/expr.h>
38+
#include <util/get_base_name.h>
39+
#include <util/invariant.h>
40+
#include <util/prefix.h>
41+
#include <util/replace_symbol.h>
42+
#include <util/run.h>
43+
#include <util/suffix.h>
44+
#include <util/tempdir.h>
45+
#include <util/tempfile.h>
46+
47+
#include <goto-programs/read_goto_binary.h>
48+
49+
#include <cbmc/version.h>
50+
51+
#include "linker_script_merge.h"
52+
53+
static std::string
54+
linker_name(const cmdlinet &cmdline, const std::string &base_name)
55+
{
56+
if(cmdline.isset("native-linker"))
57+
return cmdline.get_value("native-linker");
58+
59+
std::string::size_type pos = base_name.find("goto-ld");
60+
61+
if(
62+
pos == std::string::npos || base_name == "goto-gcc" ||
63+
base_name == "goto-ld")
64+
return "ld";
65+
66+
std::string result = base_name;
67+
result.replace(pos, 7, "ld");
68+
69+
return result;
70+
}
71+
72+
ld_modet::ld_modet(goto_cc_cmdlinet &_cmdline, const std::string &_base_name)
73+
: goto_cc_modet(_cmdline, _base_name, gcc_message_handler),
74+
goto_binary_tmp_suffix(".goto-cc-saved")
75+
{
76+
}
77+
78+
/// does it.
79+
int ld_modet::doit()
80+
{
81+
if(cmdline.isset("help"))
82+
{
83+
help();
84+
return EX_OK;
85+
}
86+
87+
native_tool_name = linker_name(cmdline, base_name);
88+
89+
if(cmdline.isset("version") || cmdline.isset("print-sysroot"))
90+
return run_ld();
91+
92+
eval_verbosity(
93+
cmdline.get_value("verbosity"), messaget::M_ERROR, gcc_message_handler);
94+
95+
compilet compiler(cmdline, gcc_message_handler, false);
96+
97+
// determine actions to be undertaken
98+
compiler.mode = compilet::LINK_LIBRARY;
99+
100+
// get configuration
101+
config.set(cmdline);
102+
103+
compiler.object_file_extension = "o";
104+
105+
if(cmdline.isset('L'))
106+
compiler.library_paths = cmdline.get_values('L');
107+
// Don't add the system paths!
108+
109+
if(cmdline.isset('l'))
110+
compiler.libraries = cmdline.get_values('l');
111+
112+
if(cmdline.isset("static"))
113+
compiler.libraries.push_back("c");
114+
115+
if(cmdline.isset('o'))
116+
{
117+
// given gcc -o file1 -o file2,
118+
// gcc will output to file2, not file1
119+
compiler.output_file_object = cmdline.get_values('o').back();
120+
compiler.output_file_executable = cmdline.get_values('o').back();
121+
}
122+
else
123+
{
124+
compiler.output_file_object = "";
125+
compiler.output_file_executable = "a.out";
126+
}
127+
128+
// We now iterate over any input files
129+
130+
for(const auto &arg : cmdline.parsed_argv)
131+
if(arg.is_infile_name)
132+
compiler.add_input_file(arg.arg);
133+
134+
// Revert to gcc in case there is no source to compile
135+
// and no binary to link.
136+
137+
if(compiler.source_files.empty() && compiler.object_files.empty())
138+
return run_ld(); // exit!
139+
140+
// do all the rest
141+
if(compiler.doit())
142+
return 1; // LD exit code for all kinds of errors
143+
144+
// We can generate hybrid ELF and Mach-O binaries
145+
// containing both executable machine code and the goto-binary.
146+
return ld_hybrid_binary(compiler);
147+
}
148+
149+
int ld_modet::run_ld()
150+
{
151+
PRECONDITION(!cmdline.parsed_argv.empty());
152+
153+
// build new argv
154+
std::vector<std::string> new_argv;
155+
new_argv.reserve(cmdline.parsed_argv.size());
156+
for(const auto &a : cmdline.parsed_argv)
157+
new_argv.push_back(a.arg);
158+
159+
// overwrite argv[0]
160+
new_argv[0] = native_tool_name;
161+
162+
debug() << "RUN:";
163+
for(std::size_t i = 0; i < new_argv.size(); i++)
164+
debug() << " " << new_argv[i];
165+
debug() << eom;
166+
167+
return run(new_argv[0], new_argv, cmdline.stdin_file, "");
168+
}
169+
170+
int ld_modet::ld_hybrid_binary(compilet &compiler)
171+
{
172+
std::string output_file;
173+
174+
if(cmdline.isset('o'))
175+
{
176+
output_file = cmdline.get_value('o');
177+
178+
if(output_file == "/dev/null")
179+
return EX_OK;
180+
}
181+
else
182+
output_file = "a.out";
183+
184+
debug() << "Running " << native_tool_name << " to generate hybrid binary"
185+
<< eom;
186+
187+
// save the goto-cc output file
188+
std::string goto_binary = output_file + goto_binary_tmp_suffix;
189+
190+
int result;
191+
192+
result = rename(output_file.c_str(), goto_binary.c_str());
193+
if(result != 0)
194+
{
195+
error() << "Rename failed: " << std::strerror(errno) << eom;
196+
return result;
197+
}
198+
199+
result = run_ld();
200+
201+
if(result == 0 && cmdline.isset('T'))
202+
{
203+
linker_script_merget ls_merge(
204+
compiler, output_file, goto_binary, cmdline, gcc_message_handler);
205+
result = ls_merge.add_linker_script_definitions();
206+
}
207+
208+
std::string objcopy_cmd;
209+
210+
if(has_suffix(linker_name(cmdline, base_name), "-ld"))
211+
{
212+
objcopy_cmd = linker_name(cmdline, base_name);
213+
objcopy_cmd.erase(objcopy_cmd.size() - 2);
214+
}
215+
216+
objcopy_cmd += "objcopy";
217+
218+
// merge output from ld with goto-binary
219+
// using objcopy, or do cleanup if an earlier call failed
220+
debug() << "merging " << output_file << " and " << goto_binary << eom;
221+
222+
#ifdef __linux__
223+
if(result == 0)
224+
{
225+
// remove any existing goto-cc section
226+
std::vector<std::string> objcopy_argv;
227+
228+
objcopy_argv.push_back(objcopy_cmd);
229+
objcopy_argv.push_back("--remove-section=goto-cc");
230+
objcopy_argv.push_back(output_file);
231+
232+
result = run(objcopy_argv[0], objcopy_argv, "", "");
233+
}
234+
235+
if(result == 0)
236+
{
237+
// now add goto-binary as goto-cc section
238+
std::vector<std::string> objcopy_argv;
239+
240+
objcopy_argv.push_back(objcopy_cmd);
241+
objcopy_argv.push_back("--add-section");
242+
objcopy_argv.push_back("goto-cc=" + goto_binary);
243+
objcopy_argv.push_back(output_file);
244+
245+
result = run(objcopy_argv[0], objcopy_argv, "", "");
246+
}
247+
248+
int remove_result = remove(goto_binary.c_str());
249+
if(remove_result != 0)
250+
{
251+
error() << "Remove failed: " << std::strerror(errno) << eom;
252+
if(result == 0)
253+
result = remove_result;
254+
}
255+
256+
#elif defined(__APPLE__)
257+
// Mac
258+
if(result == 0)
259+
{
260+
std::vector<std::string> lipo_argv;
261+
262+
// now add goto-binary as hppa7100LC section
263+
lipo_argv.push_back("lipo");
264+
lipo_argv.push_back(output_file);
265+
lipo_argv.push_back("-create");
266+
lipo_argv.push_back("-arch");
267+
lipo_argv.push_back("hppa7100LC");
268+
lipo_argv.push_back(goto_binary);
269+
lipo_argv.push_back("-output");
270+
lipo_argv.push_back(output_file);
271+
272+
result = run(lipo_argv[0], lipo_argv, "", "");
273+
}
274+
275+
int remove_result = remove(goto_binary.c_str());
276+
if(remove_result != 0)
277+
{
278+
error() << "Remove failed: " << std::strerror(errno) << eom;
279+
if(result == 0)
280+
result = remove_result;
281+
}
282+
283+
#else
284+
error() << "binary merging not implemented for this platform" << eom;
285+
result = 1;
286+
#endif
287+
288+
return result;
289+
}
290+
291+
/// display command line help
292+
void ld_modet::help_mode()
293+
{
294+
std::cout << "goto-ld understands the options of "
295+
<< "ld plus the following.\n\n";
296+
}

src/goto-cc/ld_mode.h

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*******************************************************************\
2+
3+
Module: Base class for command line interpretation
4+
5+
Author: CM Wintersteiger
6+
7+
Date: June 2006
8+
9+
\*******************************************************************/
10+
11+
/// \file
12+
/// Base class for command line interpretation
13+
14+
#ifndef CPROVER_GOTO_CC_LD_MODE_H
15+
#define CPROVER_GOTO_CC_LD_MODE_H
16+
17+
#include "compile.h"
18+
#include "goto_cc_mode.h"
19+
20+
#include <util/cout_message.h>
21+
22+
#include <set>
23+
24+
class ld_modet : public goto_cc_modet
25+
{
26+
public:
27+
int doit() final;
28+
void help_mode() final;
29+
30+
ld_modet(
31+
goto_cc_cmdlinet &_cmdline,
32+
const std::string &_base_name);
33+
34+
protected:
35+
gcc_message_handlert gcc_message_handler;
36+
37+
std::string native_tool_name;
38+
39+
const std::string goto_binary_tmp_suffix;
40+
41+
/// \brief call ld with original command line
42+
int run_ld();
43+
44+
int ld_hybrid_binary(compilet &compiler);
45+
};
46+
47+
#endif // CPROVER_GOTO_CC_LD_MODE_H

0 commit comments

Comments
 (0)