simple-object.c revision 1.1.1.4
1/* simple-object.c -- simple routines to read and write object files.
2   Copyright (C) 2010-2018 Free Software Foundation, Inc.
3   Written by Ian Lance Taylor, Google.
4
5This program is free software; you can redistribute it and/or modify it
6under the terms of the GNU General Public License as published by the
7Free Software Foundation; either version 2, or (at your option) any
8later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, 51 Franklin Street - Fifth Floor,
18Boston, MA 02110-1301, USA.  */
19
20#include "config.h"
21#include "libiberty.h"
22#include "simple-object.h"
23
24#include <errno.h>
25#include <fcntl.h>
26
27#ifdef HAVE_STDLIB_H
28#include <stdlib.h>
29#endif
30
31#ifdef HAVE_STDINT_H
32#include <stdint.h>
33#endif
34
35#ifdef HAVE_STRING_H
36#include <string.h>
37#endif
38
39#ifdef HAVE_INTTYPES_H
40#include <inttypes.h>
41#endif
42
43#ifndef SEEK_SET
44#define SEEK_SET 0
45#endif
46
47#ifndef O_BINARY
48#define O_BINARY 0
49#endif
50
51#include "simple-object-common.h"
52
53/* The known object file formats.  */
54
55static const struct simple_object_functions * const format_functions[] =
56{
57  &simple_object_elf_functions,
58  &simple_object_mach_o_functions,
59  &simple_object_coff_functions,
60  &simple_object_xcoff_functions
61};
62
63/* Read data from a file using the simple_object error reporting
64   conventions.  */
65
66int
67simple_object_internal_read (int descriptor, off_t offset,
68			     unsigned char *buffer, size_t size,
69			     const char **errmsg, int *err)
70{
71  if (lseek (descriptor, offset, SEEK_SET) < 0)
72    {
73      *errmsg = "lseek";
74      *err = errno;
75      return 0;
76    }
77
78  do
79    {
80      ssize_t got = read (descriptor, buffer, size);
81      if (got == 0)
82	break;
83      else if (got > 0)
84	{
85	  buffer += got;
86	  size -= got;
87	}
88      else if (errno != EINTR)
89	{
90	  *errmsg = "read";
91	  *err = errno;
92	  return 0;
93	}
94    }
95  while (size > 0);
96
97  if (size > 0)
98    {
99      *errmsg = "file too short";
100      *err = 0;
101      return 0;
102    }
103
104  return 1;
105}
106
107/* Write data to a file using the simple_object error reporting
108   conventions.  */
109
110int
111simple_object_internal_write (int descriptor, off_t offset,
112			      const unsigned char *buffer, size_t size,
113			      const char **errmsg, int *err)
114{
115  if (lseek (descriptor, offset, SEEK_SET) < 0)
116    {
117      *errmsg = "lseek";
118      *err = errno;
119      return 0;
120    }
121
122  do
123    {
124      ssize_t wrote = write (descriptor, buffer, size);
125      if (wrote == 0)
126	break;
127      else if (wrote > 0)
128	{
129	  buffer += wrote;
130	  size -= wrote;
131	}
132      else if (errno != EINTR)
133	{
134	  *errmsg = "write";
135	  *err = errno;
136	  return 0;
137	}
138    }
139  while (size > 0);
140
141  if (size > 0)
142    {
143      *errmsg = "short write";
144      *err = 0;
145      return 0;
146    }
147
148  return 1;
149}
150
151/* Open for read.  */
152
153simple_object_read *
154simple_object_start_read (int descriptor, off_t offset,
155			  const char *segment_name, const char **errmsg,
156			  int *err)
157{
158  unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN];
159  size_t len, i;
160
161  if (!simple_object_internal_read (descriptor, offset, header,
162				    SIMPLE_OBJECT_MATCH_HEADER_LEN,
163				    errmsg, err))
164    return NULL;
165
166  len = sizeof (format_functions) / sizeof (format_functions[0]);
167  for (i = 0; i < len; ++i)
168    {
169      void *data;
170
171      data = format_functions[i]->match (header, descriptor, offset,
172					 segment_name, errmsg, err);
173      if (data != NULL)
174	{
175	  simple_object_read *ret;
176
177	  ret = XNEW (simple_object_read);
178	  ret->descriptor = descriptor;
179	  ret->offset = offset;
180	  ret->functions = format_functions[i];
181	  ret->data = data;
182	  return ret;
183	}
184    }
185
186  *errmsg = "file not recognized";
187  *err = 0;
188  return NULL;
189}
190
191/* Find all sections.  */
192
193const char *
194simple_object_find_sections (simple_object_read *sobj,
195			     int (*pfn) (void *, const char *, off_t, off_t),
196			     void *data,
197			     int *err)
198{
199  return sobj->functions->find_sections (sobj, pfn, data, err);
200}
201
202/* Internal data passed to find_one_section.  */
203
204struct find_one_section_data
205{
206  /* The section we are looking for.  */
207  const char *name;
208  /* Where to store the section offset.  */
209  off_t *offset;
210  /* Where to store the section length.  */
211  off_t *length;
212  /* Set if the name is found.  */
213  int found;
214};
215
216/* Internal function passed to find_sections.  */
217
218static int
219find_one_section (void *data, const char *name, off_t offset, off_t length)
220{
221  struct find_one_section_data *fosd = (struct find_one_section_data *) data;
222
223  if (strcmp (name, fosd->name) != 0)
224    return 1;
225
226  *fosd->offset = offset;
227  *fosd->length = length;
228  fosd->found = 1;
229
230  /* Stop iteration.  */
231  return 0;
232}
233
234/* Find a section.  */
235
236int
237simple_object_find_section (simple_object_read *sobj, const char *name,
238			    off_t *offset, off_t *length,
239			    const char **errmsg, int *err)
240{
241  struct find_one_section_data fosd;
242
243  fosd.name = name;
244  fosd.offset = offset;
245  fosd.length = length;
246  fosd.found = 0;
247
248  *errmsg = simple_object_find_sections (sobj, find_one_section,
249					 (void *) &fosd, err);
250  if (*errmsg != NULL)
251    return 0;
252  if (!fosd.found)
253    return 0;
254  return 1;
255}
256
257/* Callback to identify and rename LTO debug sections by name.
258   Returns 1 if NAME is a LTO debug section, 0 if not.  */
259
260static char *
261handle_lto_debug_sections (const char *name)
262{
263  char *newname = XCNEWVEC (char, strlen (name) + 1);
264
265  /* ???  So we can't use .gnu.lto_ prefixed sections as the assembler
266     complains about bogus section flags.  Which means we need to arrange
267     for that to be fixed or .gnu.debuglto_ marked as SHF_EXCLUDE (to make
268     fat lto object tooling work for the fat part).  */
269  /* Also include corresponding reloc sections.  */
270  if (strncmp (name, ".rela", sizeof (".rela") - 1) == 0)
271    {
272      strncpy (newname, name, sizeof (".rela") - 1);
273      name += sizeof (".rela") - 1;
274    }
275  else if (strncmp (name, ".rel", sizeof (".rel") - 1) == 0)
276    {
277      strncpy (newname, name, sizeof (".rel") - 1);
278      name += sizeof (".rel") - 1;
279    }
280  /* ???  For now this handles both .gnu.lto_ and .gnu.debuglto_ prefixed
281     sections.  */
282  /* Copy LTO debug sections and rename them to their non-LTO name.  */
283  if (strncmp (name, ".gnu.debuglto_", sizeof (".gnu.debuglto_") - 1) == 0)
284    return strcat (newname, name + sizeof (".gnu.debuglto_") - 1);
285  else if (strncmp (name, ".gnu.lto_.debug_",
286		    sizeof (".gnu.lto_.debug_") -1) == 0)
287    return strcat (newname, name + sizeof (".gnu.lto_") - 1);
288  /* Copy over .note.GNU-stack section under the same name if present.  */
289  else if (strcmp (name, ".note.GNU-stack") == 0)
290    return strcpy (newname, name);
291  /* Copy over .comment section under the same name if present.  Solaris
292     ld uses them to relax its checking of ELF gABI access rules for
293     COMDAT sections in objects produced by GCC.  */
294  else if (strcmp (name, ".comment") == 0)
295    return strcpy (newname, name);
296  return NULL;
297}
298
299/* Copy LTO debug sections.  */
300
301const char *
302simple_object_copy_lto_debug_sections (simple_object_read *sobj,
303				       const char *dest, int *err)
304{
305  const char *errmsg;
306  simple_object_write *dest_sobj;
307  simple_object_attributes *attrs;
308  int outfd;
309
310  if (! sobj->functions->copy_lto_debug_sections)
311    {
312      *err = EINVAL;
313      return "simple_object_copy_lto_debug_sections not implemented";
314    }
315
316  attrs = simple_object_fetch_attributes (sobj, &errmsg, err);
317  if (! attrs)
318    return errmsg;
319  dest_sobj = simple_object_start_write (attrs, NULL, &errmsg, err);
320  simple_object_release_attributes (attrs);
321  if (! dest_sobj)
322    return errmsg;
323
324  errmsg = sobj->functions->copy_lto_debug_sections (sobj, dest_sobj,
325						     handle_lto_debug_sections,
326						     err);
327  if (errmsg)
328    {
329      simple_object_release_write (dest_sobj);
330      return errmsg;
331    }
332
333  outfd = open (dest, O_CREAT|O_WRONLY|O_TRUNC|O_BINARY, 00777);
334  if (outfd == -1)
335    {
336      *err = errno;
337      simple_object_release_write (dest_sobj);
338      return "open failed";
339    }
340
341  errmsg = simple_object_write_to_file (dest_sobj, outfd, err);
342  close (outfd);
343  if (errmsg)
344    {
345      simple_object_release_write (dest_sobj);
346      return errmsg;
347    }
348
349  simple_object_release_write (dest_sobj);
350  return NULL;
351}
352
353/* Fetch attributes.  */
354
355simple_object_attributes *
356simple_object_fetch_attributes (simple_object_read *sobj, const char **errmsg,
357				int *err)
358{
359  void *data;
360  simple_object_attributes *ret;
361
362  data = sobj->functions->fetch_attributes (sobj, errmsg, err);
363  if (data == NULL)
364    return NULL;
365  ret = XNEW (simple_object_attributes);
366  ret->functions = sobj->functions;
367  ret->data = data;
368  return ret;
369}
370
371/* Release an simple_object_read.  */
372
373void
374simple_object_release_read (simple_object_read *sobj)
375{
376  sobj->functions->release_read (sobj->data);
377  XDELETE (sobj);
378}
379
380/* Merge attributes.  */
381
382const char *
383simple_object_attributes_merge (simple_object_attributes *to,
384				simple_object_attributes *from,
385				int *err)
386{
387  if (to->functions != from->functions)
388    {
389      *err = 0;
390      return "different object file format";
391    }
392  return to->functions->attributes_merge (to->data, from->data, err);
393}
394
395/* Release an attributes structure.  */
396
397void
398simple_object_release_attributes (simple_object_attributes *attrs)
399{
400  attrs->functions->release_attributes (attrs->data);
401  XDELETE (attrs);
402}
403
404/* Start creating an object file.  */
405
406simple_object_write *
407simple_object_start_write (simple_object_attributes *attrs,
408			   const char *segment_name, const char **errmsg,
409			   int *err)
410{
411  void *data;
412  simple_object_write *ret;
413
414  data = attrs->functions->start_write (attrs->data, errmsg, err);
415  if (data == NULL)
416    return NULL;
417  ret = XNEW (simple_object_write);
418  ret->functions = attrs->functions;
419  ret->segment_name = segment_name ? xstrdup (segment_name) : NULL;
420  ret->sections = NULL;
421  ret->last_section = NULL;
422  ret->data = data;
423  return ret;
424}
425
426/* Start creating a section.  */
427
428simple_object_write_section *
429simple_object_write_create_section (simple_object_write *sobj, const char *name,
430				    unsigned int align,
431				    const char **errmsg ATTRIBUTE_UNUSED,
432				    int *err ATTRIBUTE_UNUSED)
433{
434  simple_object_write_section *ret;
435
436  ret = XNEW (simple_object_write_section);
437  ret->next = NULL;
438  ret->name = xstrdup (name);
439  ret->align = align;
440  ret->buffers = NULL;
441  ret->last_buffer = NULL;
442
443  if (sobj->last_section == NULL)
444    {
445      sobj->sections = ret;
446      sobj->last_section = ret;
447    }
448  else
449    {
450      sobj->last_section->next = ret;
451      sobj->last_section = ret;
452    }
453
454  return ret;
455}
456
457/* Add data to a section.  */
458
459const char *
460simple_object_write_add_data (simple_object_write *sobj ATTRIBUTE_UNUSED,
461			      simple_object_write_section *section,
462			      const void *buffer,
463			      size_t size, int copy,
464			      int *err ATTRIBUTE_UNUSED)
465{
466  struct simple_object_write_section_buffer *wsb;
467
468  wsb = XNEW (struct simple_object_write_section_buffer);
469  wsb->next = NULL;
470  wsb->size = size;
471
472  if (!copy)
473    {
474      wsb->buffer = buffer;
475      wsb->free_buffer = NULL;
476    }
477  else
478    {
479      wsb->free_buffer = (void *) XNEWVEC (char, size);
480      memcpy (wsb->free_buffer, buffer, size);
481      wsb->buffer = wsb->free_buffer;
482    }
483
484  if (section->last_buffer == NULL)
485    {
486      section->buffers = wsb;
487      section->last_buffer = wsb;
488    }
489  else
490    {
491      section->last_buffer->next = wsb;
492      section->last_buffer = wsb;
493    }
494
495  return NULL;
496}
497
498/* Write the complete object file.  */
499
500const char *
501simple_object_write_to_file (simple_object_write *sobj, int descriptor,
502			     int *err)
503{
504  return sobj->functions->write_to_file (sobj, descriptor, err);
505}
506
507/* Release an simple_object_write.  */
508
509void
510simple_object_release_write (simple_object_write *sobj)
511{
512  simple_object_write_section *section;
513
514  free (sobj->segment_name);
515
516  section = sobj->sections;
517  while (section != NULL)
518    {
519      struct simple_object_write_section_buffer *buffer;
520      simple_object_write_section *next_section;
521
522      buffer = section->buffers;
523      while (buffer != NULL)
524	{
525	  struct simple_object_write_section_buffer *next_buffer;
526
527	  if (buffer->free_buffer != NULL)
528	    XDELETEVEC (buffer->free_buffer);
529	  next_buffer = buffer->next;
530	  XDELETE (buffer);
531	  buffer = next_buffer;
532	}
533
534      next_section = section->next;
535      free (section->name);
536      XDELETE (section);
537      section = next_section;
538    }
539
540  sobj->functions->release_write (sobj->data);
541  XDELETE (sobj);
542}
543