xref: /netbsd-src/external/gpl3/gcc.old/dist/libiberty/simple-object.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
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 
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option) any
8 later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, 51 Franklin Street - Fifth Floor,
18 Boston, 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 
55 static 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 
66 int
simple_object_internal_read(int descriptor,off_t offset,unsigned char * buffer,size_t size,const char ** errmsg,int * err)67 simple_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 
110 int
simple_object_internal_write(int descriptor,off_t offset,const unsigned char * buffer,size_t size,const char ** errmsg,int * err)111 simple_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 
153 simple_object_read *
simple_object_start_read(int descriptor,off_t offset,const char * segment_name,const char ** errmsg,int * err)154 simple_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 
193 const char *
simple_object_find_sections(simple_object_read * sobj,int (* pfn)(void *,const char *,off_t,off_t),void * data,int * err)194 simple_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 
204 struct 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 
218 static int
find_one_section(void * data,const char * name,off_t offset,off_t length)219 find_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 
236 int
simple_object_find_section(simple_object_read * sobj,const char * name,off_t * offset,off_t * length,const char ** errmsg,int * err)237 simple_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 
262 static char *
handle_lto_debug_sections(const char * name,int rename)263 handle_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 
313 static char *
handle_lto_debug_sections_rename(const char * name)314 handle_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 
321 static char *
handle_lto_debug_sections_norename(const char * name)322 handle_lto_debug_sections_norename (const char *name)
323 {
324   return handle_lto_debug_sections (name, 0);
325 }
326 
327 /* Copy LTO debug sections.  */
328 
329 const char *
simple_object_copy_lto_debug_sections(simple_object_read * sobj,const char * dest,int * err,int rename)330 simple_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 
384 simple_object_attributes *
simple_object_fetch_attributes(simple_object_read * sobj,const char ** errmsg,int * err)385 simple_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 
402 void
simple_object_release_read(simple_object_read * sobj)403 simple_object_release_read (simple_object_read *sobj)
404 {
405   sobj->functions->release_read (sobj->data);
406   XDELETE (sobj);
407 }
408 
409 /* Merge attributes.  */
410 
411 const char *
simple_object_attributes_merge(simple_object_attributes * to,simple_object_attributes * from,int * err)412 simple_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 
426 void
simple_object_release_attributes(simple_object_attributes * attrs)427 simple_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 
435 simple_object_write *
simple_object_start_write(simple_object_attributes * attrs,const char * segment_name,const char ** errmsg,int * err)436 simple_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 
457 simple_object_write_section *
simple_object_write_create_section(simple_object_write * sobj,const char * name,unsigned int align,const char ** errmsg ATTRIBUTE_UNUSED,int * err ATTRIBUTE_UNUSED)458 simple_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 
488 const char *
simple_object_write_add_data(simple_object_write * sobj ATTRIBUTE_UNUSED,simple_object_write_section * section,const void * buffer,size_t size,int copy,int * err ATTRIBUTE_UNUSED)489 simple_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 
529 const char *
simple_object_write_to_file(simple_object_write * sobj,int descriptor,int * err)530 simple_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 
538 void
simple_object_release_write(simple_object_write * sobj)539 simple_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