xref: /dflybsd-src/contrib/gcc-8.0/gcc/lto/lto-object.c (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
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