simple-object.c revision 1.1.1.9
1/* simple-object.c -- simple routines to read and write object files.
2   Copyright (C) 2010-2022 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  /* Copy over .ctf section under the same name if present.  */
308  else if (strcmp (name, ".ctf") == 0)
309    return strcpy (newname, name);
310  /* Copy over .BTF section under the same name if present.  */
311  else if (strcmp (name, ".BTF") == 0)
312    return strcpy (newname, name);
313  free (newname);
314  return NULL;
315}
316
317/* Wrapper for handle_lto_debug_sections.  */
318
319static char *
320handle_lto_debug_sections_rename (const char *name)
321{
322  return handle_lto_debug_sections (name, 1);
323}
324
325/* Wrapper for handle_lto_debug_sections.  */
326
327static char *
328handle_lto_debug_sections_norename (const char *name)
329{
330  return handle_lto_debug_sections (name, 0);
331}
332
333/* Copy LTO debug sections.  */
334
335const char *
336simple_object_copy_lto_debug_sections (simple_object_read *sobj,
337				       const char *dest, int *err, int rename)
338{
339  const char *errmsg;
340  simple_object_write *dest_sobj;
341  simple_object_attributes *attrs;
342  int outfd;
343
344  if (! sobj->functions->copy_lto_debug_sections)
345    {
346      *err = EINVAL;
347      return "simple_object_copy_lto_debug_sections not implemented";
348    }
349
350  attrs = simple_object_fetch_attributes (sobj, &errmsg, err);
351  if (! attrs)
352    return errmsg;
353  dest_sobj = simple_object_start_write (attrs, NULL, &errmsg, err);
354  simple_object_release_attributes (attrs);
355  if (! dest_sobj)
356    return errmsg;
357
358  errmsg = sobj->functions->copy_lto_debug_sections
359	 	 (sobj, dest_sobj,
360		  rename ? handle_lto_debug_sections_rename
361			 : handle_lto_debug_sections_norename,  err);
362  if (errmsg)
363    {
364      simple_object_release_write (dest_sobj);
365      return errmsg;
366    }
367
368  outfd = open (dest, O_CREAT|O_WRONLY|O_TRUNC|O_BINARY, 00777);
369  if (outfd == -1)
370    {
371      *err = errno;
372      simple_object_release_write (dest_sobj);
373      return "open failed";
374    }
375
376  errmsg = simple_object_write_to_file (dest_sobj, outfd, err);
377  close (outfd);
378  if (errmsg)
379    {
380      simple_object_release_write (dest_sobj);
381      return errmsg;
382    }
383
384  simple_object_release_write (dest_sobj);
385  return NULL;
386}
387
388/* Fetch attributes.  */
389
390simple_object_attributes *
391simple_object_fetch_attributes (simple_object_read *sobj, const char **errmsg,
392				int *err)
393{
394  void *data;
395  simple_object_attributes *ret;
396
397  data = sobj->functions->fetch_attributes (sobj, errmsg, err);
398  if (data == NULL)
399    return NULL;
400  ret = XNEW (simple_object_attributes);
401  ret->functions = sobj->functions;
402  ret->data = data;
403  return ret;
404}
405
406/* Release an simple_object_read.  */
407
408void
409simple_object_release_read (simple_object_read *sobj)
410{
411  sobj->functions->release_read (sobj->data);
412  XDELETE (sobj);
413}
414
415/* Merge attributes.  */
416
417const char *
418simple_object_attributes_merge (simple_object_attributes *to,
419				simple_object_attributes *from,
420				int *err)
421{
422  if (to->functions != from->functions)
423    {
424      *err = 0;
425      return "different object file format";
426    }
427  return to->functions->attributes_merge (to->data, from->data, err);
428}
429
430/* Release an attributes structure.  */
431
432void
433simple_object_release_attributes (simple_object_attributes *attrs)
434{
435  attrs->functions->release_attributes (attrs->data);
436  XDELETE (attrs);
437}
438
439/* Start creating an object file.  */
440
441simple_object_write *
442simple_object_start_write (simple_object_attributes *attrs,
443			   const char *segment_name, const char **errmsg,
444			   int *err)
445{
446  void *data;
447  simple_object_write *ret;
448
449  data = attrs->functions->start_write (attrs->data, errmsg, err);
450  if (data == NULL)
451    return NULL;
452  ret = XNEW (simple_object_write);
453  ret->functions = attrs->functions;
454  ret->segment_name = segment_name ? xstrdup (segment_name) : NULL;
455  ret->sections = NULL;
456  ret->last_section = NULL;
457  ret->data = data;
458  return ret;
459}
460
461/* Start creating a section.  */
462
463simple_object_write_section *
464simple_object_write_create_section (simple_object_write *sobj, const char *name,
465				    unsigned int align,
466				    const char **errmsg ATTRIBUTE_UNUSED,
467				    int *err ATTRIBUTE_UNUSED)
468{
469  simple_object_write_section *ret;
470
471  ret = XNEW (simple_object_write_section);
472  ret->next = NULL;
473  ret->name = xstrdup (name);
474  ret->align = align;
475  ret->buffers = NULL;
476  ret->last_buffer = NULL;
477
478  if (sobj->last_section == NULL)
479    {
480      sobj->sections = ret;
481      sobj->last_section = ret;
482    }
483  else
484    {
485      sobj->last_section->next = ret;
486      sobj->last_section = ret;
487    }
488
489  return ret;
490}
491
492/* Add data to a section.  */
493
494const char *
495simple_object_write_add_data (simple_object_write *sobj ATTRIBUTE_UNUSED,
496			      simple_object_write_section *section,
497			      const void *buffer,
498			      size_t size, int copy,
499			      int *err ATTRIBUTE_UNUSED)
500{
501  struct simple_object_write_section_buffer *wsb;
502
503  wsb = XNEW (struct simple_object_write_section_buffer);
504  wsb->next = NULL;
505  wsb->size = size;
506
507  if (!copy)
508    {
509      wsb->buffer = buffer;
510      wsb->free_buffer = NULL;
511    }
512  else
513    {
514      wsb->free_buffer = (void *) XNEWVEC (char, size);
515      memcpy (wsb->free_buffer, buffer, size);
516      wsb->buffer = wsb->free_buffer;
517    }
518
519  if (section->last_buffer == NULL)
520    {
521      section->buffers = wsb;
522      section->last_buffer = wsb;
523    }
524  else
525    {
526      section->last_buffer->next = wsb;
527      section->last_buffer = wsb;
528    }
529
530  return NULL;
531}
532
533/* Write the complete object file.  */
534
535const char *
536simple_object_write_to_file (simple_object_write *sobj, int descriptor,
537			     int *err)
538{
539  return sobj->functions->write_to_file (sobj, descriptor, err);
540}
541
542/* Release an simple_object_write.  */
543
544void
545simple_object_release_write (simple_object_write *sobj)
546{
547  simple_object_write_section *section;
548
549  free (sobj->segment_name);
550
551  section = sobj->sections;
552  while (section != NULL)
553    {
554      struct simple_object_write_section_buffer *buffer;
555      simple_object_write_section *next_section;
556
557      buffer = section->buffers;
558      while (buffer != NULL)
559	{
560	  struct simple_object_write_section_buffer *next_buffer;
561
562	  if (buffer->free_buffer != NULL)
563	    XDELETEVEC (buffer->free_buffer);
564	  next_buffer = buffer->next;
565	  XDELETE (buffer);
566	  buffer = next_buffer;
567	}
568
569      next_section = section->next;
570      free (section->name);
571      XDELETE (section);
572      section = next_section;
573    }
574
575  sobj->functions->release_write (sobj->data);
576  XDELETE (sobj);
577}
578