local_values_(),
local_got_offsets_(),
kept_comdat_sections_(),
- comdat_groups_(),
has_eh_frame_(false)
{
}
// Record this section group in the layout, and see whether we've already
// seen one with the same signature.
- bool include_group = ((flags & elfcpp::GRP_COMDAT) == 0
- || layout->add_comdat(this, index, signature, true));
-
+ bool include_group;
Sized_relobj<size, big_endian>* kept_object = NULL;
- Comdat_group* kept_group = NULL;
+ Kept_section::Comdat_group* kept_group = NULL;
- if (!include_group)
- {
- // This group is being discarded. Find the object and group
- // that was kept in its place.
- unsigned int kept_group_index = 0;
- Relobj* kept_relobj = layout->find_kept_object(signature,
- &kept_group_index);
- kept_object = static_cast<Sized_relobj<size, big_endian>*>(kept_relobj);
- if (kept_object != NULL)
- kept_group = kept_object->find_comdat_group(kept_group_index);
- }
- else if (flags & elfcpp::GRP_COMDAT)
+ if ((flags & elfcpp::GRP_COMDAT) == 0)
+ include_group = true;
+ else
{
- // This group is being kept. Create the table to map section names
- // to section indexes and add it to the table of groups.
- kept_group = new Comdat_group();
- this->add_comdat_group(index, kept_group);
+ Kept_section this_group(this, index, true);
+ Kept_section *kept_section_group;
+ include_group = layout->find_or_add_kept_section(signature,
+ &this_group,
+ &kept_section_group);
+ if (include_group)
+ kept_section_group->group_sections = new Kept_section::Comdat_group;
+
+ kept_group = kept_section_group->group_sections;
+ kept_object = (static_cast<Sized_relobj<size, big_endian>*>
+ (kept_section_group->object));
}
size_t count = shdr.get_sh_size() / sizeof(elfcpp::Elf_Word);
{
// Find the corresponding kept section, and store that info
// in the discarded section table.
- Comdat_group::const_iterator p = kept_group->find(mname);
+ Kept_section::Comdat_group::const_iterator p =
+ kept_group->find(mname);
if (p != kept_group->end())
{
Kept_comdat_section* kept =
symname = strrchr(name, '.') + 1;
std::string sig1(symname);
std::string sig2(name);
- bool include1 = layout->add_comdat(this, index, sig1, false);
- bool include2 = layout->add_comdat(this, index, sig2, true);
+ Kept_section candidate1(this, index, false);
+ Kept_section candidate2(this, index, true);
+ Kept_section* kept1;
+ Kept_section* kept2;
+ bool include1 = layout->find_or_add_kept_section(sig1, &candidate1, &kept1);
+ bool include2 = layout->find_or_add_kept_section(sig2, &candidate2, &kept2);
if (!include2)
{
// name (i.e., the kept section was also a linkonce section).
// In this case, the section index stored with the layout object
// is the linkonce section that was kept.
- unsigned int kept_group_index = 0;
- Relobj* kept_relobj = layout->find_kept_object(sig2, &kept_group_index);
+ unsigned int kept_group_index = kept2->shndx;
+ Relobj* kept_relobj = kept2->object;
if (kept_relobj != NULL)
{
- Sized_relobj<size, big_endian>* kept_object
- = static_cast<Sized_relobj<size, big_endian>*>(kept_relobj);
+ Sized_relobj<size, big_endian>* kept_object =
+ static_cast<Sized_relobj<size, big_endian>*>(kept_relobj);
Kept_comdat_section* kept =
new Kept_comdat_section(kept_object, kept_group_index);
this->set_kept_comdat_section(index, kept);
// this linkonce section. We'll handle the simple case where
// the group has only one member section. Otherwise, it's not
// worth the effort.
- unsigned int kept_group_index = 0;
- Relobj* kept_relobj = layout->find_kept_object(sig1, &kept_group_index);
+ Relobj* kept_relobj = kept1->object;
if (kept_relobj != NULL)
{
Sized_relobj<size, big_endian>* kept_object =
- static_cast<Sized_relobj<size, big_endian>*>(kept_relobj);
- Comdat_group* kept_group =
- kept_object->find_comdat_group(kept_group_index);
+ static_cast<Sized_relobj<size, big_endian>*>(kept_relobj);
+ Kept_section::Comdat_group* kept_group = kept1->group_sections;
if (kept_group != NULL && kept_group->size() == 1)
{
- Comdat_group::const_iterator p = kept_group->begin();
+ Kept_section::Comdat_group::const_iterator p =
+ kept_group->begin();
gold_assert(p != kept_group->end());
Kept_comdat_section* kept =
new Kept_comdat_section(kept_object, p->second);
template<int size, bool big_endian>
void
Sized_relobj<size, big_endian>::do_add_symbols(Symbol_table* symtab,
- Read_symbols_data* sd)
+ Read_symbols_data* sd,
+ Layout*)
{
if (sd->symbols == NULL)
{
const unsigned int loccount = this->local_symbol_count_;
this->local_symbol_offset_ = off;
+ const bool relocatable = parameters->options().relocatable();
const Output_sections& out_sections(this->output_sections());
const std::vector<Address>& out_offsets(this->section_offsets_);
unsigned int shnum = this->shnum();
}
else if (out_offsets[shndx] == invalid_address)
{
+ uint64_t start;
+
// This is a SHF_MERGE section or one which otherwise
- // requires special handling. We get the output address
- // of the start of the merged section. If this is not a
- // section symbol, we can then determine the final
- // value. If it is a section symbol, we can not, as in
- // that case we have to consider the addend to determine
- // the value to use in a relocation.
+ // requires special handling.
if (!lv.is_section_symbol())
- lv.set_output_value(os->output_address(this, shndx,
- lv.input_value()));
+ {
+ // This is not a section symbol. We can determine
+ // the final value now.
+ lv.set_output_value(os->output_address(this, shndx,
+ lv.input_value()));
+ }
+ else if (!os->find_starting_output_address(this, shndx, &start))
+ {
+ // This is a section symbol, but apparently not one
+ // in a merged section. Just use the start of the
+ // output section. This happens with relocatable
+ // links when the input object has section symbols
+ // for arbitrary non-merge sections.
+ lv.set_output_value(os->address());
+ }
else
{
- section_offset_type start =
- os->starting_output_address(this, shndx);
+ // We have to consider the addend to determine the
+ // value to use in a relocation. START is the start
+ // of this input section.
Merged_symbol_value<size>* msv =
new Merged_symbol_value<size>(lv.input_value(), start);
lv.set_merged_symbol_value(msv);
+ out_offsets[shndx]
+ lv.input_value());
else
- lv.set_output_value(os->address()
+ lv.set_output_value((relocatable ? 0 : os->address())
+ out_offsets[shndx]
+ lv.input_value());
}
}
this->dynobj_list_.push_back(dynobj);
-
- // If this is -lc, remember the directory in which we found it.
- // We use this when issuing warnings about undefined symbols: as
- // a heuristic, we don't warn about system libraries found in
- // the same directory as -lc.
- if (strncmp(soname, "libc.so", 7) == 0)
- {
- const char* object_name = dynobj->name().c_str();
- const char* base = lbasename(object_name);
- if (base != object_name)
- this->system_library_directory_.assign(object_name,
- base - 1 - object_name);
- }
}
// Add this object to the cross-referencer if requested.
return true;
}
-// Return whether an object was found in the system library directory.
-
-bool
-Input_objects::found_in_system_library_directory(const Object* object) const
-{
- return (!this->system_library_directory_.empty()
- && object->name().compare(0,
- this->system_library_directory_.size(),
- this->system_library_directory_) == 0);
-}
-
// For each dynamic object, record whether we've seen all of its
// explicit dependencies.
namespace gold
{
+// Return whether INPUT_FILE is an ELF object.
+
+bool
+is_elf_object(Input_file* input_file, off_t offset,
+ const unsigned char** start, int *read_size)
+{
+ off_t filesize = input_file->file().filesize();
+ int want = elfcpp::Elf_sizes<64>::ehdr_size;
+ if (filesize - offset < want)
+ want = filesize - offset;
+
+ const unsigned char* p = input_file->file().get_view(offset, 0, want,
+ true, false);
+ *start = p;
+ *read_size = want;
+
+ if (want < 4)
+ return false;
+
+ static unsigned char elfmagic[4] =
+ {
+ elfcpp::ELFMAG0, elfcpp::ELFMAG1,
+ elfcpp::ELFMAG2, elfcpp::ELFMAG3
+ };
+ return memcmp(p, elfmagic, 4) == 0;
+}
+
// Read an ELF file and return the appropriate instance of Object.
Object*
make_elf_object(const std::string& name, Input_file* input_file, off_t offset,
- const unsigned char* p, section_offset_type bytes)
+ const unsigned char* p, section_offset_type bytes,
+ bool* punconfigured)
{
+ if (punconfigured != NULL)
+ *punconfigured = false;
+
if (bytes < elfcpp::EI_NIDENT)
{
gold_error(_("%s: ELF file too short"), name.c_str());
return make_elf_sized_object<32, true>(name, input_file,
offset, ehdr);
#else
- gold_error(_("%s: not configured to support "
- "32-bit big-endian object"),
- name.c_str());
+ if (punconfigured != NULL)
+ *punconfigured = true;
+ else
+ gold_error(_("%s: not configured to support "
+ "32-bit big-endian object"),
+ name.c_str());
return NULL;
#endif
}
return make_elf_sized_object<32, false>(name, input_file,
offset, ehdr);
#else
- gold_error(_("%s: not configured to support "
- "32-bit little-endian object"),
- name.c_str());
+ if (punconfigured != NULL)
+ *punconfigured = true;
+ else
+ gold_error(_("%s: not configured to support "
+ "32-bit little-endian object"),
+ name.c_str());
return NULL;
#endif
}
return make_elf_sized_object<64, true>(name, input_file,
offset, ehdr);
#else
- gold_error(_("%s: not configured to support "
- "64-bit big-endian object"),
- name.c_str());
+ if (punconfigured != NULL)
+ *punconfigured = true;
+ else
+ gold_error(_("%s: not configured to support "
+ "64-bit big-endian object"),
+ name.c_str());
return NULL;
#endif
}
return make_elf_sized_object<64, false>(name, input_file,
offset, ehdr);
#else
- gold_error(_("%s: not configured to support "
- "64-bit little-endian object"),
- name.c_str());
+ if (punconfigured != NULL)
+ *punconfigured = true;
+ else
+ gold_error(_("%s: not configured to support "
+ "64-bit little-endian object"),
+ name.c_str());
return NULL;
#endif
}