mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-24 12:39:59 +00:00
elfcpp/:
* 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/: * 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.
This commit is contained in:
parent
e322137b9b
commit
c549a6949c
@ -1,3 +1,9 @@
|
||||
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.
|
||||
|
||||
2009-07-23 Ulrich Drepper <drepper@redhat.com>
|
||||
|
||||
* elfcpp.h (enum STB): Add STB_GNU_UNIQUE.
|
||||
|
@ -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>::initialize_shnum()
|
||||
}
|
||||
}
|
||||
|
||||
// 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>
|
||||
|
@ -1,3 +1,24 @@
|
||||
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.
|
||||
|
||||
2009-10-07 Viktor Kutuzov <vkutuzov@accesssoftek.com>
|
||||
|
||||
* arm.cc (Arm_relocate_functions::extract_arm_movw_movt_addend):
|
||||
|
@ -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_link_output_file()
|
||||
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_section_data()
|
||||
"** 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.
|
||||
|
@ -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
|
||||
|
@ -2281,7 +2281,7 @@ is_elf_object(Input_file* input_file, off_t offset,
|
||||
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, off_t offset,
|
||||
*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, Input_file* input_file, off_t offset,
|
||||
if (punconfigured != NULL)
|
||||
*punconfigured = false;
|
||||
|
||||
if (bytes < elfcpp::EI_NIDENT)
|
||||
std::string error;
|
||||
bool big_endian;
|
||||
int size;
|
||||
if (!elfcpp::Elf_recognizer::is_valid_header(p, bytes, &size,
|
||||
&big_endian, &error))
|
||||
{
|
||||
gold_error(_("%s: ELF file too short"), name.c_str());
|
||||
gold_error(_("%s: %s"), name.c_str(), error.c_str());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int v = p[elfcpp::EI_VERSION];
|
||||
if (v != elfcpp::EV_CURRENT)
|
||||
if (size == 32)
|
||||
{
|
||||
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)
|
||||
{
|
||||
gold_error(_("%s: unsupported ELF data encoding %d"), name.c_str(), d);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool big_endian = d == elfcpp::ELFDATA2MSB;
|
||||
|
||||
if (c == elfcpp::ELFCLASS32)
|
||||
{
|
||||
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, Input_file* input_file, off_t offset,
|
||||
#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, Input_file* input_file, off_t offset,
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
gold_unreachable();
|
||||
}
|
||||
|
||||
// Instantiate the templates we need.
|
||||
|
@ -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.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user