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 
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 #include "simple-object-common.h"
48 
49 /* The known object file formats.  */
50 
51 static const struct simple_object_functions * const format_functions[] =
52 {
53   &simple_object_elf_functions,
54   &simple_object_mach_o_functions,
55   &simple_object_coff_functions,
56   &simple_object_xcoff_functions
57 };
58 
59 /* Read data from a file using the simple_object error reporting
60    conventions.  */
61 
62 int
simple_object_internal_read(int descriptor,off_t offset,unsigned char * buffer,size_t size,const char ** errmsg,int * err)63 simple_object_internal_read (int descriptor, off_t offset,
64 			     unsigned char *buffer, size_t size,
65 			     const char **errmsg, int *err)
66 {
67   if (lseek (descriptor, offset, SEEK_SET) < 0)
68     {
69       *errmsg = "lseek";
70       *err = errno;
71       return 0;
72     }
73 
74   do
75     {
76       ssize_t got = read (descriptor, buffer, size);
77       if (got == 0)
78 	break;
79       else if (got > 0)
80 	{
81 	  buffer += got;
82 	  size -= got;
83 	}
84       else if (errno != EINTR)
85 	{
86 	  *errmsg = "read";
87 	  *err = errno;
88 	  return 0;
89 	}
90     }
91   while (size > 0);
92 
93   if (size > 0)
94     {
95       *errmsg = "file too short";
96       *err = 0;
97       return 0;
98     }
99 
100   return 1;
101 }
102 
103 /* Write data to a file using the simple_object error reporting
104    conventions.  */
105 
106 int
simple_object_internal_write(int descriptor,off_t offset,const unsigned char * buffer,size_t size,const char ** errmsg,int * err)107 simple_object_internal_write (int descriptor, off_t offset,
108 			      const unsigned char *buffer, size_t size,
109 			      const char **errmsg, int *err)
110 {
111   if (lseek (descriptor, offset, SEEK_SET) < 0)
112     {
113       *errmsg = "lseek";
114       *err = errno;
115       return 0;
116     }
117 
118   do
119     {
120       ssize_t wrote = write (descriptor, buffer, size);
121       if (wrote == 0)
122 	break;
123       else if (wrote > 0)
124 	{
125 	  buffer += wrote;
126 	  size -= wrote;
127 	}
128       else if (errno != EINTR)
129 	{
130 	  *errmsg = "write";
131 	  *err = errno;
132 	  return 0;
133 	}
134     }
135   while (size > 0);
136 
137   if (size > 0)
138     {
139       *errmsg = "short write";
140       *err = 0;
141       return 0;
142     }
143 
144   return 1;
145 }
146 
147 /* Open for read.  */
148 
149 simple_object_read *
simple_object_start_read(int descriptor,off_t offset,const char * segment_name,const char ** errmsg,int * err)150 simple_object_start_read (int descriptor, off_t offset,
151 			  const char *segment_name, const char **errmsg,
152 			  int *err)
153 {
154   unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN];
155   size_t len, i;
156 
157   if (!simple_object_internal_read (descriptor, offset, header,
158 				    SIMPLE_OBJECT_MATCH_HEADER_LEN,
159 				    errmsg, err))
160     return NULL;
161 
162   len = sizeof (format_functions) / sizeof (format_functions[0]);
163   for (i = 0; i < len; ++i)
164     {
165       void *data;
166 
167       data = format_functions[i]->match (header, descriptor, offset,
168 					 segment_name, errmsg, err);
169       if (data != NULL)
170 	{
171 	  simple_object_read *ret;
172 
173 	  ret = XNEW (simple_object_read);
174 	  ret->descriptor = descriptor;
175 	  ret->offset = offset;
176 	  ret->functions = format_functions[i];
177 	  ret->data = data;
178 	  return ret;
179 	}
180     }
181 
182   *errmsg = "file not recognized";
183   *err = 0;
184   return NULL;
185 }
186 
187 /* Find all sections.  */
188 
189 const char *
simple_object_find_sections(simple_object_read * sobj,int (* pfn)(void *,const char *,off_t,off_t),void * data,int * err)190 simple_object_find_sections (simple_object_read *sobj,
191 			     int (*pfn) (void *, const char *, off_t, off_t),
192 			     void *data,
193 			     int *err)
194 {
195   return sobj->functions->find_sections (sobj, pfn, data, err);
196 }
197 
198 /* Internal data passed to find_one_section.  */
199 
200 struct find_one_section_data
201 {
202   /* The section we are looking for.  */
203   const char *name;
204   /* Where to store the section offset.  */
205   off_t *offset;
206   /* Where to store the section length.  */
207   off_t *length;
208   /* Set if the name is found.  */
209   int found;
210 };
211 
212 /* Internal function passed to find_sections.  */
213 
214 static int
find_one_section(void * data,const char * name,off_t offset,off_t length)215 find_one_section (void *data, const char *name, off_t offset, off_t length)
216 {
217   struct find_one_section_data *fosd = (struct find_one_section_data *) data;
218 
219   if (strcmp (name, fosd->name) != 0)
220     return 1;
221 
222   *fosd->offset = offset;
223   *fosd->length = length;
224   fosd->found = 1;
225 
226   /* Stop iteration.  */
227   return 0;
228 }
229 
230 /* Find a section.  */
231 
232 int
simple_object_find_section(simple_object_read * sobj,const char * name,off_t * offset,off_t * length,const char ** errmsg,int * err)233 simple_object_find_section (simple_object_read *sobj, const char *name,
234 			    off_t *offset, off_t *length,
235 			    const char **errmsg, int *err)
236 {
237   struct find_one_section_data fosd;
238 
239   fosd.name = name;
240   fosd.offset = offset;
241   fosd.length = length;
242   fosd.found = 0;
243 
244   *errmsg = simple_object_find_sections (sobj, find_one_section,
245 					 (void *) &fosd, err);
246   if (*errmsg != NULL)
247     return 0;
248   if (!fosd.found)
249     return 0;
250   return 1;
251 }
252 
253 /* Callback to identify and rename LTO debug sections by name.
254    Returns 1 if NAME is a LTO debug section, 0 if not.  */
255 
256 static int
handle_lto_debug_sections(const char ** name)257 handle_lto_debug_sections (const char **name)
258 {
259   /* ???  So we can't use .gnu.lto_ prefixed sections as the assembler
260      complains about bogus section flags.  Which means we need to arrange
261      for that to be fixed or .gnu.debuglto_ marked as SHF_EXCLUDE (to make
262      fat lto object tooling work for the fat part).  */
263   /* ???  For now this handles both .gnu.lto_ and .gnu.debuglto_ prefixed
264      sections.  */
265   /* Copy LTO debug sections and rename them to their non-LTO name.  */
266   if (strncmp (*name, ".gnu.debuglto_", sizeof (".gnu.debuglto_") - 1) == 0)
267     {
268       *name = *name + sizeof (".gnu.debuglto_") - 1;
269       return 1;
270     }
271   else if (strncmp (*name, ".gnu.lto_.debug_", sizeof (".gnu.lto_.debug_") -1) == 0)
272     {
273       *name = *name + sizeof (".gnu.lto_") - 1;
274       return 1;
275     }
276   /* Copy over .note.GNU-stack section under the same name if present.  */
277   else if (strcmp (*name, ".note.GNU-stack") == 0)
278     return 1;
279   return 0;
280 }
281 
282 /* Copy LTO debug sections.  */
283 
284 const char *
simple_object_copy_lto_debug_sections(simple_object_read * sobj,const char * dest,int * err)285 simple_object_copy_lto_debug_sections (simple_object_read *sobj,
286 				       const char *dest, int *err)
287 {
288   const char *errmsg;
289   simple_object_write *dest_sobj;
290   simple_object_attributes *attrs;
291   int outfd;
292 
293   if (! sobj->functions->copy_lto_debug_sections)
294     {
295       *err = EINVAL;
296       return "simple_object_copy_lto_debug_sections not implemented";
297     }
298 
299   attrs = simple_object_fetch_attributes (sobj, &errmsg, err);
300   if (! attrs)
301     return errmsg;
302   dest_sobj = simple_object_start_write (attrs, NULL, &errmsg, err);
303   simple_object_release_attributes (attrs);
304   if (! dest_sobj)
305     return errmsg;
306 
307   errmsg = sobj->functions->copy_lto_debug_sections (sobj, dest_sobj,
308 						     handle_lto_debug_sections,
309 						     err);
310   if (errmsg)
311     {
312       simple_object_release_write (dest_sobj);
313       return errmsg;
314     }
315 
316   outfd = creat (dest, 00777);
317   if (outfd == -1)
318     {
319       *err = errno;
320       simple_object_release_write (dest_sobj);
321       return "open failed";
322     }
323 
324   errmsg = simple_object_write_to_file (dest_sobj, outfd, err);
325   close (outfd);
326   if (errmsg)
327     {
328       simple_object_release_write (dest_sobj);
329       return errmsg;
330     }
331 
332   simple_object_release_write (dest_sobj);
333   return NULL;
334 }
335 
336 /* Fetch attributes.  */
337 
338 simple_object_attributes *
simple_object_fetch_attributes(simple_object_read * sobj,const char ** errmsg,int * err)339 simple_object_fetch_attributes (simple_object_read *sobj, const char **errmsg,
340 				int *err)
341 {
342   void *data;
343   simple_object_attributes *ret;
344 
345   data = sobj->functions->fetch_attributes (sobj, errmsg, err);
346   if (data == NULL)
347     return NULL;
348   ret = XNEW (simple_object_attributes);
349   ret->functions = sobj->functions;
350   ret->data = data;
351   return ret;
352 }
353 
354 /* Release an simple_object_read.  */
355 
356 void
simple_object_release_read(simple_object_read * sobj)357 simple_object_release_read (simple_object_read *sobj)
358 {
359   sobj->functions->release_read (sobj->data);
360   XDELETE (sobj);
361 }
362 
363 /* Merge attributes.  */
364 
365 const char *
simple_object_attributes_merge(simple_object_attributes * to,simple_object_attributes * from,int * err)366 simple_object_attributes_merge (simple_object_attributes *to,
367 				simple_object_attributes *from,
368 				int *err)
369 {
370   if (to->functions != from->functions)
371     {
372       *err = 0;
373       return "different object file format";
374     }
375   return to->functions->attributes_merge (to->data, from->data, err);
376 }
377 
378 /* Release an attributes structure.  */
379 
380 void
simple_object_release_attributes(simple_object_attributes * attrs)381 simple_object_release_attributes (simple_object_attributes *attrs)
382 {
383   attrs->functions->release_attributes (attrs->data);
384   XDELETE (attrs);
385 }
386 
387 /* Start creating an object file.  */
388 
389 simple_object_write *
simple_object_start_write(simple_object_attributes * attrs,const char * segment_name,const char ** errmsg,int * err)390 simple_object_start_write (simple_object_attributes *attrs,
391 			   const char *segment_name, const char **errmsg,
392 			   int *err)
393 {
394   void *data;
395   simple_object_write *ret;
396 
397   data = attrs->functions->start_write (attrs->data, errmsg, err);
398   if (data == NULL)
399     return NULL;
400   ret = XNEW (simple_object_write);
401   ret->functions = attrs->functions;
402   ret->segment_name = segment_name ? xstrdup (segment_name) : NULL;
403   ret->sections = NULL;
404   ret->last_section = NULL;
405   ret->data = data;
406   return ret;
407 }
408 
409 /* Start creating a section.  */
410 
411 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)412 simple_object_write_create_section (simple_object_write *sobj, const char *name,
413 				    unsigned int align,
414 				    const char **errmsg ATTRIBUTE_UNUSED,
415 				    int *err ATTRIBUTE_UNUSED)
416 {
417   simple_object_write_section *ret;
418 
419   ret = XNEW (simple_object_write_section);
420   ret->next = NULL;
421   ret->name = xstrdup (name);
422   ret->align = align;
423   ret->buffers = NULL;
424   ret->last_buffer = NULL;
425 
426   if (sobj->last_section == NULL)
427     {
428       sobj->sections = ret;
429       sobj->last_section = ret;
430     }
431   else
432     {
433       sobj->last_section->next = ret;
434       sobj->last_section = ret;
435     }
436 
437   return ret;
438 }
439 
440 /* Add data to a section.  */
441 
442 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)443 simple_object_write_add_data (simple_object_write *sobj ATTRIBUTE_UNUSED,
444 			      simple_object_write_section *section,
445 			      const void *buffer,
446 			      size_t size, int copy,
447 			      int *err ATTRIBUTE_UNUSED)
448 {
449   struct simple_object_write_section_buffer *wsb;
450 
451   wsb = XNEW (struct simple_object_write_section_buffer);
452   wsb->next = NULL;
453   wsb->size = size;
454 
455   if (!copy)
456     {
457       wsb->buffer = buffer;
458       wsb->free_buffer = NULL;
459     }
460   else
461     {
462       wsb->free_buffer = (void *) XNEWVEC (char, size);
463       memcpy (wsb->free_buffer, buffer, size);
464       wsb->buffer = wsb->free_buffer;
465     }
466 
467   if (section->last_buffer == NULL)
468     {
469       section->buffers = wsb;
470       section->last_buffer = wsb;
471     }
472   else
473     {
474       section->last_buffer->next = wsb;
475       section->last_buffer = wsb;
476     }
477 
478   return NULL;
479 }
480 
481 /* Write the complete object file.  */
482 
483 const char *
simple_object_write_to_file(simple_object_write * sobj,int descriptor,int * err)484 simple_object_write_to_file (simple_object_write *sobj, int descriptor,
485 			     int *err)
486 {
487   return sobj->functions->write_to_file (sobj, descriptor, err);
488 }
489 
490 /* Release an simple_object_write.  */
491 
492 void
simple_object_release_write(simple_object_write * sobj)493 simple_object_release_write (simple_object_write *sobj)
494 {
495   simple_object_write_section *section;
496 
497   free (sobj->segment_name);
498 
499   section = sobj->sections;
500   while (section != NULL)
501     {
502       struct simple_object_write_section_buffer *buffer;
503       simple_object_write_section *next_section;
504 
505       buffer = section->buffers;
506       while (buffer != NULL)
507 	{
508 	  struct simple_object_write_section_buffer *next_buffer;
509 
510 	  if (buffer->free_buffer != NULL)
511 	    XDELETEVEC (buffer->free_buffer);
512 	  next_buffer = buffer->next;
513 	  XDELETE (buffer);
514 	  buffer = next_buffer;
515 	}
516 
517       next_section = section->next;
518       free (section->name);
519       XDELETE (section);
520       section = next_section;
521     }
522 
523   sobj->functions->release_write (sobj->data);
524   XDELETE (sobj);
525 }
526