]> git.ipfire.org Git - thirdparty/gcc.git/blame - libiberty/simple-object.c
Update copyright years.
[thirdparty/gcc.git] / libiberty / simple-object.c
CommitLineData
1cfabf34 1/* simple-object.c -- simple routines to read and write object files.
a5544970 2 Copyright (C) 2010-2019 Free Software Foundation, Inc.
1cfabf34
ILT
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>
1ea85365 25#include <fcntl.h>
1cfabf34
ILT
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
51static const struct simple_object_functions * const format_functions[] =
52{
53 &simple_object_elf_functions,
54 &simple_object_mach_o_functions,
a9b01f00
DE
55 &simple_object_coff_functions,
56 &simple_object_xcoff_functions
1cfabf34
ILT
57};
58
59/* Read data from a file using the simple_object error reporting
60 conventions. */
61
62int
63simple_object_internal_read (int descriptor, off_t offset,
64 unsigned char *buffer, size_t size,
65 const char **errmsg, int *err)
66{
1cfabf34
ILT
67 if (lseek (descriptor, offset, SEEK_SET) < 0)
68 {
69 *errmsg = "lseek";
70 *err = errno;
71 return 0;
72 }
73
2486c24a 74 do
1cfabf34 75 {
2486c24a
RB
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 }
1cfabf34 90 }
2486c24a 91 while (size > 0);
1cfabf34 92
2486c24a 93 if (size > 0)
1cfabf34
ILT
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
106int
107simple_object_internal_write (int descriptor, off_t offset,
108 const unsigned char *buffer, size_t size,
109 const char **errmsg, int *err)
110{
1cfabf34
ILT
111 if (lseek (descriptor, offset, SEEK_SET) < 0)
112 {
113 *errmsg = "lseek";
114 *err = errno;
115 return 0;
116 }
117
25336bb6 118 do
1cfabf34 119 {
25336bb6
RB
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 }
1cfabf34 134 }
25336bb6 135 while (size > 0);
1cfabf34 136
25336bb6 137 if (size > 0)
1cfabf34
ILT
138 {
139 *errmsg = "short write";
140 *err = 0;
141 return 0;
142 }
143
144 return 1;
145}
146
147/* Open for read. */
148
149simple_object_read *
150simple_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
189const char *
190simple_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
200struct 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
214static int
215find_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
232int
233simple_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
1ea85365 253/* Callback to identify and rename LTO debug sections by name.
7ce4ce10
JH
254 Returns non-NULL if NAME is a LTO debug section, NULL if not.
255 If RENAME is true it will rename LTO debug sections to non-LTO
256 ones. */
1ea85365 257
bf6f2cc7 258static char *
7ce4ce10 259handle_lto_debug_sections (const char *name, int rename)
1ea85365 260{
7ce4ce10
JH
261 char *newname = rename ? XCNEWVEC (char, strlen (name) + 1)
262 : xstrdup (name);
bf6f2cc7 263
1ea85365
RB
264 /* ??? So we can't use .gnu.lto_ prefixed sections as the assembler
265 complains about bogus section flags. Which means we need to arrange
266 for that to be fixed or .gnu.debuglto_ marked as SHF_EXCLUDE (to make
267 fat lto object tooling work for the fat part). */
bf6f2cc7
RB
268 /* Also include corresponding reloc sections. */
269 if (strncmp (name, ".rela", sizeof (".rela") - 1) == 0)
1ea85365 270 {
7ce4ce10
JH
271 if (rename)
272 strncpy (newname, name, sizeof (".rela") - 1);
bf6f2cc7 273 name += sizeof (".rela") - 1;
1ea85365 274 }
bf6f2cc7 275 else if (strncmp (name, ".rel", sizeof (".rel") - 1) == 0)
1ea85365 276 {
7ce4ce10
JH
277 if (rename)
278 strncpy (newname, name, sizeof (".rel") - 1);
bf6f2cc7 279 name += sizeof (".rel") - 1;
1ea85365 280 }
bf6f2cc7
RB
281 /* ??? For now this handles both .gnu.lto_ and .gnu.debuglto_ prefixed
282 sections. */
283 /* Copy LTO debug sections and rename them to their non-LTO name. */
284 if (strncmp (name, ".gnu.debuglto_", sizeof (".gnu.debuglto_") - 1) == 0)
7ce4ce10 285 return rename ? strcat (newname, name + sizeof (".gnu.debuglto_") - 1) : newname;
bf6f2cc7
RB
286 else if (strncmp (name, ".gnu.lto_.debug_",
287 sizeof (".gnu.lto_.debug_") -1) == 0)
7ce4ce10 288 return rename ? strcat (newname, name + sizeof (".gnu.lto_") - 1) : newname;
f8049c44 289 /* Copy over .note.GNU-stack section under the same name if present. */
bf6f2cc7
RB
290 else if (strcmp (name, ".note.GNU-stack") == 0)
291 return strcpy (newname, name);
6888a172
RO
292 /* Copy over .comment section under the same name if present. Solaris
293 ld uses them to relax its checking of ELF gABI access rules for
294 COMDAT sections in objects produced by GCC. */
295 else if (strcmp (name, ".comment") == 0)
296 return strcpy (newname, name);
7ce4ce10 297 free (newname);
bf6f2cc7 298 return NULL;
1ea85365
RB
299}
300
7ce4ce10
JH
301/* Wrapper for handle_lto_debug_sections. */
302
303static char *
304handle_lto_debug_sections_rename (const char *name)
305{
306 return handle_lto_debug_sections (name, 1);
307}
308
309/* Wrapper for handle_lto_debug_sections. */
310
311static char *
312handle_lto_debug_sections_norename (const char *name)
313{
314 return handle_lto_debug_sections (name, 0);
315}
316
1ea85365
RB
317/* Copy LTO debug sections. */
318
319const char *
320simple_object_copy_lto_debug_sections (simple_object_read *sobj,
7ce4ce10 321 const char *dest, int *err, int rename)
1ea85365
RB
322{
323 const char *errmsg;
324 simple_object_write *dest_sobj;
325 simple_object_attributes *attrs;
326 int outfd;
327
328 if (! sobj->functions->copy_lto_debug_sections)
329 {
330 *err = EINVAL;
331 return "simple_object_copy_lto_debug_sections not implemented";
332 }
333
334 attrs = simple_object_fetch_attributes (sobj, &errmsg, err);
335 if (! attrs)
336 return errmsg;
337 dest_sobj = simple_object_start_write (attrs, NULL, &errmsg, err);
338 simple_object_release_attributes (attrs);
339 if (! dest_sobj)
340 return errmsg;
341
7ce4ce10
JH
342 errmsg = sobj->functions->copy_lto_debug_sections
343 (sobj, dest_sobj,
344 rename ? handle_lto_debug_sections_rename
345 : handle_lto_debug_sections_norename, err);
1ea85365
RB
346 if (errmsg)
347 {
348 simple_object_release_write (dest_sobj);
349 return errmsg;
350 }
351
352 outfd = creat (dest, 00777);
353 if (outfd == -1)
354 {
355 *err = errno;
356 simple_object_release_write (dest_sobj);
357 return "open failed";
358 }
359
360 errmsg = simple_object_write_to_file (dest_sobj, outfd, err);
361 close (outfd);
362 if (errmsg)
363 {
364 simple_object_release_write (dest_sobj);
365 return errmsg;
366 }
367
368 simple_object_release_write (dest_sobj);
369 return NULL;
370}
371
1cfabf34
ILT
372/* Fetch attributes. */
373
374simple_object_attributes *
375simple_object_fetch_attributes (simple_object_read *sobj, const char **errmsg,
376 int *err)
377{
378 void *data;
379 simple_object_attributes *ret;
380
381 data = sobj->functions->fetch_attributes (sobj, errmsg, err);
382 if (data == NULL)
383 return NULL;
384 ret = XNEW (simple_object_attributes);
385 ret->functions = sobj->functions;
386 ret->data = data;
387 return ret;
388}
389
390/* Release an simple_object_read. */
391
392void
393simple_object_release_read (simple_object_read *sobj)
394{
395 sobj->functions->release_read (sobj->data);
396 XDELETE (sobj);
397}
398
d82f74d3 399/* Merge attributes. */
1cfabf34
ILT
400
401const char *
d82f74d3
ILT
402simple_object_attributes_merge (simple_object_attributes *to,
403 simple_object_attributes *from,
404 int *err)
1cfabf34 405{
d82f74d3 406 if (to->functions != from->functions)
1cfabf34
ILT
407 {
408 *err = 0;
409 return "different object file format";
410 }
d82f74d3 411 return to->functions->attributes_merge (to->data, from->data, err);
1cfabf34
ILT
412}
413
414/* Release an attributes structure. */
415
416void
417simple_object_release_attributes (simple_object_attributes *attrs)
418{
419 attrs->functions->release_attributes (attrs->data);
420 XDELETE (attrs);
421}
422
423/* Start creating an object file. */
424
425simple_object_write *
426simple_object_start_write (simple_object_attributes *attrs,
427 const char *segment_name, const char **errmsg,
428 int *err)
429{
430 void *data;
431 simple_object_write *ret;
432
433 data = attrs->functions->start_write (attrs->data, errmsg, err);
434 if (data == NULL)
435 return NULL;
436 ret = XNEW (simple_object_write);
437 ret->functions = attrs->functions;
1ea85365 438 ret->segment_name = segment_name ? xstrdup (segment_name) : NULL;
1cfabf34
ILT
439 ret->sections = NULL;
440 ret->last_section = NULL;
441 ret->data = data;
442 return ret;
443}
444
445/* Start creating a section. */
446
447simple_object_write_section *
448simple_object_write_create_section (simple_object_write *sobj, const char *name,
449 unsigned int align,
450 const char **errmsg ATTRIBUTE_UNUSED,
451 int *err ATTRIBUTE_UNUSED)
452{
453 simple_object_write_section *ret;
454
455 ret = XNEW (simple_object_write_section);
456 ret->next = NULL;
457 ret->name = xstrdup (name);
458 ret->align = align;
459 ret->buffers = NULL;
460 ret->last_buffer = NULL;
461
462 if (sobj->last_section == NULL)
463 {
464 sobj->sections = ret;
465 sobj->last_section = ret;
466 }
467 else
468 {
469 sobj->last_section->next = ret;
470 sobj->last_section = ret;
471 }
472
473 return ret;
474}
475
476/* Add data to a section. */
477
478const char *
479simple_object_write_add_data (simple_object_write *sobj ATTRIBUTE_UNUSED,
480 simple_object_write_section *section,
481 const void *buffer,
482 size_t size, int copy,
483 int *err ATTRIBUTE_UNUSED)
484{
485 struct simple_object_write_section_buffer *wsb;
486
487 wsb = XNEW (struct simple_object_write_section_buffer);
488 wsb->next = NULL;
489 wsb->size = size;
490
491 if (!copy)
492 {
493 wsb->buffer = buffer;
494 wsb->free_buffer = NULL;
495 }
496 else
497 {
498 wsb->free_buffer = (void *) XNEWVEC (char, size);
499 memcpy (wsb->free_buffer, buffer, size);
500 wsb->buffer = wsb->free_buffer;
501 }
502
503 if (section->last_buffer == NULL)
504 {
505 section->buffers = wsb;
506 section->last_buffer = wsb;
507 }
508 else
509 {
510 section->last_buffer->next = wsb;
511 section->last_buffer = wsb;
512 }
513
514 return NULL;
515}
516
517/* Write the complete object file. */
518
519const char *
520simple_object_write_to_file (simple_object_write *sobj, int descriptor,
521 int *err)
522{
523 return sobj->functions->write_to_file (sobj, descriptor, err);
524}
525
526/* Release an simple_object_write. */
527
528void
529simple_object_release_write (simple_object_write *sobj)
530{
531 simple_object_write_section *section;
532
533 free (sobj->segment_name);
534
535 section = sobj->sections;
536 while (section != NULL)
537 {
538 struct simple_object_write_section_buffer *buffer;
539 simple_object_write_section *next_section;
540
541 buffer = section->buffers;
542 while (buffer != NULL)
543 {
544 struct simple_object_write_section_buffer *next_buffer;
545
546 if (buffer->free_buffer != NULL)
547 XDELETEVEC (buffer->free_buffer);
548 next_buffer = buffer->next;
549 XDELETE (buffer);
550 buffer = next_buffer;
551 }
552
553 next_section = section->next;
554 free (section->name);
555 XDELETE (section);
556 section = next_section;
557 }
558
559 sobj->functions->release_write (sobj->data);
560 XDELETE (sobj);
561}