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 : 28945 : lto_file_init (lto_file *file, const char *filename, off_t offset)
59 : : {
60 : 28945 : file->filename = filename;
61 : 28945 : 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 : 28945 : lto_obj_file_open (const char *filename, bool writable)
70 : : {
71 : 28945 : const char *offset_p;
72 : 28945 : long loffset;
73 : 28945 : int consumed;
74 : 28945 : char *fname;
75 : 28945 : off_t offset;
76 : 28945 : struct lto_simple_object *lo;
77 : 28945 : const char *errmsg;
78 : 28945 : int err;
79 : :
80 : 28945 : offset_p = strrchr (filename, '@');
81 : 28945 : if (offset_p != NULL
82 : 28945 : && offset_p != filename
83 : 0 : && sscanf (offset_p, "@%li%n", &loffset, &consumed) >= 1
84 : 28945 : && strlen (offset_p) == (unsigned int) consumed)
85 : : {
86 : 0 : fname = XNEWVEC (char, offset_p - filename + 1);
87 : 0 : memcpy (fname, filename, offset_p - filename);
88 : 0 : fname[offset_p - filename] = '\0';
89 : 0 : offset = (off_t) loffset;
90 : : }
91 : : else
92 : : {
93 : 28945 : fname = xstrdup (filename);
94 : 28945 : offset = 0;
95 : : }
96 : :
97 : 28945 : lo = XCNEW (struct lto_simple_object);
98 : 28945 : lto_file_init ((lto_file *) lo, fname, offset);
99 : :
100 : 49880 : lo->fd = open (fname,
101 : : (writable
102 : : ? O_WRONLY | O_CREAT | O_BINARY
103 : : : O_RDONLY | O_BINARY),
104 : : 0666);
105 : 28945 : if (lo->fd == -1)
106 : 0 : fatal_error (input_location, "open %s failed: %s", fname, xstrerror (errno));
107 : :
108 : 28945 : if (!writable)
109 : : {
110 : 20935 : simple_object_attributes *attrs;
111 : :
112 : 20935 : lo->sobj_r = simple_object_start_read (lo->fd, offset, LTO_SEGMENT_NAME,
113 : : &errmsg, &err);
114 : 20935 : if (lo->sobj_r == NULL)
115 : 0 : goto fail_errmsg;
116 : :
117 : 20935 : attrs = simple_object_fetch_attributes (lo->sobj_r, &errmsg, &err);
118 : 20935 : if (attrs == NULL)
119 : 0 : goto fail_errmsg;
120 : :
121 : 20935 : if (saved_attributes == NULL)
122 : 19907 : saved_attributes = attrs;
123 : : else
124 : : {
125 : 1028 : errmsg = simple_object_attributes_merge (saved_attributes, attrs,
126 : : &err);
127 : 1028 : if (errmsg != NULL)
128 : : {
129 : 0 : free (attrs);
130 : 0 : goto fail_errmsg;
131 : : }
132 : : }
133 : : }
134 : : else
135 : : {
136 : 8010 : gcc_assert (saved_attributes != NULL);
137 : 8010 : lo->sobj_w = simple_object_start_write (saved_attributes,
138 : : LTO_SEGMENT_NAME,
139 : : &errmsg, &err);
140 : 8010 : if (lo->sobj_w == NULL)
141 : 0 : goto fail_errmsg;
142 : : }
143 : :
144 : 28945 : return &lo->base;
145 : :
146 : 0 : fail_errmsg:
147 : 0 : if (err == 0)
148 : 0 : error ("%s: %s", fname, errmsg);
149 : : else
150 : 0 : error ("%s: %s: %s", fname, errmsg, xstrerror (err));
151 : :
152 : 0 : if (lo->fd != -1)
153 : 0 : lto_obj_file_close ((lto_file *) lo);
154 : 0 : free (lo);
155 : 0 : return NULL;
156 : : }
157 : :
158 : :
159 : : /* Close FILE. If FILE was opened for writing, it is written out
160 : : now. */
161 : :
162 : : void
163 : 28945 : lto_obj_file_close (lto_file *file)
164 : : {
165 : 28945 : struct lto_simple_object *lo = (struct lto_simple_object *) file;
166 : :
167 : 28945 : if (lo->sobj_r != NULL)
168 : 20935 : simple_object_release_read (lo->sobj_r);
169 : 8010 : else if (lo->sobj_w != NULL)
170 : : {
171 : 8010 : const char *errmsg;
172 : 8010 : int err;
173 : :
174 : 8010 : gcc_assert (lo->base.offset == 0);
175 : :
176 : 8010 : errmsg = simple_object_write_to_file (lo->sobj_w, lo->fd, &err);
177 : 8010 : if (errmsg != NULL)
178 : : {
179 : 0 : if (err == 0)
180 : 0 : fatal_error (input_location, "%s", errmsg);
181 : : else
182 : 0 : fatal_error (input_location, "%s: %s", errmsg, xstrerror (err));
183 : : }
184 : :
185 : 8010 : simple_object_release_write (lo->sobj_w);
186 : : }
187 : :
188 : 28945 : if (lo->fd != -1)
189 : : {
190 : 28945 : if (close (lo->fd) < 0)
191 : 0 : fatal_error (input_location, "close: %s", xstrerror (errno));
192 : : }
193 : 28945 : }
194 : :
195 : : /* This is passed to lto_obj_add_section. */
196 : :
197 : : struct lto_obj_add_section_data
198 : : {
199 : : /* The hash table of sections. */
200 : : htab_t section_hash_table;
201 : : /* The offset of this file. */
202 : : off_t base_offset;
203 : : /* List in linker order */
204 : : struct lto_section_list *list;
205 : : };
206 : :
207 : : /* This is called for each section in the file. */
208 : :
209 : : static int
210 : 545752 : lto_obj_add_section (void *data, const char *name, off_t offset,
211 : : off_t length)
212 : : {
213 : 545752 : struct lto_obj_add_section_data *loasd =
214 : : (struct lto_obj_add_section_data *) data;
215 : 545752 : htab_t section_hash_table = (htab_t) loasd->section_hash_table;
216 : 545752 : char *new_name;
217 : 545752 : struct lto_section_slot s_slot;
218 : 545752 : void **slot;
219 : 545752 : struct lto_section_list *list = loasd->list;
220 : :
221 : 545752 : if (strncmp (name, section_name_prefix, strlen (section_name_prefix)))
222 : : return 1;
223 : :
224 : 374572 : new_name = xstrdup (name);
225 : 374572 : s_slot.name = new_name;
226 : 374572 : slot = htab_find_slot (section_hash_table, &s_slot, INSERT);
227 : 374572 : if (*slot == NULL)
228 : : {
229 : 374572 : struct lto_section_slot *new_slot = XCNEW (struct lto_section_slot);
230 : :
231 : 374572 : new_slot->name = new_name;
232 : 374572 : new_slot->start = loasd->base_offset + offset;
233 : 374572 : new_slot->len = length;
234 : 374572 : *slot = new_slot;
235 : :
236 : 374572 : if (list != NULL)
237 : : {
238 : 374572 : if (!list->first)
239 : 20935 : list->first = new_slot;
240 : 374572 : if (list->last)
241 : 353637 : list->last->next = new_slot;
242 : 374572 : list->last = new_slot;
243 : : }
244 : : }
245 : : else
246 : : {
247 : 0 : error ("two or more sections for %s", new_name);
248 : 0 : return 0;
249 : : }
250 : :
251 : : return 1;
252 : : }
253 : :
254 : : /* Build a hash table whose key is the section name and whose data is
255 : : the start and size of each section in the .o file. */
256 : :
257 : : htab_t
258 : 20935 : lto_obj_build_section_table (lto_file *lto_file, struct lto_section_list *list)
259 : : {
260 : 20935 : struct lto_simple_object *lo = (struct lto_simple_object *) lto_file;
261 : 20935 : htab_t section_hash_table;
262 : 20935 : struct lto_obj_add_section_data loasd;
263 : 20935 : const char *errmsg;
264 : 20935 : int err;
265 : :
266 : 20935 : section_hash_table = lto_obj_create_section_hash_table ();
267 : :
268 : 20935 : gcc_assert (lo->sobj_r != NULL && lo->sobj_w == NULL);
269 : 20935 : loasd.section_hash_table = section_hash_table;
270 : 20935 : loasd.base_offset = lo->base.offset;
271 : 20935 : loasd.list = list;
272 : 20935 : errmsg = simple_object_find_sections (lo->sobj_r, lto_obj_add_section,
273 : : &loasd, &err);
274 : 20935 : if (errmsg != NULL)
275 : : {
276 : 0 : if (err == 0)
277 : 0 : error ("%s", errmsg);
278 : : else
279 : 0 : error ("%s: %s", errmsg, xstrerror (err));
280 : 0 : htab_delete (section_hash_table);
281 : 0 : return NULL;
282 : : }
283 : :
284 : : return section_hash_table;
285 : : }
286 : :
287 : : /* The current output file. */
288 : :
289 : : static lto_file *current_out_file;
290 : :
291 : : /* Set the current output file. Return the old one. */
292 : :
293 : : lto_file *
294 : 16020 : lto_set_current_out_file (lto_file *file)
295 : : {
296 : 16020 : lto_file *old_file;
297 : :
298 : 16020 : old_file = current_out_file;
299 : 16020 : current_out_file = file;
300 : 16020 : return old_file;
301 : : }
302 : :
303 : : /* Return the current output file. */
304 : :
305 : : lto_file *
306 : 0 : lto_get_current_out_file (void)
307 : : {
308 : 0 : return current_out_file;
309 : : }
310 : :
311 : : /* Begin writing a new section named NAME in the current output
312 : : file. */
313 : :
314 : : void
315 : 110632 : lto_obj_begin_section (const char *name)
316 : : {
317 : 110632 : struct lto_simple_object *lo;
318 : 110632 : int align;
319 : 110632 : const char *errmsg;
320 : 110632 : int err;
321 : :
322 : 110632 : lo = (struct lto_simple_object *) current_out_file;
323 : 110632 : gcc_assert (lo != NULL
324 : : && lo->sobj_r == NULL
325 : : && lo->sobj_w != NULL
326 : : && lo->section == NULL);
327 : :
328 : 110632 : align = ceil_log2 (POINTER_SIZE_UNITS);
329 : 110632 : lo->section = simple_object_write_create_section (lo->sobj_w, name, align,
330 : : &errmsg, &err);
331 : 110632 : if (lo->section == NULL)
332 : : {
333 : 0 : if (err == 0)
334 : 0 : fatal_error (input_location, "%s", errmsg);
335 : : else
336 : 0 : fatal_error (input_location, "%s: %s", errmsg, xstrerror (errno));
337 : : }
338 : 110632 : }
339 : :
340 : : /* Add data to a section. BLOCK is a pointer to memory containing
341 : : DATA. */
342 : :
343 : : void
344 : 299699 : lto_obj_append_data (const void *data, size_t len, void *)
345 : : {
346 : 299699 : struct lto_simple_object *lo;
347 : 299699 : const char *errmsg;
348 : 299699 : int err;
349 : :
350 : 299699 : lo = (struct lto_simple_object *) current_out_file;
351 : 299699 : gcc_assert (lo != NULL && lo->section != NULL);
352 : :
353 : 299699 : errmsg = simple_object_write_add_data (lo->sobj_w, lo->section, data, len,
354 : : 1, &err);
355 : 299699 : if (errmsg != NULL)
356 : : {
357 : 0 : if (err == 0)
358 : 0 : fatal_error (input_location, "%s", errmsg);
359 : : else
360 : 0 : fatal_error (input_location, "%s: %s", errmsg, xstrerror (errno));
361 : : }
362 : 299699 : }
363 : :
364 : : /* Stop writing to the current output section. */
365 : :
366 : : void
367 : 110632 : lto_obj_end_section (void)
368 : : {
369 : 110632 : struct lto_simple_object *lo;
370 : :
371 : 110632 : lo = (struct lto_simple_object *) current_out_file;
372 : 110632 : gcc_assert (lo != NULL && lo->section != NULL);
373 : 110632 : lo->section = NULL;
374 : 110632 : }
|