Skip to content

Commit ee3fa14

Browse files
author
Daniel Kroening
committed
add separate path for ld
1 parent f1ca099 commit ee3fa14

File tree

4 files changed

+275
-5
lines changed

4 files changed

+275
-5
lines changed

src/goto-cc/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ SRC = armcc_cmdline.cpp \
1414
goto_cc_mode.cpp \
1515
hybrid_binary.cpp \
1616
ld_cmdline.cpp \
17+
ld_mode.cpp \
1718
linker_script_merge.cpp \
1819
ms_cl_cmdline.cpp \
1920
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

+221
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
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 "hybrid_binary.h"
52+
#include "linker_script_merge.h"
53+
54+
static std::string
55+
linker_name(const cmdlinet &cmdline, 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(
63+
pos == std::string::npos || 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(goto_cc_cmdlinet &_cmdline, const std::string &_base_name)
74+
: goto_cc_modet(_cmdline, _base_name, gcc_message_handler),
75+
goto_binary_tmp_suffix(".goto-cc-saved")
76+
{
77+
}
78+
79+
/// does it.
80+
int ld_modet::doit()
81+
{
82+
if(cmdline.isset("help"))
83+
{
84+
help();
85+
return EX_OK;
86+
}
87+
88+
native_tool_name = linker_name(cmdline, base_name);
89+
90+
if(cmdline.isset("version") || cmdline.isset("print-sysroot"))
91+
return run_ld();
92+
93+
eval_verbosity(
94+
cmdline.get_value("verbosity"), messaget::M_ERROR, gcc_message_handler);
95+
96+
compilet compiler(cmdline, gcc_message_handler, false);
97+
98+
// determine actions to be undertaken
99+
compiler.mode = compilet::LINK_LIBRARY;
100+
101+
// get configuration
102+
config.set(cmdline);
103+
104+
compiler.object_file_extension = "o";
105+
106+
if(cmdline.isset('L'))
107+
compiler.library_paths = cmdline.get_values('L');
108+
// Don't add the system paths!
109+
110+
if(cmdline.isset('l'))
111+
compiler.libraries = cmdline.get_values('l');
112+
113+
if(cmdline.isset("static"))
114+
compiler.libraries.push_back("c");
115+
116+
if(cmdline.isset('o'))
117+
{
118+
// given gcc -o file1 -o file2,
119+
// gcc will output to file2, not file1
120+
compiler.output_file_object = cmdline.get_values('o').back();
121+
compiler.output_file_executable = cmdline.get_values('o').back();
122+
}
123+
else
124+
{
125+
compiler.output_file_object = "";
126+
compiler.output_file_executable = "a.out";
127+
}
128+
129+
// We now iterate over any input files
130+
131+
for(const auto &arg : cmdline.parsed_argv)
132+
if(arg.is_infile_name)
133+
compiler.add_input_file(arg.arg);
134+
135+
// Revert to gcc in case there is no source to compile
136+
// and no binary to link.
137+
138+
if(compiler.source_files.empty() && compiler.object_files.empty())
139+
return run_ld(); // exit!
140+
141+
// do all the rest
142+
if(compiler.doit())
143+
return 1; // LD exit code for all kinds of errors
144+
145+
// We can generate hybrid ELF and Mach-O binaries
146+
// containing both executable machine code and the goto-binary.
147+
return ld_hybrid_binary(compiler);
148+
}
149+
150+
int ld_modet::run_ld()
151+
{
152+
PRECONDITION(!cmdline.parsed_argv.empty());
153+
154+
// build new argv
155+
std::vector<std::string> new_argv;
156+
new_argv.reserve(cmdline.parsed_argv.size());
157+
for(const auto &a : cmdline.parsed_argv)
158+
new_argv.push_back(a.arg);
159+
160+
// overwrite argv[0]
161+
new_argv[0] = native_tool_name;
162+
163+
debug() << "RUN:";
164+
for(std::size_t i = 0; i < new_argv.size(); i++)
165+
debug() << " " << new_argv[i];
166+
debug() << eom;
167+
168+
return run(new_argv[0], new_argv, cmdline.stdin_file, "");
169+
}
170+
171+
int ld_modet::ld_hybrid_binary(compilet &compiler)
172+
{
173+
std::string output_file;
174+
175+
if(cmdline.isset('o'))
176+
{
177+
output_file = cmdline.get_value('o');
178+
179+
if(output_file == "/dev/null")
180+
return EX_OK;
181+
}
182+
else
183+
output_file = "a.out";
184+
185+
debug() << "Running " << native_tool_name << " to generate hybrid binary"
186+
<< eom;
187+
188+
// save the goto-cc output file
189+
std::string goto_binary = output_file + goto_binary_tmp_suffix;
190+
191+
int result;
192+
193+
result = rename(output_file.c_str(), goto_binary.c_str());
194+
if(result != 0)
195+
{
196+
error() << "Rename failed: " << std::strerror(errno) << eom;
197+
return result;
198+
}
199+
200+
result = run_ld();
201+
202+
if(result == 0 && cmdline.isset('T'))
203+
{
204+
linker_script_merget ls_merge(
205+
compiler, output_file, goto_binary, cmdline, get_message_handler());
206+
result = ls_merge.add_linker_script_definitions();
207+
}
208+
209+
std::string native_linker = linker_name(cmdline, base_name);
210+
211+
result = hybrid_binary(native_linker, goto_binary, output_file, get_message_handler());
212+
213+
return result;
214+
}
215+
216+
/// display command line help
217+
void ld_modet::help_mode()
218+
{
219+
std::cout << "goto-ld understands the options of "
220+
<< "ld plus the following.\n\n";
221+
}

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)