X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=libiberty%2Fsimple-object.c;h=92f5698d0a6490bc1364812af61c1a402523eab9;hb=c9debfb97e052c32cf0308157cae529ce2059f48;hp=c9bd82f271416b5bf270fd31bddded4a9f9d8cf8;hpb=ffa54e5c48223b42840f93e56a5eff69998ab4e1;p=deliverable%2Fbinutils-gdb.git diff --git a/libiberty/simple-object.c b/libiberty/simple-object.c index c9bd82f271..92f5698d0a 100644 --- a/libiberty/simple-object.c +++ b/libiberty/simple-object.c @@ -1,5 +1,5 @@ /* simple-object.c -- simple routines to read and write object files. - Copyright 2010 Free Software Foundation, Inc. + Copyright (C) 2010-2020 Free Software Foundation, Inc. Written by Ian Lance Taylor, Google. This program is free software; you can redistribute it and/or modify it @@ -22,6 +22,7 @@ Boston, MA 02110-1301, USA. */ #include "simple-object.h" #include +#include #ifdef HAVE_STDLIB_H #include @@ -43,6 +44,10 @@ Boston, MA 02110-1301, USA. */ #define SEEK_SET 0 #endif +#ifndef O_BINARY +#define O_BINARY 0 +#endif + #include "simple-object-common.h" /* The known object file formats. */ @@ -51,7 +56,8 @@ static const struct simple_object_functions * const format_functions[] = { &simple_object_elf_functions, &simple_object_mach_o_functions, - &simple_object_coff_functions + &simple_object_coff_functions, + &simple_object_xcoff_functions }; /* Read data from a file using the simple_object error reporting @@ -62,8 +68,6 @@ simple_object_internal_read (int descriptor, off_t offset, unsigned char *buffer, size_t size, const char **errmsg, int *err) { - ssize_t got; - if (lseek (descriptor, offset, SEEK_SET) < 0) { *errmsg = "lseek"; @@ -71,15 +75,26 @@ simple_object_internal_read (int descriptor, off_t offset, return 0; } - got = read (descriptor, buffer, size); - if (got < 0) + do { - *errmsg = "read"; - *err = errno; - return 0; + ssize_t got = read (descriptor, buffer, size); + if (got == 0) + break; + else if (got > 0) + { + buffer += got; + size -= got; + } + else if (errno != EINTR) + { + *errmsg = "read"; + *err = errno; + return 0; + } } + while (size > 0); - if ((size_t) got < size) + if (size > 0) { *errmsg = "file too short"; *err = 0; @@ -97,8 +112,6 @@ simple_object_internal_write (int descriptor, off_t offset, const unsigned char *buffer, size_t size, const char **errmsg, int *err) { - ssize_t wrote; - if (lseek (descriptor, offset, SEEK_SET) < 0) { *errmsg = "lseek"; @@ -106,15 +119,26 @@ simple_object_internal_write (int descriptor, off_t offset, return 0; } - wrote = write (descriptor, buffer, size); - if (wrote < 0) + do { - *errmsg = "write"; - *err = errno; - return 0; + ssize_t wrote = write (descriptor, buffer, size); + if (wrote == 0) + break; + else if (wrote > 0) + { + buffer += wrote; + size -= wrote; + } + else if (errno != EINTR) + { + *errmsg = "write"; + *err = errno; + return 0; + } } + while (size > 0); - if ((size_t) wrote < size) + if (size > 0) { *errmsg = "short write"; *err = 0; @@ -230,6 +254,131 @@ simple_object_find_section (simple_object_read *sobj, const char *name, return 1; } +/* Callback to identify and rename LTO debug sections by name. + Returns non-NULL if NAME is a LTO debug section, NULL if not. + If RENAME is true it will rename LTO debug sections to non-LTO + ones. */ + +static char * +handle_lto_debug_sections (const char *name, int rename) +{ + char *newname = rename ? XCNEWVEC (char, strlen (name) + 1) + : xstrdup (name); + + /* ??? So we can't use .gnu.lto_ prefixed sections as the assembler + complains about bogus section flags. Which means we need to arrange + for that to be fixed or .gnu.debuglto_ marked as SHF_EXCLUDE (to make + fat lto object tooling work for the fat part). */ + /* Also include corresponding reloc sections. */ + if (strncmp (name, ".rela", sizeof (".rela") - 1) == 0) + { + if (rename) + strncpy (newname, name, sizeof (".rela") - 1); + name += sizeof (".rela") - 1; + } + else if (strncmp (name, ".rel", sizeof (".rel") - 1) == 0) + { + if (rename) + strncpy (newname, name, sizeof (".rel") - 1); + name += sizeof (".rel") - 1; + } + /* ??? For now this handles both .gnu.lto_ and .gnu.debuglto_ prefixed + sections. */ + /* Copy LTO debug sections and rename them to their non-LTO name. */ + if (strncmp (name, ".gnu.debuglto_", sizeof (".gnu.debuglto_") - 1) == 0) + return rename ? strcat (newname, name + sizeof (".gnu.debuglto_") - 1) : newname; + else if (strncmp (name, ".gnu.lto_.debug_", + sizeof (".gnu.lto_.debug_") -1) == 0) + return rename ? strcat (newname, name + sizeof (".gnu.lto_") - 1) : newname; + /* Copy over .note.GNU-stack section under the same name if present. */ + else if (strcmp (name, ".note.GNU-stack") == 0) + return strcpy (newname, name); + /* Copy over .note.gnu.property section under the same name if present. */ + else if (strcmp (name, ".note.gnu.property") == 0) + return strcpy (newname, name); + /* Copy over .comment section under the same name if present. Solaris + ld uses them to relax its checking of ELF gABI access rules for + COMDAT sections in objects produced by GCC. */ + else if (strcmp (name, ".comment") == 0) + return strcpy (newname, name); + /* Copy over .GCC.command.line section under the same name if present. */ + else if (strcmp (name, ".GCC.command.line") == 0) + return strcpy (newname, name); + free (newname); + return NULL; +} + +/* Wrapper for handle_lto_debug_sections. */ + +static char * +handle_lto_debug_sections_rename (const char *name) +{ + return handle_lto_debug_sections (name, 1); +} + +/* Wrapper for handle_lto_debug_sections. */ + +static char * +handle_lto_debug_sections_norename (const char *name) +{ + return handle_lto_debug_sections (name, 0); +} + +/* Copy LTO debug sections. */ + +const char * +simple_object_copy_lto_debug_sections (simple_object_read *sobj, + const char *dest, int *err, int rename) +{ + const char *errmsg; + simple_object_write *dest_sobj; + simple_object_attributes *attrs; + int outfd; + + if (! sobj->functions->copy_lto_debug_sections) + { + *err = EINVAL; + return "simple_object_copy_lto_debug_sections not implemented"; + } + + attrs = simple_object_fetch_attributes (sobj, &errmsg, err); + if (! attrs) + return errmsg; + dest_sobj = simple_object_start_write (attrs, NULL, &errmsg, err); + simple_object_release_attributes (attrs); + if (! dest_sobj) + return errmsg; + + errmsg = sobj->functions->copy_lto_debug_sections + (sobj, dest_sobj, + rename ? handle_lto_debug_sections_rename + : handle_lto_debug_sections_norename, err); + if (errmsg) + { + simple_object_release_write (dest_sobj); + return errmsg; + } + + outfd = open (dest, O_CREAT|O_WRONLY|O_TRUNC|O_BINARY, 00777); + if (outfd == -1) + { + *err = errno; + simple_object_release_write (dest_sobj); + return "open failed"; + } + + errmsg = simple_object_write_to_file (dest_sobj, outfd, err); + close (outfd); + if (errmsg) + { + simple_object_release_write (dest_sobj); + return errmsg; + } + + simple_object_release_write (dest_sobj); + return NULL; +} + /* Fetch attributes. */ simple_object_attributes * @@ -257,20 +406,19 @@ simple_object_release_read (simple_object_read *sobj) XDELETE (sobj); } -/* Compare attributes. */ +/* Merge attributes. */ const char * -simple_object_attributes_compare (simple_object_attributes *attrs1, - simple_object_attributes *attrs2, - int *err) +simple_object_attributes_merge (simple_object_attributes *to, + simple_object_attributes *from, + int *err) { - if (attrs1->functions != attrs2->functions) + if (to->functions != from->functions) { *err = 0; return "different object file format"; } - return attrs1->functions->attributes_compare (attrs1->data, attrs2->data, - err); + return to->functions->attributes_merge (to->data, from->data, err); } /* Release an attributes structure. */ @@ -297,7 +445,7 @@ simple_object_start_write (simple_object_attributes *attrs, return NULL; ret = XNEW (simple_object_write); ret->functions = attrs->functions; - ret->segment_name = xstrdup (segment_name); + ret->segment_name = segment_name ? xstrdup (segment_name) : NULL; ret->sections = NULL; ret->last_section = NULL; ret->data = data;