{
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());
- if (this->options_.output_format() != General_options::OBJECT_FORMAT_ELF)
+ 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);
case elfcpp::SHT_RELA:
case elfcpp::SHT_REL:
case elfcpp::SHT_GROUP:
- // For a relocatable link these should be handled elsewhere.
- gold_assert(!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;
// In a relocatable link a grouped section must not be combined with
// any other sections.
- if (parameters->output_is_object()
+ if (parameters->options().relocatable()
&& (shdr.get_sh_flags() & elfcpp::SHF_GROUP) != 0)
{
name = this->namepool_.add(name, true, NULL);
Output_section* data_section,
Relocatable_relocs* rr)
{
- gold_assert(parameters->output_is_object());
+ gold_assert(parameters->options().relocatable()
+ || parameters->options().emit_relocs());
int sh_type = shdr.get_sh_type();
const elfcpp::Shdr<size, big_endian>& shdr,
const elfcpp::Elf_Word* contents)
{
- gold_assert(parameters->output_is_object());
+ 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,
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->output_is_object())
+ if (parameters->options().relocatable())
return os;
// If we have a SECTIONS clause, we can't handle the attachment
{
// If -Tbss was specified, we need to separate the data
// and BSS segments.
- if (this->options_.user_set_bss_segment_address())
+ if (this->options_.user_set_Tbss())
{
if ((type == elfcpp::SHT_NOBITS)
== (*p)->has_any_data_sections())
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
off_t
Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
- const Task* task)
+ Target* target, const Task* task)
{
- Target* const target = parameters->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->output_is_object())
+ else if (parameters->options().relocatable())
load_seg = NULL;
else
load_seg = this->find_first_load_seg();
- if (this->options_.output_format() != General_options::OBJECT_FORMAT_ELF)
+ 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;
- if (parameters->output_is_object())
+ if (parameters->options().relocatable())
segment_headers = NULL;
else
{
// 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(segment_headers);
if (this->script_options_->saw_phdrs_clause()
- && !parameters->output_is_object())
+ && !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;
- if (!parameters->output_is_object())
+ if (!parameters->options().relocatable())
off = this->set_segment_offsets(target, load_seg, &shndx);
else
off = this->set_relocatable_section_offsets(file_header, &shndx);
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;
// 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 = this->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();
// the physical address.
addr = (*p)->paddr();
}
- else if (this->options_.user_set_data_segment_address()
+ else if (this->options_.user_set_Tdata()
&& ((*p)->flags() & elfcpp::PF_W) != 0
- && (!this->options_.user_set_bss_segment_address()
+ && (!this->options_.user_set_Tbss()
|| (*p)->has_any_data_sections()))
{
- addr = this->options_.data_segment_address();
+ addr = this->options_.Tdata();
are_addresses_set = true;
}
- else if (this->options_.user_set_bss_segment_address()
+ else if (this->options_.user_set_Tbss()
&& ((*p)->flags() & elfcpp::PF_W) != 0
&& !(*p)->has_any_data_sections())
{
- addr = this->options_.bss_segment_address();
+ addr = this->options_.Tbss();
are_addresses_set = true;
}
unsigned int
Layout::set_section_indexes(unsigned int shndx)
{
- const bool output_is_object = parameters->output_is_object();
+ 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)
{
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();
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)
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->output_is_object());
+ 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();
void
Layout::write_binary(Output_file* in) const
{
- gold_assert(this->options_.output_format()
+ gold_assert(this->options_.oformat_enum()
== General_options::OBJECT_FORMAT_BINARY);
// Get the size of the binary file.
}
}
- Output_file out(parameters->output_file_name());
+ Output_file out(parameters->options().output_file_name());
out.open(max_load_address);
for (Segment_list::const_iterator p = this->segment_list_.begin();
Close_task_runner::run(Workqueue*, const Task*)
{
// If we've been asked to create a binary file, we do so here.
- if (this->options_->output_format() != General_options::OBJECT_FORMAT_ELF)
+ if (this->options_->oformat_enum() != General_options::OBJECT_FORMAT_ELF)
this->layout_->write_binary(this->of_);
this->of_->close();