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