This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [PATCH 1/2] gold: try to open the output file in incremental build and check
- From: Ian Lance Taylor <iant at google dot com>
- To: Mikolaj Zalewski <mikolajz at google dot com>
- Cc: binutils at sourceware dot org
- Date: Fri, 09 Oct 2009 09:41:54 -0700
- Subject: Re: [PATCH 1/2] gold: try to open the output file in incremental build and check
- References: <7ebec9e70909181021h7b76c171wa8e69ad86682e969@mail.gmail.com> <m31vlzhmlv.fsf@google.com> <7ebec9e70909220753j66e7a092rcb16c2657eb80f46@mail.gmail.com>
Mikolaj Zalewski <mikolajz@google.com> writes:
> 2009-09-11 Mikolaj Zalewski <mikolajz@google.com>
>
> * elf_file.h: Fix header guard.
> (Elf_recognizer): New class, code from gold/object.cc.
> (Elf_file::find_section_by_type): New method.
>
> gold:
>
> 2009-09-11 Mikolaj Zalewski <mikolajz@google.com>
>
> * incremental.cc: Include <stdarg>.
> Include "target-select.h".
> (vexplain_no_incremental): New function.
> (explain_no_incremental): New function.
> (Incremental_binary::error): New method.
> (Sized_incremental_binary::do_find_incremental_inputs_section):
> New method.
> (make_sized_incremental_binary): New function.
> (open_incremental_binary): New function.
> (can_incrementally_link_file): Add checks if output is ELF and
> has inputs section.
> * incremental.h: Include "elf_file.h".
> Include "output.h".
> (Incremental_binary): New class.
> (Sized_incremental_binary): New class.
> (open_incremental_binary): Declare.
> * object.cc (is_elf_object): Use elfcpp::Elf_recognizer::is_elf_file.
> (make_elf_object): Use elfcpp::Elf_recognizer::is_valid_header.
> * output.cc (Output_file::filesize): New method.
Committed as follows. I renamed bitness to size, adjusted a few
comments and formatting.
Thanks, and sorry for the delay.
Ian
elfcpp/:
2009-10-09 Mikolaj Zalewski <mikolajz@google.com>
* elfcpp_file.h: Fix header guard. Include <cstdio>.
(class Elf_recognizer): New class, code from gold/object.cc.
(Elf_file::find_section_by_type): New method.
gold/:
2009-10-09 Mikolaj Zalewski <mikolajz@google.com>
* incremental.cc: Include <cstdarg> and "target-select.h".
(vexplain_no_incremental): New function.
(explain_no_incremental): New function.
(Incremental_binary::error): New method.
(Sized_incremental_binary::do_find_incremental_inputs_section): New
method.
(make_sized_incremental_binary): New function.
(open_incremental_binary): New function.
(can_incrementally_link_file): Add checks if output is ELF and has
inputs section.
* incremental.h: Include "elfcpp_file.h" and "output.h".
(Incremental_binary): New class.
(Sized_incremental_binary): New class.
(open_incremental_binary): Declare.
* object.cc (is_elf_object): Use
elfcpp::Elf_recognizer::is_elf_file.
(make_elf_object): Use elfcpp::Elf_recognizer::is_valid_header.
* output.h (Output_file::filesize): New method.
Index: elfcpp/elfcpp.h
===================================================================
RCS file: /cvs/src/src/elfcpp/elfcpp.h,v
retrieving revision 1.25
diff -p -u -r1.25 elfcpp.h
--- elfcpp/elfcpp.h 23 Jul 2009 13:00:26 -0000 1.25
+++ elfcpp/elfcpp.h 9 Oct 2009 16:36:33 -0000
@@ -17,7 +17,7 @@
// combinations without any restriction coming from the use of this
// file. (The Library Public License restrictions do apply in other
// respects; for example, they cover modification of the file, and
-/// distribution when not linked into a combined executable.)
+// distribution when not linked into a combined executable.)
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -657,7 +657,7 @@ enum DT
DT_RUNPATH = 29,
DT_FLAGS = 30,
DT_ENCODING = 32,
- DT_PREINIT_ARRAY = 33,
+ DT_PREINIT_ARRAY = 32,
DT_PREINIT_ARRAYSZ = 33,
DT_LOOS = 0x6000000d,
DT_HIOS = 0x6ffff000,
Index: elfcpp/elfcpp_file.h
===================================================================
RCS file: /cvs/src/src/elfcpp/elfcpp_file.h,v
retrieving revision 1.9
diff -p -u -r1.9 elfcpp_file.h
--- elfcpp/elfcpp_file.h 19 Apr 2008 18:33:19 -0000 1.9
+++ elfcpp/elfcpp_file.h 9 Oct 2009 16:36:33 -0000
@@ -53,15 +53,45 @@
// This permits writing
// elfcpp::Shdr shdr(file, ef.section_header(n));
-#ifndef ELFPCP_FILE_H
+#ifndef ELFCPP_FILE_H
#define ELFCPP_FILE_H
#include <string>
+#include <cstdio>
#include <cstring>
namespace elfcpp
{
+// A simple helper class to recognize if a file has an ELF header.
+
+class Elf_recognizer
+{
+ public:
+ // Maximum header size. The user should try to read this much of
+ // the file when using this class.
+
+ static const int max_header_size = Elf_sizes<64>::ehdr_size;
+
+ // Checks if the file contains the ELF magic. Other header fields
+ // are not checked.
+
+ static bool
+ is_elf_file(const unsigned char* ehdr_buf, int size);
+
+ // Check if EHDR_BUF/BUFSIZE is a valid header of a 32-bit or
+ // 64-bit, little-endian or big-endian ELF file. Assumes
+ // is_elf_file() has been checked to be true. If the header is not
+ // valid, *ERROR contains a human-readable error message. If is is,
+ // *SIZE is set to either 32 or 64, *BIG_ENDIAN is set to indicate
+ // whether the file is big-endian.
+
+ static bool
+ is_valid_header(const unsigned char* ehdr_buf, off_t bufsize,
+ int* size, bool* big_endian,
+ std::string* error);
+};
+
// This object is used to read an ELF file.
// SIZE: The size of file, 32 or 64.
// BIG_ENDIAN: Whether the file is in big-endian format.
@@ -99,6 +129,11 @@ class Elf_file
shoff() const
{ return this->shoff_; }
+ // Find the first section with an sh_type field equal to TYPE and
+ // return its index. Returns SHN_UNDEF if there is no such section.
+ unsigned int
+ find_section_by_type(unsigned int type);
+
// Return the number of sections.
unsigned int
shnum()
@@ -193,6 +228,115 @@ class Elf_file
int large_shndx_offset_;
};
+// Inline function definitions.
+
+// Check for presence of the ELF magic number.
+
+inline bool
+Elf_recognizer::is_elf_file(const unsigned char* ehdr_buf, int size)
+{
+ if (size < 4)
+ return false;
+
+ static unsigned char elfmagic[4] =
+ {
+ elfcpp::ELFMAG0, elfcpp::ELFMAG1,
+ elfcpp::ELFMAG2, elfcpp::ELFMAG3
+ };
+ return memcmp(ehdr_buf, elfmagic, 4) == 0;
+}
+
+namespace
+{
+
+// Print a number to a string.
+
+inline std::string
+internal_printf_int(const char* format, int arg)
+{
+ char buf[256];
+ snprintf(buf, sizeof(buf), format, arg);
+ return std::string(buf);
+}
+
+} // End anonymous namespace.
+
+// Check the validity of the ELF header.
+
+inline bool
+Elf_recognizer::is_valid_header(
+ const unsigned char* ehdr_buf,
+ off_t bufsize,
+ int* size,
+ bool* big_endian,
+ std::string* error)
+{
+ if (bufsize < elfcpp::EI_NIDENT)
+ {
+ *error = _("ELF file too short");
+ return false;
+ }
+
+ int v = ehdr_buf[elfcpp::EI_VERSION];
+ if (v != elfcpp::EV_CURRENT)
+ {
+ if (v == elfcpp::EV_NONE)
+ *error = _("invalid ELF version 0");
+ else
+ *error = internal_printf_int(_("unsupported ELF version %d"), v);
+ return false;
+ }
+
+ int c = ehdr_buf[elfcpp::EI_CLASS];
+ if (c == elfcpp::ELFCLASSNONE)
+ {
+ *error = _("invalid ELF class 0");
+ return false;
+ }
+ else if (c != elfcpp::ELFCLASS32
+ && c != elfcpp::ELFCLASS64)
+ {
+ *error = internal_printf_int(_("unsupported ELF class %d"), c);
+ return false;
+ }
+
+ int d = ehdr_buf[elfcpp::EI_DATA];
+ if (d == elfcpp::ELFDATANONE)
+ {
+ *error = _("invalid ELF data encoding");
+ return false;
+ }
+ else if (d != elfcpp::ELFDATA2LSB
+ && d != elfcpp::ELFDATA2MSB)
+ {
+ *error = internal_printf_int(_("unsupported ELF data encoding %d"), d);
+ return false;
+ }
+
+ *big_endian = (d == elfcpp::ELFDATA2MSB);
+
+ if (c == elfcpp::ELFCLASS32)
+ {
+ if (bufsize < elfcpp::Elf_sizes<32>::ehdr_size)
+ {
+ *error = _("ELF file too short");
+ return false;
+ }
+ *size = 32;
+ }
+ else
+ {
+ if (bufsize < elfcpp::Elf_sizes<64>::ehdr_size)
+ {
+ *error = _("ELF file too short");
+ return false;
+ }
+ *size = 64;
+ }
+
+ return true;
+}
+
// Template function definitions.
// Construct an Elf_file given an ELF file header.
@@ -269,6 +413,25 @@ Elf_file<size, big_endian, File>::initia
}
}
+// Find section with sh_type equal to TYPE and return its index.
+// Returns SHN_UNDEF if not found.
+
+template<int size, bool big_endian, typename File>
+unsigned int
+Elf_file<size, big_endian, File>::find_section_by_type(unsigned int type)
+{
+ unsigned int shnum = this->shnum();
+ typename File::View v(this->file_->view(this->shoff_,
+ This::shdr_size * shnum));
+ for (unsigned int i = 0; i < shnum; i++)
+ {
+ Ef_shdr shdr(v.data() + This::shdr_size * i);
+ if (shdr.get_sh_type() == type)
+ return i;
+ }
+ return SHN_UNDEF;
+}
+
// Return the file offset of the section header of section SHNDX.
template<int size, bool big_endian, typename File>
Index: gold/incremental.cc
===================================================================
RCS file: /cvs/src/src/gold/incremental.cc,v
retrieving revision 1.6
diff -p -u -r1.6 incremental.cc
--- gold/incremental.cc 1 Sep 2009 17:32:35 -0000 1.6
+++ gold/incremental.cc 9 Oct 2009 16:36:33 -0000
@@ -21,11 +21,15 @@
// MA 02110-1301, USA.
#include "gold.h"
+
+#include <cstdarg>
+
#include "elfcpp.h"
#include "output.h"
#include "incremental.h"
#include "archive.h"
#include "output.h"
+#include "target-select.h"
using elfcpp::Convert;
@@ -150,6 +154,162 @@ class Incremental_inputs_entry_write
internal::Incremental_inputs_entry_data* p_;
};
+// Inform the user why we don't do an incremental link. Not called in
+// the obvious case of missing output file. TODO: Is this helpful?
+
+void
+vexplain_no_incremental(const char* format, va_list args)
+{
+ char* buf = NULL;
+ if (vasprintf(&buf, format, args) < 0)
+ gold_nomem();
+ gold_info(_("the link might take longer: "
+ "cannot perform incremental link: %s"), buf);
+ free(buf);
+}
+
+void
+explain_no_incremental(const char* format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ vexplain_no_incremental(format, args);
+ va_end(args);
+}
+
+// Report an error.
+
+void
+Incremental_binary::error(const char* format, ...) const
+{
+ va_list args;
+ va_start(args, format);
+ // Current code only checks if the file can be used for incremental linking,
+ // so errors shouldn't fail the build, but only result in a fallback to a
+ // full build.
+ // TODO: when we implement incremental editing of the file, we may need a
+ // flag that will cause errors to be treated seriously.
+ vexplain_no_incremental(format, args);
+ va_end(args);
+}
+
+template<int size, bool big_endian>
+bool
+Sized_incremental_binary<size, big_endian>::do_find_incremental_inputs_section(
+ Location* location)
+{
+ unsigned int shndx = this->elf_file_.find_section_by_type(
+ elfcpp::SHT_GNU_INCREMENTAL_INPUTS);
+ if (shndx == elfcpp::SHN_UNDEF) // Not found.
+ return false;
+ *location = this->elf_file_.section_contents(shndx);
+ return true;
+}
+
+namespace
+{
+
+// Create a Sized_incremental_binary object of the specified size and
+// endianness. Fails if the target architecture is not supported.
+
+template<int size, bool big_endian>
+Incremental_binary*
+make_sized_incremental_binary(Output_file* file,
+ const elfcpp::Ehdr<size, big_endian>& ehdr)
+{
+ Target* target = select_target(ehdr.get_e_machine(), size, big_endian,
+ ehdr.get_e_ident()[elfcpp::EI_OSABI],
+ ehdr.get_e_ident()[elfcpp::EI_ABIVERSION]);
+ if (target == NULL)
+ {
+ explain_no_incremental(_("unsupported ELF machine number %d"),
+ ehdr.get_e_machine());
+ return NULL;
+ }
+
+ return new Sized_incremental_binary<size, big_endian>(file, ehdr, target);
+}
+
+} // End of anonymous namespace.
+
+// Create an Incremental_binary object for FILE. Returns NULL is this is not
+// possible, e.g. FILE is not an ELF file or has an unsupported target. FILE
+// should be opened.
+
+Incremental_binary*
+open_incremental_binary(Output_file* file)
+{
+ off_t filesize = file->filesize();
+ int want = elfcpp::Elf_recognizer::max_header_size;
+ if (filesize < want)
+ want = filesize;
+
+ const unsigned char* p = file->get_input_view(0, want);
+ if (!elfcpp::Elf_recognizer::is_elf_file(p, want))
+ {
+ explain_no_incremental(_("output is not an ELF file."));
+ return NULL;
+ }
+
+ int size;
+ bool big_endian;
+ std::string error;
+ if (!elfcpp::Elf_recognizer::is_valid_header(p, want, &size, &big_endian,
+ &error))
+ {
+ explain_no_incremental(error.c_str());
+ return NULL;
+ }
+
+ Incremental_binary* result = NULL;
+ if (size == 32)
+ {
+ if (big_endian)
+ {
+#ifdef HAVE_TARGET_32_BIG
+ result = make_sized_incremental_binary<32, true>(
+ file, elfcpp::Ehdr<32, true>(p));
+#else
+ explain_no_incremental(_("unsupported file: 32-bit, big-endian"));
+#endif
+ }
+ else
+ {
+#ifdef HAVE_TARGET_32_LITTLE
+ result = make_sized_incremental_binary<32, false>(
+ file, elfcpp::Ehdr<32, false>(p));
+#else
+ explain_no_incremental(_("unsupported file: 32-bit, little-endian"));
+#endif
+ }
+ }
+ else if (size == 64)
+ {
+ if (big_endian)
+ {
+#ifdef HAVE_TARGET_64_BIG
+ result = make_sized_incremental_binary<64, true>(
+ file, elfcpp::Ehdr<64, true>(p));
+#else
+ explain_no_incremental(_("unsupported file: 64-bit, big-endian"));
+#endif
+ }
+ else
+ {
+#ifdef HAVE_TARGET_64_LITTLE
+ result = make_sized_incremental_binary<64, false>(
+ file, elfcpp::Ehdr<64, false>(p));
+#else
+ explain_no_incremental(_("unsupported file: 64-bit, little-endian"));
+#endif
+ }
+ }
+ else
+ gold_unreachable();
+
+ return result;
+}
+
// Analyzes the output file to check if incremental linking is possible and
// (to be done) what files need to be relinked.
@@ -159,6 +319,16 @@ Incremental_checker::can_incrementally_l
Output_file output(this->output_name_);
if (!output.open_for_modification())
return false;
+ Incremental_binary* binary = open_incremental_binary(&output);
+ if (binary == NULL)
+ return false;
+ Incremental_binary::Location inputs_location;
+ if (!binary->find_incremental_inputs_section(&inputs_location))
+ {
+ explain_no_incremental("no incremental data from previous build");
+ delete binary;
+ return false;
+ }
return true;
}
@@ -392,4 +562,26 @@ Incremental_inputs::sized_create_inputs_
"** incremental link inputs list");
}
+// Instantiate the templates we need.
+
+#ifdef HAVE_TARGET_32_LITTLE
+template
+class Sized_incremental_binary<32, false>;
+#endif
+
+#ifdef HAVE_TARGET_32_BIG
+template
+class Sized_incremental_binary<32, true>;
+#endif
+
+#ifdef HAVE_TARGET_64_LITTLE
+template
+class Sized_incremental_binary<64, false>;
+#endif
+
+#ifdef HAVE_TARGET_64_BIG
+template
+class Sized_incremental_binary<64, true>;
+#endif
+
} // End namespace gold.
Index: gold/incremental.h
===================================================================
RCS file: /cvs/src/src/gold/incremental.h,v
retrieving revision 1.4
diff -p -u -r1.4 incremental.h
--- gold/incremental.h 1 Sep 2009 17:32:35 -0000 1.4
+++ gold/incremental.h 9 Oct 2009 16:36:33 -0000
@@ -26,9 +26,11 @@
#include <map>
#include <vector>
+#include "elfcpp_file.h"
#include "stringpool.h"
#include "workqueue.h"
#include "fileread.h"
+#include "output.h"
namespace gold
{
@@ -50,6 +52,117 @@ enum Incremental_input_type
INCREMENTAL_INPUT_SCRIPT = 4
};
+// An object representing the ELF file we edit during an incremental build.
+// Similar to Object or Dynobj, but operates on Output_file and contains
+// method specific to file edition (TBD). This is the abstract parent class
+// implemented in Sized_incremental_binary<size, big_endian> for a specific
+// endianness and size.
+
+class Incremental_binary
+{
+ public:
+ Incremental_binary(Output_file* output, Target* target)
+ : output_(output), target_(target)
+ { }
+
+ virtual
+ ~Incremental_binary()
+ { }
+
+ // Functions and types for the elfcpp::Elf_file interface. This
+ // permit us to use Incremental_binary as the File template parameter for
+ // elfcpp::Elf_file.
+
+ // The View class is returned by view. It must support a single
+ // method, data(). This is trivial, because Output_file::get_output_view
+ // does what we need.
+ class View
+ {
+ public:
+ View(const unsigned char* p)
+ : p_(p)
+ { }
+
+ const unsigned char*
+ data() const
+ { return this->p_; }
+
+ private:
+ const unsigned char* p_;
+ };
+
+ // Return a View.
+ View
+ view(off_t file_offset, section_size_type data_size)
+ { return View(this->output_->get_input_view(file_offset, data_size)); }
+
+ // A location in the file.
+ struct Location
+ {
+ off_t file_offset;
+ off_t data_size;
+
+ Location(off_t fo, section_size_type ds)
+ : file_offset(fo), data_size(ds)
+ { }
+
+ Location()
+ : file_offset(0), data_size(0)
+ { }
+ };
+
+ // Get a View given a Location.
+ View view(Location loc)
+ { return View(this->view(loc.file_offset, loc.data_size)); }
+
+ // Report an error.
+ void
+ error(const char* format, ...) const ATTRIBUTE_PRINTF_2;
+
+
+ // Find the .gnu_incremental_inputs section. It selects the first section
+ // of type SHT_GNU_INCREMENTAL_INPUTS. Returns false if such a section
+ // is not found.
+ bool
+ find_incremental_inputs_section(Location* location)
+ { return do_find_incremental_inputs_section(location); }
+
+ protected:
+ // Find incremental inputs section.
+ virtual bool
+ do_find_incremental_inputs_section(Location* location) = 0;
+
+ private:
+ // Edited output file object.
+ Output_file* output_;
+ // Target of the output file.
+ Target* target_;
+};
+
+template<int size, bool big_endian>
+class Sized_incremental_binary : public Incremental_binary
+{
+ public:
+ Sized_incremental_binary(Output_file* output,
+ const elfcpp::Ehdr<size, big_endian>& ehdr,
+ Target* target)
+ : Incremental_binary(output, target), elf_file_(this, ehdr)
+ { }
+
+ protected:
+ virtual bool
+ do_find_incremental_inputs_section(Location* location);
+
+ private:
+ // Output as an ELF file.
+ elfcpp::Elf_file<size, big_endian, Incremental_binary> elf_file_;
+};
+
+// Create an Incremental_binary object for FILE. Returns NULL is this is not
+// possible, e.g. FILE is not an ELF file or has an unsupported target.
+Incremental_binary*
+open_incremental_binary(Output_file* file);
+
// Code invoked early during an incremental link that checks what files need
// to be relinked.
class Incremental_checker
Index: gold/object.cc
===================================================================
RCS file: /cvs/src/src/gold/object.cc,v
retrieving revision 1.101
diff -p -u -r1.101 object.cc
--- gold/object.cc 6 Oct 2009 22:58:27 -0000 1.101
+++ gold/object.cc 9 Oct 2009 16:36:33 -0000
@@ -2281,7 +2281,7 @@ is_elf_object(Input_file* input_file, of
const unsigned char** start, int *read_size)
{
off_t filesize = input_file->file().filesize();
- int want = elfcpp::Elf_sizes<64>::ehdr_size;
+ int want = elfcpp::Elf_recognizer::max_header_size;
if (filesize - offset < want)
want = filesize - offset;
@@ -2290,15 +2290,7 @@ is_elf_object(Input_file* input_file, of
*start = p;
*read_size = want;
- if (want < 4)
- return false;
-
- static unsigned char elfmagic[4] =
- {
- elfcpp::ELFMAG0, elfcpp::ELFMAG1,
- elfcpp::ELFMAG2, elfcpp::ELFMAG3
- };
- return memcmp(p, elfmagic, 4) == 0;
+ return elfcpp::Elf_recognizer::is_elf_file(p, want);
}
// Read an ELF file and return the appropriate instance of Object.
@@ -2311,57 +2303,18 @@ make_elf_object(const std::string& name,
if (punconfigured != NULL)
*punconfigured = false;
- if (bytes < elfcpp::EI_NIDENT)
- {
- gold_error(_("%s: ELF file too short"), name.c_str());
- return NULL;
- }
-
- int v = p[elfcpp::EI_VERSION];
- if (v != elfcpp::EV_CURRENT)
- {
- if (v == elfcpp::EV_NONE)
- gold_error(_("%s: invalid ELF version 0"), name.c_str());
- else
- gold_error(_("%s: unsupported ELF version %d"), name.c_str(), v);
- return NULL;
- }
-
- int c = p[elfcpp::EI_CLASS];
- if (c == elfcpp::ELFCLASSNONE)
- {
- gold_error(_("%s: invalid ELF class 0"), name.c_str());
- return NULL;
- }
- else if (c != elfcpp::ELFCLASS32
- && c != elfcpp::ELFCLASS64)
- {
- gold_error(_("%s: unsupported ELF class %d"), name.c_str(), c);
- return NULL;
- }
-
- int d = p[elfcpp::EI_DATA];
- if (d == elfcpp::ELFDATANONE)
- {
- gold_error(_("%s: invalid ELF data encoding"), name.c_str());
- return NULL;
- }
- else if (d != elfcpp::ELFDATA2LSB
- && d != elfcpp::ELFDATA2MSB)
+ std::string error;
+ bool big_endian;
+ int size;
+ if (!elfcpp::Elf_recognizer::is_valid_header(p, bytes, &size,
+ &big_endian, &error))
{
- gold_error(_("%s: unsupported ELF data encoding %d"), name.c_str(), d);
+ gold_error(_("%s: %s"), name.c_str(), error.c_str());
return NULL;
}
- bool big_endian = d == elfcpp::ELFDATA2MSB;
-
- if (c == elfcpp::ELFCLASS32)
+ if (size == 32)
{
- if (bytes < elfcpp::Elf_sizes<32>::ehdr_size)
- {
- gold_error(_("%s: ELF file too short"), name.c_str());
- return NULL;
- }
if (big_endian)
{
#ifdef HAVE_TARGET_32_BIG
@@ -2395,13 +2348,8 @@ make_elf_object(const std::string& name,
#endif
}
}
- else
+ else if (size == 64)
{
- if (bytes < elfcpp::Elf_sizes<64>::ehdr_size)
- {
- gold_error(_("%s: ELF file too short"), name.c_str());
- return NULL;
- }
if (big_endian)
{
#ifdef HAVE_TARGET_64_BIG
@@ -2435,6 +2383,8 @@ make_elf_object(const std::string& name,
#endif
}
}
+ else
+ gold_unreachable();
}
// Instantiate the templates we need.
Index: gold/output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.82
diff -p -u -r1.82 output.h
--- gold/output.h 18 Sep 2009 01:10:38 -0000 1.82
+++ gold/output.h 9 Oct 2009 16:36:33 -0000
@@ -3433,6 +3433,11 @@ class Output_file
void
close();
+ // Return the size of this file.
+ off_t
+ filesize()
+ { return this->file_size_; }
+
// We currently always use mmap which makes the view handling quite
// simple. In the future we may support other approaches.