Branch data Line data Source code
1 : : /* LTO routines to use object files.
2 : : Copyright (C) 2010-2025 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 : 32532 : lto_file_init (lto_file *file, const char *filename, off_t offset)
59 : : {
60 : 32532 : file->filename = filename;
61 : 32532 : 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 : 32532 : lto_obj_file_open (const char *filename, bool writable)
70 : : {
71 : 32532 : const char *offset_p;
72 : 32532 : int consumed;
73 : 32532 : char *fname;
74 : 32532 : int64_t offset;
75 : 32532 : struct lto_simple_object *lo;
76 : 32532 : const char *errmsg;
77 : 32532 : int err;
78 : :
79 : 32532 : offset_p = strrchr (filename, '@');
80 : 32532 : if (offset_p != NULL
81 : 32532 : && offset_p != filename
82 : 1 : && sscanf (offset_p, "@%" PRIi64 "%n", &offset, &consumed) >= 1
83 : 32533 : && 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 : 32531 : fname = xstrdup (filename);
92 : 32531 : offset = 0;
93 : : }
94 : :
95 : 32532 : lo = XCNEW (struct lto_simple_object);
96 : 32532 : lto_file_init ((lto_file *) lo, fname, offset);
97 : :
98 : 55889 : lo->fd = open (fname,
99 : : (writable
100 : : ? O_WRONLY | O_CREAT | O_BINARY
101 : : : O_RDONLY | O_BINARY),
102 : : 0666);
103 : 32532 : if (lo->fd == -1)
104 : 0 : fatal_error (input_location, "open %s failed: %s", fname, xstrerror (errno));
105 : :
106 : 32532 : if (!writable)
107 : : {
108 : 23357 : simple_object_attributes *attrs;
109 : :
110 : 23357 : lo->sobj_r = simple_object_start_read (lo->fd, offset, LTO_SEGMENT_NAME,
111 : : &errmsg, &err);
112 : 23357 : if (lo->sobj_r == NULL)
113 : 0 : goto fail_errmsg;
114 : :
115 : 23357 : attrs = simple_object_fetch_attributes (lo->sobj_r, &errmsg, &err);
116 : 23357 : if (attrs == NULL)
117 : 0 : goto fail_errmsg;
118 : :
119 : 23357 : if (saved_attributes == NULL)
120 : 22316 : saved_attributes = attrs;
121 : : else
122 : : {
123 : 1041 : errmsg = simple_object_attributes_merge (saved_attributes, attrs,
124 : : &err);
125 : 1041 : if (errmsg != NULL)
126 : : {
127 : 0 : free (attrs);
128 : 0 : goto fail_errmsg;
129 : : }
130 : : }
131 : : }
132 : : else
133 : : {
134 : 9175 : gcc_assert (saved_attributes != NULL);
135 : 9175 : lo->sobj_w = simple_object_start_write (saved_attributes,
136 : : LTO_SEGMENT_NAME,
137 : : &errmsg, &err);
138 : 9175 : if (lo->sobj_w == NULL)
139 : 0 : goto fail_errmsg;
140 : : }
141 : :
142 : 32532 : 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 : 32532 : lto_obj_file_close (lto_file *file)
162 : : {
163 : 32532 : struct lto_simple_object *lo = (struct lto_simple_object *) file;
164 : :
165 : 32532 : if (lo->sobj_r != NULL)
166 : 23357 : simple_object_release_read (lo->sobj_r);
167 : 9175 : else if (lo->sobj_w != NULL)
168 : : {
169 : 9175 : const char *errmsg;
170 : 9175 : int err;
171 : :
172 : 9175 : gcc_assert (lo->base.offset == 0);
173 : :
174 : 9175 : errmsg = simple_object_write_to_file (lo->sobj_w, lo->fd, &err);
175 : 9175 : 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 : 9175 : simple_object_release_write (lo->sobj_w);
184 : : }
185 : :
186 : 32532 : if (lo->fd != -1)
187 : : {
188 : 32532 : if (close (lo->fd) < 0)
189 : 0 : fatal_error (input_location, "close: %s", xstrerror (errno));
190 : : }
191 : 32532 : }
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 : 588052 : lto_obj_add_section (void *data, const char *name, off_t offset,
209 : : off_t length)
210 : : {
211 : 588052 : struct lto_obj_add_section_data *loasd =
212 : : (struct lto_obj_add_section_data *) data;
213 : 588052 : htab_t section_hash_table = (htab_t) loasd->section_hash_table;
214 : 588052 : char *new_name;
215 : 588052 : struct lto_section_slot s_slot;
216 : 588052 : void **slot;
217 : 588052 : struct lto_section_list *list = loasd->list;
218 : :
219 : 588052 : if (strncmp (name, section_name_prefix, strlen (section_name_prefix)))
220 : : return 1;
221 : :
222 : 402762 : new_name = xstrdup (name);
223 : 402762 : s_slot.name = new_name;
224 : 402762 : slot = htab_find_slot (section_hash_table, &s_slot, INSERT);
225 : 402762 : if (*slot == NULL)
226 : : {
227 : 402762 : struct lto_section_slot *new_slot = XCNEW (struct lto_section_slot);
228 : :
229 : 402762 : new_slot->name = new_name;
230 : 402762 : new_slot->start = loasd->base_offset + offset;
231 : 402762 : new_slot->len = length;
232 : 402762 : *slot = new_slot;
233 : :
234 : 402762 : if (list != NULL)
235 : : {
236 : 402762 : if (!list->first)
237 : 23357 : list->first = new_slot;
238 : 402762 : if (list->last)
239 : 379405 : list->last->next = new_slot;
240 : 402762 : 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 : 23357 : lto_obj_build_section_table (lto_file *lto_file, struct lto_section_list *list)
257 : : {
258 : 23357 : struct lto_simple_object *lo = (struct lto_simple_object *) lto_file;
259 : 23357 : htab_t section_hash_table;
260 : 23357 : struct lto_obj_add_section_data loasd;
261 : 23357 : const char *errmsg;
262 : 23357 : int err;
263 : :
264 : 23357 : section_hash_table = lto_obj_create_section_hash_table ();
265 : :
266 : 23357 : gcc_assert (lo->sobj_r != NULL && lo->sobj_w == NULL);
267 : 23357 : loasd.section_hash_table = section_hash_table;
268 : 23357 : loasd.base_offset = lo->base.offset;
269 : 23357 : loasd.list = list;
270 : 23357 : errmsg = simple_object_find_sections (lo->sobj_r, lto_obj_add_section,
271 : : &loasd, &err);
272 : 23357 : 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 : 18350 : lto_set_current_out_file (lto_file *file)
293 : : {
294 : 18350 : lto_file *old_file;
295 : :
296 : 18350 : old_file = current_out_file;
297 : 18350 : current_out_file = file;
298 : 18350 : 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 : 122664 : lto_obj_begin_section (const char *name)
314 : : {
315 : 122664 : struct lto_simple_object *lo;
316 : 122664 : int align;
317 : 122664 : const char *errmsg;
318 : 122664 : int err;
319 : :
320 : 122664 : lo = (struct lto_simple_object *) current_out_file;
321 : 122664 : gcc_assert (lo != NULL
322 : : && lo->sobj_r == NULL
323 : : && lo->sobj_w != NULL
324 : : && lo->section == NULL);
325 : :
326 : 122664 : align = ceil_log2 (POINTER_SIZE_UNITS);
327 : 122664 : lo->section = simple_object_write_create_section (lo->sobj_w, name, align,
328 : : &errmsg, &err);
329 : 122664 : 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 : 122664 : }
337 : :
338 : : /* Add data to a section. BLOCK is a pointer to memory containing
339 : : DATA. */
340 : :
341 : : void
342 : 327911 : lto_obj_append_data (const void *data, size_t len, void *)
343 : : {
344 : 327911 : struct lto_simple_object *lo;
345 : 327911 : const char *errmsg;
346 : 327911 : int err;
347 : :
348 : 327911 : lo = (struct lto_simple_object *) current_out_file;
349 : 327911 : gcc_assert (lo != NULL && lo->section != NULL);
350 : :
351 : 327911 : errmsg = simple_object_write_add_data (lo->sobj_w, lo->section, data, len,
352 : : 1, &err);
353 : 327911 : 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 : 327911 : }
361 : :
362 : : /* Stop writing to the current output section. */
363 : :
364 : : void
365 : 122664 : lto_obj_end_section (void)
366 : : {
367 : 122664 : struct lto_simple_object *lo;
368 : :
369 : 122664 : lo = (struct lto_simple_object *) current_out_file;
370 : 122664 : gcc_assert (lo != NULL && lo->section != NULL);
371 : 122664 : lo->section = NULL;
372 : 122664 : }
|