void
Symbol_table::allocate_commons(const General_options& options, Layout* layout)
{
- if (parameters->get_size() == 32)
+ if (parameters->target().get_size() == 32)
{
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
this->do_allocate_commons<32>(options, layout);
gold_unreachable();
#endif
}
- else if (parameters->get_size() == 64)
+ else if (parameters->target().get_size() == 64)
{
#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
this->do_allocate_commons<64>(options, layout);
*compressed_data = new char[*compressed_size];
int compress_level;
- if (parameters->optimize() >= 1)
+ if (parameters->options().optimize() >= 1)
compress_level = 9;
else
compress_level = 1;
Dwarf_line_info::one_addr2line(Object* object,
unsigned int shndx, off_t offset)
{
- if (parameters->get_size() == 32 && !parameters->is_big_endian())
+ switch (parameters->size_and_endianness())
+ {
#ifdef HAVE_TARGET_32_LITTLE
- return Sized_dwarf_line_info<32, false>(object, shndx).addr2line(shndx,
- offset);
-#else
- gold_unreachable();
+ case Parameters::TARGET_32_LITTLE:
+ return Sized_dwarf_line_info<32, false>(object, shndx).addr2line(shndx,
+ offset);
#endif
- else if (parameters->get_size() == 32 && parameters->is_big_endian())
#ifdef HAVE_TARGET_32_BIG
- return Sized_dwarf_line_info<32, true>(object, shndx).addr2line(shndx,
- offset);
-#else
- gold_unreachable();
+ case Parameters::TARGET_32_BIG:
+ return Sized_dwarf_line_info<32, true>(object, shndx).addr2line(shndx,
+ offset);
#endif
- else if (parameters->get_size() == 64 && !parameters->is_big_endian())
#ifdef HAVE_TARGET_64_LITTLE
- return Sized_dwarf_line_info<64, false>(object, shndx).addr2line(shndx,
- offset);
-#else
- gold_unreachable();
+ case Parameters::TARGET_64_LITTLE:
+ return Sized_dwarf_line_info<64, false>(object, shndx).addr2line(shndx,
+ offset);
#endif
- else if (parameters->get_size() == 64 && parameters->is_big_endian())
-#ifdef HAVE_TARGET_64_BIT
- return Sized_dwarf_line_info<64, true>(object, shndx).addr2line(shndx,
- offset);
-#else
- gold_unreachable();
+#ifdef HAVE_TARGET_64_BIG
+ case Parameters::TARGET_64_BIG:
+ return Sized_dwarf_line_info<64, true>(object, shndx).addr2line(shndx,
+ offset);
#endif
- else
- gold_unreachable();
+ default:
+ gold_unreachable();
+ }
}
#ifdef HAVE_TARGET_32_LITTLE
* 4);
unsigned char* phash = new unsigned char[hashlen];
- if (parameters->is_big_endian())
+ if (parameters->target().is_big_endian())
{
#if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG)
Dynobj::sized_create_elf_hash_table<true>(bucket, chain, phash,
// For the actual data generation we call out to a templatized
// function.
- int size = parameters->get_size();
- bool big_endian = parameters->is_big_endian();
+ int size = parameters->target().get_size();
+ bool big_endian = parameters->target().is_big_endian();
if (size == 32)
{
if (big_endian)
{
// We always need a base version, so define that first. Nothing
// explicitly declares itself as part of base, so it doesn't need to
- // be in version_table_.
+ // be in version_table_.
// FIXME: Should use soname here when creating a shared object. Is
// this fixme still valid? It looks like it's doing the right thing
// to me.
- if (parameters->output_is_shared())
+ if (parameters->options().shared())
{
- const char* name = dynpool->add(parameters->output_file_name(),
+ const char* name = dynpool->add(parameters->options().output_file_name(),
false, NULL);
Verdef* vdbase = new Verdef(name, std::vector<std::string>(),
true, false, true);
{
gold_assert(!this->is_finalized_);
gold_assert(sym->version() != NULL);
-
+
Stringpool::Key version_key;
const char* version = dynpool->add(sym->version(), false, &version_key);
if (!sym->is_from_dynobj() && !sym->is_copied_from_dynobj())
{
- if (parameters->output_is_shared())
+ if (parameters->options().shared())
this->add_def(sym, version, version_key);
}
else
// If we are creating a shared object, it is an error to
// find a definition of a symbol with a version which is not
// in the version script.
- if (parameters->output_is_shared())
+ if (parameters->options().shared())
{
gold_error(_("symbol %s has undefined version %s"),
sym->demangled_name().c_str(), version);
Key k;
if (!sym->is_from_dynobj() && !sym->is_copied_from_dynobj())
{
- if (!parameters->output_is_shared())
+ if (!parameters->options().shared())
return elfcpp::VER_NDX_GLOBAL;
k = Key(version_key, 0);
}
void
Eh_frame_hdr::do_write(Output_file* of)
{
- if (parameters->get_size() == 32)
+ switch (parameters->size_and_endianness())
{
- if (!parameters->is_big_endian())
- {
#ifdef HAVE_TARGET_32_LITTLE
- this->do_sized_write<32, false>(of);
-#else
- gold_unreachable();
+ case Parameters::TARGET_32_LITTLE:
+ this->do_sized_write<32, false>(of);
+ break;
#endif
- }
- else
- {
#ifdef HAVE_TARGET_32_BIG
- this->do_sized_write<32, true>(of);
-#else
- gold_unreachable();
+ case Parameters::TARGET_32_BIG:
+ this->do_sized_write<32, true>(of);
+ break;
#endif
- }
- }
- else if (parameters->get_size() == 64)
- {
- if (!parameters->is_big_endian())
- {
#ifdef HAVE_TARGET_64_LITTLE
- this->do_sized_write<64, false>(of);
-#else
- gold_unreachable();
+ case Parameters::TARGET_64_LITTLE:
+ this->do_sized_write<64, false>(of);
+ break;
#endif
- }
- else
- {
#ifdef HAVE_TARGET_64_BIG
- this->do_sized_write<64, true>(of);
-#else
- gold_unreachable();
+ case Parameters::TARGET_64_BIG:
+ this->do_sized_write<64, true>(of);
+ break;
#endif
- }
+ default:
+ gold_unreachable();
}
- else
- gold_unreachable();
}
// Write the data to the file with the right endianness.
const off_t oview_size = this->data_size();
unsigned char* const oview = of->get_output_view(offset, oview_size);
- if (parameters->get_size() == 32)
+ switch (parameters->size_and_endianness())
{
- if (!parameters->is_big_endian())
- {
#ifdef HAVE_TARGET_32_LITTLE
- this->do_sized_write<32, false>(oview);
-#else
- gold_unreachable();
+ case Parameters::TARGET_32_LITTLE:
+ this->do_sized_write<32, false>(oview);
+ break;
#endif
- }
- else
- {
#ifdef HAVE_TARGET_32_BIG
- this->do_sized_write<32, true>(oview);
-#else
- gold_unreachable();
+ case Parameters::TARGET_32_BIG:
+ this->do_sized_write<32, true>(oview);
+ break;
#endif
- }
- }
- else if (parameters->get_size() == 64)
- {
- if (!parameters->is_big_endian())
- {
#ifdef HAVE_TARGET_64_LITTLE
- this->do_sized_write<64, false>(oview);
-#else
- gold_unreachable();
+ case Parameters::TARGET_64_LITTLE:
+ this->do_sized_write<64, false>(oview);
+ break;
#endif
- }
- else
- {
#ifdef HAVE_TARGET_64_BIG
- this->do_sized_write<64, true>(oview);
-#else
- gold_unreachable();
+ case Parameters::TARGET_64_BIG:
+ this->do_sized_write<64, true>(oview);
+ break;
#endif
- }
+ default:
+ gold_unreachable();
}
- else
- gold_unreachable();
of->write_output_view(offset, oview_size, oview);
}
*eei->result_section_pointer = sym->output_section();
- if (parameters->get_size() == 32)
+ if (parameters->target().get_size() == 32)
return eei->symtab->get_sized_symbol<32>(sym)->value();
- else if (parameters->get_size() == 64)
+ else if (parameters->target().get_size() == 64)
return eei->symtab->get_sized_symbol<64>(sym)->value();
else
gold_unreachable();
{ \
Output_section* arg_section; \
uint64_t ret = OPERATOR this->arg_value(eei, &arg_section); \
- if (arg_section != NULL && parameters->output_is_object()) \
+ if (arg_section != NULL && parameters->options().relocatable()) \
gold_warning(_("unary " #NAME " applied to section " \
"relative value")); \
return ret; \
*eei->result_section_pointer = left_section; \
else if ((WARN || left_section != right_section) \
&& (left_section != NULL || right_section != NULL) \
- && parameters->output_is_object()) \
+ && parameters->options().relocatable()) \
gold_warning(_("binary " #NAME " applied to section " \
"relative value")); \
if (IS_DIV && right == 0) \
if (left_section == right_section)
*eei->result_section_pointer = left_section;
else if ((left_section != NULL || right_section != NULL)
- && parameters->output_is_object())
+ && parameters->options().relocatable())
gold_warning(_("max applied to section relative value"));
return std::max(left, right);
}
if (left_section == right_section)
*eei->result_section_pointer = left_section;
else if ((left_section != NULL || right_section != NULL)
- && parameters->output_is_object())
+ && parameters->options().relocatable())
gold_warning(_("min applied to section relative value"));
return std::min(left, right);
}
Output_section* align_section;
uint64_t align = this->right_value(eei, &align_section);
if (align_section != NULL
- && parameters->output_is_object())
+ && parameters->options().relocatable())
gold_warning(_("aligning to section relative value"));
uint64_t value = this->left_value(eei, eei->result_section_pointer);
switch (this->function_)
{
case CONSTANT_MAXPAGESIZE:
- return parameters->target()->abi_pagesize();
+ return parameters->target().abi_pagesize();
case CONSTANT_COMMONPAGESIZE:
- return parameters->target()->common_pagesize();
+ return parameters->target().common_pagesize();
default:
gold_unreachable();
}
{
unsigned int ehdr_size;
unsigned int phdr_size;
- if (parameters->get_size() == 32)
+ if (parameters->target().get_size() == 32)
{
ehdr_size = elfcpp::Elf_sizes<32>::ehdr_size;
phdr_size = elfcpp::Elf_sizes<32>::phdr_size;
}
- else if (parameters->get_size() == 64)
+ else if (parameters->target().get_size() == 64)
{
ehdr_size = elfcpp::Elf_sizes<64>::ehdr_size;
phdr_size = elfcpp::Elf_sizes<64>::phdr_size;
// Open a file for --format binary.
bool
-Input_file::open_binary(const General_options& options,
+Input_file::open_binary(const General_options&,
const Task* task, const std::string& name)
{
// In order to open a binary file, we need machine code, size, and
// endianness. We may not have a valid target at this point, in
// which case we use the default target.
- Target* target;
- if (parameters->is_target_valid())
- target = parameters->target();
+ const Target* target;
+ if (parameters->target_valid())
+ target = ¶meters->target();
else
- target = options.default_target();
+ target = ¶meters->default_target();
Binary_to_elf binary_to_elf(target->machine_code(),
target->get_size(),
#include <pthread.h>
#endif
+#include "options.h"
#include "parameters.h"
#include "gold-threads.h"
Lock::Lock()
{
- if (!parameters->threads())
+ if (!parameters->options().threads())
this->lock_ = new Lock_impl_nothreads;
else
{
Condvar::Condvar(Lock& lock)
: lock_(lock)
{
- if (!parameters->threads())
+ if (!parameters->options().threads())
this->condvar_ = new Condvar_impl_nothreads;
else
{
gold_exit(bool status)
{
if (!status && parameters != NULL && parameters->options_valid())
- unlink_if_ordinary(parameters->output_file_name());
+ unlink_if_ordinary(parameters->options().output_file_name());
exit(status ? EXIT_SUCCESS : EXIT_FAILURE);
}
// pass an empty archive to the linker and get an empty object file
// out. In order to do this we need to use a default target.
if (input_objects->number_of_input_objects() == 0)
- set_parameters_target(options.default_target());
+ set_parameters_target(¶meters->default_target());
int thread_count = options.thread_count_middle();
if (thread_count == 0)
// Now we have seen all the input files.
const bool doing_static_link = (!input_objects->any_dynamic()
- && !parameters->output_is_shared());
+ && !parameters->options().shared());
set_parameters_doing_static_link(doing_static_link);
if (!doing_static_link && options.is_static())
{
gold_error(_("cannot mix -static with dynamic object %s"),
(*input_objects->dynobj_begin())->name().c_str());
}
- if (!doing_static_link && parameters->output_is_object())
+ if (!doing_static_link && parameters->options().relocatable())
gold_error(_("cannot mix -r with dynamic object %s"),
(*input_objects->dynobj_begin())->name().c_str());
if (!doing_static_link
// Define symbols from any linker scripts.
layout->define_script_symbols(symtab);
- if (!parameters->output_is_object())
+ if (!parameters->options().relocatable())
{
// Predefine standard symbols.
define_standard_symbols(symtab, layout);
// symbol table, but is independent of the relocation processing.
// FIXME: We should have an option to do this even for a relocatable
// link.
- if (!parameters->output_is_object())
+ if (!parameters->options().relocatable())
{
blocker->add_blocker();
workqueue->queue(new Allocate_commons_task(options, symtab, layout,
// When all those tasks are complete, we can start laying out the
// output file.
+ // TODO(csilvers): figure out a more principled way to get the target
+ Target* target = const_cast<Target*>(¶meters->target());
workqueue->queue(new Task_function(new Layout_task_runner(options,
input_objects,
symtab,
+ target,
layout),
blocker,
"Task_function Layout_task_runner"));
// Return a string used to fill a code section with nops.
std::string
- do_code_fill(section_size_type length);
+ do_code_fill(section_size_type length) const;
// Return whether SYM is defined by the ABI.
bool
bool
may_need_copy_reloc(Symbol* gsym)
{
- return (!parameters->output_is_shared()
+ return (!parameters->options().shared()
&& gsym->is_from_dynobj()
&& gsym->type() != elfcpp::STT_FUNC);
}
elfcpp::Elf_types<32>::Elf_Addr plt_address = this->address();
elfcpp::Elf_types<32>::Elf_Addr got_address = this->got_plt_->address();
- if (parameters->output_is_shared())
+ if (parameters->options().shared())
memcpy(pov, dyn_first_plt_entry, plt_entry_size);
else
{
{
// Set and adjust the PLT entry itself.
- if (parameters->output_is_shared())
+ if (parameters->options().shared())
{
memcpy(pov, dyn_plt_entry, plt_entry_size);
elfcpp::Swap_unaligned<32, false>::writeval(pov + 2, got_offset);
{
// If we are generating a shared library, then we can't do anything
// in the linker.
- if (parameters->output_is_shared())
+ if (parameters->options().shared())
return tls::TLSOPT_NONE;
switch (r_type)
// apply the link-time value, so we flag the location with
// an R_386_RELATIVE relocation so the dynamic loader can
// relocate it easily.
- if (parameters->output_is_position_independent())
+ if (parameters->options().output_is_position_independent())
{
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
// this location. Because the addend needs to remain in the
// data section, we need to be careful not to apply this
// relocation statically.
- if (parameters->output_is_position_independent())
+ if (parameters->options().output_is_position_independent())
{
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
if (lsym.get_st_type() != elfcpp::STT_SECTION)
{
// If we are generating a shared object, we need to add a
// dynamic RELATIVE relocation for this symbol's GOT entry.
- if (parameters->output_is_position_independent())
+ if (parameters->options().output_is_position_independent())
{
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
case elfcpp::R_386_TLS_LE: // Local-exec
case elfcpp::R_386_TLS_LE_32:
{
- bool output_is_shared = parameters->output_is_shared();
+ bool output_is_shared = parameters->options().shared();
const tls::Tls_optimization optimized_type
= Target_i386::optimize_tls_reloc(!output_is_shared, r_type);
switch (r_type)
// For the R_386_TLS_IE relocation, we need to create a
// dynamic relocation when building a shared library.
if (r_type == elfcpp::R_386_TLS_IE
- && parameters->output_is_shared())
+ && parameters->options().shared())
{
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
unsigned int r_sym
// taking the address of a function. In that case we need to
// set the entry in the dynamic symbol table to the address of
// the PLT entry.
- if (gsym->is_from_dynobj() && !parameters->output_is_shared())
+ if (gsym->is_from_dynobj() && !parameters->options().shared())
gsym->set_needs_dynsym_value();
}
// Make a dynamic relocation if necessary.
// PLT entry and let the dynamic linker bind the call directly
// to the target. For smaller relocations, we should use a
// PLT entry to ensure that the call can reach.
- if (!parameters->output_is_shared()
+ if (!parameters->options().shared()
|| r_type != elfcpp::R_386_PC32)
target->make_plt_entry(symtab, layout, gsym);
}
// For the R_386_TLS_IE relocation, we need to create a
// dynamic relocation when building a shared library.
if (r_type == elfcpp::R_386_TLS_IE
- && parameters->output_is_shared())
+ && parameters->options().shared())
{
Reloc_section* rel_dyn = target->rel_dyn_section(layout);
rel_dyn->add_global_relative(gsym, elfcpp::R_386_RELATIVE,
case elfcpp::R_386_TLS_LE: // Local-exec
case elfcpp::R_386_TLS_LE_32:
layout->set_has_static_tls();
- if (parameters->output_is_shared())
+ if (parameters->options().shared())
{
// We need to create a dynamic relocation.
unsigned int dyn_r_type = (r_type == elfcpp::R_386_TLS_LE_32
elfcpp::Elf_sizes<32>::rel_size);
}
- if (!parameters->output_is_shared())
+ if (!parameters->options().shared())
{
// The value of the DT_DEBUG tag is filled in by the dynamic
// linker at run time, and used by the debugger.
// (b) the relocation is absolute (not pc- or segment-relative), and
// (c) the relocation is not 32 bits wide.
if (gsym == NULL)
- return !(parameters->output_is_position_independent()
+ return !(parameters->options().output_is_position_independent()
&& (ref_flags & Symbol::ABSOLUTE_REF)
&& !is_32bit);
|| r_type == elfcpp::R_386_PC32);
if (gsym != NULL
&& (gsym->is_from_dynobj()
- || (parameters->output_is_shared()
+ || (parameters->options().shared()
&& (gsym->is_undefined() || gsym->is_preemptible())))
&& gsym->has_plt_offset()
- && (!is_nonpic || !parameters->output_is_shared()))
+ && (!is_nonpic || !parameters->options().shared()))
{
symval.set_output_value(target->plt_section()->address()
+ gsym->plt_offset());
elfcpp::Elf_types<32>::Elf_Addr value = psymval->value(object, 0);
- const bool is_final = (gsym == NULL
- ? !parameters->output_is_position_independent()
- : gsym->final_value_is_known());
+ const bool is_final =
+ (gsym == NULL
+ ? !parameters->options().output_is_position_independent()
+ : gsym->final_value_is_known());
const tls::Tls_optimization optimized_type
= Target_i386::optimize_tls_reloc(is_final, r_type);
switch (r_type)
case elfcpp::R_386_TLS_LE: // Local-exec
// If we're creating a shared library, a dynamic relocation will
// have been created for this location, so do not apply it now.
- if (!parameters->output_is_shared())
+ if (!parameters->options().shared())
{
gold_assert(tls_segment != NULL);
value -= tls_segment->memsz();
case elfcpp::R_386_TLS_LE_32:
// If we're creating a shared library, a dynamic relocation will
// have been created for this location, so do not apply it now.
- if (!parameters->output_is_shared())
+ if (!parameters->options().shared())
{
gold_assert(tls_segment != NULL);
value = tls_segment->memsz() - value;
// the specified length.
std::string
-Target_i386::do_code_fill(section_size_type length)
+Target_i386::do_code_fill(section_size_type length) const
{
if (length >= 16)
{
{
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() != General_options::OBJECT_FORMAT_ELF)
of->set_is_temporary();
of->open(file_size);
case elfcpp::SHT_GROUP:
// If we are emitting relocations these should be handled
// elsewhere.
- gold_assert(!parameters->output_is_object()
- && !parameters->emit_relocs());
+ 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.
// 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() || parameters->emit_relocs());
+ 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->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
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.
// 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();
// Lay out the segment headers.
Output_segment_headers* segment_headers;
- if (parameters->output_is_object())
+ if (parameters->options().relocatable())
segment_headers = NULL;
else
{
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;
uint64_t addr;
if (this->options_.user_set_Ttext())
addr = this->options_.Ttext();
- else if (parameters->output_is_shared())
+ else if (parameters->options().shared())
addr = 0;
else
addr = target->default_text_segment_address();
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
+ SELECT_SIZE_ENDIAN_NAME(32, false)(
+ versions, symtab, local_symcount, dynamic_symbols, dynstr
+ SELECT_SIZE_ENDIAN(32, false));
+ 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
+ SELECT_SIZE_ENDIAN_NAME(32, true)(
+ versions, symtab, local_symcount, dynamic_symbols, dynstr
+ SELECT_SIZE_ENDIAN(32, true));
+ 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
+ SELECT_SIZE_ENDIAN_NAME(64, false)(
+ versions, symtab, local_symcount, dynamic_symbols, dynstr
+ SELECT_SIZE_ENDIAN(64, false));
+ break;
#endif
- }
+#ifdef HAVE_TARGET_64_BIG
+ case Parameters::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));
+ break;
+#endif
+ default:
+ gold_unreachable();
}
- else
- gold_unreachable();
}
// Create the version sections, sized version.
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();
}
}
- 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();
Layout_task_runner(const General_options& options,
const Input_objects* input_objects,
Symbol_table* symtab,
+ Target* target,
Layout* layout)
: options_(options), input_objects_(input_objects), symtab_(symtab),
- layout_(layout)
+ target_(target), layout_(layout)
{ }
// Run the operation.
const General_options& options_;
const Input_objects* input_objects_;
Symbol_table* symtab_;
+ Target* target_;
Layout* layout_;
};
// Finalize the layout after all the input sections have been added.
off_t
- finalize(const Input_objects*, Symbol_table*, const Task*);
+ finalize(const Input_objects*, Symbol_table*, Target*, const Task*);
// Return whether any sections require postprocessing.
bool
// Initialize the global parameters, to let random code get to the
// errors object.
- initialize_parameters(&errors);
+ set_parameters_errors(&errors);
// Handle the command line options.
Command_line command_line;
start_time = get_run_time();
// Store some options in the globally accessible parameters.
- set_parameters_from_options(&command_line.options());
+ set_parameters_options(&command_line.options());
// Do this as early as possible (since it prints a welcome message).
write_debug_script(command_line.options().output_file_name(),
// permit symbols to be forced local with -r, though, as it would
// permit some linker optimizations. Perhaps we need yet another
// option to control this. FIXME.
- if (parameters->output_is_object())
+ if (parameters->options().relocatable())
command_line.script_options().version_script_info()->clear();
// The work queue.
if ((flags & elfcpp::GRP_COMDAT) == 0
|| layout->add_comdat(signature, true))
{
- if (parameters->output_is_object())
+ if (parameters->options().relocatable())
layout->layout_group(symtab, this, index, name, signature, shdr,
pword);
return true;
std::vector<bool> omit(shnum, false);
// Keep track of reloc sections when emitting relocations.
- const bool output_is_object = parameters->output_is_object();
- const bool emit_relocs = output_is_object || parameters->emit_relocs();
+ const bool relocatable = parameters->options().relocatable();
+ const bool emit_relocs = (relocatable
+ || parameters->options().emit_relocs());
std::vector<unsigned int> reloc_sections;
// Keep track of .eh_frame sections.
if (this->handle_gnu_warning_section(name, i, symtab))
{
- if (!output_is_object)
+ if (!relocatable)
omit[i] = true;
}
continue;
}
- if (output_is_object && shdr.get_sh_type() == elfcpp::SHT_GROUP)
+ if (relocatable && shdr.get_sh_type() == elfcpp::SHT_GROUP)
continue;
// The .eh_frame section is special. It holds exception frame
// sections so that the exception frame reader can reliably
// determine which sections are being discarded, and discard the
// corresponding information.
- if (!output_is_object
+ if (!relocatable
&& strcmp(name, ".eh_frame") == 0
&& this->check_eh_frame_flags(&shdr))
{
const Stringpool* sympool,
const Stringpool* dynpool)
{
- if (parameters->strip_all() && this->output_local_dynsym_count_ == 0)
+ if (parameters->options().strip_all()
+ && this->output_local_dynsym_count_ == 0)
return;
gold_assert(this->symtab_shndx_ != -1U);
}
// Write the symbol to the output symbol table.
- if (!parameters->strip_all()
+ if (!parameters->options().strip_all()
&& this->local_values_[i].needs_output_symtab_entry())
{
elfcpp::Sym_write<size, big_endian> osym(ov);
else
{
info->enclosing_symbol_name = symbol_names + sym.get_st_name();
- if (parameters->demangle())
+ if (parameters->options().demangle())
{
char* demangled_name = cplus_demangle(
info->enclosing_symbol_name.c_str(),
{
// Set the global target from the first object file we recognize.
Target* target = obj->target();
- if (!parameters->is_target_valid())
+ if (!parameters->target_valid())
set_parameters_target(target);
- else if (target != parameters->target())
+ else if (target != ¶meters->target())
{
obj->error(_("incompatible target"));
return false;
#include "debug.h"
#include "script.h"
-#include "target-select.h"
#include "options.h"
namespace gold
this->oformat_ = string_to_object_format(arg);
}
-// The x86_64 kernel build converts a binary file to an object file
-// using -r --format binary --oformat elf32-i386 foo.o. In order to
-// support that for gold we support determining the default target
-// choice from the output format. We recognize names that the GNU
-// linker uses.
-
-Target*
-General_options::default_target() const
-{
- if (this->oformat_string_ != NULL)
- {
- Target* target = select_target_by_name(this->oformat_string_);
- if (target != NULL)
- return target;
-
- gold_error(_("unrecognized output format %s"),
- this->oformat_string_);
- }
-
- // The GOLD_DEFAULT_xx macros are defined by the configure script.
- Target* target = select_target(elfcpp::GOLD_DEFAULT_MACHINE,
- GOLD_DEFAULT_SIZE,
- GOLD_DEFAULT_BIG_ENDIAN,
- 0, 0);
- gold_assert(target != NULL);
- return target;
-}
-
// Handle the -z option.
void
oformat() const
{ return this->oformat_; }
+ const char*
+ oformat_string() const
+ { return this->oformat_string_; }
+
// Return the default target.
Target*
default_target() const;
shared() const
{ return this->is_shared_; }
+ // This is not defined via a flag, but combines flags to say whether
+ // the output is position-independent or not.
+ bool
+ output_is_position_independent() const
+ { return this->shared(); }
+
// --static: Whether doing a static link.
bool
is_static() const
uint64_t
Output_data::default_alignment()
{
- return Output_data::default_alignment_for_size(parameters->get_size());
+ return Output_data::default_alignment_for_size(
+ parameters->target().get_size());
}
// Return the default alignment for a size--32 or 64.
{
// Count all the sections. Start with 1 for the null section.
off_t count = 1;
- if (!parameters->output_is_object())
+ if (!parameters->options().relocatable())
{
for (Layout::Segment_list::const_iterator p = segment_list->begin();
p != segment_list->end();
}
count += unattached_section_list->size();
- const int size = parameters->get_size();
+ const int size = parameters->target().get_size();
int shdr_size;
if (size == 32)
shdr_size = elfcpp::Elf_sizes<32>::shdr_size;
void
Output_section_headers::do_write(Output_file* of)
{
- if (parameters->get_size() == 32)
+ switch (parameters->size_and_endianness())
{
- if (parameters->is_big_endian())
- {
-#ifdef HAVE_TARGET_32_BIG
- this->do_sized_write<32, true>(of);
-#else
- gold_unreachable();
-#endif
- }
- else
- {
#ifdef HAVE_TARGET_32_LITTLE
- this->do_sized_write<32, false>(of);
-#else
- gold_unreachable();
+ case Parameters::TARGET_32_LITTLE:
+ this->do_sized_write<32, false>(of);
+ break;
#endif
- }
- }
- else if (parameters->get_size() == 64)
- {
- if (parameters->is_big_endian())
- {
-#ifdef HAVE_TARGET_64_BIG
- this->do_sized_write<64, true>(of);
-#else
- gold_unreachable();
+#ifdef HAVE_TARGET_32_BIG
+ case Parameters::TARGET_32_BIG:
+ this->do_sized_write<32, true>(of);
+ break;
#endif
- }
- else
- {
#ifdef HAVE_TARGET_64_LITTLE
- this->do_sized_write<64, false>(of);
-#else
- gold_unreachable();
+ case Parameters::TARGET_64_LITTLE:
+ this->do_sized_write<64, false>(of);
+ break;
#endif
- }
+#ifdef HAVE_TARGET_64_BIG
+ case Parameters::TARGET_64_BIG:
+ this->do_sized_write<64, true>(of);
+ break;
+#endif
+ default:
+ gold_unreachable();
}
- else
- gold_unreachable();
}
template<int size, bool big_endian>
v += shdr_size;
unsigned int shndx = 1;
- if (!parameters->output_is_object())
+ if (!parameters->options().relocatable())
{
for (Layout::Segment_list::const_iterator p =
this->segment_list_->begin();
// For a relocatable link, we did unallocated group sections
// above, since they have to come first.
if ((*p)->type() == elfcpp::SHT_GROUP
- && parameters->output_is_object())
+ && parameters->options().relocatable())
continue;
gold_assert(shndx == (*p)->out_shndx());
elfcpp::Shdr_write<size, big_endian> oshdr(v);
const Layout::Segment_list& segment_list)
: segment_list_(segment_list)
{
- const int size = parameters->get_size();
+ const int size = parameters->target().get_size();
int phdr_size;
if (size == 32)
phdr_size = elfcpp::Elf_sizes<32>::phdr_size;
void
Output_segment_headers::do_write(Output_file* of)
{
- if (parameters->get_size() == 32)
+ switch (parameters->size_and_endianness())
{
- if (parameters->is_big_endian())
- {
-#ifdef HAVE_TARGET_32_BIG
- this->do_sized_write<32, true>(of);
-#else
- gold_unreachable();
-#endif
- }
- else
- {
#ifdef HAVE_TARGET_32_LITTLE
- this->do_sized_write<32, false>(of);
-#else
- gold_unreachable();
+ case Parameters::TARGET_32_LITTLE:
+ this->do_sized_write<32, false>(of);
+ break;
#endif
- }
- }
- else if (parameters->get_size() == 64)
- {
- if (parameters->is_big_endian())
- {
-#ifdef HAVE_TARGET_64_BIG
- this->do_sized_write<64, true>(of);
-#else
- gold_unreachable();
+#ifdef HAVE_TARGET_32_BIG
+ case Parameters::TARGET_32_BIG:
+ this->do_sized_write<32, true>(of);
+ break;
#endif
- }
- else
- {
#ifdef HAVE_TARGET_64_LITTLE
- this->do_sized_write<64, false>(of);
-#else
- gold_unreachable();
+ case Parameters::TARGET_64_LITTLE:
+ this->do_sized_write<64, false>(of);
+ break;
#endif
- }
+#ifdef HAVE_TARGET_64_BIG
+ case Parameters::TARGET_64_BIG:
+ this->do_sized_write<64, true>(of);
+ break;
+#endif
+ default:
+ gold_unreachable();
}
- else
- gold_unreachable();
}
template<int size, bool big_endian>
shstrtab_(NULL),
entry_(entry)
{
- const int size = parameters->get_size();
+ const int size = parameters->target().get_size();
int ehdr_size;
if (size == 32)
ehdr_size = elfcpp::Elf_sizes<32>::ehdr_size;
{
gold_assert(this->offset() == 0);
- if (parameters->get_size() == 32)
+ switch (parameters->size_and_endianness())
{
- if (parameters->is_big_endian())
- {
-#ifdef HAVE_TARGET_32_BIG
- this->do_sized_write<32, true>(of);
-#else
- gold_unreachable();
-#endif
- }
- else
- {
#ifdef HAVE_TARGET_32_LITTLE
- this->do_sized_write<32, false>(of);
-#else
- gold_unreachable();
+ case Parameters::TARGET_32_LITTLE:
+ this->do_sized_write<32, false>(of);
+ break;
#endif
- }
- }
- else if (parameters->get_size() == 64)
- {
- if (parameters->is_big_endian())
- {
-#ifdef HAVE_TARGET_64_BIG
- this->do_sized_write<64, true>(of);
-#else
- gold_unreachable();
+#ifdef HAVE_TARGET_32_BIG
+ case Parameters::TARGET_32_BIG:
+ this->do_sized_write<32, true>(of);
+ break;
#endif
- }
- else
- {
#ifdef HAVE_TARGET_64_LITTLE
- this->do_sized_write<64, false>(of);
-#else
- gold_unreachable();
+ case Parameters::TARGET_64_LITTLE:
+ this->do_sized_write<64, false>(of);
+ break;
#endif
- }
+#ifdef HAVE_TARGET_64_BIG
+ case Parameters::TARGET_64_BIG:
+ this->do_sized_write<64, true>(of);
+ break;
+#endif
+ default:
+ gold_unreachable();
}
- else
- gold_unreachable();
}
// Write out the file header with appropriate size and endianess.
oehdr.put_e_ident(e_ident);
elfcpp::ET e_type;
- if (parameters->output_is_object())
+ if (parameters->options().relocatable())
e_type = elfcpp::ET_REL;
- else if (parameters->output_is_shared())
+ else if (parameters->options().shared())
e_type = elfcpp::ET_DYN;
else
e_type = elfcpp::ET_EXEC;
Output_file_header::entry()
{
const bool should_issue_warning = (this->entry_ != NULL
- && parameters->output_is_executable());
+ && !parameters->options().relocatable()
+ && !parameters->options().shared());
// FIXME: Need to support target specific entry symbol.
const char* entry = this->entry_;
void
Output_data_dynamic::do_adjust_output_section(Output_section* os)
{
- if (parameters->get_size() == 32)
+ if (parameters->target().get_size() == 32)
os->set_entsize(elfcpp::Elf_sizes<32>::dyn_size);
- else if (parameters->get_size() == 64)
+ else if (parameters->target().get_size() == 64)
os->set_entsize(elfcpp::Elf_sizes<64>::dyn_size);
else
gold_unreachable();
this->add_constant(elfcpp::DT_NULL, 0);
int dyn_size;
- if (parameters->get_size() == 32)
+ if (parameters->target().get_size() == 32)
dyn_size = elfcpp::Elf_sizes<32>::dyn_size;
- else if (parameters->get_size() == 64)
+ else if (parameters->target().get_size() == 64)
dyn_size = elfcpp::Elf_sizes<64>::dyn_size;
else
gold_unreachable();
void
Output_data_dynamic::do_write(Output_file* of)
{
- if (parameters->get_size() == 32)
+ switch (parameters->size_and_endianness())
{
- if (parameters->is_big_endian())
- {
-#ifdef HAVE_TARGET_32_BIG
- this->sized_write<32, true>(of);
-#else
- gold_unreachable();
-#endif
- }
- else
- {
#ifdef HAVE_TARGET_32_LITTLE
- this->sized_write<32, false>(of);
-#else
- gold_unreachable();
+ case Parameters::TARGET_32_LITTLE:
+ this->sized_write<32, false>(of);
+ break;
#endif
- }
- }
- else if (parameters->get_size() == 64)
- {
- if (parameters->is_big_endian())
- {
-#ifdef HAVE_TARGET_64_BIG
- this->sized_write<64, true>(of);
-#else
- gold_unreachable();
+#ifdef HAVE_TARGET_32_BIG
+ case Parameters::TARGET_32_BIG:
+ this->sized_write<32, true>(of);
+ break;
#endif
- }
- else
- {
#ifdef HAVE_TARGET_64_LITTLE
- this->sized_write<64, false>(of);
-#else
- gold_unreachable();
+ case Parameters::TARGET_64_LITTLE:
+ this->sized_write<64, false>(of);
+ break;
#endif
- }
+#ifdef HAVE_TARGET_64_BIG
+ case Parameters::TARGET_64_BIG:
+ this->sized_write<64, true>(of);
+ break;
+#endif
+ default:
+ gold_unreachable();
}
- else
- gold_unreachable();
}
template<int size, bool big_endian>
p != this->fills_.end();
++p)
{
- std::string fill_data(parameters->target()->code_fill(p->length()));
+ std::string fill_data(parameters->target().code_fill(p->length()));
of->write(output_section_file_offset + p->section_offset(),
fill_data.data(), fill_data.size());
}
{
gold_assert(this->requires_postprocessing());
- Target* target = parameters->target();
unsigned char* buffer = this->postprocessing_buffer();
for (Fill_list::iterator p = this->fills_.begin();
p != this->fills_.end();
++p)
{
- std::string fill_data(target->code_fill(p->length()));
+ std::string fill_data(parameters->target().code_fill(p->length()));
memcpy(buffer + p->section_offset(), fill_data.data(),
fill_data.size());
}
if (::stat(this->name_, &s) == 0 && s.st_size != 0)
unlink_if_ordinary(this->name_);
- int mode = parameters->output_is_object() ? 0666 : 0777;
+ int mode = parameters->options().relocatable() ? 0666 : 0777;
int o = ::open(this->name_, O_RDWR | O_CREAT | O_TRUNC, mode);
if (o < 0)
gold_fatal(_("%s: open: %s"), this->name_, strerror(errno));
#include "options.h"
#include "target.h"
-#include "parameters.h"
+#include "target-select.h"
namespace gold
{
-// Initialize the parameters from the options.
-
-Parameters::Parameters(Errors* errors)
- : errors_(errors), threads_(false), output_file_name_(NULL),
- output_file_type_(OUTPUT_INVALID), emit_relocs_(false), sysroot_(),
- strip_(STRIP_INVALID), allow_shlib_undefined_(false),
- symbolic_(false), demangle_(false), detect_odr_violations_(false),
- optimization_level_(0), export_dynamic_(false), debug_(0),
- is_doing_static_link_valid_(false), doing_static_link_(false),
- is_target_valid_(false), target_(NULL), size_(0), is_big_endian_(false),
- max_page_size_(0), common_page_size_(0)
+void
+Parameters::set_errors(Errors* errors)
{
+ gold_assert(this->errors_ == NULL);
+ this->errors_ = errors;
}
-// Set fields from the command line options.
-
void
-Parameters::set_from_options(const General_options* options)
+Parameters::set_options(const General_options* options)
{
- this->threads_ = options->threads();
- this->output_file_name_ = options->output_file_name();
- this->emit_relocs_ = options->emit_relocs();
- this->sysroot_ = options->sysroot();
- this->allow_shlib_undefined_ = options->allow_shlib_undefined();
- this->symbolic_ = options->Bsymbolic();
- this->demangle_ = options->demangle();
- this->detect_odr_violations_ = options->detect_odr_violations();
- this->optimization_level_ = options->optimize();
- this->export_dynamic_ = options->export_dynamic();
- this->debug_ = options->debug();
-
- if (options->shared())
- this->output_file_type_ = OUTPUT_SHARED;
- else if (options->relocatable())
- this->output_file_type_ = OUTPUT_OBJECT;
- else
- this->output_file_type_ = OUTPUT_EXECUTABLE;
-
- if (options->strip_all())
- this->strip_ = STRIP_ALL;
- else if (options->strip_debug())
- this->strip_ = STRIP_DEBUG;
- else if (options->strip_debug_gdb())
- this->strip_ = STRIP_DEBUG_UNUSED_BY_GDB;
- else
- this->strip_ = STRIP_NONE;
-
- this->max_page_size_ = options->max_page_size();
- this->common_page_size_ = options->common_page_size();
-
- this->options_valid_ = true;
+ gold_assert(!this->options_valid());
+ this->options_ = options;
+ // For speed, we make our own copy of the debug variable.
+ this->debug_ = this->options().debug();
}
-// Set whether we are doing a static link.
-
void
Parameters::set_doing_static_link(bool doing_static_link)
{
+ gold_assert(!this->doing_static_link_valid_);
this->doing_static_link_ = doing_static_link;
- this->is_doing_static_link_valid_ = true;
+ this->doing_static_link_valid_ = true;
}
-// Set the target.
-
void
-Parameters::set_target(Target* target)
+Parameters::set_target(const Target* target)
{
- if (!this->is_target_valid_)
- {
- this->target_ = target;
- this->size_ = target->get_size();
- this->is_big_endian_ = target->is_big_endian();
- this->is_target_valid_ = true;
- }
+ if (!this->target_valid())
+ this->target_ = target;
else
gold_assert(target == this->target_);
}
-// Our local version of the variable, which is not const.
-
-static Parameters* static_parameters;
+// The x86_64 kernel build converts a binary file to an object file
+// using -r --format binary --oformat elf32-i386 foo.o. In order to
+// support that for gold we support determining the default target
+// choice from the output format. We recognize names that the GNU
+// linker uses.
-// The global variable.
+const Target&
+Parameters::default_target() const
+{
+ gold_assert(this->options_valid());
+ if (this->options().oformat_string() != NULL)
+ {
+ const Target* target
+ = select_target_by_name(this->options().oformat_string());
+ if (target != NULL)
+ return *target;
-const Parameters* parameters;
+ gold_error(_("unrecognized output format %s"),
+ this->options().oformat_string());
+ }
-// Initialize the global variable.
+ // The GOLD_DEFAULT_xx macros are defined by the configure script.
+ const Target* target = select_target(elfcpp::GOLD_DEFAULT_MACHINE,
+ GOLD_DEFAULT_SIZE,
+ GOLD_DEFAULT_BIG_ENDIAN,
+ 0, 0);
+ gold_assert(target != NULL);
+ return *target;
+}
-void
-initialize_parameters(Errors* errors)
+Parameters::Target_size_endianness
+Parameters::size_and_endianness() const
{
- parameters = static_parameters = new Parameters(errors);
+ if (this->target().get_size() == 32)
+ {
+ if (!this->target().is_big_endian())
+ {
+#ifdef HAVE_TARGET_32_LITTLE
+ return TARGET_32_LITTLE;
+#else
+ gold_unreachable();
+#endif
+ }
+ else
+ {
+#ifdef HAVE_TARGET_32_BIG
+ return TARGET_32_BIG;
+#else
+ gold_unreachable();
+#endif
+ }
+ }
+ else if (parameters->target().get_size() == 64)
+ {
+ if (!parameters->target().is_big_endian())
+ {
+#ifdef HAVE_TARGET_64_LITTLE
+ return TARGET_64_LITTLE;
+#else
+ gold_unreachable();
+#endif
+ }
+ else
+ {
+#ifdef HAVE_TARGET_64_BIG
+ return TARGET_64_BIG;
+#else
+ gold_unreachable();
+#endif
+ }
+ }
+ else
+ gold_unreachable();
}
-// Set values from the options.
-void
-set_parameters_from_options(const General_options* options)
-{
- static_parameters->set_from_options(options);
-}
+// Our local version of the variable, which is not const.
+
+static Parameters static_parameters;
+
+// The global variable.
-// Set whether we are doing a static link.
+const Parameters* parameters = &static_parameters;
void
-set_parameters_doing_static_link(bool doing_static_link)
-{
- static_parameters->set_doing_static_link(doing_static_link);
-}
+set_parameters_errors(Errors* errors)
+{ static_parameters.set_errors(errors); }
-// Set the target.
+void
+set_parameters_options(const General_options* options)
+{ static_parameters.set_options(options); }
void
-set_parameters_target(Target* target)
-{
- static_parameters->set_target(target);
-}
+set_parameters_target(const Target* target)
+{ static_parameters.set_target(target); }
+
+void
+set_parameters_doing_static_link(bool doing_static_link)
+{ static_parameters.set_doing_static_link(doing_static_link); }
} // End namespace gold.
// Here we define the Parameters class which simply holds simple
// general parameters which apply to the entire link. We use a global
-// variable for this. This is in contrast to the General_options
-// class, which holds the complete state of position independent
-// command line options. The hope is that Parameters will stay fairly
-// simple, so that if this turns into a library it will be clear how
-// these parameters should be set.
+// variable for this. The parameters class holds three types of data:
+// 1) An Errors struct. Any part of the code that wants to log an
+// error can use parameters->errors().
+// 2) A const General_options. These are the options as read on
+// the commandline.
+// 3) Target information, such as size and endian-ness. This is
+// available as soon as we've decided on the Target (after
+// parsing the first .o file).
+// 4) Whether we're doing a static link or not. This is set
+// after all inputs have been read and we know if any is a
+// dynamic library.
class Parameters
{
public:
- Parameters(Errors*);
+ Parameters()
+ : errors_(NULL), options_(NULL), target_(NULL),
+ doing_static_link_valid_(false), doing_static_link_(false),
+ debug_(0)
+ { }
+
+ // These should be called as soon as they are known.
+ void
+ set_errors(Errors* errors);
+
+ void
+ set_options(const General_options* options);
+
+ void
+ set_target(const Target* target);
+
+ void
+ set_doing_static_link(bool doing_static_link);
// Return the error object.
Errors*
// called, but it is needed by gold_exit.
bool
options_valid() const
- { return this->options_valid_; }
-
- // Whether to use threads.
- bool
- threads() const
- {
- gold_assert(this->options_valid_);
- return this->threads_;
- }
-
- // Return the output file name.
- const char*
- output_file_name() const
- {
- gold_assert(this->options_valid_);
- return this->output_file_name_;
- }
-
- // Whether we are generating a regular executable.
- bool
- output_is_executable() const
- {
- gold_assert(this->output_file_type_ != OUTPUT_INVALID);
- return this->output_file_type_ == OUTPUT_EXECUTABLE;
- }
-
- // Whether we are generating a shared library.
- bool
- output_is_shared() const
- {
- gold_assert(this->output_file_type_ != OUTPUT_INVALID);
- return this->output_file_type_ == OUTPUT_SHARED;
- }
-
- // Whether we are generating an object file.
- bool
- output_is_object() const
- {
- gold_assert(this->output_file_type_ != OUTPUT_INVALID);
- return this->output_file_type_ == OUTPUT_OBJECT;
- }
-
- // Whether we are generating position-independent output.
- // This is the case when generating either a shared library
- // or a regular executable with the --pic-executable option.
- // FIXME: support --pic-executable
- bool
- output_is_position_independent() const
- { return output_is_shared(); }
-
- // Whether to emit relocations in the output.
- bool
- emit_relocs() const
- { return this->emit_relocs_; }
-
- // The target system root directory. This is NULL if there isn't
- // one.
- const std::string&
- sysroot() const
- {
- gold_assert(this->options_valid_);
- return this->sysroot_;
- }
-
- // Whether to strip all symbols.
- bool
- strip_all() const
- {
- gold_assert(this->strip_ != STRIP_INVALID);
- return this->strip_ == STRIP_ALL;
- }
-
- // Whether to strip debugging information.
- bool
- strip_debug() const
- {
- gold_assert(this->strip_ != STRIP_INVALID);
- return this->strip_ == STRIP_ALL || this->strip_ == STRIP_DEBUG;
- }
-
- // Whether to strip debugging information that's not used by gdb.
- bool
- strip_debug_gdb() const
- {
- gold_assert(this->strip_ != STRIP_INVALID);
- return this->strip_debug() || this->strip_ == STRIP_DEBUG_UNUSED_BY_GDB;
- }
-
- // Whether to permit unresolved references from shared libraries.
- bool
- allow_shlib_undefined() const
- {
- gold_assert(this->options_valid_);
- return this->allow_shlib_undefined_;
- }
-
- // Whether we are doing a symbolic link, in which all defined
- // symbols are bound locally.
- bool
- Bsymbolic() const
- {
- gold_assert(this->options_valid_);
- return this->symbolic_;
- }
-
- // Whether we should demangle C++ symbols in our log messages.
- bool
- demangle() const
- { return this->demangle_; }
-
- // Whether we should try to detect violations of the One Definition Rule.
- bool
- detect_odr_violations() const
- {
- gold_assert(this->options_valid_);
- return this->detect_odr_violations_;
- }
-
- // The general linker optimization level (-O).
- int
- optimize() const
- {
- gold_assert(this->options_valid_);
- return this->optimization_level_;
- }
-
- // Whether the -E/--export-dynamic flag is set.
- bool
- export_dynamic() const
- {
- gold_assert(this->options_valid_);
- return this->export_dynamic_;
- }
+ { return this->options_ != NULL; }
- // Return the debug flags. These are the flags for which we should
- // report internal debugging information.
- unsigned int
- debug() const
- {
- gold_assert(this->options_valid_);
- return this->debug_;
- }
-
- // Whether we are doing a static link--a link in which none of the
- // input files are shared libraries. This is only known after we
- // have seen all the input files.
- bool
- doing_static_link() const
+ // Return the options object.
+ const General_options&
+ options() const
{
- gold_assert(this->is_doing_static_link_valid_);
- return this->doing_static_link_;
+ gold_assert(this->options_valid());
+ return *this->options_;
}
// Return whether the target field has been set.
bool
- is_target_valid() const
- { return this->is_target_valid_; }
+ target_valid() const
+ { return this->target_ != NULL; }
// The target of the output file we are generating.
- Target*
+ const Target&
target() const
{
- gold_assert(this->is_target_valid_);
- return this->target_;
+ gold_assert(this->target_valid());
+ return *this->target_;
}
- // The size of the output file we are generating. This should
- // return 32 or 64.
- int
- get_size() const
- {
- gold_assert(this->is_target_valid_);
- return this->size_;
- }
+ // When we don't have an output file to associate a target, make a
+ // default one, with guesses about size and endianness.
+ const Target&
+ default_target() const;
- // Whether the output is big endian.
bool
- is_big_endian() const
- {
- gold_assert(this->is_target_valid_);
- return this->is_big_endian_;
- }
-
- // The maximum page size
- uint64_t
- max_page_size() const
+ doing_static_link() const
{
- gold_assert(this->is_target_valid_);
- return this->max_page_size_;
+ gold_assert(this->doing_static_link_valid_);
+ return this->doing_static_link_;
}
- // The common page size
- uint64_t
- common_page_size() const
+ // This is just a copy of options().debug(). We make a copy so we
+ // don't have to #include options.h in order to inline
+ // is_debugging_enabled, below.
+ int
+ debug() const
{
- gold_assert(this->is_target_valid_);
- return this->common_page_size_;
+ gold_assert(this->options_valid());
+ return debug_;
}
- // Set values recorded from options.
- void
- set_from_options(const General_options*);
+ // A convenience routine for combining size and endianness. It also
+ // checks the HAVE_TARGET_FOO configure options and dies if the
+ // current target's size/endianness is not supported according to
+ // HAVE_TARGET_FOO. Otherwise it returns this enum
+ enum Target_size_endianness
+ { TARGET_32_LITTLE, TARGET_32_BIG, TARGET_64_LITTLE, TARGET_64_BIG };
- // Set whether we are doing a static link.
- void
- set_doing_static_link(bool doing_static_link);
+ Target_size_endianness
+ size_and_endianness() const;
- // Set the target.
- void
- set_target(Target* target);
private:
- // The types of output files.
- enum Output_file_type
- {
- // Uninitialized.
- OUTPUT_INVALID,
- // Generating executable.
- OUTPUT_EXECUTABLE,
- // Generating shared library.
- OUTPUT_SHARED,
- // Generating object file.
- OUTPUT_OBJECT
- };
-
- // Which symbols to strip.
- enum Strip
- {
- // Uninitialize.
- STRIP_INVALID,
- // Don't strip any symbols.
- STRIP_NONE,
- // Strip all symbols.
- STRIP_ALL,
- // Strip debugging information.
- STRIP_DEBUG,
- // Strip debugging information that's not used by gdb (at least <= 6.7)
- STRIP_DEBUG_UNUSED_BY_GDB
- };
-
- // A pointer to the error handling object.
Errors* errors_;
-
- // Whether the fields set from the options are valid.
- bool options_valid_;
- // Whether to use threads.
- bool threads_;
- // The output file name.
- const char* output_file_name_;
- // The type of the output file.
- Output_file_type output_file_type_;
- // Whether to emit relocations (-q/--emit-relocs).
- bool emit_relocs_;
- // The target system root directory.
- std::string sysroot_;
- // Which symbols to strip.
- Strip strip_;
- // Whether to allow undefined references from shared libraries.
- bool allow_shlib_undefined_;
- // Whether we are doing a symbolic link.
- bool symbolic_;
- // Whether we should demangle C++ symbols in our log messages.
- bool demangle_;
- // Whether we try to detect One Definition Rule violations.
- bool detect_odr_violations_;
- // The optimization level.
- int optimization_level_;
- // Whether the -E/--export-dynamic flag is set.
- bool export_dynamic_;
- // The debug flags.
- unsigned int debug_;
-
- // Whether the doing_static_link_ field is valid.
- bool is_doing_static_link_valid_;
- // Whether we are doing a static link.
+ const General_options* options_;
+ const Target* target_;
+ bool doing_static_link_valid_;
bool doing_static_link_;
- // Whether the target_ field is valid.
- bool is_target_valid_;
- // The target.
- Target* target_;
- // The size of the output file--32 or 64.
- int size_;
- // Whether the output file is big endian.
- bool is_big_endian_;
- // The maximum page size and common page size
- int max_page_size_;
- int common_page_size_;
+ int debug_;
};
// This is a global variable.
extern const Parameters* parameters;
-// Initialize the global variable.
-extern void initialize_parameters(Errors*);
+// We use free functions for these since they affect a global variable
+// that is internal to parameters.cc.
-// Set the options.
-extern void set_parameters_from_options(const General_options*);
+extern void
+set_parameters_errors(Errors* errors);
-// Set the target recorded in the global parameters variable.
-extern void set_parameters_target(Target* target);
+extern void
+set_parameters_options(const General_options* options);
-// Set whether we are doing a static link.
-extern void set_parameters_doing_static_link(bool doing_static_link);
+extern void
+set_parameters_target(const Target* target);
+extern void
+set_parameters_doing_static_link(bool doing_static_link);
+
// Return whether we are doing a particular debugging type. The
// argument is one of the flags from debug.h.
bool is_section_allocated = ((secshdr.get_sh_flags() & elfcpp::SHF_ALLOC)
!= 0);
if (!is_section_allocated
- && !parameters->output_is_object()
- && !parameters->emit_relocs())
+ && !parameters->options().relocatable()
+ && !parameters->options().emit_relocs())
continue;
if (shdr.get_sh_link() != this->symtab_shndx_)
p != rd->relocs.end();
++p)
{
- if (!parameters->output_is_object())
+ if (!parameters->options().relocatable())
{
// As noted above, when not generating an object file, we
// only scan allocated sections. We may see a non-allocated
p->needs_special_offset_handling,
this->local_symbol_count_,
local_symbols);
- if (parameters->emit_relocs())
+ if (parameters->options().emit_relocs())
this->emit_relocs_scan(options, symtab, layout, local_symbols, p);
}
else
if (shdr.get_sh_type() == elfcpp::SHT_NOBITS)
continue;
- if ((parameters->output_is_object() || parameters->emit_relocs())
+ if ((parameters->options().relocatable()
+ || parameters->options().emit_relocs())
&& (shdr.get_sh_type() == elfcpp::SHT_REL
|| shdr.get_sh_type() == elfcpp::SHT_RELA)
&& (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
off_t output_offset = map_sections[index].offset;
gold_assert((*pviews)[index].view != NULL);
- if (parameters->output_is_object())
+ if (parameters->options().relocatable())
gold_assert((*pviews)[i].view != NULL);
if (shdr.get_sh_link() != this->symtab_shndx_)
relinfo.reloc_shndx = i;
relinfo.data_shndx = index;
- if (!parameters->output_is_object())
+ if (!parameters->options().relocatable())
{
target->relocate_section(&relinfo,
sh_type,
(*pviews)[index].view,
(*pviews)[index].address,
(*pviews)[index].view_size);
- if (parameters->emit_relocs())
+ if (parameters->options().emit_relocs())
this->emit_relocs(&relinfo, i, sh_type, prelocs, reloc_count,
os, output_offset,
(*pviews)[index].view,
// is an ODR violation. But it's helpful to warn about.)
// We use orig_sym here because we want the symbol exactly as it
// appears in the object file, not munged via our future processing.
- if (parameters->detect_odr_violations()
+ if (parameters->options().detect_odr_violations()
&& orig_sym.get_st_bind() == elfcpp::STB_WEAK
&& to->binding() == elfcpp::STB_WEAK
&& orig_sym.get_st_shndx() != elfcpp::SHN_UNDEF
this->dot_value_,
this->dot_section_, &dummy);
- if (parameters->is_big_endian())
+ if (parameters->target().is_big_endian())
this->endian_write_to_buffer<true>(val, buf);
else
this->endian_write_to_buffer<false>(val, buf);
elfcpp::Swap_unaligned<32, big_endian>::writeval(buf, val);
break;
case 8:
- if (parameters->get_size() == 32)
+ if (parameters->target().get_size() == 32)
{
val &= 0xffffffff;
if (this->is_signed_ && (val & 0x80000000) != 0)
size_t segment_count = layout->segment_count();
size_t file_header_size;
size_t segment_headers_size;
- if (parameters->get_size() == 32)
+ if (parameters->target().get_size() == 32)
{
file_header_size = elfcpp::Elf_sizes<32>::ehdr_size;
segment_headers_size = segment_count * elfcpp::Elf_sizes<32>::phdr_size;
}
- else if (parameters->get_size() == 64)
+ else if (parameters->target().get_size() == 64)
{
file_header_size = elfcpp::Elf_sizes<64>::ehdr_size;
segment_headers_size = segment_count * elfcpp::Elf_sizes<64>::phdr_size;
Script_sections::header_size_adjustment(uint64_t lma,
size_t sizeof_headers) const
{
- const uint64_t abi_pagesize = parameters->target()->abi_pagesize();
+ const uint64_t abi_pagesize = parameters->target().abi_pagesize();
uint64_t hdr_lma = lma - sizeof_headers;
hdr_lma &= ~(abi_pagesize - 1);
return lma - hdr_lma;
{
gold_assert(this->saw_sections_clause_);
- if (parameters->output_is_object())
+ if (parameters->options().relocatable())
return NULL;
if (this->saw_phdrs_clause())
this->create_note_and_tls_segments(layout, §ions);
// Walk through the sections adding them to PT_LOAD segments.
- const uint64_t abi_pagesize = parameters->target()->abi_pagesize();
+ const uint64_t abi_pagesize = parameters->target().abi_pagesize();
Output_segment* first_seg = NULL;
Output_segment* current_seg = NULL;
bool is_current_seg_readonly = true;
return;
}
- if (parameters->get_size() == 32)
+ if (parameters->target().get_size() == 32)
{
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
this->sized_finalize<32>(symtab, layout, is_dot_available, dot_value,
gold_unreachable();
#endif
}
- else if (parameters->get_size() == 64)
+ else if (parameters->target().get_size() == 64)
{
#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
this->sized_finalize<64>(symtab, layout, is_dot_available, dot_value,
if (val_section != NULL)
return;
- if (parameters->get_size() == 32)
+ if (parameters->target().get_size() == 32)
{
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
Sized_symbol<32>* ssym = symtab->get_sized_symbol<32>(this->sym_);
gold_unreachable();
#endif
}
- else if (parameters->get_size() == 64)
+ else if (parameters->target().get_size() == 64)
{
#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
Sized_symbol<64>* ssym = symtab->get_sized_symbol<64>(this->sym_);
{
if (closure->is_in_sysroot())
{
- const std::string& sysroot(parameters->sysroot());
+ const std::string& sysroot(parameters->options().sysroot());
gold_assert(!sysroot.empty());
name_string = sysroot + name_string;
}
// the strtab size, and gives a relatively small benefit (it's
// typically rare for a symbol to be a suffix of another), we only
// take the time to sort when the user asks for heavy optimization.
- if (parameters->optimize() < 2)
+ if (parameters->options().optimize() < 2)
{
for (typename String_set_type::iterator curr = this->string_set_.begin();
curr != this->string_set_.end();
static std::string
demangle(const char* name)
{
- if (!parameters->demangle())
+ if (!parameters->options().demangle())
return name;
// cplus_demangle allocates memory for the result it returns,
// If exporting all symbols or building a shared library,
// and the symbol is defined in a regular object and is
// externally visible, we need to add it.
- if ((parameters->export_dynamic() || parameters->output_is_shared())
+ if ((parameters->options().export_dynamic() || parameters->options().shared())
&& !this->is_from_dynobj()
&& this->is_externally_visible())
return true;
{
// If we are not generating an executable, then no final values are
// known, since they will change at runtime.
- if (!parameters->output_is_executable())
+ if (parameters->options().shared() || parameters->options().relocatable())
return false;
// If the symbol is not from an object file, then it is defined, and
typename Sized_relobj<size, big_endian>::Symbols* sympointers)
{
gold_assert(size == relobj->target()->get_size());
- gold_assert(size == parameters->get_size());
+ gold_assert(size == parameters->target().get_size());
const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
const std::vector<const char*>* version_map)
{
gold_assert(size == dynobj->target()->get_size());
- gold_assert(size == parameters->get_size());
+ gold_assert(size == parameters->target().get_size());
if (dynobj->just_symbols())
{
}
}
- const Target* target = parameters->target();
- if (!target->has_make_symbol())
+ const Target& target = parameters->target();
+ if (!target.has_make_symbol())
sym = new Sized_symbol<size>();
else
{
- gold_assert(target->get_size() == size);
- gold_assert(target->is_big_endian() ? big_endian : !big_endian);
+ gold_assert(target.get_size() == size);
+ gold_assert(target.is_big_endian() ? big_endian : !big_endian);
typedef Sized_target<size, big_endian> My_target;
const My_target* sized_target =
- static_cast<const My_target*>(target);
+ static_cast<const My_target*>(&target);
sym = sized_target->make_symbol();
if (sym == NULL)
return NULL;
bool offset_is_from_end,
bool only_if_ref)
{
- if (parameters->get_size() == 32)
+ if (parameters->target().get_size() == 32)
{
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
return this->do_define_in_output_data<32>(name, version, od,
gold_unreachable();
#endif
}
- else if (parameters->get_size() == 64)
+ else if (parameters->target().get_size() == 64)
{
#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
return this->do_define_in_output_data<64>(name, version, od,
Sized_symbol<size>* sym;
Sized_symbol<size>* oldsym;
- if (parameters->is_big_endian())
+ if (parameters->target().is_big_endian())
{
#if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG)
sym = this->define_special_symbol SELECT_SIZE_ENDIAN_NAME(size, true) (
Symbol::Segment_offset_base offset_base,
bool only_if_ref)
{
- if (parameters->get_size() == 32)
+ if (parameters->target().get_size() == 32)
{
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
return this->do_define_in_output_segment<32>(name, version, os,
gold_unreachable();
#endif
}
- else if (parameters->get_size() == 64)
+ else if (parameters->target().get_size() == 64)
{
#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
return this->do_define_in_output_segment<64>(name, version, os,
Sized_symbol<size>* sym;
Sized_symbol<size>* oldsym;
- if (parameters->is_big_endian())
+ if (parameters->target().is_big_endian())
{
#if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG)
sym = this->define_special_symbol SELECT_SIZE_ENDIAN_NAME(size, true) (
bool only_if_ref,
bool force_override)
{
- if (parameters->get_size() == 32)
+ if (parameters->target().get_size() == 32)
{
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
return this->do_define_as_constant<32>(name, version, value,
gold_unreachable();
#endif
}
- else if (parameters->get_size() == 64)
+ else if (parameters->target().get_size() == 64)
{
#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
return this->do_define_as_constant<64>(name, version, value,
Sized_symbol<size>* sym;
Sized_symbol<size>* oldsym;
- if (parameters->is_big_endian())
+ if (parameters->target().is_big_endian())
{
#if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG)
sym = this->define_special_symbol SELECT_SIZE_ENDIAN_NAME(size, true) (
this->first_dynamic_global_index_ = dyn_global_index;
this->dynamic_count_ = dyncount;
- if (parameters->get_size() == 32)
+ if (parameters->target().get_size() == 32)
{
#if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_32_LITTLE)
ret = this->sized_finalize<32>(off, pool, plocal_symcount);
gold_unreachable();
#endif
}
- else if (parameters->get_size() == 64)
+ else if (parameters->target().get_size() == 64)
{
#if defined(HAVE_TARGET_64_BIG) || defined(HAVE_TARGET_64_LITTLE)
ret = this->sized_finalize<64>(off, pool, plocal_symcount);
sym->set_value(value);
- if (parameters->strip_all())
+ if (parameters->options().strip_all())
{
sym->set_symtab_index(-1U);
return false;
const Stringpool* sympool,
const Stringpool* dynpool, Output_file* of) const
{
- if (parameters->get_size() == 32)
+ switch (parameters->size_and_endianness())
{
- if (parameters->is_big_endian())
- {
-#ifdef HAVE_TARGET_32_BIG
- this->sized_write_globals<32, true>(input_objects, sympool,
- dynpool, of);
-#else
- gold_unreachable();
-#endif
- }
- else
- {
#ifdef HAVE_TARGET_32_LITTLE
- this->sized_write_globals<32, false>(input_objects, sympool,
- dynpool, of);
-#else
- gold_unreachable();
+ case Parameters::TARGET_32_LITTLE:
+ this->sized_write_globals<32, false>(input_objects, sympool,
+ dynpool, of);
+ break;
#endif
- }
- }
- else if (parameters->get_size() == 64)
- {
- if (parameters->is_big_endian())
- {
-#ifdef HAVE_TARGET_64_BIG
- this->sized_write_globals<64, true>(input_objects, sympool,
- dynpool, of);
-#else
- gold_unreachable();
+#ifdef HAVE_TARGET_32_BIG
+ case Parameters::TARGET_32_BIG:
+ this->sized_write_globals<32, true>(input_objects, sympool,
+ dynpool, of);
+ break;
#endif
- }
- else
- {
#ifdef HAVE_TARGET_64_LITTLE
- this->sized_write_globals<64, false>(input_objects, sympool,
- dynpool, of);
-#else
- gold_unreachable();
+ case Parameters::TARGET_64_LITTLE:
+ this->sized_write_globals<64, false>(input_objects, sympool,
+ dynpool, of);
+ break;
#endif
- }
+#ifdef HAVE_TARGET_64_BIG
+ case Parameters::TARGET_64_BIG:
+ this->sized_write_globals<64, true>(input_objects, sympool,
+ dynpool, of);
+ break;
+#endif
+ default:
+ gold_unreachable();
}
- else
- gold_unreachable();
}
// Write out the global symbols.
const Stringpool* dynpool,
Output_file* of) const
{
- const Target* const target = parameters->target();
+ const Target& target = parameters->target();
const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
if (symobj->is_dynamic())
{
if (sym->needs_dynsym_value())
- dynsym_value = target->dynsym_value(sym);
+ dynsym_value = target.dynsym_value(sym);
shndx = elfcpp::SHN_UNDEF;
}
else if (in_shndx == elfcpp::SHN_UNDEF
// In object files symbol values are section
// relative.
- if (parameters->output_is_object())
+ if (parameters->options().relocatable())
sym_value -= os->address();
}
}
&& sym->object()->is_dynamic()
&& sym->shndx() == elfcpp::SHN_UNDEF
&& sym->binding() != elfcpp::STB_WEAK
- && !parameters->allow_shlib_undefined()
- && !parameters->target()->is_defined_by_abi(sym)
+ && !parameters->options().allow_shlib_undefined()
+ && !parameters->target().is_defined_by_abi(sym)
&& !input_objects->found_in_system_library_directory(sym->object()))
{
// A very ugly cast.
Output_file* of,
off_t offset) const
{
- if (parameters->get_size() == 32)
+ switch (parameters->size_and_endianness())
{
- if (parameters->is_big_endian())
- {
-#ifdef HAVE_TARGET_32_BIG
- this->sized_write_section_symbol<32, true>(os, of, offset);
-#else
- gold_unreachable();
-#endif
- }
- else
- {
#ifdef HAVE_TARGET_32_LITTLE
- this->sized_write_section_symbol<32, false>(os, of, offset);
-#else
- gold_unreachable();
+ case Parameters::TARGET_32_LITTLE:
+ this->sized_write_section_symbol<32, false>(os, of, offset);
+ break;
#endif
- }
- }
- else if (parameters->get_size() == 64)
- {
- if (parameters->is_big_endian())
- {
-#ifdef HAVE_TARGET_64_BIG
- this->sized_write_section_symbol<64, true>(os, of, offset);
-#else
- gold_unreachable();
+#ifdef HAVE_TARGET_32_BIG
+ case Parameters::TARGET_32_BIG:
+ this->sized_write_section_symbol<32, true>(os, of, offset);
+ break;
#endif
- }
- else
- {
#ifdef HAVE_TARGET_64_LITTLE
- this->sized_write_section_symbol<64, false>(os, of, offset);
-#else
- gold_unreachable();
+ case Parameters::TARGET_64_LITTLE:
+ this->sized_write_section_symbol<64, false>(os, of, offset);
+ break;
#endif
- }
+#ifdef HAVE_TARGET_64_BIG
+ case Parameters::TARGET_64_BIG:
+ this->sized_write_section_symbol<64, true>(os, of, offset);
+ break;
+#endif
+ default:
+ gold_unreachable();
}
- else
- gold_unreachable();
}
// Write out a section symbol, specialized for size and endianness.
&& this->visibility_ != elfcpp::STV_HIDDEN
&& this->visibility_ != elfcpp::STV_PROTECTED
&& !this->is_forced_local_
- && parameters->output_is_shared()
- && !parameters->Bsymbolic());
+ && parameters->options().shared()
+ && !parameters->options().Bsymbolic());
}
// Return true if this symbol is a function that needs a PLT entry.
// An absolute reference within a position-independent output file
// will need a dynamic relocation.
if ((flags & ABSOLUTE_REF)
- && parameters->output_is_position_independent())
+ && parameters->options().output_is_position_independent())
return true;
// A function call that can branch to a local PLT entry does not need
// shared library cannot use a PLT entry.
if ((flags & FUNCTION_CALL)
&& this->has_plt_offset()
- && !((flags & NON_PIC_REF) && parameters->output_is_shared()))
+ && !((flags & NON_PIC_REF) && parameters->options().shared()))
return false;
// A reference to any PLT entry in a non-position-independent executable
// does not need a dynamic relocation.
- if (!parameters->output_is_position_independent()
+ if (!parameters->options().output_is_position_independent()
&& this->has_plt_offset())
return false;
Sized_symbol<size>*
Symbol_table::get_sized_symbol(Symbol* sym ACCEPT_SIZE) const
{
- gold_assert(size == parameters->get_size());
+ gold_assert(size == parameters->target().get_size());
return static_cast<Sized_symbol<size>*>(sym);
}
const Sized_symbol<size>*
Symbol_table::get_sized_symbol(const Symbol* sym ACCEPT_SIZE) const
{
- gold_assert(size == parameters->get_size());
+ gold_assert(size == parameters->target().get_size());
return static_cast<const Sized_symbol<size>*>(sym);
}
if (sym != NULL
&& sym->is_undefined()
&& sym->binding() != elfcpp::STB_WEAK
- && !parameters->output_is_shared())
+ && !parameters->options().shared())
gold_undefined_symbol(sym, relinfo, i, offset);
if (sym != NULL && sym->has_warning())
#define GOLD_TARGET_H
#include "elfcpp.h"
+#include "options.h"
#include "parameters.h"
namespace gold
uint64_t
abi_pagesize() const
{
- if (parameters->max_page_size() > 0)
- return parameters->max_page_size();
+ if (parameters->options().max_page_size() > 0)
+ return parameters->options().max_page_size();
else
return this->pti_->abi_pagesize;
}
uint64_t
common_pagesize() const
{
- if (parameters->common_page_size() > 0)
- return std::min(parameters->common_page_size(),
+ if (parameters->options().common_page_size() > 0)
+ return std::min(parameters->options().common_page_size(),
this->abi_pagesize());
else
return std::min(this->pti_->common_pagesize,
// basically one or more NOPS which must fill out the specified
// length in bytes.
std::string
- code_fill(section_size_type length)
+ code_fill(section_size_type length) const
{ return this->do_code_fill(length); }
// Return whether SYM is known to be defined by the ABI. This is
// Virtual function which must be implemented by the child class if
// needed.
virtual std::string
- do_code_fill(section_size_type)
+ do_code_fill(section_size_type) const
{ gold_unreachable(); }
// Virtual function which may be implemented by the child class.
Binary_test(Test_report*)
{
Errors errors(gold::program_name);
- initialize_parameters(&errors);
+ set_parameters_errors(&errors);
General_options options;
- set_parameters_from_options(&options);
+ set_parameters_options(&options);
int fail = 0;
// Return a string used to fill a code section with nops.
std::string
- do_code_fill(section_size_type length);
+ do_code_fill(section_size_type length) const;
// Return whether SYM is defined by the ABI.
bool
bool
may_need_copy_reloc(Symbol* gsym)
{
- return (!parameters->output_is_shared()
+ return (!parameters->options().shared()
&& gsym->is_from_dynobj()
&& gsym->type() != elfcpp::STT_FUNC);
}
{
// If we are generating a shared library, then we can't do anything
// in the linker.
- if (parameters->output_is_shared())
+ if (parameters->options().shared())
return tls::TLSOPT_NONE;
switch (r_type)
// link-time value, so we flag the location with an
// R_X86_64_RELATIVE relocation so the dynamic loader can
// relocate it easily.
- if (parameters->output_is_position_independent())
+ if (parameters->options().output_is_position_independent())
{
unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
// executable), we need to create a dynamic relocation for this
// location. We can't use an R_X86_64_RELATIVE relocation
// because that is always a 64-bit relocation.
- if (parameters->output_is_position_independent())
+ if (parameters->options().output_is_position_independent())
{
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
if (lsym.get_st_type() != elfcpp::STT_SECTION)
{
// If we are generating a shared object, we need to add a
// dynamic relocation for this symbol's GOT entry.
- if (parameters->output_is_position_independent())
+ if (parameters->options().output_is_position_independent())
{
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
// R_X86_64_RELATIVE assumes a 64-bit relocation.
case elfcpp::R_X86_64_GOTTPOFF: // Initial-exec
case elfcpp::R_X86_64_TPOFF32: // Local-exec
{
- bool output_is_shared = parameters->output_is_shared();
+ bool output_is_shared = parameters->options().shared();
const tls::Tls_optimization optimized_type
= Target_x86_64::optimize_tls_reloc(!output_is_shared, r_type);
switch (r_type)
// taking the address of a function. In that case we need to
// set the entry in the dynamic symbol table to the address of
// the PLT entry.
- if (gsym->is_from_dynobj() && !parameters->output_is_shared())
+ if (gsym->is_from_dynobj() && !parameters->options().shared())
gsym->set_needs_dynsym_value();
}
// Make a dynamic relocation if necessary.
case elfcpp::R_X86_64_TPOFF32: // Local-exec
layout->set_has_static_tls();
- if (parameters->output_is_shared())
+ if (parameters->options().shared())
unsupported_reloc_local(object, r_type);
break;
elfcpp::Elf_sizes<64>::rela_size);
}
- if (!parameters->output_is_shared())
+ if (!parameters->options().shared())
{
// The value of the DT_DEBUG tag is filled in by the dynamic
// linker at run time, and used by the debugger.
Symbol_value<64> symval;
if (gsym != NULL
&& (gsym->is_from_dynobj()
- || (parameters->output_is_shared()
+ || (parameters->options().shared()
&& (gsym->is_undefined() || gsym->is_preemptible())))
&& gsym->has_plt_offset())
{
elfcpp::Elf_types<64>::Elf_Addr value = psymval->value(relinfo->object, 0);
const bool is_final = (gsym == NULL
- ? !parameters->output_is_position_independent()
+ ? !parameters->options().output_is_position_independent()
: gsym->final_value_is_known());
const tls::Tls_optimization optimized_type
= Target_x86_64::optimize_tls_reloc(is_final, r_type);
// the specified length.
std::string
-Target_x86_64::do_code_fill(section_size_type length)
+Target_x86_64::do_code_fill(section_size_type length) const
{
if (length >= 16)
{