Commit | Line | Data |
---|---|---|
bae7f79e ILT |
1 | // ld.c -- linker main function |
2 | ||
3 | #include "gold.h" | |
4 | ||
5 | #include <cstdlib> | |
6 | #include <cstdio> | |
7 | #include <cstring> | |
8 | #include <unistd.h> | |
9 | ||
10 | #include "options.h" | |
11 | #include "workqueue.h" | |
12 | #include "dirsearch.h" | |
13 | #include "readsyms.h" | |
14bfc3f5 | 14 | #include "symtab.h" |
ead1e424 | 15 | #include "common.h" |
54dc6425 | 16 | #include "object.h" |
a2fb1b05 | 17 | #include "layout.h" |
61ba1cf9 | 18 | #include "reloc.h" |
ead1e424 | 19 | #include "defstd.h" |
bae7f79e ILT |
20 | |
21 | namespace gold | |
22 | { | |
23 | ||
24 | const char* program_name; | |
25 | ||
26 | void | |
27 | gold_exit(bool status) | |
28 | { | |
29 | exit(status ? EXIT_SUCCESS : EXIT_FAILURE); | |
30 | } | |
31 | ||
32 | void | |
33 | gold_fatal(const char* msg, bool perrno) | |
34 | { | |
35 | fprintf(stderr, "%s: ", program_name); | |
36 | if (perrno) | |
37 | perror(msg); | |
38 | else | |
39 | fprintf(stderr, "%s\n", msg); | |
40 | gold_exit(false); | |
41 | } | |
42 | ||
43 | void | |
44 | gold_nomem() | |
45 | { | |
46 | // We are out of memory, so try hard to print a reasonable message. | |
47 | // Note that we don't try to translate this message, since the | |
48 | // translation process itself will require memory. | |
49 | write(2, program_name, strlen(program_name)); | |
50 | const char* const s = ": out of memory\n"; | |
51 | write(2, s, strlen(s)); | |
52 | gold_exit(false); | |
53 | } | |
54 | ||
55 | void | |
56 | gold_unreachable() | |
57 | { | |
58 | abort(); | |
59 | } | |
60 | ||
92e059d8 ILT |
61 | // This class arranges to run the functions done in the middle of the |
62 | // link. It is just a closure. | |
bae7f79e | 63 | |
92e059d8 | 64 | class Middle_runner : public Task_function_runner |
bae7f79e | 65 | { |
92e059d8 ILT |
66 | public: |
67 | Middle_runner(const General_options& options, | |
68 | const Input_objects* input_objects, | |
69 | Symbol_table* symtab, | |
70 | Layout* layout) | |
71 | : options_(options), input_objects_(input_objects), symtab_(symtab), | |
72 | layout_(layout) | |
73 | { } | |
74 | ||
75 | void | |
76 | run(Workqueue*); | |
77 | ||
78 | private: | |
79 | const General_options& options_; | |
80 | const Input_objects* input_objects_; | |
81 | Symbol_table* symtab_; | |
82 | Layout* layout_; | |
83 | }; | |
bae7f79e | 84 | |
92e059d8 ILT |
85 | void |
86 | Middle_runner::run(Workqueue* workqueue) | |
87 | { | |
88 | queue_middle_tasks(this->options_, this->input_objects_, this->symtab_, | |
89 | this->layout_, workqueue); | |
90 | } | |
bae7f79e ILT |
91 | |
92 | // Queue up the initial set of tasks for this link job. | |
93 | ||
94 | void | |
95 | queue_initial_tasks(const General_options& options, | |
96 | const Dirsearch& search_path, | |
ead1e424 | 97 | const Command_line& cmdline, |
54dc6425 | 98 | Workqueue* workqueue, Input_objects* input_objects, |
12e14209 | 99 | Symbol_table* symtab, Layout* layout) |
bae7f79e | 100 | { |
ead1e424 | 101 | if (cmdline.begin() == cmdline.end()) |
bae7f79e ILT |
102 | gold_fatal(_("no input files"), false); |
103 | ||
104 | // Read the input files. We have to add the symbols to the symbol | |
105 | // table in order. We do this by creating a separate blocker for | |
106 | // each input file. We associate the blocker with the following | |
107 | // input file, to give us a convenient place to delete it. | |
108 | Task_token* this_blocker = NULL; | |
ead1e424 ILT |
109 | for (Command_line::const_iterator p = cmdline.begin(); |
110 | p != cmdline.end(); | |
bae7f79e ILT |
111 | ++p) |
112 | { | |
113 | Task_token* next_blocker = new Task_token(); | |
114 | next_blocker->add_blocker(); | |
12e14209 | 115 | workqueue->queue(new Read_symbols(options, input_objects, symtab, layout, |
dbe717ef | 116 | search_path, &*p, NULL, this_blocker, |
a2fb1b05 | 117 | next_blocker)); |
bae7f79e ILT |
118 | this_blocker = next_blocker; |
119 | } | |
120 | ||
92e059d8 ILT |
121 | workqueue->queue(new Task_function(new Middle_runner(options, |
122 | input_objects, | |
123 | symtab, | |
124 | layout), | |
125 | this_blocker)); | |
bae7f79e ILT |
126 | } |
127 | ||
92e059d8 ILT |
128 | // Queue up the middle set of tasks. These are the tasks which run |
129 | // after all the input objects have been found and all the symbols | |
130 | // have been read, but before we lay out the output file. | |
bae7f79e | 131 | |
92e059d8 ILT |
132 | void |
133 | queue_middle_tasks(const General_options& options, | |
134 | const Input_objects* input_objects, | |
135 | Symbol_table* symtab, | |
136 | Layout* layout, | |
137 | Workqueue* workqueue) | |
61ba1cf9 | 138 | { |
ead1e424 ILT |
139 | // Predefine standard symbols. This should be fast, so we don't |
140 | // bother to create a task for it. | |
141 | define_standard_symbols(symtab, layout, input_objects->target()); | |
142 | ||
92e059d8 ILT |
143 | // Read the relocations of the input files. We do this to find |
144 | // which symbols are used by relocations which require a GOT and/or | |
145 | // a PLT entry, or a COPY reloc. When we implement garbage | |
146 | // collection we will do it here by reading the relocations in a | |
147 | // breadth first search by references. | |
148 | // | |
149 | // We could also read the relocations during the first pass, and | |
150 | // mark symbols at that time. That is how the old GNU linker works. | |
151 | // Doing that is more complex, since we may later decide to discard | |
152 | // some of the sections, and thus change our minds about the types | |
153 | // of references made to the symbols. | |
154 | Task_token* blocker = new Task_token(); | |
155 | Task_token* symtab_lock = new Task_token(); | |
f6ce93d6 ILT |
156 | for (Input_objects::Relobj_iterator p = input_objects->relobj_begin(); |
157 | p != input_objects->relobj_end(); | |
92e059d8 ILT |
158 | ++p) |
159 | { | |
160 | // We can read and process the relocations in any order. But we | |
161 | // only want one task to write to the symbol table at a time. | |
162 | // So we queue up a task for each object to read the | |
163 | // relocations. That task will in turn queue a task to wait | |
164 | // until it can write to the symbol table. | |
165 | blocker->add_blocker(); | |
ead1e424 ILT |
166 | workqueue->queue(new Read_relocs(options, symtab, layout, *p, |
167 | symtab_lock, blocker)); | |
92e059d8 ILT |
168 | } |
169 | ||
170 | // Allocate common symbols. This requires write access to the | |
171 | // symbol table, but is independent of the relocation processing. | |
ead1e424 ILT |
172 | blocker->add_blocker(); |
173 | workqueue->queue(new Allocate_commons_task(options, symtab, layout, | |
174 | symtab_lock, blocker)); | |
92e059d8 ILT |
175 | |
176 | // When all those tasks are complete, we can start laying out the | |
177 | // output file. | |
178 | workqueue->queue(new Task_function(new Layout_task_runner(options, | |
179 | input_objects, | |
180 | symtab, | |
181 | layout), | |
182 | blocker)); | |
183 | } | |
61ba1cf9 ILT |
184 | |
185 | // Queue up the final set of tasks. This is called at the end of | |
186 | // Layout_task. | |
187 | ||
188 | void | |
189 | queue_final_tasks(const General_options& options, | |
190 | const Input_objects* input_objects, | |
191 | const Symbol_table* symtab, | |
192 | const Layout* layout, | |
193 | Workqueue* workqueue, | |
194 | Output_file* of) | |
195 | { | |
196 | // Use a blocker to block the final cleanup task. | |
197 | Task_token* final_blocker = new Task_token(); | |
198 | ||
199 | // Queue a task for each input object to relocate the sections and | |
200 | // write out the local symbols. | |
f6ce93d6 ILT |
201 | for (Input_objects::Relobj_iterator p = input_objects->relobj_begin(); |
202 | p != input_objects->relobj_end(); | |
61ba1cf9 ILT |
203 | ++p) |
204 | { | |
205 | final_blocker->add_blocker(); | |
92e059d8 ILT |
206 | workqueue->queue(new Relocate_task(options, symtab, layout, *p, of, |
207 | final_blocker)); | |
61ba1cf9 ILT |
208 | } |
209 | ||
210 | // Queue a task to write out the symbol table. | |
211 | final_blocker->add_blocker(); | |
212 | workqueue->queue(new Write_symbols_task(symtab, input_objects->target(), | |
213 | layout->sympool(), of, | |
214 | final_blocker)); | |
215 | ||
216 | // Queue a task to write out everything else. | |
217 | final_blocker->add_blocker(); | |
218 | workqueue->queue(new Write_data_task(layout, of, final_blocker)); | |
219 | ||
220 | // Queue a task to close the output file. This will be blocked by | |
221 | // FINAL_BLOCKER. | |
92e059d8 ILT |
222 | workqueue->queue(new Task_function(new Close_task_runner(of), |
223 | final_blocker)); | |
61ba1cf9 ILT |
224 | } |
225 | ||
226 | } // End namespace gold. | |
227 | ||
92e059d8 ILT |
228 | using namespace gold; |
229 | ||
bae7f79e ILT |
230 | int |
231 | main(int argc, char** argv) | |
232 | { | |
233 | #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) | |
234 | setlocale (LC_MESSAGES, ""); | |
235 | #endif | |
236 | #if defined (HAVE_SETLOCALE) | |
237 | setlocale (LC_CTYPE, ""); | |
238 | #endif | |
239 | bindtextdomain (PACKAGE, LOCALEDIR); | |
240 | textdomain (PACKAGE); | |
241 | ||
242 | gold::program_name = argv[0]; | |
243 | ||
244 | // Handle the command line options. | |
245 | gold::Command_line command_line; | |
246 | command_line.process(argc - 1, argv + 1); | |
247 | ||
248 | // The work queue. | |
249 | gold::Workqueue workqueue(command_line.options()); | |
250 | ||
a2fb1b05 | 251 | // The list of input objects. |
54dc6425 | 252 | Input_objects input_objects; |
a2fb1b05 | 253 | |
bae7f79e | 254 | // The symbol table. |
14bfc3f5 | 255 | Symbol_table symtab; |
bae7f79e | 256 | |
12e14209 ILT |
257 | // The layout object. |
258 | Layout layout(command_line.options()); | |
259 | ||
bae7f79e ILT |
260 | // Get the search path from the -L options. |
261 | Dirsearch search_path; | |
262 | search_path.add(&workqueue, command_line.options().search_path()); | |
263 | ||
264 | // Queue up the first set of tasks. | |
265 | queue_initial_tasks(command_line.options(), search_path, | |
ead1e424 | 266 | command_line, &workqueue, &input_objects, |
12e14209 | 267 | &symtab, &layout); |
bae7f79e ILT |
268 | |
269 | // Run the main task processing loop. | |
270 | workqueue.process(); | |
271 | ||
272 | gold::gold_exit(true); | |
273 | } |