From c990877a412109c1e7eac6506239a27ab309051f Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 14 Dec 2011 01:36:11 +0000 Subject: [PATCH] compiler: Move import of Go export data to gcc side of interface. * go-backend.c: #include "simple-object.h" and "intl.h". (GO_EXPORT_SEGMENT_NAME): Define if not defined. (GO_EXPORT_SECTION_NAME): Likewise. (go_write_export_data): Use GO_EXPORT_SECTION_NAME. (go_read_export_data): New function. * go-c.h (go_read_export_data): Declare. From-SVN: r182321 --- gcc/go/ChangeLog | 9 ++++ gcc/go/go-backend.c | 97 ++++++++++++++++++++++++++++++++++++- gcc/go/go-c.h | 2 + gcc/go/gofrontend/import.cc | 46 +++++------------- gcc/go/gofrontend/import.h | 4 +- 5 files changed, 120 insertions(+), 38 deletions(-) diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog index 47910fd75a9..9b17bf4b234 100644 --- a/gcc/go/ChangeLog +++ b/gcc/go/ChangeLog @@ -1,3 +1,12 @@ +2011-12-13 Ian Lance Taylor + + * go-backend.c: #include "simple-object.h" and "intl.h". + (GO_EXPORT_SEGMENT_NAME): Define if not defined. + (GO_EXPORT_SECTION_NAME): Likewise. + (go_write_export_data): Use GO_EXPORT_SECTION_NAME. + (go_read_export_data): New function. + * go-c.h (go_read_export_data): Declare. + 2011-11-29 Sanjoy Das Ian Lance Taylor diff --git a/gcc/go/go-backend.c b/gcc/go/go-backend.c index 62102a2e08b..4d1ea827c5e 100644 --- a/gcc/go/go-backend.c +++ b/gcc/go/go-backend.c @@ -20,16 +20,31 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" +#include "simple-object.h" #include "tm.h" #include "rtl.h" #include "tree.h" #include "tm_p.h" +#include "intl.h" #include "output.h" #include "target.h" #include "common/common-target.h" #include "go-c.h" +/* The segment name we pass to simple_object_start_read to find Go + export data. */ + +#ifndef GO_EXPORT_SEGMENT_NAME +#define GO_EXPORT_SEGMENT_NAME "__GNU_GO" +#endif + +/* The section name we use when reading and writing export data. */ + +#ifndef GO_EXPORT_SECTION_NAME +#define GO_EXPORT_SECTION_NAME ".go_export" +#endif + /* This file holds all the cases where the Go frontend needs information from gcc's backend. */ @@ -95,7 +110,7 @@ go_imported_unsafe (void) } /* This is called by the Go frontend proper to add data to the - .go_export section. */ + section containing Go export data. */ void go_write_export_data (const char *bytes, unsigned int size) @@ -105,9 +120,87 @@ go_write_export_data (const char *bytes, unsigned int size) if (sec == NULL) { gcc_assert (targetm_common.have_named_sections); - sec = get_section (".go_export", SECTION_DEBUG, NULL); + sec = get_section (GO_EXPORT_SECTION_NAME, SECTION_DEBUG, NULL); } switch_to_section (sec); assemble_string (bytes, size); } + +/* The go_read_export_data function is called by the Go frontend + proper to read Go export data from an object file. FD is a file + descriptor open for reading. OFFSET is the offset within the file + where the object file starts; this will be 0 except when reading an + archive. On success this returns NULL and sets *PBUF to a buffer + allocated using malloc, of size *PLEN, holding the export data. If + the data is not found, this returns NULL and sets *PBUF to NULL and + *PLEN to 0. If some error occurs, this returns an error message + and sets *PERR to an errno value or 0 if there is no relevant + errno. */ + +const char * +go_read_export_data (int fd, off_t offset, char **pbuf, size_t *plen, + int *perr) +{ + simple_object_read *sobj; + const char *errmsg; + off_t sec_offset; + off_t sec_length; + int found; + char *buf; + ssize_t c; + + *pbuf = NULL; + *plen = 0; + + sobj = simple_object_start_read (fd, offset, GO_EXPORT_SEGMENT_NAME, + &errmsg, perr); + if (sobj == NULL) + { + /* If we get an error here, just pretend that we didn't find any + export data. This is the right thing to do if the error is + that the file was not recognized as an object file. This + will ignore file I/O errors, but it's not too big a deal + because we will wind up giving some other error later. */ + return NULL; + } + + found = simple_object_find_section (sobj, GO_EXPORT_SECTION_NAME, + &sec_offset, &sec_length, + &errmsg, perr); + simple_object_release_read (sobj); + if (!found) + return errmsg; + + if (lseek (fd, offset + sec_offset, SEEK_SET) < 0) + { + *perr = errno; + return _("lseek failed while reading export data"); + } + + buf = XNEWVEC (char, sec_length); + if (buf == NULL) + { + *perr = errno; + return _("memory allocation failed while reading export data"); + } + + c = read (fd, buf, sec_length); + if (c < 0) + { + *perr = errno; + free (buf); + return _("read failed while reading export data"); + } + + if (c < sec_length) + { + free (buf); + return _("short read while reading export data"); + } + + *pbuf = buf; + *plen = sec_length; + + return NULL; +} diff --git a/gcc/go/go-c.h b/gcc/go/go-c.h index f5ecbebace3..5e65dead72e 100644 --- a/gcc/go/go-c.h +++ b/gcc/go/go-c.h @@ -69,6 +69,8 @@ extern void go_imported_unsafe (void); extern void go_write_export_data (const char *, unsigned int); +extern const char *go_read_export_data (int, off_t, char **, size_t *, int *); + #if defined(__cplusplus) && !defined(ENABLE_BUILD_WITH_CXX) } /* End extern "C". */ #endif diff --git a/gcc/go/gofrontend/import.cc b/gcc/go/gofrontend/import.cc index 075109c0c04..a62069e8e23 100644 --- a/gcc/go/gofrontend/import.cc +++ b/gcc/go/gofrontend/import.cc @@ -215,46 +215,24 @@ Import::find_object_export_data(const std::string& filename, off_t offset, Location location) { - const char* errmsg; + char *buf; + size_t len; int err; - simple_object_read* sobj = simple_object_start_read(fd, offset, - "__GNU_GO", - &errmsg, &err); - if (sobj == NULL) - return NULL; - - off_t sec_offset; - off_t sec_length; - int found = simple_object_find_section(sobj, ".go_export", &sec_offset, - &sec_length, &errmsg, &err); - - simple_object_release_read(sobj); - - if (!found) - return NULL; - - if (lseek(fd, offset + sec_offset, SEEK_SET) < 0) + const char *errmsg = go_read_export_data(fd, offset, &buf, &len, &err); + if (errmsg != NULL) { - error_at(location, "lseek %s failed: %m", filename.c_str()); + if (err == 0) + error_at(location, "%s: %s", filename.c_str(), errmsg); + else + error_at(location, "%s: %s: %s", filename.c_str(), errmsg, + xstrerror(err)); return NULL; } - char* buf = new char[sec_length]; - ssize_t c = read(fd, buf, sec_length); - if (c < 0) - { - error_at(location, "read %s failed: %m", filename.c_str()); - delete[] buf; - return NULL; - } - if (c < sec_length) - { - error_at(location, "%s: short read", filename.c_str()); - delete[] buf; - return NULL; - } + if (buf == NULL) + return NULL; - return new Stream_from_buffer(buf, sec_length); + return new Stream_from_buffer(buf, len); } // Class Import. diff --git a/gcc/go/gofrontend/import.h b/gcc/go/gofrontend/import.h index f5b4b3d2be3..bdff0c2a9e1 100644 --- a/gcc/go/gofrontend/import.h +++ b/gcc/go/gofrontend/import.h @@ -287,7 +287,7 @@ class Stream_from_string : public Import::Stream size_t pos_; }; -// Read import data from an allocated buffer. +// Read import data from a buffer allocated using malloc. class Stream_from_buffer : public Import::Stream { @@ -297,7 +297,7 @@ class Stream_from_buffer : public Import::Stream { } ~Stream_from_buffer() - { delete[] this->buf_; } + { free(this->buf_); } protected: bool -- 2.30.2