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