Skip to content

Commit 0829acb

Browse files
author
Daniel Kroening
committed
add separate path for ld
1 parent 0d95cc5 commit 0829acb

File tree

4 files changed

+355
-5
lines changed

4 files changed

+355
-5
lines changed

src/goto-cc/Makefile

+1
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

+6-5
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

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

src/goto-cc/ld_mode.h

+47
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)