mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-24 12:39:59 +00:00
Split Object into Dynobj and Relobj, incorporate elfcpp swapping changes.
This commit is contained in:
parent
8d9455b422
commit
f6ce93d6e9
@ -70,7 +70,7 @@ Archive::setup()
|
||||
|
||||
// Numbers in the armap are always big-endian.
|
||||
const elfcpp::Elf_Word* pword = reinterpret_cast<const elfcpp::Elf_Word*>(p);
|
||||
unsigned int nsyms = elfcpp::read_elf_word<true>(pword);
|
||||
unsigned int nsyms = elfcpp::Swap<32, true>::readval(pword);
|
||||
++pword;
|
||||
|
||||
// Note that the addition is in units of sizeof(elfcpp::Elf_Word).
|
||||
@ -81,7 +81,7 @@ Archive::setup()
|
||||
for (unsigned int i = 0; i < nsyms; ++i)
|
||||
{
|
||||
this->armap_[i].name = pnames;
|
||||
this->armap_[i].offset = elfcpp::read_elf_word<true>(pword);
|
||||
this->armap_[i].offset = elfcpp::Swap<32, true>::readval(pword);
|
||||
pnames += strlen(pnames) + 1;
|
||||
++pword;
|
||||
}
|
||||
@ -215,8 +215,8 @@ Archive::read_header(off_t off, std::string* pname)
|
||||
// may be satisfied by other objects in the archive.
|
||||
|
||||
void
|
||||
Archive::add_symbols(Symbol_table* symtab, Layout* layout,
|
||||
Input_objects* input_objects)
|
||||
Archive::add_symbols(const General_options& options, Symbol_table* symtab,
|
||||
Layout* layout, Input_objects* input_objects)
|
||||
{
|
||||
const size_t armap_size = this->armap_.size();
|
||||
|
||||
@ -248,7 +248,7 @@ Archive::add_symbols(Symbol_table* symtab, Layout* layout,
|
||||
|
||||
// We want to include this object in the link.
|
||||
last = this->armap_[i].offset;
|
||||
this->include_member(symtab, layout, input_objects, last);
|
||||
this->include_member(options, symtab, layout, input_objects, last);
|
||||
this->seen_[i] = true;
|
||||
added_new_object = true;
|
||||
}
|
||||
@ -260,8 +260,9 @@ Archive::add_symbols(Symbol_table* symtab, Layout* layout,
|
||||
// the member header.
|
||||
|
||||
void
|
||||
Archive::include_member(Symbol_table* symtab, Layout* layout,
|
||||
Input_objects* input_objects, off_t off)
|
||||
Archive::include_member(const General_options& options, Symbol_table* symtab,
|
||||
Layout* layout, Input_objects* input_objects,
|
||||
off_t off)
|
||||
{
|
||||
std::string n;
|
||||
this->read_header(off, &n);
|
||||
@ -303,7 +304,7 @@ Archive::include_member(Symbol_table* symtab, Layout* layout,
|
||||
|
||||
Read_symbols_data sd;
|
||||
obj->read_symbols(&sd);
|
||||
obj->layout(layout, &sd);
|
||||
obj->layout(options, symtab, layout, &sd);
|
||||
obj->add_symbols(symtab, &sd);
|
||||
}
|
||||
|
||||
@ -352,7 +353,7 @@ Add_archive_symbols::locks(Workqueue* workqueue)
|
||||
void
|
||||
Add_archive_symbols::run(Workqueue*)
|
||||
{
|
||||
this->archive_->add_symbols(this->symtab_, this->layout_,
|
||||
this->archive_->add_symbols(this->options_, this->symtab_, this->layout_,
|
||||
this->input_objects_);
|
||||
|
||||
if (this->input_group_ != NULL)
|
||||
|
@ -11,6 +11,7 @@
|
||||
namespace gold
|
||||
{
|
||||
|
||||
class General_options;
|
||||
class Input_file;
|
||||
class Input_objects;
|
||||
class Input_group;
|
||||
@ -68,14 +69,13 @@ class Archive
|
||||
// Select members from the archive as needed and add them to the
|
||||
// link.
|
||||
void
|
||||
add_symbols(Symbol_table*, Layout*, Input_objects*);
|
||||
add_symbols(const General_options&, Symbol_table*, Layout*, Input_objects*);
|
||||
|
||||
private:
|
||||
Archive(const Archive&);
|
||||
Archive& operator=(const Archive&);
|
||||
|
||||
struct Archive_header;
|
||||
class Add_archive_symbols_locker;
|
||||
|
||||
// Get a view into the underlying file.
|
||||
const unsigned char*
|
||||
@ -89,7 +89,8 @@ class Archive
|
||||
|
||||
// Include an archive member in the link.
|
||||
void
|
||||
include_member(Symbol_table*, Layout*, Input_objects*, off_t off);
|
||||
include_member(const General_options&, Symbol_table*, Layout*,
|
||||
Input_objects*, off_t off);
|
||||
|
||||
// An entry in the archive map of symbols to object files.
|
||||
struct Armap_entry
|
||||
@ -119,14 +120,15 @@ class Archive
|
||||
class Add_archive_symbols : public Task
|
||||
{
|
||||
public:
|
||||
Add_archive_symbols(Symbol_table* symtab, Layout* layout,
|
||||
Input_objects* input_objects,
|
||||
Add_archive_symbols(const General_options& options, Symbol_table* symtab,
|
||||
Layout* layout, Input_objects* input_objects,
|
||||
Archive* archive, Input_group* input_group,
|
||||
Task_token* this_blocker,
|
||||
Task_token* next_blocker)
|
||||
: symtab_(symtab), layout_(layout), input_objects_(input_objects),
|
||||
archive_(archive), input_group_(input_group),
|
||||
this_blocker_(this_blocker), next_blocker_(next_blocker)
|
||||
: options_(options), symtab_(symtab), layout_(layout),
|
||||
input_objects_(input_objects), archive_(archive),
|
||||
input_group_(input_group), this_blocker_(this_blocker),
|
||||
next_blocker_(next_blocker)
|
||||
{ }
|
||||
|
||||
~Add_archive_symbols();
|
||||
@ -145,6 +147,7 @@ class Add_archive_symbols : public Task
|
||||
private:
|
||||
class Add_archive_symbols_locker;
|
||||
|
||||
const General_options& options_;
|
||||
Symbol_table* symtab_;
|
||||
Layout* layout_;
|
||||
Input_objects* input_objects_;
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "workqueue.h"
|
||||
#include "layout.h"
|
||||
#include "output.h"
|
||||
#include "symtab.h"
|
||||
#include "common.h"
|
||||
|
||||
namespace gold
|
||||
|
118
gold/defstd.cc
118
gold/defstd.cc
@ -94,9 +94,9 @@ const int in_section_count = sizeof in_section / sizeof in_section[0];
|
||||
const Define_symbol_in_segment in_segment[] =
|
||||
{
|
||||
{
|
||||
"_end", // name
|
||||
"__executable_start", // name
|
||||
elfcpp::PT_LOAD, // segment_type
|
||||
elfcpp::PF_W, // segment_flags_set
|
||||
elfcpp::PF(0), // segment_flags_set
|
||||
elfcpp::PF(0), // segment_flags_clear
|
||||
0, // value
|
||||
0, // size
|
||||
@ -104,7 +104,119 @@ const Define_symbol_in_segment in_segment[] =
|
||||
elfcpp::STB_GLOBAL, // binding
|
||||
elfcpp::STV_DEFAULT, // visibility
|
||||
0, // nonvis
|
||||
Symbol::SEGMENT_START, // offset_from_bas
|
||||
Symbol::SEGMENT_START, // offset_from_base
|
||||
true // only_if_ref
|
||||
},
|
||||
{
|
||||
"etext", // name
|
||||
elfcpp::PT_LOAD, // segment_type
|
||||
elfcpp::PF_X, // segment_flags_set
|
||||
elfcpp::PF_W, // segment_flags_clear
|
||||
0, // value
|
||||
0, // size
|
||||
elfcpp::STT_NOTYPE, // type
|
||||
elfcpp::STB_GLOBAL, // binding
|
||||
elfcpp::STV_DEFAULT, // visibility
|
||||
0, // nonvis
|
||||
Symbol::SEGMENT_END, // offset_from_base
|
||||
true // only_if_ref
|
||||
},
|
||||
{
|
||||
"_etext", // name
|
||||
elfcpp::PT_LOAD, // segment_type
|
||||
elfcpp::PF_X, // segment_flags_set
|
||||
elfcpp::PF_W, // segment_flags_clear
|
||||
0, // value
|
||||
0, // size
|
||||
elfcpp::STT_NOTYPE, // type
|
||||
elfcpp::STB_GLOBAL, // binding
|
||||
elfcpp::STV_DEFAULT, // visibility
|
||||
0, // nonvis
|
||||
Symbol::SEGMENT_END, // offset_from_base
|
||||
true // only_if_ref
|
||||
},
|
||||
{
|
||||
"__etext", // name
|
||||
elfcpp::PT_LOAD, // segment_type
|
||||
elfcpp::PF_X, // segment_flags_set
|
||||
elfcpp::PF_W, // segment_flags_clear
|
||||
0, // value
|
||||
0, // size
|
||||
elfcpp::STT_NOTYPE, // type
|
||||
elfcpp::STB_GLOBAL, // binding
|
||||
elfcpp::STV_DEFAULT, // visibility
|
||||
0, // nonvis
|
||||
Symbol::SEGMENT_END, // offset_from_base
|
||||
true // only_if_ref
|
||||
},
|
||||
{
|
||||
"_edata", // name
|
||||
elfcpp::PT_LOAD, // segment_type
|
||||
elfcpp::PF_X, // segment_flags_set
|
||||
elfcpp::PF(0), // segment_flags_clear
|
||||
0, // value
|
||||
0, // size
|
||||
elfcpp::STT_NOTYPE, // type
|
||||
elfcpp::STB_GLOBAL, // binding
|
||||
elfcpp::STV_DEFAULT, // visibility
|
||||
0, // nonvis
|
||||
Symbol::SEGMENT_BSS, // offset_from_base
|
||||
false // only_if_ref
|
||||
},
|
||||
{
|
||||
"edata", // name
|
||||
elfcpp::PT_LOAD, // segment_type
|
||||
elfcpp::PF_X, // segment_flags_set
|
||||
elfcpp::PF(0), // segment_flags_clear
|
||||
0, // value
|
||||
0, // size
|
||||
elfcpp::STT_NOTYPE, // type
|
||||
elfcpp::STB_GLOBAL, // binding
|
||||
elfcpp::STV_DEFAULT, // visibility
|
||||
0, // nonvis
|
||||
Symbol::SEGMENT_BSS, // offset_from_base
|
||||
true // only_if_ref
|
||||
},
|
||||
{
|
||||
"__bss_start", // name
|
||||
elfcpp::PT_LOAD, // segment_type
|
||||
elfcpp::PF_X, // segment_flags_set
|
||||
elfcpp::PF(0), // segment_flags_clear
|
||||
0, // value
|
||||
0, // size
|
||||
elfcpp::STT_NOTYPE, // type
|
||||
elfcpp::STB_GLOBAL, // binding
|
||||
elfcpp::STV_DEFAULT, // visibility
|
||||
0, // nonvis
|
||||
Symbol::SEGMENT_BSS, // offset_from_base
|
||||
false // only_if_ref
|
||||
},
|
||||
{
|
||||
"_end", // name
|
||||
elfcpp::PT_LOAD, // segment_type
|
||||
elfcpp::PF_X, // segment_flags_set
|
||||
elfcpp::PF(0), // segment_flags_clear
|
||||
0, // value
|
||||
0, // size
|
||||
elfcpp::STT_NOTYPE, // type
|
||||
elfcpp::STB_GLOBAL, // binding
|
||||
elfcpp::STV_DEFAULT, // visibility
|
||||
0, // nonvis
|
||||
Symbol::SEGMENT_START, // offset_from_base
|
||||
false // only_if_ref
|
||||
},
|
||||
{
|
||||
"end", // name
|
||||
elfcpp::PT_LOAD, // segment_type
|
||||
elfcpp::PF_X, // segment_flags_set
|
||||
elfcpp::PF(0), // segment_flags_clear
|
||||
0, // value
|
||||
0, // size
|
||||
elfcpp::STT_NOTYPE, // type
|
||||
elfcpp::STB_GLOBAL, // binding
|
||||
elfcpp::STV_DEFAULT, // visibility
|
||||
0, // nonvis
|
||||
Symbol::SEGMENT_START, // offset_from_base
|
||||
false // only_if_ref
|
||||
}
|
||||
};
|
||||
|
56
gold/dynobj.h
Normal file
56
gold/dynobj.h
Normal file
@ -0,0 +1,56 @@
|
||||
// dynobj.h -- dynamic object support for gold -*- C++ -*-
|
||||
|
||||
#ifndef GOLD_DYNOBJ_H
|
||||
#define GOLD_DYNOBJ_H
|
||||
|
||||
#include "object.h"
|
||||
|
||||
namespace gold
|
||||
{
|
||||
|
||||
// A dynamic object (ET_DYN). This is an abstract base class itself.
|
||||
// The implementations is the template class Sized_dynobj.
|
||||
|
||||
class Dynobj : public Object
|
||||
{
|
||||
public:
|
||||
Dynobj(const std::string& name, Input_file* input_file, off_t offset = 0)
|
||||
: Object(name, input_file, true, offset)
|
||||
{ }
|
||||
};
|
||||
|
||||
// A dynamic object, size and endian specific version.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
class Sized_dynobj : public Dynobj
|
||||
{
|
||||
public:
|
||||
Sized_dynobj(const std::string& name, Input_file* input_file, off_t offset,
|
||||
const typename elfcpp::Ehdr<size, big_endian>&);
|
||||
|
||||
// Read the symbols.
|
||||
void
|
||||
do_read_symbols(Read_symbols_data*);
|
||||
|
||||
// Lay out the input sections.
|
||||
void
|
||||
do_layout(const General_options&, Symbol_table*, Layout*,
|
||||
Read_symbols_data*);
|
||||
|
||||
// Add the symbols to the symbol table.
|
||||
void
|
||||
do_add_symbols(Symbol_table*, Read_symbols_data*);
|
||||
|
||||
// Return a view of the contents of a section. Set *PLEN to the
|
||||
// size.
|
||||
const unsigned char*
|
||||
do_section_contents(unsigned int shnum, off_t* plen) = 0;
|
||||
|
||||
// Get the name of a section.
|
||||
std::string
|
||||
do_section_name(unsigned int shnum);
|
||||
};
|
||||
|
||||
} // End namespace gold.
|
||||
|
||||
#endif // !defined(GOLD_DYNOBJ_H)
|
@ -314,9 +314,13 @@ Input_file::open(const General_options& options, const Dirsearch& dirpath)
|
||||
std::string n1("lib");
|
||||
n1 += this->input_argument_.name();
|
||||
std::string n2;
|
||||
if (!options.is_static())
|
||||
n2 = n1 + ".so";
|
||||
n1 += ".a";
|
||||
if (options.is_static())
|
||||
n1 += ".a";
|
||||
else
|
||||
{
|
||||
n2 = n1 + ".a";
|
||||
n1 += ".so";
|
||||
}
|
||||
name = dirpath.find(n1, n2);
|
||||
if (name.empty())
|
||||
{
|
||||
|
@ -153,8 +153,8 @@ queue_middle_tasks(const General_options& options,
|
||||
// of references made to the symbols.
|
||||
Task_token* blocker = new Task_token();
|
||||
Task_token* symtab_lock = new Task_token();
|
||||
for (Input_objects::Object_list::const_iterator p = input_objects->begin();
|
||||
p != input_objects->end();
|
||||
for (Input_objects::Relobj_iterator p = input_objects->relobj_begin();
|
||||
p != input_objects->relobj_end();
|
||||
++p)
|
||||
{
|
||||
// We can read and process the relocations in any order. But we
|
||||
@ -198,8 +198,8 @@ queue_final_tasks(const General_options& options,
|
||||
|
||||
// Queue a task for each input object to relocate the sections and
|
||||
// write out the local symbols.
|
||||
for (Input_objects::Object_list::const_iterator p = input_objects->begin();
|
||||
p != input_objects->end();
|
||||
for (Input_objects::Relobj_iterator p = input_objects->relobj_begin();
|
||||
p != input_objects->relobj_end();
|
||||
++p)
|
||||
{
|
||||
final_blocker->add_blocker();
|
||||
|
12
gold/i386.cc
12
gold/i386.cc
@ -35,7 +35,7 @@ class Target_i386 : public Sized_target<32, false>
|
||||
scan_relocs(const General_options& options,
|
||||
Symbol_table* symtab,
|
||||
Layout* layout,
|
||||
Sized_object<32, false>* object,
|
||||
Sized_relobj<32, false>* object,
|
||||
unsigned int sh_type,
|
||||
const unsigned char* prelocs,
|
||||
size_t reloc_count,
|
||||
@ -60,14 +60,14 @@ class Target_i386 : public Sized_target<32, false>
|
||||
inline void
|
||||
local(const General_options& options, Symbol_table* symtab,
|
||||
Layout* layout, Target_i386* target,
|
||||
Sized_object<32, false>* object,
|
||||
Sized_relobj<32, false>* object,
|
||||
const elfcpp::Rel<32, false>& reloc, unsigned int r_type,
|
||||
const elfcpp::Sym<32, false>& lsym);
|
||||
|
||||
inline void
|
||||
global(const General_options& options, Symbol_table* symtab,
|
||||
Layout* layout, Target_i386* target,
|
||||
Sized_object<32, false>* object,
|
||||
Sized_relobj<32, false>* object,
|
||||
const elfcpp::Rel<32, false>& reloc, unsigned int r_type,
|
||||
Symbol* gsym);
|
||||
};
|
||||
@ -265,7 +265,7 @@ Target_i386::Scan::local(const General_options& options,
|
||||
Symbol_table* symtab,
|
||||
Layout* layout,
|
||||
Target_i386* target,
|
||||
Sized_object<32, false>* object,
|
||||
Sized_relobj<32, false>* object,
|
||||
const elfcpp::Rel<32, false>&, unsigned int r_type,
|
||||
const elfcpp::Sym<32, false>&)
|
||||
{
|
||||
@ -368,7 +368,7 @@ Target_i386::Scan::global(const General_options& options,
|
||||
Symbol_table* symtab,
|
||||
Layout* layout,
|
||||
Target_i386* target,
|
||||
Sized_object<32, false>* object,
|
||||
Sized_relobj<32, false>* object,
|
||||
const elfcpp::Rel<32, false>&, unsigned int r_type,
|
||||
Symbol* gsym)
|
||||
{
|
||||
@ -496,7 +496,7 @@ void
|
||||
Target_i386::scan_relocs(const General_options& options,
|
||||
Symbol_table* symtab,
|
||||
Layout* layout,
|
||||
Sized_object<32, false>* object,
|
||||
Sized_relobj<32, false>* object,
|
||||
unsigned int sh_type,
|
||||
const unsigned char* prelocs,
|
||||
size_t reloc_count,
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <utility>
|
||||
|
||||
#include "output.h"
|
||||
#include "symtab.h"
|
||||
#include "layout.h"
|
||||
|
||||
namespace gold
|
||||
@ -151,7 +152,7 @@ Layout::get_output_section(const char* name, elfcpp::Elf_Word type,
|
||||
|
||||
template<int size, bool big_endian>
|
||||
Output_section*
|
||||
Layout::layout(Object* object, unsigned int shndx, const char* name,
|
||||
Layout::layout(Relobj* object, unsigned int shndx, const char* name,
|
||||
const elfcpp::Shdr<size, big_endian>& shdr, off_t* off)
|
||||
{
|
||||
if (!this->include_section(object, name, shdr))
|
||||
@ -656,8 +657,8 @@ Layout::create_symtab_sections(int size, const Input_objects* input_objects,
|
||||
// never bother to write this out--it will just be left as zero.
|
||||
off += symsize;
|
||||
|
||||
for (Input_objects::Object_list::const_iterator p = input_objects->begin();
|
||||
p != input_objects->end();
|
||||
for (Input_objects::Relobj_iterator p = input_objects->relobj_begin();
|
||||
p != input_objects->relobj_end();
|
||||
++p)
|
||||
{
|
||||
Task_lock_obj<Object> tlo(**p);
|
||||
@ -956,22 +957,22 @@ Close_task_runner::run(Workqueue*)
|
||||
|
||||
template
|
||||
Output_section*
|
||||
Layout::layout<32, false>(Object* object, unsigned int shndx, const char* name,
|
||||
Layout::layout<32, false>(Relobj* object, unsigned int shndx, const char* name,
|
||||
const elfcpp::Shdr<32, false>& shdr, off_t*);
|
||||
|
||||
template
|
||||
Output_section*
|
||||
Layout::layout<32, true>(Object* object, unsigned int shndx, const char* name,
|
||||
Layout::layout<32, true>(Relobj* object, unsigned int shndx, const char* name,
|
||||
const elfcpp::Shdr<32, true>& shdr, off_t*);
|
||||
|
||||
template
|
||||
Output_section*
|
||||
Layout::layout<64, false>(Object* object, unsigned int shndx, const char* name,
|
||||
Layout::layout<64, false>(Relobj* object, unsigned int shndx, const char* name,
|
||||
const elfcpp::Shdr<64, false>& shdr, off_t*);
|
||||
|
||||
template
|
||||
Output_section*
|
||||
Layout::layout<64, true>(Object* object, unsigned int shndx, const char* name,
|
||||
Layout::layout<64, true>(Relobj* object, unsigned int shndx, const char* name,
|
||||
const elfcpp::Shdr<64, true>& shdr, off_t*);
|
||||
|
||||
|
||||
|
@ -70,7 +70,7 @@ class Layout
|
||||
// output section.
|
||||
template<int size, bool big_endian>
|
||||
Output_section*
|
||||
layout(Object *object, unsigned int shndx, const char* name,
|
||||
layout(Relobj *object, unsigned int shndx, const char* name,
|
||||
const elfcpp::Shdr<size, big_endian>& shdr, off_t* offset);
|
||||
|
||||
// Add an Output_section_data to the layout. This is used for
|
||||
|
121
gold/object.cc
121
gold/object.cc
@ -6,25 +6,25 @@
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
#include "object.h"
|
||||
#include "target-select.h"
|
||||
#include "layout.h"
|
||||
#include "output.h"
|
||||
#include "symtab.h"
|
||||
#include "object.h"
|
||||
#include "dynobj.h"
|
||||
|
||||
namespace gold
|
||||
{
|
||||
|
||||
// Class Object.
|
||||
|
||||
// Class Sized_object.
|
||||
// Class Sized_relobj.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
Sized_object<size, big_endian>::Sized_object(
|
||||
Sized_relobj<size, big_endian>::Sized_relobj(
|
||||
const std::string& name,
|
||||
Input_file* input_file,
|
||||
off_t offset,
|
||||
const elfcpp::Ehdr<size, big_endian>& ehdr)
|
||||
: Object(name, input_file, false, offset),
|
||||
: Relobj(name, input_file, offset),
|
||||
section_headers_(NULL),
|
||||
flags_(ehdr.get_e_flags()),
|
||||
shoff_(ehdr.get_e_shoff()),
|
||||
@ -53,7 +53,7 @@ Sized_object<size, big_endian>::Sized_object(
|
||||
}
|
||||
|
||||
template<int size, bool big_endian>
|
||||
Sized_object<size, big_endian>::~Sized_object()
|
||||
Sized_relobj<size, big_endian>::~Sized_relobj()
|
||||
{
|
||||
}
|
||||
|
||||
@ -61,21 +61,20 @@ Sized_object<size, big_endian>::~Sized_object()
|
||||
|
||||
template<int size, bool big_endian>
|
||||
inline const unsigned char*
|
||||
Sized_object<size, big_endian>::section_header(unsigned int shnum)
|
||||
Sized_relobj<size, big_endian>::section_header(unsigned int shnum)
|
||||
{
|
||||
assert(shnum < this->shnum());
|
||||
off_t symtabshdroff = this->shoff_ + shnum * This::shdr_size;
|
||||
return this->get_view(symtabshdroff, This::shdr_size);
|
||||
}
|
||||
|
||||
// Return the name of section SHNUM.
|
||||
// Return the name of section SHNUM. The object must already be
|
||||
// locked.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
std::string
|
||||
Sized_object<size, big_endian>::do_section_name(unsigned int shnum)
|
||||
Sized_relobj<size, big_endian>::do_section_name(unsigned int shnum)
|
||||
{
|
||||
Task_lock_obj<Object> tl(*this);
|
||||
|
||||
// Read the section names.
|
||||
typename This::Shdr shdrnames(this->section_header(this->shstrndx_));
|
||||
const unsigned char* pnamesu = this->get_view(shdrnames.get_sh_offset(),
|
||||
@ -95,12 +94,27 @@ Sized_object<size, big_endian>::do_section_name(unsigned int shnum)
|
||||
return std::string(pnames + shdr.get_sh_name());
|
||||
}
|
||||
|
||||
// Return a view of the contents of section SHNUM. The object does
|
||||
// not have to be locked.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
const unsigned char*
|
||||
Sized_relobj<size, big_endian>::do_section_contents(unsigned int shnum,
|
||||
off_t* plen)
|
||||
{
|
||||
Task_locker_obj<Object> tl(*this);
|
||||
|
||||
typename This::Shdr shdr(this->section_header(shnum));
|
||||
*plen = shdr.get_sh_size();
|
||||
return this->get_view(shdr.get_sh_offset(), shdr.get_sh_size());
|
||||
}
|
||||
|
||||
// Set up an object file bsaed on the file header. This sets up the
|
||||
// target and reads the section information.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Sized_object<size, big_endian>::setup(
|
||||
Sized_relobj<size, big_endian>::setup(
|
||||
const elfcpp::Ehdr<size, big_endian>& ehdr)
|
||||
{
|
||||
int machine = ehdr.get_e_machine();
|
||||
@ -159,7 +173,7 @@ Sized_object<size, big_endian>::setup(
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Sized_object<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
|
||||
Sized_relobj<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
|
||||
{
|
||||
// Transfer our view of the section headers to SD.
|
||||
sd->section_headers = this->section_headers_;
|
||||
@ -236,7 +250,7 @@ Sized_object<size, big_endian>::do_read_symbols(Read_symbols_data* sd)
|
||||
|
||||
template<int size, bool big_endian>
|
||||
bool
|
||||
Sized_object<size, big_endian>::include_section_group(
|
||||
Sized_relobj<size, big_endian>::include_section_group(
|
||||
Layout* layout,
|
||||
unsigned int index,
|
||||
const elfcpp::Shdr<size, big_endian>& shdr,
|
||||
@ -251,7 +265,7 @@ Sized_object<size, big_endian>::include_section_group(
|
||||
// The first word contains flags. We only care about COMDAT section
|
||||
// groups. Other section groups are always included in the link
|
||||
// just like ordinary sections.
|
||||
elfcpp::Elf_Word flags = elfcpp::read_elf_word<big_endian>(pword);
|
||||
elfcpp::Elf_Word flags = elfcpp::Swap<32, big_endian>::readval(pword);
|
||||
if ((flags & elfcpp::GRP_COMDAT) == 0)
|
||||
return true;
|
||||
|
||||
@ -345,7 +359,8 @@ Sized_object<size, big_endian>::include_section_group(
|
||||
size_t count = shdr.get_sh_size() / sizeof(elfcpp::Elf_Word);
|
||||
for (size_t i = 1; i < count; ++i)
|
||||
{
|
||||
elfcpp::Elf_Word secnum = elfcpp::read_elf_word<big_endian>(pword + i);
|
||||
elfcpp::Elf_Word secnum =
|
||||
elfcpp::Swap<32, big_endian>::readval(pword + i);
|
||||
if (secnum >= this->shnum())
|
||||
{
|
||||
fprintf(stderr,
|
||||
@ -377,7 +392,7 @@ Sized_object<size, big_endian>::include_section_group(
|
||||
|
||||
template<int size, bool big_endian>
|
||||
bool
|
||||
Sized_object<size, big_endian>::include_linkonce_section(
|
||||
Sized_relobj<size, big_endian>::include_linkonce_section(
|
||||
Layout* layout,
|
||||
const char* name,
|
||||
const elfcpp::Shdr<size, big_endian>&)
|
||||
@ -395,7 +410,9 @@ Sized_object<size, big_endian>::include_linkonce_section(
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Sized_object<size, big_endian>::do_layout(Layout* layout,
|
||||
Sized_relobj<size, big_endian>::do_layout(const General_options& options,
|
||||
Symbol_table* symtab,
|
||||
Layout* layout,
|
||||
Read_symbols_data* sd)
|
||||
{
|
||||
unsigned int shnum = this->shnum();
|
||||
@ -415,7 +432,12 @@ Sized_object<size, big_endian>::do_layout(Layout* layout,
|
||||
// Keep track of which sections to omit.
|
||||
std::vector<bool> omit(shnum, false);
|
||||
|
||||
for (unsigned int i = 0; i < shnum; ++i, pshdrs += This::shdr_size)
|
||||
const char warn_prefix[] = ".gnu.warning.";
|
||||
const int warn_prefix_len = sizeof warn_prefix - 1;
|
||||
|
||||
// Skip the first, dummy, section.
|
||||
pshdrs += This::shdr_size;
|
||||
for (unsigned int i = 1; i < shnum; ++i, pshdrs += This::shdr_size)
|
||||
{
|
||||
typename This::Shdr shdr(pshdrs);
|
||||
|
||||
@ -430,6 +452,13 @@ Sized_object<size, big_endian>::do_layout(Layout* layout,
|
||||
|
||||
const char* name = pnames + shdr.get_sh_name();
|
||||
|
||||
if (strncmp(name, warn_prefix, warn_prefix_len) == 0)
|
||||
{
|
||||
symtab->add_warning(name + warn_prefix_len, this, i);
|
||||
if (!options.is_relocatable())
|
||||
omit[i] = true;
|
||||
}
|
||||
|
||||
bool discard = omit[i];
|
||||
if (!discard)
|
||||
{
|
||||
@ -469,7 +498,7 @@ Sized_object<size, big_endian>::do_layout(Layout* layout,
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Sized_object<size, big_endian>::do_add_symbols(Symbol_table* symtab,
|
||||
Sized_relobj<size, big_endian>::do_add_symbols(Symbol_table* symtab,
|
||||
Read_symbols_data* sd)
|
||||
{
|
||||
if (sd->symbols == NULL)
|
||||
@ -490,13 +519,12 @@ Sized_object<size, big_endian>::do_add_symbols(Symbol_table* symtab,
|
||||
|
||||
this->symbols_ = new Symbol*[symcount];
|
||||
|
||||
const unsigned char* psyms = sd->symbols->data();
|
||||
const elfcpp::Sym<size, big_endian>* syms =
|
||||
reinterpret_cast<const elfcpp::Sym<size, big_endian>*>(psyms);
|
||||
const char* sym_names =
|
||||
reinterpret_cast<const char*>(sd->symbol_names->data());
|
||||
symtab->add_from_object(this, syms, symcount, sym_names,
|
||||
sd->symbol_names_size, this->symbols_);
|
||||
symtab->add_from_object<size, big_endian>(this, sd->symbols->data(),
|
||||
symcount, sym_names,
|
||||
sd->symbol_names_size,
|
||||
this->symbols_);
|
||||
|
||||
delete sd->symbols;
|
||||
sd->symbols = NULL;
|
||||
@ -512,7 +540,7 @@ Sized_object<size, big_endian>::do_add_symbols(Symbol_table* symtab,
|
||||
|
||||
template<int size, bool big_endian>
|
||||
off_t
|
||||
Sized_object<size, big_endian>::do_finalize_local_symbols(off_t off,
|
||||
Sized_relobj<size, big_endian>::do_finalize_local_symbols(off_t off,
|
||||
Stringpool* pool)
|
||||
{
|
||||
if (this->symtab_shnum_ == 0)
|
||||
@ -598,9 +626,12 @@ Sized_object<size, big_endian>::do_finalize_local_symbols(off_t off,
|
||||
+ sym.get_st_value());
|
||||
}
|
||||
|
||||
pool->add(pnames + sym.get_st_name());
|
||||
off += sym_size;
|
||||
++count;
|
||||
if (sym.get_st_type() != elfcpp::STT_SECTION)
|
||||
{
|
||||
pool->add(pnames + sym.get_st_name());
|
||||
off += sym_size;
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
this->output_local_symbol_count_ = count;
|
||||
@ -612,7 +643,7 @@ Sized_object<size, big_endian>::do_finalize_local_symbols(off_t off,
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Sized_object<size, big_endian>::write_local_symbols(Output_file* of,
|
||||
Sized_relobj<size, big_endian>::write_local_symbols(Output_file* of,
|
||||
const Stringpool* sympool)
|
||||
{
|
||||
if (this->symtab_shnum_ == 0)
|
||||
@ -655,7 +686,9 @@ Sized_object<size, big_endian>::write_local_symbols(Output_file* of,
|
||||
for (unsigned int i = 1; i < loccount; ++i, psyms += sym_size)
|
||||
{
|
||||
elfcpp::Sym<size, big_endian> isym(psyms);
|
||||
elfcpp::Sym_write<size, big_endian> osym(ov);
|
||||
|
||||
if (isym.get_st_type() == elfcpp::STT_SECTION)
|
||||
continue;
|
||||
|
||||
unsigned int st_shndx = isym.get_st_shndx();
|
||||
if (st_shndx < elfcpp::SHN_LORESERVE)
|
||||
@ -666,6 +699,8 @@ Sized_object<size, big_endian>::write_local_symbols(Output_file* of,
|
||||
st_shndx = mo[st_shndx].output_section->out_shndx();
|
||||
}
|
||||
|
||||
elfcpp::Sym_write<size, big_endian> osym(ov);
|
||||
|
||||
osym.put_st_name(sympool->get_offset(pnames + isym.get_st_name()));
|
||||
osym.put_st_value(this->values_[i]);
|
||||
osym.put_st_size(isym.get_st_size());
|
||||
@ -683,10 +718,15 @@ Sized_object<size, big_endian>::write_local_symbols(Output_file* of,
|
||||
|
||||
// Input_objects methods.
|
||||
|
||||
// Add a regular relocatable object to the list.
|
||||
|
||||
void
|
||||
Input_objects::add_object(Object* obj)
|
||||
{
|
||||
this->object_list_.push_back(obj);
|
||||
if (obj->is_dynamic())
|
||||
this->dynobj_list_.push_back(static_cast<Dynobj*>(obj));
|
||||
else
|
||||
this->relobj_list_.push_back(static_cast<Relobj*>(obj));
|
||||
|
||||
Target* target = obj->target();
|
||||
if (this->target_ == NULL)
|
||||
@ -697,9 +737,6 @@ Input_objects::add_object(Object* obj)
|
||||
program_name, obj->name().c_str());
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
if (obj->is_dynamic())
|
||||
this->any_dynamic_ = true;
|
||||
}
|
||||
|
||||
// Relocate_info methods.
|
||||
@ -752,8 +789,8 @@ make_elf_sized_object(const std::string& name, Input_file* input_file,
|
||||
|
||||
if (et == elfcpp::ET_REL)
|
||||
{
|
||||
Sized_object<size, big_endian>* obj =
|
||||
new Sized_object<size, big_endian>(name, input_file, offset, ehdr);
|
||||
Sized_relobj<size, big_endian>* obj =
|
||||
new Sized_relobj<size, big_endian>(name, input_file, offset, ehdr);
|
||||
obj->setup(ehdr);
|
||||
return obj;
|
||||
}
|
||||
@ -881,16 +918,16 @@ make_elf_object(const std::string& name, Input_file* input_file, off_t offset,
|
||||
// script to restrict this to only the ones for implemented targets.
|
||||
|
||||
template
|
||||
class Sized_object<32, false>;
|
||||
class Sized_relobj<32, false>;
|
||||
|
||||
template
|
||||
class Sized_object<32, true>;
|
||||
class Sized_relobj<32, true>;
|
||||
|
||||
template
|
||||
class Sized_object<64, false>;
|
||||
class Sized_relobj<64, false>;
|
||||
|
||||
template
|
||||
class Sized_object<64, true>;
|
||||
class Sized_relobj<64, true>;
|
||||
|
||||
template
|
||||
struct Relocate_info<32, false>;
|
||||
|
276
gold/object.h
276
gold/object.h
@ -4,14 +4,12 @@
|
||||
#define GOLD_OBJECT_H
|
||||
|
||||
#include <cassert>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "elfcpp.h"
|
||||
#include "fileread.h"
|
||||
#include "target.h"
|
||||
#include "symtab.h"
|
||||
|
||||
namespace gold
|
||||
{
|
||||
@ -21,6 +19,7 @@ class Stringpool;
|
||||
class Layout;
|
||||
class Output_section;
|
||||
class Output_file;
|
||||
class Dynobj;
|
||||
|
||||
// Data to pass from read_symbols() to add_symbols().
|
||||
|
||||
@ -71,10 +70,9 @@ struct Read_relocs_data
|
||||
File_view* local_symbols;
|
||||
};
|
||||
|
||||
// Object is an interface which represents either a 32-bit or a 64-bit
|
||||
// input object. This can be a regular object file (ET_REL) or a
|
||||
// shared object (ET_DYN). The actual instantiations are
|
||||
// Sized_object<32> and Sized_object<64>
|
||||
// Object is an abstract base class which represents either a 32-bit
|
||||
// or a 64-bit input object. This can be a regular object file
|
||||
// (ET_REL) or a shared object (ET_DYN).
|
||||
|
||||
class Object
|
||||
{
|
||||
@ -86,8 +84,7 @@ class Object
|
||||
Object(const std::string& name, Input_file* input_file, bool is_dynamic,
|
||||
off_t offset = 0)
|
||||
: name_(name), input_file_(input_file), offset_(offset),
|
||||
shnum_(0), is_dynamic_(is_dynamic), target_(NULL),
|
||||
map_to_output_()
|
||||
is_dynamic_(is_dynamic), target_(NULL)
|
||||
{ }
|
||||
|
||||
virtual ~Object()
|
||||
@ -138,14 +135,124 @@ class Object
|
||||
// Pass sections which should be included in the link to the Layout
|
||||
// object, and record where the sections go in the output file.
|
||||
void
|
||||
layout(Layout* lay, Read_symbols_data* sd)
|
||||
{ this->do_layout(lay, sd); }
|
||||
layout(const General_options& options, Symbol_table* symtab,
|
||||
Layout* layout, Read_symbols_data* sd)
|
||||
{ this->do_layout(options, symtab, layout, sd); }
|
||||
|
||||
// Add symbol information to the global symbol table.
|
||||
void
|
||||
add_symbols(Symbol_table* symtab, Read_symbols_data* sd)
|
||||
{ this->do_add_symbols(symtab, sd); }
|
||||
|
||||
// Return a view of the contents of a section. Set *PLEN to the
|
||||
// size.
|
||||
const unsigned char*
|
||||
section_contents(unsigned int shnum, off_t* plen)
|
||||
{ return this->do_section_contents(shnum, plen); }
|
||||
|
||||
// Return the name of a section given a section index. This is only
|
||||
// used for error messages.
|
||||
std::string
|
||||
section_name(unsigned int shnum)
|
||||
{ return this->do_section_name(shnum); }
|
||||
|
||||
protected:
|
||||
// Read the symbols--implemented by child class.
|
||||
virtual void
|
||||
do_read_symbols(Read_symbols_data*) = 0;
|
||||
|
||||
// Lay out sections--implemented by child class.
|
||||
virtual void
|
||||
do_layout(const General_options&, Symbol_table*, Layout*,
|
||||
Read_symbols_data*) = 0;
|
||||
|
||||
// Add symbol information to the global symbol table--implemented by
|
||||
// child class.
|
||||
virtual void
|
||||
do_add_symbols(Symbol_table*, Read_symbols_data*) = 0;
|
||||
|
||||
// Return a view of the contents of a section. Set *PLEN to the
|
||||
// size. Implemented by child class.
|
||||
virtual const unsigned char*
|
||||
do_section_contents(unsigned int shnum, off_t* plen) = 0;
|
||||
|
||||
// Get the name of a section--implemented by child class.
|
||||
virtual std::string
|
||||
do_section_name(unsigned int shnum) = 0;
|
||||
|
||||
// Get the file.
|
||||
Input_file*
|
||||
input_file() const
|
||||
{ return this->input_file_; }
|
||||
|
||||
// Get the offset into the file.
|
||||
off_t
|
||||
offset() const
|
||||
{ return this->offset_; }
|
||||
|
||||
// Get a view into the underlying file.
|
||||
const unsigned char*
|
||||
get_view(off_t start, off_t size)
|
||||
{ return this->input_file_->file().get_view(start + this->offset_, size); }
|
||||
|
||||
// Get a lasting view into the underlying file.
|
||||
File_view*
|
||||
get_lasting_view(off_t start, off_t size)
|
||||
{
|
||||
return this->input_file_->file().get_lasting_view(start + this->offset_,
|
||||
size);
|
||||
}
|
||||
|
||||
// Read data from the underlying file.
|
||||
void
|
||||
read(off_t start, off_t size, void* p)
|
||||
{ this->input_file_->file().read(start + this->offset_, size, p); }
|
||||
|
||||
// Set the target.
|
||||
void
|
||||
set_target(Target* target)
|
||||
{ this->target_ = target; }
|
||||
|
||||
private:
|
||||
// This class may not be copied.
|
||||
Object(const Object&);
|
||||
Object& operator=(const Object&);
|
||||
|
||||
// Name of object as printed to user.
|
||||
std::string name_;
|
||||
// For reading the file.
|
||||
Input_file* input_file_;
|
||||
// Offset within the file--0 for an object file, non-0 for an
|
||||
// archive.
|
||||
off_t offset_;
|
||||
// Whether this is a dynamic object.
|
||||
bool is_dynamic_;
|
||||
// Target functions--may be NULL if the target is not known.
|
||||
Target* target_;
|
||||
};
|
||||
|
||||
// Implement sized_target inline for efficiency. This approach breaks
|
||||
// static type checking, but is made safe using asserts.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
inline Sized_target<size, big_endian>*
|
||||
Object::sized_target(ACCEPT_SIZE_ENDIAN_ONLY)
|
||||
{
|
||||
assert(this->target_->get_size() == size);
|
||||
assert(this->target_->is_big_endian() ? big_endian : !big_endian);
|
||||
return static_cast<Sized_target<size, big_endian>*>(this->target_);
|
||||
}
|
||||
|
||||
// A regular object (ET_REL). This is an abstract base class itself.
|
||||
// The implementations is the template class Sized_relobj.
|
||||
|
||||
class Relobj : public Object
|
||||
{
|
||||
public:
|
||||
Relobj(const std::string& name, Input_file* input_file, off_t offset = 0)
|
||||
: Object(name, input_file, false, offset)
|
||||
{ }
|
||||
|
||||
// Read the relocs.
|
||||
void
|
||||
read_relocs(Read_relocs_data* rd)
|
||||
@ -192,12 +299,6 @@ class Object
|
||||
this->map_to_output_[shndx].offset = off;
|
||||
}
|
||||
|
||||
// Return the name of a section given a section index. This is only
|
||||
// used for error messages.
|
||||
std::string
|
||||
section_name(unsigned int shnum)
|
||||
{ return this->do_section_name(shnum); }
|
||||
|
||||
protected:
|
||||
// What we need to know to map an input section to an output
|
||||
// section. We keep an array of these, one for each input section,
|
||||
@ -211,15 +312,6 @@ class Object
|
||||
off_t offset;
|
||||
};
|
||||
|
||||
// Read the symbols--implemented by child class.
|
||||
virtual void
|
||||
do_read_symbols(Read_symbols_data*) = 0;
|
||||
|
||||
// Add symbol information to the global symbol table--implemented by
|
||||
// child class.
|
||||
virtual void
|
||||
do_add_symbols(Symbol_table*, Read_symbols_data*) = 0;
|
||||
|
||||
// Read the relocs--implemented by child class.
|
||||
virtual void
|
||||
do_read_relocs(Read_relocs_data*) = 0;
|
||||
@ -229,10 +321,6 @@ class Object
|
||||
do_scan_relocs(const General_options&, Symbol_table*, Layout*,
|
||||
Read_relocs_data*) = 0;
|
||||
|
||||
// Lay out sections--implemented by child class.
|
||||
virtual void
|
||||
do_layout(Layout*, Read_symbols_data*) = 0;
|
||||
|
||||
// Finalize local symbols--implemented by child class.
|
||||
virtual off_t
|
||||
do_finalize_local_symbols(off_t, Stringpool*) = 0;
|
||||
@ -243,25 +331,6 @@ class Object
|
||||
do_relocate(const General_options& options, const Symbol_table* symtab,
|
||||
const Layout*, Output_file* of) = 0;
|
||||
|
||||
// Get the name of a section--implemented by child class.
|
||||
virtual std::string
|
||||
do_section_name(unsigned int shnum) = 0;
|
||||
|
||||
// Get the file.
|
||||
Input_file*
|
||||
input_file() const
|
||||
{ return this->input_file_; }
|
||||
|
||||
// Get the offset into the file.
|
||||
off_t
|
||||
offset() const
|
||||
{ return this->offset_; }
|
||||
|
||||
// Get a view into the underlying file.
|
||||
const unsigned char*
|
||||
get_view(off_t start, off_t size)
|
||||
{ return this->input_file_->file().get_view(start + this->offset_, size); }
|
||||
|
||||
// Get the number of sections.
|
||||
unsigned int
|
||||
shnum() const
|
||||
@ -272,66 +341,21 @@ class Object
|
||||
set_shnum(int shnum)
|
||||
{ this->shnum_ = shnum; }
|
||||
|
||||
// Set the target.
|
||||
void
|
||||
set_target(Target* target)
|
||||
{ this->target_ = target; }
|
||||
|
||||
// Read data from the underlying file.
|
||||
void
|
||||
read(off_t start, off_t size, void* p)
|
||||
{ this->input_file_->file().read(start + this->offset_, size, p); }
|
||||
|
||||
// Get a lasting view into the underlying file.
|
||||
File_view*
|
||||
get_lasting_view(off_t start, off_t size)
|
||||
{
|
||||
return this->input_file_->file().get_lasting_view(start + this->offset_,
|
||||
size);
|
||||
}
|
||||
|
||||
// Return the vector mapping input sections to output sections.
|
||||
std::vector<Map_to_output>&
|
||||
map_to_output()
|
||||
{ return this->map_to_output_; }
|
||||
|
||||
private:
|
||||
// This class may not be copied.
|
||||
Object(const Object&);
|
||||
Object& operator=(const Object&);
|
||||
|
||||
// Name of object as printed to user.
|
||||
std::string name_;
|
||||
// For reading the file.
|
||||
Input_file* input_file_;
|
||||
// Offset within the file--0 for an object file, non-0 for an
|
||||
// archive.
|
||||
off_t offset_;
|
||||
// Number of input sections.
|
||||
unsigned int shnum_;
|
||||
// Whether this is a dynamic object.
|
||||
bool is_dynamic_;
|
||||
// Target functions--may be NULL if the target is not known.
|
||||
Target* target_;
|
||||
// Mapping from input sections to output section.
|
||||
std::vector<Map_to_output> map_to_output_;
|
||||
};
|
||||
|
||||
// Implement sized_target inline for efficiency. This approach breaks
|
||||
// static type checking, but is made safe using asserts.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
inline Sized_target<size, big_endian>*
|
||||
Object::sized_target(ACCEPT_SIZE_ENDIAN_ONLY)
|
||||
{
|
||||
assert(this->target_->get_size() == size);
|
||||
assert(this->target_->is_big_endian() ? big_endian : !big_endian);
|
||||
return static_cast<Sized_target<size, big_endian>*>(this->target_);
|
||||
}
|
||||
|
||||
// Implement Object::output_section inline for efficiency.
|
||||
inline Output_section*
|
||||
Object::output_section(unsigned int shnum, off_t* poff)
|
||||
Relobj::output_section(unsigned int shnum, off_t* poff)
|
||||
{
|
||||
assert(shnum < this->map_to_output_.size());
|
||||
const Map_to_output& mo(this->map_to_output_[shnum]);
|
||||
@ -342,13 +366,13 @@ Object::output_section(unsigned int shnum, off_t* poff)
|
||||
// A regular object file. This is size and endian specific.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
class Sized_object : public Object
|
||||
class Sized_relobj : public Relobj
|
||||
{
|
||||
public:
|
||||
Sized_object(const std::string& name, Input_file* input_file, off_t offset,
|
||||
Sized_relobj(const std::string& name, Input_file* input_file, off_t offset,
|
||||
const typename elfcpp::Ehdr<size, big_endian>&);
|
||||
|
||||
~Sized_object();
|
||||
~Sized_relobj();
|
||||
|
||||
// Set up the object file based on the ELF header.
|
||||
void
|
||||
@ -373,7 +397,8 @@ class Sized_object : public Object
|
||||
|
||||
// Lay out the input sections.
|
||||
void
|
||||
do_layout(Layout*, Read_symbols_data*);
|
||||
do_layout(const General_options&, Symbol_table*, Layout*,
|
||||
Read_symbols_data*);
|
||||
|
||||
// Finalize the local symbols.
|
||||
off_t
|
||||
@ -388,6 +413,11 @@ class Sized_object : public Object
|
||||
std::string
|
||||
do_section_name(unsigned int shnum);
|
||||
|
||||
// Return a view of the contents of a section. Set *PLEN to the
|
||||
// size.
|
||||
const unsigned char*
|
||||
do_section_contents(unsigned int shnum, off_t* plen);
|
||||
|
||||
// Return the appropriate Sized_target structure.
|
||||
Sized_target<size, big_endian>*
|
||||
sized_target()
|
||||
@ -398,12 +428,8 @@ class Sized_object : public Object
|
||||
}
|
||||
|
||||
private:
|
||||
// This object may not be copied.
|
||||
Sized_object(const Sized_object&);
|
||||
Sized_object& operator=(const Sized_object&);
|
||||
|
||||
// For convenience.
|
||||
typedef Sized_object<size, big_endian> This;
|
||||
typedef Sized_relobj<size, big_endian> This;
|
||||
static const int ehdr_size = elfcpp::Elf_sizes<size>::ehdr_size;
|
||||
static const int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
|
||||
static const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
|
||||
@ -477,11 +503,16 @@ class Input_objects
|
||||
{
|
||||
public:
|
||||
Input_objects()
|
||||
: object_list_(), target_(NULL), any_dynamic_(false)
|
||||
: relobj_list_(), target_(NULL)
|
||||
{ }
|
||||
|
||||
// The type of the list of input objects.
|
||||
typedef std::list<Object*> Object_list;
|
||||
// The type of the list of input relocateable objects.
|
||||
typedef std::vector<Relobj*> Relobj_list;
|
||||
typedef Relobj_list::const_iterator Relobj_iterator;
|
||||
|
||||
// The type of the list of input dynamic objects.
|
||||
typedef std::vector<Dynobj*> Dynobj_list;
|
||||
typedef Dynobj_list::const_iterator Dynobj_iterator;
|
||||
|
||||
// Add an object to the list.
|
||||
void
|
||||
@ -492,27 +523,38 @@ class Input_objects
|
||||
target() const
|
||||
{ return this->target_; }
|
||||
|
||||
// Iterate over all objects.
|
||||
Object_list::const_iterator
|
||||
begin() const
|
||||
{ return this->object_list_.begin(); }
|
||||
// Iterate over all regular objects.
|
||||
|
||||
Object_list::const_iterator
|
||||
end() const
|
||||
{ return this->object_list_.end(); }
|
||||
Relobj_iterator
|
||||
relobj_begin() const
|
||||
{ return this->relobj_list_.begin(); }
|
||||
|
||||
Relobj_iterator
|
||||
relobj_end() const
|
||||
{ return this->relobj_list_.end(); }
|
||||
|
||||
// Iterate over all dynamic objects.
|
||||
|
||||
Dynobj_iterator
|
||||
dynobj_begin() const
|
||||
{ return this->dynobj_list_.begin(); }
|
||||
|
||||
Dynobj_iterator
|
||||
dynobj_end() const
|
||||
{ return this->dynobj_list_.end(); }
|
||||
|
||||
// Return whether we have seen any dynamic objects.
|
||||
bool
|
||||
any_dynamic() const
|
||||
{ return this->any_dynamic_; }
|
||||
{ return !this->dynobj_list_.empty(); }
|
||||
|
||||
private:
|
||||
Input_objects(const Input_objects&);
|
||||
Input_objects& operator=(const Input_objects&);
|
||||
|
||||
Object_list object_list_;
|
||||
Relobj_list relobj_list_;
|
||||
Dynobj_list dynobj_list_;
|
||||
Target* target_;
|
||||
bool any_dynamic_;
|
||||
};
|
||||
|
||||
// Some of the information we pass to the relocation routines. We
|
||||
@ -528,7 +570,7 @@ struct Relocate_info
|
||||
// Layout.
|
||||
const Layout* layout;
|
||||
// Object being relocated.
|
||||
Sized_object<size, big_endian>* object;
|
||||
Sized_relobj<size, big_endian>* object;
|
||||
// Number of local symbols.
|
||||
unsigned int local_symbol_count;
|
||||
// Values of local symbols.
|
||||
|
@ -399,7 +399,7 @@ Output_section_got<size, big_endian>::Got_entry::write(unsigned char* pov)
|
||||
}
|
||||
|
||||
Valtype* povv = reinterpret_cast<Valtype*>(pov);
|
||||
Swap<size, big_endian>::writeval(povv, val);
|
||||
elfcpp::Swap<size, big_endian>::writeval(povv, val);
|
||||
}
|
||||
|
||||
// Output_section_data methods.
|
||||
@ -509,7 +509,7 @@ Output_section::~Output_section()
|
||||
|
||||
template<int size, bool big_endian>
|
||||
off_t
|
||||
Output_section::add_input_section(Object* object, unsigned int shndx,
|
||||
Output_section::add_input_section(Relobj* object, unsigned int shndx,
|
||||
const char* secname,
|
||||
const elfcpp::Shdr<size, big_endian>& shdr)
|
||||
{
|
||||
@ -1091,7 +1091,7 @@ Output_file::close()
|
||||
template
|
||||
off_t
|
||||
Output_section::add_input_section<32, false>(
|
||||
Object* object,
|
||||
Relobj* object,
|
||||
unsigned int shndx,
|
||||
const char* secname,
|
||||
const elfcpp::Shdr<32, false>& shdr);
|
||||
@ -1099,7 +1099,7 @@ Output_section::add_input_section<32, false>(
|
||||
template
|
||||
off_t
|
||||
Output_section::add_input_section<32, true>(
|
||||
Object* object,
|
||||
Relobj* object,
|
||||
unsigned int shndx,
|
||||
const char* secname,
|
||||
const elfcpp::Shdr<32, true>& shdr);
|
||||
@ -1107,7 +1107,7 @@ Output_section::add_input_section<32, true>(
|
||||
template
|
||||
off_t
|
||||
Output_section::add_input_section<64, false>(
|
||||
Object* object,
|
||||
Relobj* object,
|
||||
unsigned int shndx,
|
||||
const char* secname,
|
||||
const elfcpp::Shdr<64, false>& shdr);
|
||||
@ -1115,7 +1115,7 @@ Output_section::add_input_section<64, false>(
|
||||
template
|
||||
off_t
|
||||
Output_section::add_input_section<64, true>(
|
||||
Object* object,
|
||||
Relobj* object,
|
||||
unsigned int shndx,
|
||||
const char* secname,
|
||||
const elfcpp::Shdr<64, true>& shdr);
|
||||
|
@ -504,7 +504,7 @@ class Output_section : public Output_data
|
||||
// object OBJECT. Return the offset within the output section.
|
||||
template<int size, bool big_endian>
|
||||
off_t
|
||||
add_input_section(Object* object, unsigned int shndx, const char *name,
|
||||
add_input_section(Relobj* object, unsigned int shndx, const char *name,
|
||||
const elfcpp::Shdr<size, big_endian>& shdr);
|
||||
|
||||
// Add generated data ODATA to this output section.
|
||||
@ -613,7 +613,7 @@ class Output_section : public Output_data
|
||||
: shndx_(0), p2align_(0), data_size_(0)
|
||||
{ this->u_.object = NULL; }
|
||||
|
||||
Input_section(Object* object, unsigned int shndx, off_t data_size,
|
||||
Input_section(Relobj* object, unsigned int shndx, off_t data_size,
|
||||
uint64_t addralign)
|
||||
: shndx_(shndx),
|
||||
p2align_(ffsll(static_cast<long long>(addralign))),
|
||||
@ -665,7 +665,7 @@ class Output_section : public Output_data
|
||||
{
|
||||
// If shndx_ != -1U, this points to the object which holds the
|
||||
// input section.
|
||||
Object* object;
|
||||
Relobj* object;
|
||||
// If shndx_ == -1U, this is the data to write out.
|
||||
Output_section_data* posd;
|
||||
} u_;
|
||||
|
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2006-11-03 10:45-0800\n"
|
||||
"POT-Creation-Date: 2006-11-06 13:40-0800\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -51,7 +51,7 @@ msgstr ""
|
||||
msgid "%s: %s: bad extended name entry at header %ld\n"
|
||||
msgstr ""
|
||||
|
||||
#: archive.cc:279 archive.cc:292
|
||||
#: archive.cc:280 archive.cc:293
|
||||
#, c-format
|
||||
msgid "%s: %s: member at %ld is not an ELF object"
|
||||
msgstr ""
|
||||
@ -81,12 +81,12 @@ msgstr ""
|
||||
msgid "%s: %s: file too short: read only %lld of %lld bytes at %lld\n"
|
||||
msgstr ""
|
||||
|
||||
#: fileread.cc:323
|
||||
#: fileread.cc:327
|
||||
#, c-format
|
||||
msgid "%s: cannot find %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: fileread.cc:331
|
||||
#: fileread.cc:335
|
||||
#, c-format
|
||||
msgid "%s: cannot open %s: %s\n"
|
||||
msgstr ""
|
||||
@ -205,103 +205,103 @@ msgstr ""
|
||||
msgid "%s: %s: bad e_shentsize field (%d != %d)\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:89 object.cc:329 object.cc:425
|
||||
#: object.cc:88 object.cc:343 object.cc:447
|
||||
#, c-format
|
||||
msgid "%s: %s: bad section name offset for section %u: %lu\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:112
|
||||
#: object.cc:126
|
||||
#, c-format
|
||||
msgid "%s: %s: unsupported ELF machine number %d\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:207
|
||||
#: object.cc:221
|
||||
#, c-format
|
||||
msgid "%s: %s: invalid symbol table name index: %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:215
|
||||
#: object.cc:229
|
||||
#, c-format
|
||||
msgid "%s: %s: symbol table name section has wrong type: %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:267
|
||||
#: object.cc:281
|
||||
#, c-format
|
||||
msgid "%s: %s: section group %u link %u out of range\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:277
|
||||
#: object.cc:291
|
||||
#, c-format
|
||||
msgid "%s: %s: section group %u info %u out of range\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:288
|
||||
#: object.cc:302
|
||||
#, c-format
|
||||
msgid "%s; %s: symtab section %u link %u out of range\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:304
|
||||
#: object.cc:318
|
||||
#, c-format
|
||||
msgid "%s: %s: symbol %u name offset %u out of range\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:352
|
||||
#: object.cc:367
|
||||
#, c-format
|
||||
msgid "%s: %s: section %u in section group %u out of range"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:486
|
||||
#: object.cc:515
|
||||
#, c-format
|
||||
msgid "%s: %s: size of symbols is not multiple of symbol size\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:573
|
||||
#: object.cc:601
|
||||
#, c-format
|
||||
msgid "%s: %s: unknown section index %u for local symbol %u\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:584
|
||||
#: object.cc:612
|
||||
#, c-format
|
||||
msgid "%s: %s: local symbol %u section index %u out of range\n"
|
||||
msgstr ""
|
||||
|
||||
#. elfcpp::ET_DYN
|
||||
#: object.cc:763
|
||||
#: object.cc:800
|
||||
#, c-format
|
||||
msgid "%s: %s: dynamic objects are not yet supported\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:787 object.cc:840 object.cc:861
|
||||
#: object.cc:824 object.cc:877 object.cc:898
|
||||
#, c-format
|
||||
msgid "%s: %s: ELF file too short\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:796
|
||||
#: object.cc:833
|
||||
#, c-format
|
||||
msgid "%s: %s: invalid ELF version 0\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:799
|
||||
#: object.cc:836
|
||||
#, c-format
|
||||
msgid "%s: %s: unsupported ELF version %d\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:807
|
||||
#: object.cc:844
|
||||
#, c-format
|
||||
msgid "%s: %s: invalid ELF class 0\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:814
|
||||
#: object.cc:851
|
||||
#, c-format
|
||||
msgid "%s: %s: unsupported ELF class %d\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:822
|
||||
#: object.cc:859
|
||||
#, c-format
|
||||
msgid "%s: %s: invalid ELF data encoding\n"
|
||||
msgstr ""
|
||||
|
||||
#: object.cc:829
|
||||
#: object.cc:866
|
||||
#, c-format
|
||||
msgid "%s: %s: unsupported ELF data encoding %d\n"
|
||||
msgstr ""
|
||||
@ -436,13 +436,13 @@ msgstr ""
|
||||
msgid "%s: %s: close: %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: readsyms.cc:84
|
||||
#: readsyms.cc:85
|
||||
#, c-format
|
||||
msgid "%s: %s: ordinary object found in input group\n"
|
||||
msgstr ""
|
||||
|
||||
#. Here we have to handle any other input file types we need.
|
||||
#: readsyms.cc:126
|
||||
#: readsyms.cc:129
|
||||
#, c-format
|
||||
msgid "%s: %s: not an object or archive\n"
|
||||
msgstr ""
|
||||
@ -477,21 +477,26 @@ msgstr ""
|
||||
msgid "%s: %s: unsupported symbol binding %d for symbol %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: symtab.cc:429
|
||||
#: symtab.cc:432
|
||||
#, c-format
|
||||
msgid "%s: %s: mixing 32-bit and 64-bit ELF objects\n"
|
||||
msgstr ""
|
||||
|
||||
#: symtab.cc:446
|
||||
#: symtab.cc:449
|
||||
#, c-format
|
||||
msgid "%s: %s: bad global symbol name offset %u at %lu\n"
|
||||
msgstr ""
|
||||
|
||||
#: symtab.cc:854 symtab.cc:989
|
||||
#: symtab.cc:865 symtab.cc:1004
|
||||
#, c-format
|
||||
msgid "%s: %s: unsupported symbol section 0x%x\n"
|
||||
msgstr ""
|
||||
|
||||
#: symtab.cc:1114
|
||||
#, c-format
|
||||
msgid "%s: %s: warning: %s\n"
|
||||
msgstr ""
|
||||
|
||||
#: target-reloc.h:181
|
||||
#, c-format
|
||||
msgid "%s: %s: reloc has bad offset %zu\n"
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "elfcpp.h"
|
||||
#include "options.h"
|
||||
#include "dirsearch.h"
|
||||
#include "symtab.h"
|
||||
#include "object.h"
|
||||
#include "archive.h"
|
||||
#include "readsyms.h"
|
||||
@ -91,7 +92,8 @@ Read_symbols::run(Workqueue* workqueue)
|
||||
|
||||
Read_symbols_data* sd = new Read_symbols_data;
|
||||
obj->read_symbols(sd);
|
||||
workqueue->queue_front(new Add_symbols(this->input_objects_,
|
||||
workqueue->queue_front(new Add_symbols(this->options_,
|
||||
this->input_objects_,
|
||||
this->symtab_, this->layout_,
|
||||
obj, sd,
|
||||
this->this_blocker_,
|
||||
@ -111,7 +113,8 @@ Read_symbols::run(Workqueue* workqueue)
|
||||
// This is an archive.
|
||||
Archive* arch = new Archive(this->input_.file().name(), input_file);
|
||||
arch->setup();
|
||||
workqueue->queue(new Add_archive_symbols(this->symtab_,
|
||||
workqueue->queue(new Add_archive_symbols(this->options_,
|
||||
this->symtab_,
|
||||
this->layout_,
|
||||
this->input_objects_,
|
||||
arch,
|
||||
@ -159,7 +162,8 @@ Read_symbols::do_group(Workqueue* workqueue)
|
||||
}
|
||||
|
||||
const int saw_undefined = this->symtab_->saw_undefined();
|
||||
workqueue->queue(new Finish_group(this->input_objects_,
|
||||
workqueue->queue(new Finish_group(this->options_,
|
||||
this->input_objects_,
|
||||
this->symtab_,
|
||||
this->layout_,
|
||||
input_group,
|
||||
@ -217,7 +221,8 @@ void
|
||||
Add_symbols::run(Workqueue*)
|
||||
{
|
||||
this->input_objects_->add_object(this->object_);
|
||||
this->object_->layout(this->layout_, this->sd_);
|
||||
this->object_->layout(this->options_, this->symtab_, this->layout_,
|
||||
this->sd_);
|
||||
this->object_->add_symbols(this->symtab_, this->sd_);
|
||||
delete this->sd_;
|
||||
this->sd_ = NULL;
|
||||
@ -265,7 +270,7 @@ Finish_group::run(Workqueue*)
|
||||
{
|
||||
Task_lock_obj<Archive> tl(**p);
|
||||
|
||||
(*p)->add_symbols(this->symtab_, this->layout_,
|
||||
(*p)->add_symbols(this->options_, this->symtab_, this->layout_,
|
||||
this->input_objects_);
|
||||
}
|
||||
}
|
||||
|
@ -83,11 +83,12 @@ class Add_symbols : public Task
|
||||
// THIS_BLOCKER is used to prevent this task from running before the
|
||||
// one for the previous input file. NEXT_BLOCKER is used to prevent
|
||||
// the next task from running.
|
||||
Add_symbols(Input_objects* input_objects, Symbol_table* symtab,
|
||||
Layout* layout, Object* object, Read_symbols_data* sd,
|
||||
Task_token* this_blocker, Task_token* next_blocker)
|
||||
: input_objects_(input_objects), symtab_(symtab), layout_(layout),
|
||||
object_(object), sd_(sd), this_blocker_(this_blocker),
|
||||
Add_symbols(const General_options& options, Input_objects* input_objects,
|
||||
Symbol_table* symtab, Layout* layout, Object* object,
|
||||
Read_symbols_data* sd, Task_token* this_blocker,
|
||||
Task_token* next_blocker)
|
||||
: options_(options), input_objects_(input_objects), symtab_(symtab),
|
||||
layout_(layout), object_(object), sd_(sd), this_blocker_(this_blocker),
|
||||
next_blocker_(next_blocker)
|
||||
{ }
|
||||
|
||||
@ -107,6 +108,7 @@ class Add_symbols : public Task
|
||||
private:
|
||||
class Add_symbols_locker;
|
||||
|
||||
const General_options& options_;
|
||||
Input_objects* input_objects_;
|
||||
Symbol_table* symtab_;
|
||||
Layout* layout_;
|
||||
@ -153,13 +155,14 @@ class Input_group
|
||||
class Finish_group : public Task
|
||||
{
|
||||
public:
|
||||
Finish_group(Input_objects* input_objects, Symbol_table* symtab,
|
||||
Layout* layout, Input_group* input_group,
|
||||
Finish_group(const General_options& options, Input_objects* input_objects,
|
||||
Symbol_table* symtab, Layout* layout, Input_group* input_group,
|
||||
int saw_undefined, Task_token* this_blocker,
|
||||
Task_token* next_blocker)
|
||||
: input_objects_(input_objects), symtab_(symtab), layout_(layout),
|
||||
input_group_(input_group), saw_undefined_(saw_undefined),
|
||||
this_blocker_(this_blocker), next_blocker_(next_blocker)
|
||||
: options_(options), input_objects_(input_objects), symtab_(symtab),
|
||||
layout_(layout), input_group_(input_group),
|
||||
saw_undefined_(saw_undefined), this_blocker_(this_blocker),
|
||||
next_blocker_(next_blocker)
|
||||
{ }
|
||||
|
||||
~Finish_group();
|
||||
@ -176,6 +179,7 @@ class Finish_group : public Task
|
||||
run(Workqueue*);
|
||||
|
||||
private:
|
||||
const General_options& options_;
|
||||
Input_objects* input_objects_;
|
||||
Symbol_table* symtab_;
|
||||
Layout* layout_;
|
||||
|
@ -140,7 +140,7 @@ Relocate_task::run(Workqueue*)
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Sized_object<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
|
||||
Sized_relobj<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
|
||||
{
|
||||
rd->relocs.clear();
|
||||
|
||||
@ -248,7 +248,7 @@ Sized_object<size, big_endian>::do_read_relocs(Read_relocs_data* rd)
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Sized_object<size, big_endian>::do_scan_relocs(const General_options& options,
|
||||
Sized_relobj<size, big_endian>::do_scan_relocs(const General_options& options,
|
||||
Symbol_table* symtab,
|
||||
Layout* layout,
|
||||
Read_relocs_data* rd)
|
||||
@ -285,7 +285,7 @@ Sized_object<size, big_endian>::do_scan_relocs(const General_options& options,
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Sized_object<size, big_endian>::do_relocate(const General_options& options,
|
||||
Sized_relobj<size, big_endian>::do_relocate(const General_options& options,
|
||||
const Symbol_table* symtab,
|
||||
const Layout* layout,
|
||||
Output_file* of)
|
||||
@ -327,7 +327,7 @@ Sized_object<size, big_endian>::do_relocate(const General_options& options,
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Sized_object<size, big_endian>::write_sections(const unsigned char* pshdrs,
|
||||
Sized_relobj<size, big_endian>::write_sections(const unsigned char* pshdrs,
|
||||
Output_file* of,
|
||||
Views* pviews)
|
||||
{
|
||||
@ -374,7 +374,7 @@ Sized_object<size, big_endian>::write_sections(const unsigned char* pshdrs,
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Sized_object<size, big_endian>::relocate_sections(
|
||||
Sized_relobj<size, big_endian>::relocate_sections(
|
||||
const General_options& options,
|
||||
const Symbol_table* symtab,
|
||||
const Layout* layout,
|
||||
@ -475,72 +475,72 @@ Sized_object<size, big_endian>::relocate_sections(
|
||||
|
||||
template
|
||||
void
|
||||
Sized_object<32, false>::do_read_relocs(Read_relocs_data* rd);
|
||||
Sized_relobj<32, false>::do_read_relocs(Read_relocs_data* rd);
|
||||
|
||||
template
|
||||
void
|
||||
Sized_object<32, true>::do_read_relocs(Read_relocs_data* rd);
|
||||
Sized_relobj<32, true>::do_read_relocs(Read_relocs_data* rd);
|
||||
|
||||
template
|
||||
void
|
||||
Sized_object<64, false>::do_read_relocs(Read_relocs_data* rd);
|
||||
Sized_relobj<64, false>::do_read_relocs(Read_relocs_data* rd);
|
||||
|
||||
template
|
||||
void
|
||||
Sized_object<64, true>::do_read_relocs(Read_relocs_data* rd);
|
||||
Sized_relobj<64, true>::do_read_relocs(Read_relocs_data* rd);
|
||||
|
||||
template
|
||||
void
|
||||
Sized_object<32, false>::do_scan_relocs(const General_options& options,
|
||||
Sized_relobj<32, false>::do_scan_relocs(const General_options& options,
|
||||
Symbol_table* symtab,
|
||||
Layout* layout,
|
||||
Read_relocs_data* rd);
|
||||
|
||||
template
|
||||
void
|
||||
Sized_object<32, true>::do_scan_relocs(const General_options& options,
|
||||
Sized_relobj<32, true>::do_scan_relocs(const General_options& options,
|
||||
Symbol_table* symtab,
|
||||
Layout* layout,
|
||||
Read_relocs_data* rd);
|
||||
|
||||
template
|
||||
void
|
||||
Sized_object<64, false>::do_scan_relocs(const General_options& options,
|
||||
Sized_relobj<64, false>::do_scan_relocs(const General_options& options,
|
||||
Symbol_table* symtab,
|
||||
Layout* layout,
|
||||
Read_relocs_data* rd);
|
||||
|
||||
template
|
||||
void
|
||||
Sized_object<64, true>::do_scan_relocs(const General_options& options,
|
||||
Sized_relobj<64, true>::do_scan_relocs(const General_options& options,
|
||||
Symbol_table* symtab,
|
||||
Layout* layout,
|
||||
Read_relocs_data* rd);
|
||||
|
||||
template
|
||||
void
|
||||
Sized_object<32, false>::do_relocate(const General_options& options,
|
||||
Sized_relobj<32, false>::do_relocate(const General_options& options,
|
||||
const Symbol_table* symtab,
|
||||
const Layout* layout,
|
||||
Output_file* of);
|
||||
|
||||
template
|
||||
void
|
||||
Sized_object<32, true>::do_relocate(const General_options& options,
|
||||
Sized_relobj<32, true>::do_relocate(const General_options& options,
|
||||
const Symbol_table* symtab,
|
||||
const Layout* layout,
|
||||
Output_file* of);
|
||||
|
||||
template
|
||||
void
|
||||
Sized_object<64, false>::do_relocate(const General_options& options,
|
||||
Sized_relobj<64, false>::do_relocate(const General_options& options,
|
||||
const Symbol_table* symtab,
|
||||
const Layout* layout,
|
||||
Output_file* of);
|
||||
|
||||
template
|
||||
void
|
||||
Sized_object<64, true>::do_relocate(const General_options& options,
|
||||
Sized_relobj<64, true>::do_relocate(const General_options& options,
|
||||
const Symbol_table* symtab,
|
||||
const Layout* layout,
|
||||
Output_file* of);
|
||||
|
352
gold/reloc.h
352
gold/reloc.h
@ -10,7 +10,7 @@
|
||||
namespace gold
|
||||
{
|
||||
|
||||
class Object;
|
||||
class Relobj;
|
||||
class Read_relocs_data;
|
||||
class Stringpool;
|
||||
class Layout;
|
||||
@ -25,7 +25,7 @@ class Read_relocs : public Task
|
||||
// SYMTAB_LOCK is used to lock the symbol table. BLOCKER should be
|
||||
// unblocked when the Scan_relocs task completes.
|
||||
Read_relocs(const General_options& options, Symbol_table* symtab,
|
||||
Layout* layout, Object* object, Task_token* symtab_lock,
|
||||
Layout* layout, Relobj* object, Task_token* symtab_lock,
|
||||
Task_token* blocker)
|
||||
: options_(options), symtab_(symtab), layout_(layout), object_(object),
|
||||
symtab_lock_(symtab_lock), blocker_(blocker)
|
||||
@ -46,7 +46,7 @@ class Read_relocs : public Task
|
||||
const General_options& options_;
|
||||
Symbol_table* symtab_;
|
||||
Layout* layout_;
|
||||
Object* object_;
|
||||
Relobj* object_;
|
||||
Task_token* symtab_lock_;
|
||||
Task_token* blocker_;
|
||||
};
|
||||
@ -60,7 +60,7 @@ class Scan_relocs : public Task
|
||||
// SYMTAB_LOCK is used to lock the symbol table. BLOCKER should be
|
||||
// unblocked when the task completes.
|
||||
Scan_relocs(const General_options& options, Symbol_table* symtab,
|
||||
Layout* layout, Object* object, Read_relocs_data* rd,
|
||||
Layout* layout, Relobj* object, Read_relocs_data* rd,
|
||||
Task_token* symtab_lock, Task_token* blocker)
|
||||
: options_(options), symtab_(symtab), layout_(layout), object_(object),
|
||||
rd_(rd), symtab_lock_(symtab_lock), blocker_(blocker)
|
||||
@ -83,7 +83,7 @@ class Scan_relocs : public Task
|
||||
const General_options& options_;
|
||||
Symbol_table* symtab_;
|
||||
Layout* layout_;
|
||||
Object* object_;
|
||||
Relobj* object_;
|
||||
Read_relocs_data* rd_;
|
||||
Task_token* symtab_lock_;
|
||||
Task_token* blocker_;
|
||||
@ -95,7 +95,7 @@ class Relocate_task : public Task
|
||||
{
|
||||
public:
|
||||
Relocate_task(const General_options& options, const Symbol_table* symtab,
|
||||
const Layout* layout, Object* object, Output_file* of,
|
||||
const Layout* layout, Relobj* object, Output_file* of,
|
||||
Task_token* final_blocker)
|
||||
: options_(options), symtab_(symtab), layout_(layout), object_(object),
|
||||
of_(of), final_blocker_(final_blocker)
|
||||
@ -118,327 +118,11 @@ class Relocate_task : public Task
|
||||
const General_options& options_;
|
||||
const Symbol_table* symtab_;
|
||||
const Layout* layout_;
|
||||
Object* object_;
|
||||
Relobj* object_;
|
||||
Output_file* of_;
|
||||
Task_token* final_blocker_;
|
||||
};
|
||||
|
||||
// Integer swapping routines used by relocation functions. FIXME:
|
||||
// Maybe these should be more general, and/or shared with elfcpp.
|
||||
|
||||
// Endian simply indicates whether the host is big endian or not,
|
||||
// based on the results of the configure script.
|
||||
|
||||
struct Endian
|
||||
{
|
||||
public:
|
||||
// Used for template specializations.
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
static const bool host_big_endian = true;
|
||||
#else
|
||||
static const bool host_big_endian = false;
|
||||
#endif
|
||||
};
|
||||
|
||||
// Valtype_base is a template based on size (8, 16, 32, 64) which
|
||||
// defines a typedef Valtype for the unsigned integer of the specified
|
||||
// size.
|
||||
|
||||
template<int size>
|
||||
struct Valtype_base;
|
||||
|
||||
template<>
|
||||
struct Valtype_base<8>
|
||||
{
|
||||
typedef unsigned char Valtype;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Valtype_base<16>
|
||||
{
|
||||
typedef uint16_t Valtype;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Valtype_base<32>
|
||||
{
|
||||
typedef uint32_t Valtype;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Valtype_base<64>
|
||||
{
|
||||
typedef uint64_t Valtype;
|
||||
};
|
||||
|
||||
// Convert_host is a template based on size and on whether the host
|
||||
// and target have the same endianness. It defines the type Valtype,
|
||||
// and defines a function convert_host which takes an argument of type
|
||||
// Valtype and swaps it if the host and target have different
|
||||
// endianness.
|
||||
|
||||
template<int size, bool same_endian>
|
||||
struct Convert_host;
|
||||
|
||||
template<int size>
|
||||
struct Convert_host<size, true>
|
||||
{
|
||||
typedef typename Valtype_base<size>::Valtype Valtype;
|
||||
|
||||
static inline Valtype
|
||||
convert_host(Valtype v)
|
||||
{ return v; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Convert_host<8, false>
|
||||
{
|
||||
typedef Valtype_base<8>::Valtype Valtype;
|
||||
|
||||
static inline Valtype
|
||||
convert_host(Valtype v)
|
||||
{ return v; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Convert_host<16, false>
|
||||
{
|
||||
typedef Valtype_base<16>::Valtype Valtype;
|
||||
|
||||
static inline Valtype
|
||||
convert_host(Valtype v)
|
||||
{ return bswap_16(v); }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Convert_host<32, false>
|
||||
{
|
||||
typedef Valtype_base<32>::Valtype Valtype;
|
||||
|
||||
static inline Valtype
|
||||
convert_host(Valtype v)
|
||||
{ return bswap_32(v); }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Convert_host<64, false>
|
||||
{
|
||||
typedef Valtype_base<64>::Valtype Valtype;
|
||||
|
||||
static inline Valtype
|
||||
convert_host(Valtype v)
|
||||
{ return bswap_64(v); }
|
||||
};
|
||||
|
||||
// Convert is a template based on size and on whether we have a big
|
||||
// endian target. It defines Valtype and convert_host like
|
||||
// Convert_host. That is, it is just like Convert_host except in the
|
||||
// meaning of the second template parameter.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
struct Convert
|
||||
{
|
||||
typedef typename Valtype_base<size>::Valtype Valtype;
|
||||
|
||||
static inline Valtype
|
||||
convert_host(Valtype v)
|
||||
{ return Convert_host<size, big_endian == Endian::host_big_endian>
|
||||
::convert_host(v); }
|
||||
};
|
||||
|
||||
// Swap is a template based on size and on whether the target is big
|
||||
// endian. It defines the type Valtype and the functions readval and
|
||||
// writeval. The functions read and write values of the appropriate
|
||||
// size out of buffers, swapping them if necessary.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
struct Swap
|
||||
{
|
||||
typedef typename Valtype_base<size>::Valtype Valtype;
|
||||
|
||||
static inline Valtype
|
||||
readval(const Valtype* wv)
|
||||
{ return Convert<size, big_endian>::convert_host(*wv); }
|
||||
|
||||
static inline void
|
||||
writeval(Valtype* wv, Valtype v)
|
||||
{ *wv = Convert<size, big_endian>::convert_host(v); }
|
||||
};
|
||||
|
||||
// Swap_unaligned is a template based on size and on whether the
|
||||
// target is big endian. It defines the type Valtype and the
|
||||
// functions readval_unaligned and writeval_unaligned. The functions
|
||||
// read and write values of the appropriate size out of buffers which
|
||||
// may be misaligned.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
class Swap_unaligned;
|
||||
|
||||
template<bool big_endian>
|
||||
class Swap_unaligned<8, big_endian>
|
||||
{
|
||||
public:
|
||||
typedef typename Valtype_base<8>::Valtype Valtype;
|
||||
|
||||
static inline Valtype
|
||||
readval_unaligned(const unsigned char* wv)
|
||||
{ return *wv; }
|
||||
|
||||
static inline void
|
||||
writeval_unaligned(unsigned char* wv, Valtype v)
|
||||
{ *wv = v; }
|
||||
};
|
||||
|
||||
template<>
|
||||
class Swap_unaligned<16, false>
|
||||
{
|
||||
public:
|
||||
typedef Valtype_base<16>::Valtype Valtype;
|
||||
|
||||
static inline Valtype
|
||||
readval_unaligned(const unsigned char* wv)
|
||||
{
|
||||
return (wv[1] << 8) | wv[0];
|
||||
}
|
||||
|
||||
static inline void
|
||||
writeval_unaligned(unsigned char* wv, Valtype v)
|
||||
{
|
||||
wv[1] = v >> 8;
|
||||
wv[0] = v;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class Swap_unaligned<16, true>
|
||||
{
|
||||
public:
|
||||
typedef Valtype_base<16>::Valtype Valtype;
|
||||
|
||||
static inline Valtype
|
||||
readval_unaligned(const unsigned char* wv)
|
||||
{
|
||||
return (wv[0] << 8) | wv[1];
|
||||
}
|
||||
|
||||
static inline void
|
||||
writeval_unaligned(unsigned char* wv, Valtype v)
|
||||
{
|
||||
wv[0] = v >> 8;
|
||||
wv[1] = v;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class Swap_unaligned<32, false>
|
||||
{
|
||||
public:
|
||||
typedef Valtype_base<32>::Valtype Valtype;
|
||||
|
||||
static inline Valtype
|
||||
readval_unaligned(const unsigned char* wv)
|
||||
{
|
||||
return (wv[3] << 24) | (wv[2] << 16) | (wv[1] << 8) | wv[0];
|
||||
}
|
||||
|
||||
static inline void
|
||||
writeval_unaligned(unsigned char* wv, Valtype v)
|
||||
{
|
||||
wv[3] = v >> 24;
|
||||
wv[2] = v >> 16;
|
||||
wv[1] = v >> 8;
|
||||
wv[0] = v;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class Swap_unaligned<32, true>
|
||||
{
|
||||
public:
|
||||
typedef Valtype_base<32>::Valtype Valtype;
|
||||
|
||||
static inline Valtype
|
||||
readval_unaligned(const unsigned char* wv)
|
||||
{
|
||||
return (wv[0] << 24) | (wv[1] << 16) | (wv[2] << 8) | wv[3];
|
||||
}
|
||||
|
||||
static inline void
|
||||
writeval_unaligned(unsigned char* wv, Valtype v)
|
||||
{
|
||||
wv[0] = v >> 24;
|
||||
wv[1] = v >> 16;
|
||||
wv[2] = v >> 8;
|
||||
wv[3] = v;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class Swap_unaligned<64, false>
|
||||
{
|
||||
public:
|
||||
typedef Valtype_base<64>::Valtype Valtype;
|
||||
|
||||
static inline Valtype
|
||||
readval_unaligned(const unsigned char* wv)
|
||||
{
|
||||
return ((static_cast<Valtype>(wv[7]) << 56)
|
||||
| (static_cast<Valtype>(wv[6]) << 48)
|
||||
| (static_cast<Valtype>(wv[5]) << 40)
|
||||
| (static_cast<Valtype>(wv[4]) << 32)
|
||||
| (static_cast<Valtype>(wv[3]) << 24)
|
||||
| (static_cast<Valtype>(wv[2]) << 16)
|
||||
| (static_cast<Valtype>(wv[1]) << 8)
|
||||
| static_cast<Valtype>(wv[0]));
|
||||
}
|
||||
|
||||
static inline void
|
||||
writeval_unaligned(unsigned char* wv, Valtype v)
|
||||
{
|
||||
wv[7] = v >> 56;
|
||||
wv[6] = v >> 48;
|
||||
wv[5] = v >> 40;
|
||||
wv[4] = v >> 32;
|
||||
wv[3] = v >> 24;
|
||||
wv[2] = v >> 16;
|
||||
wv[1] = v >> 8;
|
||||
wv[0] = v;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class Swap_unaligned<64, true>
|
||||
{
|
||||
public:
|
||||
typedef Valtype_base<64>::Valtype Valtype;
|
||||
|
||||
static inline Valtype
|
||||
readval_unaligned(const unsigned char* wv)
|
||||
{
|
||||
return ((static_cast<Valtype>(wv[0]) << 56)
|
||||
| (static_cast<Valtype>(wv[1]) << 48)
|
||||
| (static_cast<Valtype>(wv[2]) << 40)
|
||||
| (static_cast<Valtype>(wv[3]) << 32)
|
||||
| (static_cast<Valtype>(wv[4]) << 24)
|
||||
| (static_cast<Valtype>(wv[5]) << 16)
|
||||
| (static_cast<Valtype>(wv[6]) << 8)
|
||||
| static_cast<Valtype>(wv[7]));
|
||||
}
|
||||
|
||||
static inline void
|
||||
writeval_unaligned(unsigned char* wv, Valtype v)
|
||||
{
|
||||
wv[7] = v >> 56;
|
||||
wv[6] = v >> 48;
|
||||
wv[5] = v >> 40;
|
||||
wv[4] = v >> 32;
|
||||
wv[3] = v >> 24;
|
||||
wv[2] = v >> 16;
|
||||
wv[1] = v >> 8;
|
||||
wv[0] = v;
|
||||
}
|
||||
};
|
||||
|
||||
// Standard relocation routines which are used on many targets. Here
|
||||
// SIZE and BIG_ENDIAN refer to the target, not the relocation type.
|
||||
|
||||
@ -450,25 +134,27 @@ private:
|
||||
// VALSIZE is the size of the value.
|
||||
template<int valsize>
|
||||
static inline void
|
||||
rel(unsigned char* view, typename Swap<valsize, big_endian>::Valtype value)
|
||||
rel(unsigned char* view,
|
||||
typename elfcpp::Swap<valsize, big_endian>::Valtype value)
|
||||
{
|
||||
typedef typename Swap<valsize, big_endian>::Valtype Valtype;
|
||||
typedef typename elfcpp::Swap<valsize, big_endian>::Valtype Valtype;
|
||||
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
||||
Valtype x = Swap<valsize, big_endian>::readval(wv);
|
||||
Swap<valsize, big_endian>::writeval(wv, x + value);
|
||||
Valtype x = elfcpp::Swap<valsize, big_endian>::readval(wv);
|
||||
elfcpp::Swap<valsize, big_endian>::writeval(wv, x + value);
|
||||
}
|
||||
|
||||
// Do a simple PC relative relocation with the addend in the section
|
||||
// contents. VALSIZE is the size of the value.
|
||||
template<int valsize>
|
||||
static inline void
|
||||
pcrel(unsigned char* view, typename Swap<valsize, big_endian>::Valtype value,
|
||||
pcrel(unsigned char* view,
|
||||
typename elfcpp::Swap<valsize, big_endian>::Valtype value,
|
||||
typename elfcpp::Elf_types<size>::Elf_Addr address)
|
||||
{
|
||||
typedef typename Swap<valsize, big_endian>::Valtype Valtype;
|
||||
typedef typename elfcpp::Swap<valsize, big_endian>::Valtype Valtype;
|
||||
Valtype* wv = reinterpret_cast<Valtype*>(view);
|
||||
Valtype x = Swap<valsize, big_endian>::readval(wv);
|
||||
Swap<valsize, big_endian>::writeval(wv, x + value - address);
|
||||
Valtype x = elfcpp::Swap<valsize, big_endian>::readval(wv);
|
||||
elfcpp::Swap<valsize, big_endian>::writeval(wv, x + value - address);
|
||||
}
|
||||
|
||||
typedef Relocate_functions<size, big_endian> This;
|
||||
@ -528,7 +214,7 @@ public:
|
||||
// Do a simple 64-bit REL relocation with the addend in the section
|
||||
// contents.
|
||||
static inline void
|
||||
rel64(unsigned char* view, elfcpp::Elf_Word value)
|
||||
rel64(unsigned char* view, elfcpp::Elf_Xword value)
|
||||
{
|
||||
This::template rel<64>(view, value);
|
||||
}
|
||||
@ -536,7 +222,7 @@ public:
|
||||
// Do a simple 64-bit PC relative REL relocation with the addend in
|
||||
// the section contents.
|
||||
static inline void
|
||||
pcrel64(unsigned char* view, elfcpp::Elf_Word value,
|
||||
pcrel64(unsigned char* view, elfcpp::Elf_Xword value,
|
||||
typename elfcpp::Elf_types<size>::Elf_Addr address)
|
||||
{
|
||||
This::template pcrel<64>(view, value, address);
|
||||
|
130
gold/symtab.cc
130
gold/symtab.cc
@ -37,6 +37,7 @@ Symbol::init_fields(const char* name, const char* version,
|
||||
this->is_forwarder_ = false;
|
||||
this->in_dyn_ = false;
|
||||
this->has_got_offset_ = false;
|
||||
this->has_warning_ = false;
|
||||
}
|
||||
|
||||
// Initialize the fields in the base class Symbol for SYM in OBJECT.
|
||||
@ -159,7 +160,7 @@ Sized_symbol<size>::init(const char* name, Value_type value, Size_type symsize,
|
||||
|
||||
Symbol_table::Symbol_table()
|
||||
: size_(0), saw_undefined_(0), offset_(0), table_(), namepool_(),
|
||||
forwarders_(), commons_()
|
||||
forwarders_(), commons_(), warnings_()
|
||||
{
|
||||
}
|
||||
|
||||
@ -279,7 +280,7 @@ Symbol_table::resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from
|
||||
|
||||
template<int size, bool big_endian>
|
||||
Symbol*
|
||||
Symbol_table::add_from_object(Sized_object<size, big_endian>* object,
|
||||
Symbol_table::add_from_object(Object* object,
|
||||
const char *name,
|
||||
const char *version, bool def,
|
||||
const elfcpp::Sym<size, big_endian>& sym)
|
||||
@ -360,7 +361,9 @@ Symbol_table::add_from_object(Sized_object<size, big_endian>* object,
|
||||
}
|
||||
else
|
||||
{
|
||||
Sized_target<size, big_endian>* target = object->sized_target();
|
||||
Sized_target<size, big_endian>* target =
|
||||
object->sized_target SELECT_SIZE_ENDIAN_NAME(size, big_endian) (
|
||||
SELECT_SIZE_ENDIAN_ONLY(size, big_endian));
|
||||
if (!target->has_make_symbol())
|
||||
ret = new Sized_symbol<size>();
|
||||
else
|
||||
@ -408,13 +411,13 @@ Symbol_table::add_from_object(Sized_object<size, big_endian>* object,
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Add all the symbols in an object to the hash table.
|
||||
// Add all the symbols in a relocatable object to the hash table.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Symbol_table::add_from_object(
|
||||
Sized_object<size, big_endian>* object,
|
||||
const elfcpp::Sym<size, big_endian>* syms,
|
||||
Relobj* object,
|
||||
const unsigned char* syms,
|
||||
size_t count,
|
||||
const char* sym_names,
|
||||
size_t sym_name_size,
|
||||
@ -433,7 +436,7 @@ Symbol_table::add_from_object(
|
||||
|
||||
const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
|
||||
|
||||
const unsigned char* p = reinterpret_cast<const unsigned char*>(syms);
|
||||
const unsigned char* p = syms;
|
||||
for (size_t i = 0; i < count; ++i, p += sym_size)
|
||||
{
|
||||
elfcpp::Sym<size, big_endian> sym(p);
|
||||
@ -512,7 +515,7 @@ Symbol_table::define_special_symbol(Target* target, const char* name,
|
||||
if (only_if_ref)
|
||||
{
|
||||
oldsym = this->lookup(name, NULL);
|
||||
if (oldsym == NULL)
|
||||
if (oldsym == NULL || !oldsym->is_undefined())
|
||||
return NULL;
|
||||
sym = NULL;
|
||||
|
||||
@ -810,12 +813,20 @@ Symbol_table::define_symbols(const Layout* layout, Target* target, int count,
|
||||
off_t
|
||||
Symbol_table::finalize(off_t off, Stringpool* pool)
|
||||
{
|
||||
off_t ret;
|
||||
|
||||
if (this->size_ == 32)
|
||||
return this->sized_finalize<32>(off, pool);
|
||||
ret = this->sized_finalize<32>(off, pool);
|
||||
else if (this->size_ == 64)
|
||||
return this->sized_finalize<64>(off, pool);
|
||||
ret = this->sized_finalize<64>(off, pool);
|
||||
else
|
||||
abort();
|
||||
|
||||
// Now that we have the final symbol table, we can reliably note
|
||||
// which symbols should get warnings.
|
||||
this->warnings_.note_warnings(this);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Set the final value for all the symbols. This is called after
|
||||
@ -856,15 +867,21 @@ Symbol_table::sized_finalize(off_t off, Stringpool* pool)
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
if (shnum == elfcpp::SHN_UNDEF)
|
||||
Object* symobj = sym->object();
|
||||
if (symobj->is_dynamic())
|
||||
{
|
||||
value = 0;
|
||||
shnum = elfcpp::SHN_UNDEF;
|
||||
}
|
||||
else if (shnum == elfcpp::SHN_UNDEF)
|
||||
value = 0;
|
||||
else if (shnum == elfcpp::SHN_ABS)
|
||||
value = sym->value();
|
||||
else
|
||||
{
|
||||
Relobj* relobj = static_cast<Relobj*>(symobj);
|
||||
off_t secoff;
|
||||
Output_section* os = sym->object()->output_section(shnum,
|
||||
&secoff);
|
||||
Output_section* os = relobj->output_section(shnum, &secoff);
|
||||
|
||||
if (os == NULL)
|
||||
{
|
||||
@ -973,8 +990,6 @@ Symbol_table::sized_write_globals(const Target*,
|
||||
{
|
||||
Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(p->second);
|
||||
|
||||
// FIXME: This repeats sized_finalize().
|
||||
|
||||
unsigned int shndx;
|
||||
switch (sym->source())
|
||||
{
|
||||
@ -991,13 +1006,19 @@ Symbol_table::sized_write_globals(const Target*,
|
||||
gold_exit(false);
|
||||
}
|
||||
|
||||
if (shnum == elfcpp::SHN_UNDEF || shnum == elfcpp::SHN_ABS)
|
||||
Object* symobj = sym->object();
|
||||
if (symobj->is_dynamic())
|
||||
{
|
||||
// FIXME.
|
||||
shndx = elfcpp::SHN_UNDEF;
|
||||
}
|
||||
else if (shnum == elfcpp::SHN_UNDEF || shnum == elfcpp::SHN_ABS)
|
||||
shndx = shnum;
|
||||
else
|
||||
{
|
||||
Relobj* relobj = static_cast<Relobj*>(symobj);
|
||||
off_t secoff;
|
||||
Output_section* os = sym->object()->output_section(shnum,
|
||||
&secoff);
|
||||
Output_section* os = relobj->output_section(shnum, &secoff);
|
||||
if (os == NULL)
|
||||
continue;
|
||||
|
||||
@ -1037,6 +1058,63 @@ Symbol_table::sized_write_globals(const Target*,
|
||||
of->write_output_view(this->offset_, this->output_count_ * sym_size, psyms);
|
||||
}
|
||||
|
||||
// Warnings functions.
|
||||
|
||||
// Add a new warning.
|
||||
|
||||
void
|
||||
Warnings::add_warning(Symbol_table* symtab, const char* name, Object* obj,
|
||||
unsigned int shndx)
|
||||
{
|
||||
name = symtab->canonicalize_name(name);
|
||||
this->warnings_[name].set(obj, shndx);
|
||||
}
|
||||
|
||||
// Look through the warnings and mark the symbols for which we should
|
||||
// warn. This is called during Layout::finalize when we know the
|
||||
// sources for all the symbols.
|
||||
|
||||
void
|
||||
Warnings::note_warnings(Symbol_table* symtab)
|
||||
{
|
||||
for (Warning_table::iterator p = this->warnings_.begin();
|
||||
p != this->warnings_.end();
|
||||
++p)
|
||||
{
|
||||
Symbol* sym = symtab->lookup(p->first, NULL);
|
||||
if (sym != NULL
|
||||
&& sym->source() == Symbol::FROM_OBJECT
|
||||
&& sym->object() == p->second.object)
|
||||
{
|
||||
sym->set_has_warning();
|
||||
|
||||
// Read the section contents to get the warning text. It
|
||||
// would be nicer if we only did this if we have to actually
|
||||
// issue a warning. Unfortunately, warnings are issued as
|
||||
// we relocate sections. That means that we can not lock
|
||||
// the object then, as we might try to issue the same
|
||||
// warning multiple times simultaneously.
|
||||
const unsigned char* c;
|
||||
off_t len;
|
||||
c = p->second.object->section_contents(p->second.shndx, &len);
|
||||
p->second.set_text(reinterpret_cast<const char*>(c), len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Issue a warning. This is called when we see a relocation against a
|
||||
// symbol for which has a warning.
|
||||
|
||||
void
|
||||
Warnings::issue_warning(Symbol* sym, const std::string& location) const
|
||||
{
|
||||
assert(sym->has_warning());
|
||||
Warning_table::const_iterator p = this->warnings_.find(sym->name());
|
||||
assert(p != this->warnings_.end());
|
||||
fprintf(stderr, _("%s: %s: warning: %s\n"), program_name, location.c_str(),
|
||||
p->second.text.c_str());
|
||||
}
|
||||
|
||||
// Instantiate the templates we need. We could use the configure
|
||||
// script to restrict this to only the ones needed for implemented
|
||||
// targets.
|
||||
@ -1044,8 +1122,8 @@ Symbol_table::sized_write_globals(const Target*,
|
||||
template
|
||||
void
|
||||
Symbol_table::add_from_object<32, true>(
|
||||
Sized_object<32, true>* object,
|
||||
const elfcpp::Sym<32, true>* syms,
|
||||
Relobj* object,
|
||||
const unsigned char* syms,
|
||||
size_t count,
|
||||
const char* sym_names,
|
||||
size_t sym_name_size,
|
||||
@ -1054,8 +1132,8 @@ Symbol_table::add_from_object<32, true>(
|
||||
template
|
||||
void
|
||||
Symbol_table::add_from_object<32, false>(
|
||||
Sized_object<32, false>* object,
|
||||
const elfcpp::Sym<32, false>* syms,
|
||||
Relobj* object,
|
||||
const unsigned char* syms,
|
||||
size_t count,
|
||||
const char* sym_names,
|
||||
size_t sym_name_size,
|
||||
@ -1064,8 +1142,8 @@ Symbol_table::add_from_object<32, false>(
|
||||
template
|
||||
void
|
||||
Symbol_table::add_from_object<64, true>(
|
||||
Sized_object<64, true>* object,
|
||||
const elfcpp::Sym<64, true>* syms,
|
||||
Relobj* object,
|
||||
const unsigned char* syms,
|
||||
size_t count,
|
||||
const char* sym_names,
|
||||
size_t sym_name_size,
|
||||
@ -1074,8 +1152,8 @@ Symbol_table::add_from_object<64, true>(
|
||||
template
|
||||
void
|
||||
Symbol_table::add_from_object<64, false>(
|
||||
Sized_object<64, false>* object,
|
||||
const elfcpp::Sym<64, false>* syms,
|
||||
Relobj* object,
|
||||
const unsigned char* syms,
|
||||
size_t count,
|
||||
const char* sym_names,
|
||||
size_t sym_name_size,
|
||||
|
151
gold/symtab.h
151
gold/symtab.h
@ -10,6 +10,7 @@
|
||||
|
||||
#include "elfcpp.h"
|
||||
#include "stringpool.h"
|
||||
#include "object.h"
|
||||
|
||||
#ifndef GOLD_SYMTAB_H
|
||||
#define GOLD_SYMTAB_H
|
||||
@ -18,14 +19,13 @@ namespace gold
|
||||
{
|
||||
|
||||
class Object;
|
||||
class Relobj;
|
||||
class Dynobj;
|
||||
class Output_data;
|
||||
class Output_segment;
|
||||
class Output_file;
|
||||
class Target;
|
||||
|
||||
template<int size, bool big_endian>
|
||||
class Sized_object;
|
||||
|
||||
// The base class of an entry in the symbol table. The symbol table
|
||||
// can have a lot of entries, so we don't want this class to big.
|
||||
// Size dependent fields can be found in the template class
|
||||
@ -40,7 +40,8 @@ class Symbol
|
||||
// sources of symbols we support.
|
||||
enum Source
|
||||
{
|
||||
// Symbol defined in an input file--this is the most common case.
|
||||
// Symbol defined in a relocatable or dynamic input file--this is
|
||||
// the most common case.
|
||||
FROM_OBJECT,
|
||||
// Symbol defined in an Output_data, a special section created by
|
||||
// the target.
|
||||
@ -89,7 +90,8 @@ class Symbol
|
||||
return this->u_.from_object.object;
|
||||
}
|
||||
|
||||
// Return the index of the section in the input object file.
|
||||
// Return the index of the section in the input relocatable or
|
||||
// dynamic object file.
|
||||
unsigned int
|
||||
shnum() const
|
||||
{
|
||||
@ -167,12 +169,12 @@ class Symbol
|
||||
set_forwarder()
|
||||
{ this->is_forwarder_ = true; }
|
||||
|
||||
// Return whether this symbol was seen in a dynamic object.
|
||||
// Return whether this symbol was ever seen in a dynamic object.
|
||||
bool
|
||||
in_dyn() const
|
||||
{ return this->in_dyn_; }
|
||||
|
||||
// Mark this symbol as seen in a dynamic object.
|
||||
// Mark this symbol as having been seen in a dynamic object.
|
||||
void
|
||||
set_in_dyn()
|
||||
{ this->in_dyn_ = true; }
|
||||
@ -207,6 +209,16 @@ class Symbol
|
||||
is_resolved_locally() const
|
||||
{ return !this->in_dyn_; }
|
||||
|
||||
// Return whether this is a defined symbol (not undefined or
|
||||
// common).
|
||||
bool
|
||||
is_defined() const
|
||||
{
|
||||
return (this->source_ != FROM_OBJECT
|
||||
|| (this->u_.from_object.shnum != elfcpp::SHN_UNDEF
|
||||
&& this->u_.from_object.shnum != elfcpp::SHN_COMMON));
|
||||
}
|
||||
|
||||
// Return whether this is an undefined symbol.
|
||||
bool
|
||||
is_undefined() const
|
||||
@ -218,14 +230,27 @@ class Symbol
|
||||
bool
|
||||
is_common() const
|
||||
{
|
||||
return this->source_ == FROM_OBJECT && this->shnum() == elfcpp::SHN_COMMON;
|
||||
return (this->source_ == FROM_OBJECT
|
||||
&& (this->u_.from_object.shnum == elfcpp::SHN_COMMON
|
||||
|| this->type_ == elfcpp::STT_COMMON));
|
||||
}
|
||||
|
||||
// Return whether there should be a warning for references to this
|
||||
// symbol.
|
||||
bool
|
||||
has_warning() const
|
||||
{ return this->has_warning_; }
|
||||
|
||||
// Mark this symbol as having a warning.
|
||||
void
|
||||
set_has_warning()
|
||||
{ this->has_warning_ = true; }
|
||||
|
||||
protected:
|
||||
// Instances of this class should always be created at a specific
|
||||
// size.
|
||||
Symbol()
|
||||
{ }
|
||||
{ memset(this, 0, sizeof *this); }
|
||||
|
||||
// Initialize the general fields.
|
||||
void
|
||||
@ -317,7 +342,7 @@ class Symbol
|
||||
// Rest of symbol st_other field.
|
||||
unsigned int nonvis_ : 6;
|
||||
// The type of symbol.
|
||||
Source source_ : 2;
|
||||
Source source_ : 3;
|
||||
// True if this symbol always requires special target-specific
|
||||
// handling.
|
||||
bool is_target_special_ : 1;
|
||||
@ -335,6 +360,8 @@ class Symbol
|
||||
bool in_dyn_ : 1;
|
||||
// True if the symbol has an entry in the GOT section.
|
||||
bool has_got_offset_ : 1;
|
||||
// True if there is a warning for this symbol.
|
||||
bool has_warning_ : 1;
|
||||
};
|
||||
|
||||
// The parts of a symbol which are size specific. Using a template
|
||||
@ -484,6 +511,78 @@ struct Define_symbol_in_segment
|
||||
bool only_if_ref;
|
||||
};
|
||||
|
||||
// This class manages warnings. Warnings are a GNU extension. When
|
||||
// we see a section named .gnu.warning.SYM in an object file, and if
|
||||
// we wind using the definition of SYM from that object file, then we
|
||||
// will issue a warning for any relocation against SYM from a
|
||||
// different object file. The text of the warning is the contents of
|
||||
// the section. This is not precisely the definition used by the old
|
||||
// GNU linker; the old GNU linker treated an occurrence of
|
||||
// .gnu.warning.SYM as defining a warning symbol. A warning symbol
|
||||
// would trigger a warning on any reference. However, it was
|
||||
// inconsistent in that a warning in a dynamic object only triggered
|
||||
// if there was no definition in a regular object. This linker is
|
||||
// different in that we only issue a warning if we use the symbol
|
||||
// definition from the same object file as the warning section.
|
||||
|
||||
class Warnings
|
||||
{
|
||||
public:
|
||||
Warnings()
|
||||
: warnings_()
|
||||
{ }
|
||||
|
||||
// Add a warning for symbol NAME in section SHNDX in object OBJ.
|
||||
void
|
||||
add_warning(Symbol_table* symtab, const char* name, Object* obj,
|
||||
unsigned int shndx);
|
||||
|
||||
// For each symbol for which we should give a warning, make a note
|
||||
// on the symbol.
|
||||
void
|
||||
note_warnings(Symbol_table* symtab);
|
||||
|
||||
// Issue a warning for a reference to SYM at LOCATION.
|
||||
void
|
||||
issue_warning(Symbol* sym, const std::string& location) const;
|
||||
|
||||
private:
|
||||
Warnings(const Warnings&);
|
||||
Warnings& operator=(const Warnings&);
|
||||
|
||||
// What we need to know to get the warning text.
|
||||
struct Warning_location
|
||||
{
|
||||
// The object the warning is in.
|
||||
Object* object;
|
||||
// The index of the warning section.
|
||||
unsigned int shndx;
|
||||
// The warning text if we have already loaded it.
|
||||
std::string text;
|
||||
|
||||
Warning_location()
|
||||
: object(NULL), shndx(0), text()
|
||||
{ }
|
||||
|
||||
void
|
||||
set(Object* o, unsigned int s)
|
||||
{
|
||||
this->object = o;
|
||||
this->shndx = s;
|
||||
}
|
||||
|
||||
void
|
||||
set_text(const char* t, off_t l)
|
||||
{ this->text.assign(t, l); }
|
||||
};
|
||||
|
||||
// A mapping from warning symbol names (canonicalized in
|
||||
// Symbol_table's namepool_ field) to
|
||||
typedef Unordered_map<const char*, Warning_location> Warning_table;
|
||||
|
||||
Warning_table warnings_;
|
||||
};
|
||||
|
||||
// The main linker symbol table.
|
||||
|
||||
class Symbol_table
|
||||
@ -493,14 +592,13 @@ class Symbol_table
|
||||
|
||||
~Symbol_table();
|
||||
|
||||
// Add COUNT external symbols from OBJECT to the symbol table. SYMS
|
||||
// is the symbols, SYM_NAMES is their names, SYM_NAME_SIZE is the
|
||||
// size of SYM_NAMES. This sets SYMPOINTERS to point to the symbols
|
||||
// in the symbol table.
|
||||
// Add COUNT external symbols from the relocatable object OBJECT to
|
||||
// the symbol table. SYMS is the symbols, SYM_NAMES is their names,
|
||||
// SYM_NAME_SIZE is the size of SYM_NAMES. This sets SYMPOINTERS to
|
||||
// point to the symbols in the symbol table.
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
add_from_object(Sized_object<size, big_endian>* object,
|
||||
const elfcpp::Sym<size, big_endian>* syms,
|
||||
add_from_object(Relobj* object, const unsigned char* syms,
|
||||
size_t count, const char* sym_names, size_t sym_name_size,
|
||||
Symbol** sympointers);
|
||||
|
||||
@ -577,6 +675,22 @@ class Symbol_table
|
||||
void
|
||||
allocate_commons(const General_options&, Layout*);
|
||||
|
||||
// Add a warning for symbol NAME in section SHNDX in object OBJ.
|
||||
void
|
||||
add_warning(const char* name, Object* obj, unsigned int shndx)
|
||||
{ this->warnings_.add_warning(this, name, obj, shndx); }
|
||||
|
||||
// Canonicalize a symbol name for use in the hash table.
|
||||
const char*
|
||||
canonicalize_name(const char* name)
|
||||
{ return this->namepool_.add(name); }
|
||||
|
||||
// Possibly issue a warning for a reference to SYM at LOCATION which
|
||||
// is in OBJ.
|
||||
void
|
||||
issue_warning(Symbol* sym, const std::string& location) const
|
||||
{ this->warnings_.issue_warning(sym, location); }
|
||||
|
||||
// Finalize the symbol table after we have set the final addresses
|
||||
// of all the input sections. This sets the final symbol values and
|
||||
// adds the names to *POOL. It records the file offset OFF, and
|
||||
@ -604,7 +718,7 @@ class Symbol_table
|
||||
// Add a symbol.
|
||||
template<int size, bool big_endian>
|
||||
Symbol*
|
||||
add_from_object(Sized_object<size, big_endian>*, const char *name,
|
||||
add_from_object(Object*, const char *name,
|
||||
const char *version, bool def,
|
||||
const elfcpp::Sym<size, big_endian>& sym);
|
||||
|
||||
@ -720,6 +834,9 @@ class Symbol_table
|
||||
// symbol is no longer a common symbol. It may also have become a
|
||||
// forwarder.
|
||||
Commons_type commons_;
|
||||
|
||||
// Manage symbol warnings.
|
||||
Warnings warnings_;
|
||||
};
|
||||
|
||||
// We inline get_sized_symbol for efficiency.
|
||||
|
@ -44,7 +44,7 @@ scan_relocs(
|
||||
Symbol_table* symtab,
|
||||
Layout* layout,
|
||||
Target_type* target,
|
||||
Sized_object<size, big_endian>* object,
|
||||
Sized_relobj<size, big_endian>* object,
|
||||
const unsigned char* prelocs,
|
||||
size_t reloc_count,
|
||||
size_t local_count,
|
||||
@ -193,6 +193,9 @@ relocate_section(
|
||||
sym->name());
|
||||
// gold_exit(false);
|
||||
}
|
||||
|
||||
if (sym != NULL && sym->has_warning())
|
||||
relinfo->symtab->issue_warning(sym, relinfo->location(i, offset));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include <cassert>
|
||||
|
||||
#include "elfcpp.h"
|
||||
#include "symtab.h"
|
||||
|
||||
namespace gold
|
||||
{
|
||||
@ -24,9 +23,13 @@ namespace gold
|
||||
class General_options;
|
||||
class Object;
|
||||
template<int size, bool big_endian>
|
||||
class Sized_object;
|
||||
class Sized_relobj;
|
||||
template<int size, bool big_endian>
|
||||
struct Relocate_info;
|
||||
class Symbol;
|
||||
template<int size>
|
||||
class Sized_symbol;
|
||||
class Symbol_table;
|
||||
|
||||
// The abstract class for target specific handling.
|
||||
|
||||
@ -150,7 +153,7 @@ class Sized_target : public Target
|
||||
scan_relocs(const General_options& options,
|
||||
Symbol_table* symtab,
|
||||
Layout* layout,
|
||||
Sized_object<size, big_endian>* object,
|
||||
Sized_relobj<size, big_endian>* object,
|
||||
unsigned int sh_type,
|
||||
const unsigned char* prelocs,
|
||||
size_t reloc_count,
|
||||
|
Loading…
Reference in New Issue
Block a user