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
7 changed files with 513 additions and 63 deletions
|
@ -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>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue