Line data Source code
1 : /* LTO routines to use object files.
2 : Copyright (C) 2010-2026 Free Software Foundation, Inc.
3 : Written by Ian Lance Taylor, Google.
4 :
5 : This file is part of GCC.
6 :
7 : GCC is free software; you can redistribute it and/or modify it under
8 : the terms of the GNU General Public License as published by the Free
9 : Software Foundation; either version 3, or (at your option) any later
10 : version.
11 :
12 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 : for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with GCC; see the file COPYING3. If not see
19 : <http://www.gnu.org/licenses/>. */
20 :
21 : #include "config.h"
22 : #include "system.h"
23 : #include "coretypes.h"
24 : #include "tm.h"
25 : #include "diagnostic-core.h"
26 : #include "lto.h"
27 : #include "lto-section-names.h"
28 : #include "simple-object.h"
29 :
30 : /* An LTO file wrapped around an simple_object. */
31 :
32 : struct lto_simple_object
33 : {
34 : /* The base information. */
35 : lto_file base;
36 :
37 : /* The system file descriptor. */
38 : int fd;
39 :
40 : /* The simple_object if we are reading the file. */
41 : simple_object_read *sobj_r;
42 :
43 : /* The simple_object if we are writing the file. */
44 : simple_object_write *sobj_w;
45 :
46 : /* The currently active section. */
47 : simple_object_write_section *section;
48 : };
49 :
50 : /* Saved simple_object attributes. FIXME: Once set, this is never
51 : cleared. */
52 :
53 : static simple_object_attributes *saved_attributes;
54 :
55 : /* Initialize FILE, an LTO file object for FILENAME. */
56 :
57 : static void
58 29637 : lto_file_init (lto_file *file, const char *filename, off_t offset)
59 : {
60 29637 : file->filename = filename;
61 29637 : file->offset = offset;
62 0 : }
63 :
64 : /* Open the file FILENAME. It WRITABLE is true, the file is opened
65 : for write and, if necessary, created. Otherwise, the file is
66 : opened for reading. Returns the opened file. */
67 :
68 : lto_file *
69 29637 : lto_obj_file_open (const char *filename, bool writable)
70 : {
71 29637 : const char *offset_p;
72 29637 : int consumed;
73 29637 : char *fname;
74 29637 : int64_t offset;
75 29637 : struct lto_simple_object *lo;
76 29637 : const char *errmsg;
77 29637 : int err;
78 :
79 29637 : offset_p = strrchr (filename, '@');
80 29637 : if (offset_p != NULL
81 29637 : && offset_p != filename
82 1 : && sscanf (offset_p, "@%" PRIi64 "%n", &offset, &consumed) >= 1
83 29638 : && strlen (offset_p) == (unsigned int) consumed)
84 : {
85 1 : fname = XNEWVEC (char, offset_p - filename + 1);
86 1 : memcpy (fname, filename, offset_p - filename);
87 1 : fname[offset_p - filename] = '\0';
88 : }
89 : else
90 : {
91 29636 : fname = xstrdup (filename);
92 29636 : offset = 0;
93 : }
94 :
95 29637 : lo = XCNEW (struct lto_simple_object);
96 29637 : lto_file_init ((lto_file *) lo, fname, offset);
97 :
98 51084 : lo->fd = open (fname,
99 : (writable
100 : ? O_WRONLY | O_CREAT | O_BINARY
101 : : O_RDONLY | O_BINARY),
102 : 0666);
103 29637 : if (lo->fd == -1)
104 0 : fatal_error (input_location, "open %s failed: %s", fname, xstrerror (errno));
105 :
106 29637 : if (!writable)
107 : {
108 21447 : simple_object_attributes *attrs;
109 :
110 21447 : lo->sobj_r = simple_object_start_read (lo->fd, offset, LTO_SEGMENT_NAME,
111 : &errmsg, &err);
112 21447 : if (lo->sobj_r == NULL)
113 0 : goto fail_errmsg;
114 :
115 21447 : attrs = simple_object_fetch_attributes (lo->sobj_r, &errmsg, &err);
116 21447 : if (attrs == NULL)
117 0 : goto fail_errmsg;
118 :
119 21447 : if (saved_attributes == NULL)
120 20392 : saved_attributes = attrs;
121 : else
122 : {
123 1055 : errmsg = simple_object_attributes_merge (saved_attributes, attrs,
124 : &err);
125 1055 : if (errmsg != NULL)
126 : {
127 0 : free (attrs);
128 0 : goto fail_errmsg;
129 : }
130 : }
131 : }
132 : else
133 : {
134 8190 : gcc_assert (saved_attributes != NULL);
135 8190 : lo->sobj_w = simple_object_start_write (saved_attributes,
136 : LTO_SEGMENT_NAME,
137 : &errmsg, &err);
138 8190 : if (lo->sobj_w == NULL)
139 0 : goto fail_errmsg;
140 : }
141 :
142 29637 : return &lo->base;
143 :
144 0 : fail_errmsg:
145 0 : if (err == 0)
146 0 : error ("%s: %s", fname, errmsg);
147 : else
148 0 : error ("%s: %s: %s", fname, errmsg, xstrerror (err));
149 :
150 0 : if (lo->fd != -1)
151 0 : lto_obj_file_close ((lto_file *) lo);
152 0 : free (lo);
153 0 : return NULL;
154 : }
155 :
156 :
157 : /* Close FILE. If FILE was opened for writing, it is written out
158 : now. */
159 :
160 : void
161 29637 : lto_obj_file_close (lto_file *file)
162 : {
163 29637 : struct lto_simple_object *lo = (struct lto_simple_object *) file;
164 :
165 29637 : if (lo->sobj_r != NULL)
166 21447 : simple_object_release_read (lo->sobj_r);
167 8190 : else if (lo->sobj_w != NULL)
168 : {
169 8190 : const char *errmsg;
170 8190 : int err;
171 :
172 8190 : gcc_assert (lo->base.offset == 0);
173 :
174 8190 : errmsg = simple_object_write_to_file (lo->sobj_w, lo->fd, &err);
175 8190 : if (errmsg != NULL)
176 : {
177 0 : if (err == 0)
178 0 : fatal_error (input_location, "%s", errmsg);
179 : else
180 0 : fatal_error (input_location, "%s: %s", errmsg, xstrerror (err));
181 : }
182 :
183 8190 : simple_object_release_write (lo->sobj_w);
184 : }
185 :
186 29637 : if (lo->fd != -1)
187 : {
188 29637 : if (close (lo->fd) < 0)
189 0 : fatal_error (input_location, "close: %s", xstrerror (errno));
190 : }
191 29637 : }
192 :
193 : /* This is passed to lto_obj_add_section. */
194 :
195 : struct lto_obj_add_section_data
196 : {
197 : /* The hash table of sections. */
198 : htab_t section_hash_table;
199 : /* The offset of this file. */
200 : off_t base_offset;
201 : /* List in linker order */
202 : struct lto_section_list *list;
203 : };
204 :
205 : /* This is called for each section in the file. */
206 :
207 : static int
208 560441 : lto_obj_add_section (void *data, const char *name, off_t offset,
209 : off_t length)
210 : {
211 560441 : struct lto_obj_add_section_data *loasd =
212 : (struct lto_obj_add_section_data *) data;
213 560441 : htab_t section_hash_table = (htab_t) loasd->section_hash_table;
214 560441 : char *new_name;
215 560441 : struct lto_section_slot s_slot;
216 560441 : void **slot;
217 560441 : struct lto_section_list *list = loasd->list;
218 :
219 560441 : if (strncmp (name, section_name_prefix, strlen (section_name_prefix)))
220 : return 1;
221 :
222 384177 : new_name = xstrdup (name);
223 384177 : s_slot.name = new_name;
224 384177 : slot = htab_find_slot (section_hash_table, &s_slot, INSERT);
225 384177 : if (*slot == NULL)
226 : {
227 384177 : struct lto_section_slot *new_slot = XCNEW (struct lto_section_slot);
228 :
229 384177 : new_slot->name = new_name;
230 384177 : new_slot->start = loasd->base_offset + offset;
231 384177 : new_slot->len = length;
232 384177 : *slot = new_slot;
233 :
234 384177 : if (list != NULL)
235 : {
236 384177 : if (!list->first)
237 21447 : list->first = new_slot;
238 384177 : if (list->last)
239 362730 : list->last->next = new_slot;
240 384177 : list->last = new_slot;
241 : }
242 : }
243 : else
244 : {
245 0 : error ("two or more sections for %s", new_name);
246 0 : return 0;
247 : }
248 :
249 : return 1;
250 : }
251 :
252 : /* Build a hash table whose key is the section name and whose data is
253 : the start and size of each section in the .o file. */
254 :
255 : htab_t
256 21447 : lto_obj_build_section_table (lto_file *lto_file, struct lto_section_list *list)
257 : {
258 21447 : struct lto_simple_object *lo = (struct lto_simple_object *) lto_file;
259 21447 : htab_t section_hash_table;
260 21447 : struct lto_obj_add_section_data loasd;
261 21447 : const char *errmsg;
262 21447 : int err;
263 :
264 21447 : section_hash_table = lto_obj_create_section_hash_table ();
265 :
266 21447 : gcc_assert (lo->sobj_r != NULL && lo->sobj_w == NULL);
267 21447 : loasd.section_hash_table = section_hash_table;
268 21447 : loasd.base_offset = lo->base.offset;
269 21447 : loasd.list = list;
270 21447 : errmsg = simple_object_find_sections (lo->sobj_r, lto_obj_add_section,
271 : &loasd, &err);
272 21447 : if (errmsg != NULL)
273 : {
274 0 : if (err == 0)
275 0 : error ("%s", errmsg);
276 : else
277 0 : error ("%s: %s", errmsg, xstrerror (err));
278 0 : htab_delete (section_hash_table);
279 0 : return NULL;
280 : }
281 :
282 : return section_hash_table;
283 : }
284 :
285 : /* The current output file. */
286 :
287 : static lto_file *current_out_file;
288 :
289 : /* Set the current output file. Return the old one. */
290 :
291 : lto_file *
292 16380 : lto_set_current_out_file (lto_file *file)
293 : {
294 16380 : lto_file *old_file;
295 :
296 16380 : old_file = current_out_file;
297 16380 : current_out_file = file;
298 16380 : return old_file;
299 : }
300 :
301 : /* Return the current output file. */
302 :
303 : lto_file *
304 0 : lto_get_current_out_file (void)
305 : {
306 0 : return current_out_file;
307 : }
308 :
309 : /* Begin writing a new section named NAME in the current output
310 : file. */
311 :
312 : void
313 113196 : lto_obj_begin_section (const char *name)
314 : {
315 113196 : struct lto_simple_object *lo;
316 113196 : int align;
317 113196 : const char *errmsg;
318 113196 : int err;
319 :
320 113196 : lo = (struct lto_simple_object *) current_out_file;
321 113196 : gcc_assert (lo != NULL
322 : && lo->sobj_r == NULL
323 : && lo->sobj_w != NULL
324 : && lo->section == NULL);
325 :
326 113196 : align = ceil_log2 (POINTER_SIZE_UNITS);
327 113196 : lo->section = simple_object_write_create_section (lo->sobj_w, name, align,
328 : &errmsg, &err);
329 113196 : if (lo->section == NULL)
330 : {
331 0 : if (err == 0)
332 0 : fatal_error (input_location, "%s", errmsg);
333 : else
334 0 : fatal_error (input_location, "%s: %s", errmsg, xstrerror (errno));
335 : }
336 113196 : }
337 :
338 : /* Add data to a section. BLOCK is a pointer to memory containing
339 : DATA. */
340 :
341 : void
342 306639 : lto_obj_append_data (const void *data, size_t len, void *)
343 : {
344 306639 : struct lto_simple_object *lo;
345 306639 : const char *errmsg;
346 306639 : int err;
347 :
348 306639 : lo = (struct lto_simple_object *) current_out_file;
349 306639 : gcc_assert (lo != NULL && lo->section != NULL);
350 :
351 306639 : errmsg = simple_object_write_add_data (lo->sobj_w, lo->section, data, len,
352 : 1, &err);
353 306639 : if (errmsg != NULL)
354 : {
355 0 : if (err == 0)
356 0 : fatal_error (input_location, "%s", errmsg);
357 : else
358 0 : fatal_error (input_location, "%s: %s", errmsg, xstrerror (errno));
359 : }
360 306639 : }
361 :
362 : /* Stop writing to the current output section. */
363 :
364 : void
365 113196 : lto_obj_end_section (void)
366 : {
367 113196 : struct lto_simple_object *lo;
368 :
369 113196 : lo = (struct lto_simple_object *) current_out_file;
370 113196 : gcc_assert (lo != NULL && lo->section != NULL);
371 113196 : lo->section = NULL;
372 113196 : }
|