1/* simple-object.c -- simple routines to read and write object files.
2   Copyright (C) 2010-2020 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 non-NULL if NAME is a LTO debug section, NULL if not.
259   If RENAME is true it will rename LTO debug sections to non-LTO
260   ones.  */
261
262static char *
263handle_lto_debug_sections (const char *name, int rename)
264{
265  char *newname = rename ? XCNEWVEC (char, strlen (name) + 1)
266	  	         : xstrdup (name);
267
268  /* ???  So we can't use .gnu.lto_ prefixed sections as the assembler
269     complains about bogus section flags.  Which means we need to arrange
270     for that to be fixed or .gnu.debuglto_ marked as SHF_EXCLUDE (to make
271     fat lto object tooling work for the fat part).  */
272  /* Also include corresponding reloc sections.  */
273  if (strncmp (name, ".rela", sizeof (".rela") - 1) == 0)
274    {
275      if (rename)
276        strncpy (newname, name, sizeof (".rela") - 1);
277      name += sizeof (".rela") - 1;
278    }
279  else if (strncmp (name, ".rel", sizeof (".rel") - 1) == 0)
280    {
281      if (rename)
282        strncpy (newname, name, sizeof (".rel") - 1);
283      name += sizeof (".rel") - 1;
284    }
285  /* ???  For now this handles both .gnu.lto_ and .gnu.debuglto_ prefixed
286     sections.  */
287  /* Copy LTO debug sections and rename them to their non-LTO name.  */
288  if (strncmp (name, ".gnu.debuglto_", sizeof (".gnu.debuglto_") - 1) == 0)
289    return rename ? strcat (newname, name + sizeof (".gnu.debuglto_") - 1) : newname;
290  else if (strncmp (name, ".gnu.lto_.debug_",
291		    sizeof (".gnu.lto_.debug_") -1) == 0)
292    return rename ? strcat (newname, name + sizeof (".gnu.lto_") - 1) : newname;
293  /* Copy over .note.GNU-stack section under the same name if present.  */
294  else if (strcmp (name, ".note.GNU-stack") == 0)
295    return strcpy (newname, name);
296  /* Copy over .note.gnu.property section under the same name if present.  */
297  else if (strcmp (name, ".note.gnu.property") == 0)
298    return strcpy (newname, name);
299  /* Copy over .comment section under the same name if present.  Solaris
300     ld uses them to relax its checking of ELF gABI access rules for
301     COMDAT sections in objects produced by GCC.  */
302  else if (strcmp (name, ".comment") == 0)
303    return strcpy (newname, name);
304  /* Copy over .GCC.command.line section under the same name if present.  */
305  else if (strcmp (name, ".GCC.command.line") == 0)
306    return strcpy (newname, name);
307  free (newname);
308  return NULL;
309}
310
311/* Wrapper for handle_lto_debug_sections.  */
312
313static char *
314handle_lto_debug_sections_rename (const char *name)
315{
316  return handle_lto_debug_sections (name, 1);
317}
318
319/* Wrapper for handle_lto_debug_sections.  */
320
321static char *
322handle_lto_debug_sections_norename (const char *name)
323{
324  return handle_lto_debug_sections (name, 0);
325}
326
327/* Copy LTO debug sections.  */
328
329const char *
330simple_object_copy_lto_debug_sections (simple_object_read *sobj,
331				       const char *dest, int *err, int rename)
332{
333  const char *errmsg;
334  simple_object_write *dest_sobj;
335  simple_object_attributes *attrs;
336  int outfd;
337
338  if (! sobj->functions->copy_lto_debug_sections)
339    {
340      *err = EINVAL;
341      return "simple_object_copy_lto_debug_sections not implemented";
342    }
343
344  attrs = simple_object_fetch_attributes (sobj, &errmsg, err);
345  if (! attrs)
346    return errmsg;
347  dest_sobj = simple_object_start_write (attrs, NULL, &errmsg, err);
348  simple_object_release_attributes (attrs);
349  if (! dest_sobj)
350    return errmsg;
351
352  errmsg = sobj->functions->copy_lto_debug_sections
353	 	 (sobj, dest_sobj,
354		  rename ? handle_lto_debug_sections_rename
355			 : handle_lto_debug_sections_norename,  err);
356  if (errmsg)
357    {
358      simple_object_release_write (dest_sobj);
359      return errmsg;
360    }
361
362  outfd = open (dest, O_CREAT|O_WRONLY|O_TRUNC|O_BINARY, 00777);
363  if (outfd == -1)
364    {
365      *err = errno;
366      simple_object_release_write (dest_sobj);
367      return "open failed";
368    }
369
370  errmsg = simple_object_write_to_file (dest_sobj, outfd, err);
371  close (outfd);
372  if (errmsg)
373    {
374      simple_object_release_write (dest_sobj);
375      return errmsg;
376    }
377
378  simple_object_release_write (dest_sobj);
379  return NULL;
380}
381
382/* Fetch attributes.  */
383
384simple_object_attributes *
385simple_object_fetch_attributes (simple_object_read *sobj, const char **errmsg,
386				int *err)
387{
388  void *data;
389  simple_object_attributes *ret;
390
391  data = sobj->functions->fetch_attributes (sobj, errmsg, err);
392  if (data == NULL)
393    return NULL;
394  ret = XNEW (simple_object_attributes);
395  ret->functions = sobj->functions;
396  ret->data = data;
397  return ret;
398}
399
400/* Release an simple_object_read.  */
401
402void
403simple_object_release_read (simple_object_read *sobj)
404{
405  sobj->functions->release_read (sobj->data);
406  XDELETE (sobj);
407}
408
409/* Merge attributes.  */
410
411const char *
412simple_object_attributes_merge (simple_object_attributes *to,
413				simple_object_attributes *from,
414				int *err)
415{
416  if (to->functions != from->functions)
417    {
418      *err = 0;
419      return "different object file format";
420    }
421  return to->functions->attributes_merge (to->data, from->data, err);
422}
423
424/* Release an attributes structure.  */
425
426void
427simple_object_release_attributes (simple_object_attributes *attrs)
428{
429  attrs->functions->release_attributes (attrs->data);
430  XDELETE (attrs);
431}
432
433/* Start creating an object file.  */
434
435simple_object_write *
436simple_object_start_write (simple_object_attributes *attrs,
437			   const char *segment_name, const char **errmsg,
438			   int *err)
439{
440  void *data;
441  simple_object_write *ret;
442
443  data = attrs->functions->start_write (attrs->data, errmsg, err);
444  if (data == NULL)
445    return NULL;
446  ret = XNEW (simple_object_write);
447  ret->functions = attrs->functions;
448  ret->segment_name = segment_name ? xstrdup (segment_name) : NULL;
449  ret->sections = NULL;
450  ret->last_section = NULL;
451  ret->data = data;
452  return ret;
453}
454
455/* Start creating a section.  */
456
457simple_object_write_section *
458simple_object_write_create_section (simple_object_write *sobj, const char *name,
459				    unsigned int align,
460				    const char **errmsg ATTRIBUTE_UNUSED,
461				    int *err ATTRIBUTE_UNUSED)
462{
463  simple_object_write_section *ret;
464
465  ret = XNEW (simple_object_write_section);
466  ret->next = NULL;
467  ret->name = xstrdup (name);
468  ret->align = align;
469  ret->buffers = NULL;
470  ret->last_buffer = NULL;
471
472  if (sobj->last_section == NULL)
473    {
474      sobj->sections = ret;
475      sobj->last_section = ret;
476    }
477  else
478    {
479      sobj->last_section->next = ret;
480      sobj->last_section = ret;
481    }
482
483  return ret;
484}
485
486/* Add data to a section.  */
487
488const char *
489simple_object_write_add_data (simple_object_write *sobj ATTRIBUTE_UNUSED,
490			      simple_object_write_section *section,
491			      const void *buffer,
492			      size_t size, int copy,
493			      int *err ATTRIBUTE_UNUSED)
494{
495  struct simple_object_write_section_buffer *wsb;
496
497  wsb = XNEW (struct simple_object_write_section_buffer);
498  wsb->next = NULL;
499  wsb->size = size;
500
501  if (!copy)
502    {
503      wsb->buffer = buffer;
504      wsb->free_buffer = NULL;
505    }
506  else
507    {
508      wsb->free_buffer = (void *) XNEWVEC (char, size);
509      memcpy (wsb->free_buffer, buffer, size);
510      wsb->buffer = wsb->free_buffer;
511    }
512
513  if (section->last_buffer == NULL)
514    {
515      section->buffers = wsb;
516      section->last_buffer = wsb;
517    }
518  else
519    {
520      section->last_buffer->next = wsb;
521      section->last_buffer = wsb;
522    }
523
524  return NULL;
525}
526
527/* Write the complete object file.  */
528
529const char *
530simple_object_write_to_file (simple_object_write *sobj, int descriptor,
531			     int *err)
532{
533  return sobj->functions->write_to_file (sobj, descriptor, err);
534}
535
536/* Release an simple_object_write.  */
537
538void
539simple_object_release_write (simple_object_write *sobj)
540{
541  simple_object_write_section *section;
542
543  free (sobj->segment_name);
544
545  section = sobj->sections;
546  while (section != NULL)
547    {
548      struct simple_object_write_section_buffer *buffer;
549      simple_object_write_section *next_section;
550
551      buffer = section->buffers;
552      while (buffer != NULL)
553	{
554	  struct simple_object_write_section_buffer *next_buffer;
555
556	  if (buffer->free_buffer != NULL)
557	    XDELETEVEC (buffer->free_buffer);
558	  next_buffer = buffer->next;
559	  XDELETE (buffer);
560	  buffer = next_buffer;
561	}
562
563      next_section = section->next;
564      free (section->name);
565      XDELETE (section);
566      section = next_section;
567    }
568
569  sobj->functions->release_write (sobj->data);
570  XDELETE (sobj);
571}
572