#include "dynobj.h"
#include "ehframe.h"
#include "compressed_output.h"
+#include "reloc.h"
#include "layout.h"
namespace gold
{
off_t file_size = this->layout_->finalize(this->input_objects_,
this->symtab_,
+ this->target_,
task);
// Now we know the final size of the output file and we know where
// each piece of information goes.
- Output_file* of = new Output_file(parameters->output_file_name());
+ Output_file* of = new Output_file(parameters->options().output_file_name());
+ if (this->options_.oformat_enum() != General_options::OBJECT_FORMAT_ELF)
+ of->set_is_temporary();
of->open(file_size);
// Queue up the final set of tasks.
unattached_section_list_(), special_output_list_(),
section_headers_(NULL), tls_segment_(NULL), symtab_section_(NULL),
dynsym_section_(NULL), dynamic_section_(NULL), dynamic_data_(NULL),
- eh_frame_section_(NULL), output_file_size_(-1),
+ eh_frame_section_(NULL), group_signatures_(), output_file_size_(-1),
input_requires_executable_stack_(false),
input_with_gnu_stack_note_(false),
input_without_gnu_stack_note_(false),
Layout::include_section(Sized_relobj<size, big_endian>*, const char* name,
const elfcpp::Shdr<size, big_endian>& shdr)
{
- // Some section types are never linked. Some are only linked when
- // doing a relocateable link.
switch (shdr.get_sh_type())
{
case elfcpp::SHT_NULL:
case elfcpp::SHT_RELA:
case elfcpp::SHT_REL:
case elfcpp::SHT_GROUP:
- return parameters->output_is_object();
+ // If we are emitting relocations these should be handled
+ // elsewhere.
+ gold_assert(!parameters->options().relocatable()
+ && !parameters->options().emit_relocs());
+ return false;
case elfcpp::SHT_PROGBITS:
- if (parameters->strip_debug()
+ if (parameters->options().strip_debug()
&& (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
{
// Debugging sections can only be recognized by name.
|| is_prefix_of(".stab", name))
return false;
}
- if (parameters->strip_debug_gdb()
+ if (parameters->options().strip_debug_gdb()
&& (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
{
// Debugging sections can only be recognized by name.
else
{
// This is the first time we've seen this name/type/flags
- // combination.
- Output_section* os = this->make_output_section(name, type, flags);
+ // combination. If the section has contents but no flags, then
+ // see whether we have an existing section with the same name.
+ // This is a workaround for cases where assembler code forgets
+ // to set section flags, and the GNU linker would simply pick an
+ // existing section with the same name. FIXME: Perhaps there
+ // should be an option to control this.
+ Output_section* os = NULL;
+ if (type == elfcpp::SHT_PROGBITS && flags == 0)
+ {
+ os = this->find_output_section(name);
+ if (os != NULL && os->type() != elfcpp::SHT_PROGBITS)
+ os = NULL;
+ }
+ if (os == NULL)
+ os = this->make_output_section(name, type, flags);
ins.first->second = os;
return os;
}
// output section.
size_t len = strlen(name);
- if (adjust_name && !parameters->output_is_object())
+ if (adjust_name && !parameters->options().relocatable())
name = Layout::output_section_name(name, &len);
Stringpool::Key name_key;
if (!this->include_section(object, name, shdr))
return NULL;
- Output_section* os = this->choose_output_section(object,
- name,
- shdr.get_sh_type(),
- shdr.get_sh_flags(),
- true);
- if (os == NULL)
- return NULL;
+ Output_section* os;
+
+ // In a relocatable link a grouped section must not be combined with
+ // any other sections.
+ if (parameters->options().relocatable()
+ && (shdr.get_sh_flags() & elfcpp::SHF_GROUP) != 0)
+ {
+ name = this->namepool_.add(name, true, NULL);
+ os = this->make_output_section(name, shdr.get_sh_type(),
+ shdr.get_sh_flags());
+ }
+ else
+ {
+ os = this->choose_output_section(object, name, shdr.get_sh_type(),
+ shdr.get_sh_flags(), true);
+ if (os == NULL)
+ return NULL;
+ }
// FIXME: Handle SHF_LINK_ORDER somewhere.
return os;
}
+// Handle a relocation section when doing a relocatable link.
+
+template<int size, bool big_endian>
+Output_section*
+Layout::layout_reloc(Sized_relobj<size, big_endian>* object,
+ unsigned int,
+ const elfcpp::Shdr<size, big_endian>& shdr,
+ Output_section* data_section,
+ Relocatable_relocs* rr)
+{
+ gold_assert(parameters->options().relocatable()
+ || parameters->options().emit_relocs());
+
+ int sh_type = shdr.get_sh_type();
+
+ std::string name;
+ if (sh_type == elfcpp::SHT_REL)
+ name = ".rel";
+ else if (sh_type == elfcpp::SHT_RELA)
+ name = ".rela";
+ else
+ gold_unreachable();
+ name += data_section->name();
+
+ Output_section* os = this->choose_output_section(object, name.c_str(),
+ sh_type,
+ shdr.get_sh_flags(),
+ false);
+
+ os->set_should_link_to_symtab();
+ os->set_info_section(data_section);
+
+ Output_section_data* posd;
+ if (sh_type == elfcpp::SHT_REL)
+ {
+ os->set_entsize(elfcpp::Elf_sizes<size>::rel_size);
+ posd = new Output_relocatable_relocs<elfcpp::SHT_REL,
+ size,
+ big_endian>(rr);
+ }
+ else if (sh_type == elfcpp::SHT_RELA)
+ {
+ os->set_entsize(elfcpp::Elf_sizes<size>::rela_size);
+ posd = new Output_relocatable_relocs<elfcpp::SHT_RELA,
+ size,
+ big_endian>(rr);
+ }
+ else
+ gold_unreachable();
+
+ os->add_output_section_data(posd);
+ rr->set_output_data(posd);
+
+ return os;
+}
+
+// Handle a group section when doing a relocatable link.
+
+template<int size, bool big_endian>
+void
+Layout::layout_group(Symbol_table* symtab,
+ Sized_relobj<size, big_endian>* object,
+ unsigned int,
+ const char* group_section_name,
+ const char* signature,
+ const elfcpp::Shdr<size, big_endian>& shdr,
+ const elfcpp::Elf_Word* contents)
+{
+ gold_assert(parameters->options().relocatable());
+ gold_assert(shdr.get_sh_type() == elfcpp::SHT_GROUP);
+ group_section_name = this->namepool_.add(group_section_name, true, NULL);
+ Output_section* os = this->make_output_section(group_section_name,
+ elfcpp::SHT_GROUP,
+ shdr.get_sh_flags());
+
+ // We need to find a symbol with the signature in the symbol table.
+ // If we don't find one now, we need to look again later.
+ Symbol* sym = symtab->lookup(signature, NULL);
+ if (sym != NULL)
+ os->set_info_symndx(sym);
+ else
+ {
+ // We will wind up using a symbol whose name is the signature.
+ // So just put the signature in the symbol name pool to save it.
+ signature = symtab->canonicalize_name(signature);
+ this->group_signatures_.push_back(Group_signature(os, signature));
+ }
+
+ os->set_should_link_to_symtab();
+ os->set_entsize(4);
+
+ section_size_type entry_count =
+ convert_to_section_size_type(shdr.get_sh_size() / 4);
+ Output_section_data* posd =
+ new Output_data_group<size, big_endian>(object, entry_count, contents);
+ os->add_output_section_data(posd);
+}
+
// Special GNU handling of sections name .eh_frame. They will
// normally hold exception frame data as defined by the C++ ABI
// (http://codesourcery.com/cxx-abi/).
this->eh_frame_data_ = new Eh_frame();
os->add_output_section_data(this->eh_frame_data_);
- if (this->options_.create_eh_frame_hdr())
+ if (this->options_.eh_frame_hdr())
{
Output_section* hdr_os =
this->choose_output_section(NULL,
this->unattached_section_list_.push_back(os);
else
{
+ if (parameters->options().relocatable())
+ return os;
+
// If we have a SECTIONS clause, we can't handle the attachment
// to segments until after we've seen all the sections.
if (this->script_options_->saw_sections_clause())
elfcpp::Elf_Word seg_flags = Layout::section_flags_to_segment(flags);
- // The only thing we really care about for PT_LOAD segments is
- // whether or not they are writable, so that is how we search
- // for them. People who need segments sorted on some other
- // basis will have to wait until we implement a mechanism for
- // them to describe the segments they want.
+ // In general the only thing we really care about for PT_LOAD
+ // segments is whether or not they are writable, so that is how
+ // we search for them. People who need segments sorted on some
+ // other basis will have to use a linker script.
Segment_list::const_iterator p;
for (p = this->segment_list_.begin();
if ((*p)->type() == elfcpp::PT_LOAD
&& ((*p)->flags() & elfcpp::PF_W) == (seg_flags & elfcpp::PF_W))
{
+ // If -Tbss was specified, we need to separate the data
+ // and BSS segments.
+ if (this->options_.user_set_Tbss())
+ {
+ if ((type == elfcpp::SHT_NOBITS)
+ == (*p)->has_any_data_sections())
+ continue;
+ }
+
(*p)->add_output_section(os, seg_flags);
break;
}
return os;
}
+// Make an output section for a script.
+
+Output_section*
+Layout::make_output_section_for_script(const char* name)
+{
+ name = this->namepool_.add(name, false, NULL);
+ Output_section* os = this->make_output_section(name, elfcpp::SHT_PROGBITS,
+ elfcpp::SHF_ALLOC);
+ os->set_found_in_sections_clause();
+ return os;
+}
+
// Return the number of segments we expect to see.
size_t
}
}
+// Define symbols for group signatures.
+
+void
+Layout::define_group_signatures(Symbol_table* symtab)
+{
+ for (Group_signatures::iterator p = this->group_signatures_.begin();
+ p != this->group_signatures_.end();
+ ++p)
+ {
+ Symbol* sym = symtab->lookup(p->signature, NULL);
+ if (sym != NULL)
+ p->section->set_info_symndx(sym);
+ else
+ {
+ // Force the name of the group section to the group
+ // signature, and use the group's section symbol as the
+ // signature symbol.
+ if (strcmp(p->section->name(), p->signature) != 0)
+ {
+ const char* name = this->namepool_.add(p->signature,
+ true, NULL);
+ p->section->set_name(name);
+ }
+ p->section->set_needs_symtab_index();
+ p->section->set_info_section_symndx(p->section);
+ }
+ }
+
+ this->group_signatures_.clear();
+}
+
// Find the first read-only PT_LOAD segment, creating one if
// necessary.
off_t
Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
- const Task* task)
+ Target* target, const Task* task)
{
- Target* const target = input_objects->target();
-
target->finalize_sections(this);
this->count_local_symbols(task, input_objects);
this->create_executable_stack_info(target);
Output_segment* phdr_seg = NULL;
- if (!parameters->output_is_object() && !parameters->doing_static_link())
+ if (!parameters->options().relocatable() && !parameters->doing_static_link())
{
// There was a dynamic object in the link. We need to create
// some information for the dynamic linker.
Output_section* dynstr;
std::vector<Symbol*> dynamic_symbols;
unsigned int local_dynamic_count;
- Versions versions(this->options_, &this->dynpool_);
+ Versions versions(*this->script_options()->version_script_info(),
+ &this->dynpool_);
this->create_dynamic_symtab(input_objects, symtab, &dynstr,
&local_dynamic_count, &dynamic_symbols,
&versions);
// Create the .interp section to hold the name of the
// interpreter, and put it in a PT_INTERP segment.
- if (!parameters->output_is_shared())
+ if (!parameters->options().shared())
this->create_interp(target);
// Finish the .dynamic section to hold the dynamic data, and put
Output_segment* load_seg;
if (this->script_options_->saw_sections_clause())
load_seg = this->set_section_addresses_from_script(symtab);
+ else if (parameters->options().relocatable())
+ load_seg = NULL;
else
load_seg = this->find_first_load_seg();
+ if (this->options_.oformat_enum() != General_options::OBJECT_FORMAT_ELF)
+ load_seg = NULL;
+
gold_assert(phdr_seg == NULL || load_seg != NULL);
// Lay out the segment headers.
Output_segment_headers* segment_headers;
- segment_headers = new Output_segment_headers(this->segment_list_);
- if (load_seg != NULL)
- load_seg->add_initial_output_data(segment_headers);
- if (phdr_seg != NULL)
- phdr_seg->add_initial_output_data(segment_headers);
+ if (parameters->options().relocatable())
+ segment_headers = NULL;
+ else
+ {
+ segment_headers = new Output_segment_headers(this->segment_list_);
+ if (load_seg != NULL)
+ load_seg->add_initial_output_data(segment_headers);
+ if (phdr_seg != NULL)
+ phdr_seg->add_initial_output_data(segment_headers);
+ }
// Lay out the file header.
Output_file_header* file_header;
file_header = new Output_file_header(target, symtab, segment_headers,
- this->script_options_->entry());
+ this->options_.entry());
if (load_seg != NULL)
load_seg->add_initial_output_data(file_header);
this->special_output_list_.push_back(file_header);
- this->special_output_list_.push_back(segment_headers);
+ if (segment_headers != NULL)
+ this->special_output_list_.push_back(segment_headers);
- if (this->script_options_->saw_phdrs_clause())
+ if (this->script_options_->saw_phdrs_clause()
+ && !parameters->options().relocatable())
{
// Support use of FILEHDRS and PHDRS attachments in a PHDRS
// clause in a linker script.
// Set the file offsets of all the segments, and all the sections
// they contain.
- off_t off = this->set_segment_offsets(target, load_seg, &shndx);
+ off_t off;
+ if (!parameters->options().relocatable())
+ off = this->set_segment_offsets(target, load_seg, &shndx);
+ else
+ off = this->set_relocatable_section_offsets(file_header, &shndx);
// Set the file offsets of all the non-data sections we've seen so
// far which don't have to wait for the input sections. We need
void
Layout::create_gold_note()
{
- if (parameters->output_is_object())
+ if (parameters->options().relocatable())
return;
// Authorities all agree that the values in a .note field should
// .note.ABI-tag (as of version 1.6), so that's the one we go with
// here.
#ifdef GABI_FORMAT_FOR_DOTNOTE_SECTION // This is not defined by default.
- const int size = parameters->get_size();
+ const int size = parameters->target().get_size();
#else
const int size = 32;
#endif
gold_assert(sizeof buffer >= notesz);
memset(buffer, 0, notesz);
- bool is_big_endian = parameters->is_big_endian();
+ bool is_big_endian = parameters->target().is_big_endian();
if (size == 32)
{
is_stack_executable = false;
}
- if (parameters->output_is_object())
+ if (parameters->options().relocatable())
{
const char* name = this->namepool_.add(".note.GNU-stack", false, NULL);
elfcpp::Elf_Xword flags = 0;
return false;
// We sort PT_LOAD segments based on the flags. Readonly segments
- // come before writable segments. Then executable segments come
- // before non-executable segments. Then the unlikely case of a
- // non-readable segment comes before the normal case of a readable
- // segment. If there are multiple segments with the same type and
- // flags, we require that the address be set, and we sort by
- // virtual address and then physical address.
+ // come before writable segments. Then writable segments with data
+ // come before writable segments without data. Then executable
+ // segments come before non-executable segments. Then the unlikely
+ // case of a non-readable segment comes before the normal case of a
+ // readable segment. If there are multiple segments with the same
+ // type and flags, we require that the address be set, and we sort
+ // by virtual address and then physical address.
if ((flags1 & elfcpp::PF_W) != (flags2 & elfcpp::PF_W))
return (flags1 & elfcpp::PF_W) == 0;
+ if ((flags1 & elfcpp::PF_W) != 0
+ && seg1->has_any_data_sections() != seg2->has_any_data_sections())
+ return seg1->has_any_data_sections();
if ((flags1 & elfcpp::PF_X) != (flags2 & elfcpp::PF_X))
return (flags1 & elfcpp::PF_X) != 0;
if ((flags1 & elfcpp::PF_R) != (flags2 & elfcpp::PF_R))
// Find the PT_LOAD segments, and set their addresses and offsets
// and their section's addresses and offsets.
uint64_t addr;
- if (this->options_.user_set_text_segment_address())
- addr = options_.text_segment_address();
- else if (parameters->output_is_shared())
+ if (this->options_.user_set_Ttext())
+ addr = this->options_.Ttext();
+ else if (parameters->options().shared())
addr = 0;
else
addr = target->default_text_segment_address();
gold_unreachable();
load_seg = NULL;
+ bool are_addresses_set = (*p)->are_addresses_set();
+ if (are_addresses_set)
+ {
+ // When it comes to setting file offsets, we care about
+ // the physical address.
+ addr = (*p)->paddr();
+ }
+ else if (this->options_.user_set_Tdata()
+ && ((*p)->flags() & elfcpp::PF_W) != 0
+ && (!this->options_.user_set_Tbss()
+ || (*p)->has_any_data_sections()))
+ {
+ addr = this->options_.Tdata();
+ are_addresses_set = true;
+ }
+ else if (this->options_.user_set_Tbss()
+ && ((*p)->flags() & elfcpp::PF_W) != 0
+ && !(*p)->has_any_data_sections())
+ {
+ addr = this->options_.Tbss();
+ are_addresses_set = true;
+ }
+
uint64_t orig_addr = addr;
uint64_t orig_off = off;
// FIXME: This should depend on the -n and -N options.
(*p)->set_minimum_p_align(target->common_pagesize());
- bool are_addresses_set = (*p)->are_addresses_set();
if (are_addresses_set)
{
- // When it comes to setting file offsets, we care about
- // the physical address.
- addr = (*p)->paddr();
-
// Adjust the file offset to the same address modulo the
// page size.
uint64_t unsigned_off = off;
return off;
}
+// Set the offsets of all the allocated sections when doing a
+// relocatable link. This does the same jobs as set_segment_offsets,
+// only for a relocatable link.
+
+off_t
+Layout::set_relocatable_section_offsets(Output_data* file_header,
+ unsigned int *pshndx)
+{
+ off_t off = 0;
+
+ file_header->set_address_and_file_offset(0, 0);
+ off += file_header->data_size();
+
+ for (Section_list::iterator p = this->section_list_.begin();
+ p != this->section_list_.end();
+ ++p)
+ {
+ // We skip unallocated sections here, except that group sections
+ // have to come first.
+ if (((*p)->flags() & elfcpp::SHF_ALLOC) == 0
+ && (*p)->type() != elfcpp::SHT_GROUP)
+ continue;
+
+ off = align_address(off, (*p)->addralign());
+
+ // The linker script might have set the address.
+ if (!(*p)->is_address_valid())
+ (*p)->set_address(0);
+ (*p)->set_file_offset(off);
+ (*p)->finalize_data_size();
+ off += (*p)->data_size();
+
+ (*p)->set_out_shndx(*pshndx);
+ ++*pshndx;
+ }
+
+ return off;
+}
+
// Set the file offset of all the sections not associated with a
// segment.
unsigned int
Layout::set_section_indexes(unsigned int shndx)
{
+ const bool output_is_object = parameters->options().relocatable();
for (Section_list::iterator p = this->unattached_section_list_.begin();
p != this->unattached_section_list_.end();
++p)
{
+ // In a relocatable link, we already did group sections.
+ if (output_is_object
+ && (*p)->type() == elfcpp::SHT_GROUP)
+ continue;
+
(*p)->set_out_shndx(shndx);
++shndx;
}
{
int symsize;
unsigned int align;
- if (parameters->get_size() == 32)
+ if (parameters->target().get_size() == 32)
{
symsize = elfcpp::Elf_sizes<32>::sym_size;
align = 4;
}
- else if (parameters->get_size() == 64)
+ else if (parameters->target().get_size() == 64)
{
symsize = elfcpp::Elf_sizes<64>::sym_size;
align = 8;
off = symtab->finalize(off, dynoff, dyn_global_index, dyncount,
&this->sympool_, &local_symcount);
- if (!parameters->strip_all())
+ if (!parameters->options().strip_all())
{
this->sympool_.set_string_offsets();
Output_section_headers* oshdrs;
oshdrs = new Output_section_headers(this,
&this->segment_list_,
+ &this->section_list_,
&this->unattached_section_list_,
&this->namepool_);
off_t off = align_address(*poff, oshdrs->addralign());
int symsize;
unsigned int align;
- const int size = parameters->get_size();
+ const int size = parameters->target().get_size();
if (size == 32)
{
symsize = elfcpp::Elf_sizes<32>::sym_size;
if (!versions->any_defs() && !versions->any_needs())
return;
- if (parameters->get_size() == 32)
+ switch (parameters->size_and_endianness())
{
- if (parameters->is_big_endian())
- {
-#ifdef HAVE_TARGET_32_BIG
- this->sized_create_version_sections
- SELECT_SIZE_ENDIAN_NAME(32, true)(
- versions, symtab, local_symcount, dynamic_symbols, dynstr
- SELECT_SIZE_ENDIAN(32, true));
-#else
- gold_unreachable();
-#endif
- }
- else
- {
#ifdef HAVE_TARGET_32_LITTLE
- this->sized_create_version_sections
- SELECT_SIZE_ENDIAN_NAME(32, false)(
- versions, symtab, local_symcount, dynamic_symbols, dynstr
- SELECT_SIZE_ENDIAN(32, false));
-#else
- gold_unreachable();
+ case Parameters::TARGET_32_LITTLE:
+ this->sized_create_version_sections<32, false>(versions, symtab,
+ local_symcount,
+ dynamic_symbols, dynstr);
+ break;
#endif
- }
- }
- else if (parameters->get_size() == 64)
- {
- if (parameters->is_big_endian())
- {
-#ifdef HAVE_TARGET_64_BIG
- this->sized_create_version_sections
- SELECT_SIZE_ENDIAN_NAME(64, true)(
- versions, symtab, local_symcount, dynamic_symbols, dynstr
- SELECT_SIZE_ENDIAN(64, true));
-#else
- gold_unreachable();
+#ifdef HAVE_TARGET_32_BIG
+ case Parameters::TARGET_32_BIG:
+ this->sized_create_version_sections<32, true>(versions, symtab,
+ local_symcount,
+ dynamic_symbols, dynstr);
+ break;
#endif
- }
- else
- {
#ifdef HAVE_TARGET_64_LITTLE
- this->sized_create_version_sections
- SELECT_SIZE_ENDIAN_NAME(64, false)(
- versions, symtab, local_symcount, dynamic_symbols, dynstr
- SELECT_SIZE_ENDIAN(64, false));
-#else
- gold_unreachable();
+ case Parameters::TARGET_64_LITTLE:
+ this->sized_create_version_sections<64, false>(versions, symtab,
+ local_symcount,
+ dynamic_symbols, dynstr);
+ break;
#endif
- }
+#ifdef HAVE_TARGET_64_BIG
+ case Parameters::TARGET_64_BIG:
+ this->sized_create_version_sections<64, true>(versions, symtab,
+ local_symcount,
+ dynamic_symbols, dynstr);
+ break;
+#endif
+ default:
+ gold_unreachable();
}
- else
- gold_unreachable();
}
// Create the version sections, sized version.
const Symbol_table* symtab,
unsigned int local_symcount,
const std::vector<Symbol*>& dynamic_symbols,
- const Output_section* dynstr
- ACCEPT_SIZE_ENDIAN)
+ const Output_section* dynstr)
{
Output_section* vsec = this->choose_output_section(NULL, ".gnu.version",
elfcpp::SHT_GNU_versym,
unsigned char* vbuf;
unsigned int vsize;
- versions->symbol_section_contents SELECT_SIZE_ENDIAN_NAME(size, big_endian)(
- symtab, &this->dynpool_, local_symcount, dynamic_symbols, &vbuf, &vsize
- SELECT_SIZE_ENDIAN(size, big_endian));
+ versions->symbol_section_contents<size, big_endian>(symtab, &this->dynpool_,
+ local_symcount,
+ dynamic_symbols,
+ &vbuf, &vsize);
Output_section_data* vdata = new Output_data_const_buffer(vbuf, vsize, 2);
unsigned char* vdbuf;
unsigned int vdsize;
unsigned int vdentries;
- versions->def_section_contents SELECT_SIZE_ENDIAN_NAME(size, big_endian)(
- &this->dynpool_, &vdbuf, &vdsize, &vdentries
- SELECT_SIZE_ENDIAN(size, big_endian));
+ versions->def_section_contents<size, big_endian>(&this->dynpool_, &vdbuf,
+ &vdsize, &vdentries);
Output_section_data* vddata = new Output_data_const_buffer(vdbuf,
vdsize,
unsigned char* vnbuf;
unsigned int vnsize;
unsigned int vnentries;
- versions->need_section_contents SELECT_SIZE_ENDIAN_NAME(size, big_endian)
- (&this->dynpool_, &vnbuf, &vnsize, &vnentries
- SELECT_SIZE_ENDIAN(size, big_endian));
+ versions->need_section_contents<size, big_endian>(&this->dynpool_,
+ &vnbuf, &vnsize,
+ &vnentries);
Output_section_data* vndata = new Output_data_const_buffer(vnbuf,
vnsize,
odyn->add_string(elfcpp::DT_NEEDED, (*p)->soname());
}
- if (parameters->output_is_shared())
+ if (parameters->options().shared())
{
const char* soname = this->options_.soname();
if (soname != NULL)
// Look for text segments that have dynamic relocations.
bool have_textrel = false;
- for (Segment_list::const_iterator p = this->segment_list_.begin();
- p != this->segment_list_.end();
- ++p)
+ if (!this->script_options_->saw_sections_clause())
{
- if (((*p)->flags() & elfcpp::PF_W) == 0
- && (*p)->dynamic_reloc_count() > 0)
- {
- have_textrel = true;
- break;
- }
+ for (Segment_list::const_iterator p = this->segment_list_.begin();
+ p != this->segment_list_.end();
+ ++p)
+ {
+ if (((*p)->flags() & elfcpp::PF_W) == 0
+ && (*p)->dynamic_reloc_count() > 0)
+ {
+ have_textrel = true;
+ break;
+ }
+ }
+ }
+ else
+ {
+ // We don't know the section -> segment mapping, so we are
+ // conservative and just look for readonly sections with
+ // relocations. If those sections wind up in writable segments,
+ // then we have created an unnecessary DT_TEXTREL entry.
+ for (Section_list::const_iterator p = this->section_list_.begin();
+ p != this->section_list_.end();
+ ++p)
+ {
+ if (((*p)->flags() & elfcpp::SHF_ALLOC) != 0
+ && ((*p)->flags() & elfcpp::SHF_WRITE) == 0
+ && ((*p)->dynamic_reloc_count() > 0))
+ {
+ have_textrel = true;
+ break;
+ }
+ }
}
// Add a DT_FLAGS entry. We add it even if no flags are set so that
odyn->add_constant(elfcpp::DT_TEXTREL, 0);
flags |= elfcpp::DF_TEXTREL;
}
- if (parameters->output_is_shared() && this->has_static_tls())
+ if (parameters->options().shared() && this->has_static_tls())
flags |= elfcpp::DF_STATIC_TLS;
odyn->add_constant(elfcpp::DT_FLAGS, flags);
}
Output_segment*
Layout::make_output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags)
{
+ gold_assert(!parameters->options().relocatable());
Output_segment* oseg = new Output_segment(type, flags);
this->segment_list_.push_back(oseg);
return oseg;
void
Layout::write_data(const Symbol_table* symtab, Output_file* of) const
{
- if (!parameters->strip_all())
+ if (!parameters->options().strip_all())
{
const Output_section* symtab_section = this->symtab_section_;
for (Section_list::const_iterator p = this->section_list_.begin();
this->section_headers_->write(of);
}
+// Write out a binary file. This is called after the link is
+// complete. IN is the temporary output file we used to generate the
+// ELF code. We simply walk through the segments, read them from
+// their file offset in IN, and write them to their load address in
+// the output file. FIXME: with a bit more work, we could support
+// S-records and/or Intel hex format here.
+
+void
+Layout::write_binary(Output_file* in) const
+{
+ gold_assert(this->options_.oformat_enum()
+ == General_options::OBJECT_FORMAT_BINARY);
+
+ // Get the size of the binary file.
+ uint64_t max_load_address = 0;
+ for (Segment_list::const_iterator p = this->segment_list_.begin();
+ p != this->segment_list_.end();
+ ++p)
+ {
+ if ((*p)->type() == elfcpp::PT_LOAD && (*p)->filesz() > 0)
+ {
+ uint64_t max_paddr = (*p)->paddr() + (*p)->filesz();
+ if (max_paddr > max_load_address)
+ max_load_address = max_paddr;
+ }
+ }
+
+ Output_file out(parameters->options().output_file_name());
+ out.open(max_load_address);
+
+ for (Segment_list::const_iterator p = this->segment_list_.begin();
+ p != this->segment_list_.end();
+ ++p)
+ {
+ if ((*p)->type() == elfcpp::PT_LOAD && (*p)->filesz() > 0)
+ {
+ const unsigned char* vin = in->get_input_view((*p)->offset(),
+ (*p)->filesz());
+ unsigned char* vout = out.get_output_view((*p)->paddr(),
+ (*p)->filesz());
+ memcpy(vout, vin, (*p)->filesz());
+ out.write_output_view((*p)->paddr(), (*p)->filesz(), vout);
+ in->free_input_view((*p)->offset(), (*p)->filesz(), vin);
+ }
+ }
+
+ out.close();
+}
+
// Print statistical information to stderr. This is used for --stats.
void
void
Close_task_runner::run(Workqueue*, const Task*)
{
+ // If we've been asked to create a binary file, we do so here.
+ if (this->options_->oformat_enum() != General_options::OBJECT_FORMAT_ELF)
+ this->layout_->write_binary(this->of_);
+
this->of_->close();
}
#ifdef HAVE_TARGET_32_LITTLE
template
Output_section*
+Layout::layout_reloc<32, false>(Sized_relobj<32, false>* object,
+ unsigned int reloc_shndx,
+ const elfcpp::Shdr<32, false>& shdr,
+ Output_section* data_section,
+ Relocatable_relocs* rr);
+#endif
+
+#ifdef HAVE_TARGET_32_BIG
+template
+Output_section*
+Layout::layout_reloc<32, true>(Sized_relobj<32, true>* object,
+ unsigned int reloc_shndx,
+ const elfcpp::Shdr<32, true>& shdr,
+ Output_section* data_section,
+ Relocatable_relocs* rr);
+#endif
+
+#ifdef HAVE_TARGET_64_LITTLE
+template
+Output_section*
+Layout::layout_reloc<64, false>(Sized_relobj<64, false>* object,
+ unsigned int reloc_shndx,
+ const elfcpp::Shdr<64, false>& shdr,
+ Output_section* data_section,
+ Relocatable_relocs* rr);
+#endif
+
+#ifdef HAVE_TARGET_64_BIG
+template
+Output_section*
+Layout::layout_reloc<64, true>(Sized_relobj<64, true>* object,
+ unsigned int reloc_shndx,
+ const elfcpp::Shdr<64, true>& shdr,
+ Output_section* data_section,
+ Relocatable_relocs* rr);
+#endif
+
+#ifdef HAVE_TARGET_32_LITTLE
+template
+void
+Layout::layout_group<32, false>(Symbol_table* symtab,
+ Sized_relobj<32, false>* object,
+ unsigned int,
+ const char* group_section_name,
+ const char* signature,
+ const elfcpp::Shdr<32, false>& shdr,
+ const elfcpp::Elf_Word* contents);
+#endif
+
+#ifdef HAVE_TARGET_32_BIG
+template
+void
+Layout::layout_group<32, true>(Symbol_table* symtab,
+ Sized_relobj<32, true>* object,
+ unsigned int,
+ const char* group_section_name,
+ const char* signature,
+ const elfcpp::Shdr<32, true>& shdr,
+ const elfcpp::Elf_Word* contents);
+#endif
+
+#ifdef HAVE_TARGET_64_LITTLE
+template
+void
+Layout::layout_group<64, false>(Symbol_table* symtab,
+ Sized_relobj<64, false>* object,
+ unsigned int,
+ const char* group_section_name,
+ const char* signature,
+ const elfcpp::Shdr<64, false>& shdr,
+ const elfcpp::Elf_Word* contents);
+#endif
+
+#ifdef HAVE_TARGET_64_BIG
+template
+void
+Layout::layout_group<64, true>(Symbol_table* symtab,
+ Sized_relobj<64, true>* object,
+ unsigned int,
+ const char* group_section_name,
+ const char* signature,
+ const elfcpp::Shdr<64, true>& shdr,
+ const elfcpp::Elf_Word* contents);
+#endif
+
+#ifdef HAVE_TARGET_32_LITTLE
+template
+Output_section*
Layout::layout_eh_frame<32, false>(Sized_relobj<32, false>* object,
const unsigned char* symbols,
off_t symbols_size,