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