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