]> git.ipfire.org Git - thirdparty/gcc.git/blame - libiberty/simple-object.c
* config/microblaze/microblaze.c (microblaze_expand_block_move): Treat
[thirdparty/gcc.git] / libiberty / simple-object.c
CommitLineData
ebb6c20c 1/* simple-object.c -- simple routines to read and write object files.
fbd26352 2 Copyright (C) 2010-2019 Free Software Foundation, Inc.
ebb6c20c 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>
7b53e714 25#include <fcntl.h>
ebb6c20c 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
090bd8bc 47#ifndef O_BINARY
48#define O_BINARY 0
49#endif
50
ebb6c20c 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,
2c64b281 59 &simple_object_coff_functions,
60 &simple_object_xcoff_functions
ebb6c20c 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{
ebb6c20c 71 if (lseek (descriptor, offset, SEEK_SET) < 0)
72 {
73 *errmsg = "lseek";
74 *err = errno;
75 return 0;
76 }
77
fa1d2c56 78 do
ebb6c20c 79 {
fa1d2c56 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 }
ebb6c20c 94 }
fa1d2c56 95 while (size > 0);
ebb6c20c 96
fa1d2c56 97 if (size > 0)
ebb6c20c 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{
ebb6c20c 115 if (lseek (descriptor, offset, SEEK_SET) < 0)
116 {
117 *errmsg = "lseek";
118 *err = errno;
119 return 0;
120 }
121
1adaa21e 122 do
ebb6c20c 123 {
1adaa21e 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 }
ebb6c20c 138 }
1adaa21e 139 while (size > 0);
ebb6c20c 140
1adaa21e 141 if (size > 0)
ebb6c20c 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
7b53e714 257/* Callback to identify and rename LTO debug sections by name.
35fc616f 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. */
7b53e714 261
04aaa94d 262static char *
35fc616f 263handle_lto_debug_sections (const char *name, int rename)
7b53e714 264{
35fc616f 265 char *newname = rename ? XCNEWVEC (char, strlen (name) + 1)
266 : xstrdup (name);
04aaa94d 267
7b53e714 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). */
04aaa94d 272 /* Also include corresponding reloc sections. */
273 if (strncmp (name, ".rela", sizeof (".rela") - 1) == 0)
7b53e714 274 {
35fc616f 275 if (rename)
276 strncpy (newname, name, sizeof (".rela") - 1);
04aaa94d 277 name += sizeof (".rela") - 1;
7b53e714 278 }
04aaa94d 279 else if (strncmp (name, ".rel", sizeof (".rel") - 1) == 0)
7b53e714 280 {
35fc616f 281 if (rename)
282 strncpy (newname, name, sizeof (".rel") - 1);
04aaa94d 283 name += sizeof (".rel") - 1;
7b53e714 284 }
04aaa94d 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)
35fc616f 289 return rename ? strcat (newname, name + sizeof (".gnu.debuglto_") - 1) : newname;
04aaa94d 290 else if (strncmp (name, ".gnu.lto_.debug_",
291 sizeof (".gnu.lto_.debug_") -1) == 0)
35fc616f 292 return rename ? strcat (newname, name + sizeof (".gnu.lto_") - 1) : newname;
becd73a9 293 /* Copy over .note.GNU-stack section under the same name if present. */
04aaa94d 294 else if (strcmp (name, ".note.GNU-stack") == 0)
295 return strcpy (newname, name);
b60bff00 296 /* Copy over .comment section under the same name if present. Solaris
297 ld uses them to relax its checking of ELF gABI access rules for
298 COMDAT sections in objects produced by GCC. */
299 else if (strcmp (name, ".comment") == 0)
300 return strcpy (newname, name);
35fc616f 301 free (newname);
04aaa94d 302 return NULL;
7b53e714 303}
304
35fc616f 305/* Wrapper for handle_lto_debug_sections. */
306
307static char *
308handle_lto_debug_sections_rename (const char *name)
309{
310 return handle_lto_debug_sections (name, 1);
311}
312
313/* Wrapper for handle_lto_debug_sections. */
314
315static char *
316handle_lto_debug_sections_norename (const char *name)
317{
318 return handle_lto_debug_sections (name, 0);
319}
320
7b53e714 321/* Copy LTO debug sections. */
322
323const char *
324simple_object_copy_lto_debug_sections (simple_object_read *sobj,
35fc616f 325 const char *dest, int *err, int rename)
7b53e714 326{
327 const char *errmsg;
328 simple_object_write *dest_sobj;
329 simple_object_attributes *attrs;
330 int outfd;
331
332 if (! sobj->functions->copy_lto_debug_sections)
333 {
334 *err = EINVAL;
335 return "simple_object_copy_lto_debug_sections not implemented";
336 }
337
338 attrs = simple_object_fetch_attributes (sobj, &errmsg, err);
339 if (! attrs)
340 return errmsg;
341 dest_sobj = simple_object_start_write (attrs, NULL, &errmsg, err);
342 simple_object_release_attributes (attrs);
343 if (! dest_sobj)
344 return errmsg;
345
35fc616f 346 errmsg = sobj->functions->copy_lto_debug_sections
347 (sobj, dest_sobj,
348 rename ? handle_lto_debug_sections_rename
349 : handle_lto_debug_sections_norename, err);
7b53e714 350 if (errmsg)
351 {
352 simple_object_release_write (dest_sobj);
353 return errmsg;
354 }
355
090bd8bc 356 outfd = open (dest, O_CREAT|O_WRONLY|O_TRUNC|O_BINARY, 00777);
7b53e714 357 if (outfd == -1)
358 {
359 *err = errno;
360 simple_object_release_write (dest_sobj);
361 return "open failed";
362 }
363
364 errmsg = simple_object_write_to_file (dest_sobj, outfd, err);
365 close (outfd);
366 if (errmsg)
367 {
368 simple_object_release_write (dest_sobj);
369 return errmsg;
370 }
371
372 simple_object_release_write (dest_sobj);
373 return NULL;
374}
375
ebb6c20c 376/* Fetch attributes. */
377
378simple_object_attributes *
379simple_object_fetch_attributes (simple_object_read *sobj, const char **errmsg,
380 int *err)
381{
382 void *data;
383 simple_object_attributes *ret;
384
385 data = sobj->functions->fetch_attributes (sobj, errmsg, err);
386 if (data == NULL)
387 return NULL;
388 ret = XNEW (simple_object_attributes);
389 ret->functions = sobj->functions;
390 ret->data = data;
391 return ret;
392}
393
394/* Release an simple_object_read. */
395
396void
397simple_object_release_read (simple_object_read *sobj)
398{
399 sobj->functions->release_read (sobj->data);
400 XDELETE (sobj);
401}
402
2e521e13 403/* Merge attributes. */
ebb6c20c 404
405const char *
2e521e13 406simple_object_attributes_merge (simple_object_attributes *to,
407 simple_object_attributes *from,
408 int *err)
ebb6c20c 409{
2e521e13 410 if (to->functions != from->functions)
ebb6c20c 411 {
412 *err = 0;
413 return "different object file format";
414 }
2e521e13 415 return to->functions->attributes_merge (to->data, from->data, err);
ebb6c20c 416}
417
418/* Release an attributes structure. */
419
420void
421simple_object_release_attributes (simple_object_attributes *attrs)
422{
423 attrs->functions->release_attributes (attrs->data);
424 XDELETE (attrs);
425}
426
427/* Start creating an object file. */
428
429simple_object_write *
430simple_object_start_write (simple_object_attributes *attrs,
431 const char *segment_name, const char **errmsg,
432 int *err)
433{
434 void *data;
435 simple_object_write *ret;
436
437 data = attrs->functions->start_write (attrs->data, errmsg, err);
438 if (data == NULL)
439 return NULL;
440 ret = XNEW (simple_object_write);
441 ret->functions = attrs->functions;
7b53e714 442 ret->segment_name = segment_name ? xstrdup (segment_name) : NULL;
ebb6c20c 443 ret->sections = NULL;
444 ret->last_section = NULL;
445 ret->data = data;
446 return ret;
447}
448
449/* Start creating a section. */
450
451simple_object_write_section *
452simple_object_write_create_section (simple_object_write *sobj, const char *name,
453 unsigned int align,
454 const char **errmsg ATTRIBUTE_UNUSED,
455 int *err ATTRIBUTE_UNUSED)
456{
457 simple_object_write_section *ret;
458
459 ret = XNEW (simple_object_write_section);
460 ret->next = NULL;
461 ret->name = xstrdup (name);
462 ret->align = align;
463 ret->buffers = NULL;
464 ret->last_buffer = NULL;
465
466 if (sobj->last_section == NULL)
467 {
468 sobj->sections = ret;
469 sobj->last_section = ret;
470 }
471 else
472 {
473 sobj->last_section->next = ret;
474 sobj->last_section = ret;
475 }
476
477 return ret;
478}
479
480/* Add data to a section. */
481
482const char *
483simple_object_write_add_data (simple_object_write *sobj ATTRIBUTE_UNUSED,
484 simple_object_write_section *section,
485 const void *buffer,
486 size_t size, int copy,
487 int *err ATTRIBUTE_UNUSED)
488{
489 struct simple_object_write_section_buffer *wsb;
490
491 wsb = XNEW (struct simple_object_write_section_buffer);
492 wsb->next = NULL;
493 wsb->size = size;
494
495 if (!copy)
496 {
497 wsb->buffer = buffer;
498 wsb->free_buffer = NULL;
499 }
500 else
501 {
502 wsb->free_buffer = (void *) XNEWVEC (char, size);
503 memcpy (wsb->free_buffer, buffer, size);
504 wsb->buffer = wsb->free_buffer;
505 }
506
507 if (section->last_buffer == NULL)
508 {
509 section->buffers = wsb;
510 section->last_buffer = wsb;
511 }
512 else
513 {
514 section->last_buffer->next = wsb;
515 section->last_buffer = wsb;
516 }
517
518 return NULL;
519}
520
521/* Write the complete object file. */
522
523const char *
524simple_object_write_to_file (simple_object_write *sobj, int descriptor,
525 int *err)
526{
527 return sobj->functions->write_to_file (sobj, descriptor, err);
528}
529
530/* Release an simple_object_write. */
531
532void
533simple_object_release_write (simple_object_write *sobj)
534{
535 simple_object_write_section *section;
536
537 free (sobj->segment_name);
538
539 section = sobj->sections;
540 while (section != NULL)
541 {
542 struct simple_object_write_section_buffer *buffer;
543 simple_object_write_section *next_section;
544
545 buffer = section->buffers;
546 while (buffer != NULL)
547 {
548 struct simple_object_write_section_buffer *next_buffer;
549
550 if (buffer->free_buffer != NULL)
551 XDELETEVEC (buffer->free_buffer);
552 next_buffer = buffer->next;
553 XDELETE (buffer);
554 buffer = next_buffer;
555 }
556
557 next_section = section->next;
558 free (section->name);
559 XDELETE (section);
560 section = next_section;
561 }
562
563 sobj->functions->release_write (sobj->data);
564 XDELETE (sobj);
565}