+
+ bool discard = omit[i];
+ if (!discard)
+ {
+ if (shdr.get_sh_type() == elfcpp::SHT_GROUP)
+ {
+ if (!this->include_section_group(symtab, layout, i, name,
+ shdrs, pnames,
+ section_names_size,
+ &omit))
+ discard = true;
+ }
+ else if ((shdr.get_sh_flags() & elfcpp::SHF_GROUP) == 0
+ && Layout::is_linkonce(name))
+ {
+ if (!this->include_linkonce_section(layout, i, name, shdr))
+ discard = true;
+ }
+ }
+
+ if (discard)
+ {
+ // Do not include this section in the link.
+ out_sections[i] = NULL;
+ out_section_offsets[i] = invalid_address;
+ continue;
+ }
+ }
+
+ if (is_gc_pass_one && parameters->options().gc_sections())
+ {
+ if (is_section_name_included(name)
+ || shdr.get_sh_type() == elfcpp::SHT_INIT_ARRAY
+ || shdr.get_sh_type() == elfcpp::SHT_FINI_ARRAY)
+ {
+ symtab->gc()->worklist().push(Section_id(this, i));
+ }
+ }
+
+ // When doing a relocatable link we are going to copy input
+ // reloc sections into the output. We only want to copy the
+ // ones associated with sections which are not being discarded.
+ // However, we don't know that yet for all sections. So save
+ // reloc sections and process them later. Garbage collection is
+ // not triggered when relocatable code is desired.
+ if (emit_relocs
+ && (shdr.get_sh_type() == elfcpp::SHT_REL
+ || shdr.get_sh_type() == elfcpp::SHT_RELA))
+ {
+ reloc_sections.push_back(i);
+ continue;
+ }
+
+ if (relocatable && shdr.get_sh_type() == elfcpp::SHT_GROUP)
+ continue;
+
+ // The .eh_frame section is special. It holds exception frame
+ // information that we need to read in order to generate the
+ // exception frame header. We process these after all the other
+ // sections so that the exception frame reader can reliably
+ // determine which sections are being discarded, and discard the
+ // corresponding information.
+ if (!relocatable
+ && strcmp(name, ".eh_frame") == 0
+ && this->check_eh_frame_flags(&shdr))
+ {
+ if (is_gc_pass_one)
+ {
+ out_sections[i] = reinterpret_cast<Output_section*>(1);
+ out_section_offsets[i] = invalid_address;
+ }
+ else
+ eh_frame_sections.push_back(i);
+ continue;
+ }
+
+ if (is_gc_pass_two && parameters->options().gc_sections())
+ {
+ // This is executed during the second pass of garbage
+ // collection. do_layout has been called before and some
+ // sections have been already discarded. Simply ignore
+ // such sections this time around.
+ if (out_sections[i] == NULL)
+ {
+ gold_assert(out_section_offsets[i] == invalid_address);
+ continue;
+ }
+ if (((shdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0)
+ && symtab->gc()->is_section_garbage(this, i))
+ {
+ if (parameters->options().print_gc_sections())
+ gold_info(_("%s: removing unused section from '%s'"
+ " in file '%s'"),
+ program_name, this->section_name(i).c_str(),
+ this->name().c_str());
+ out_sections[i] = NULL;
+ out_section_offsets[i] = invalid_address;
+ continue;
+ }
+ }
+
+ if (is_gc_pass_two && parameters->options().icf_enabled())
+ {
+ if (out_sections[i] == NULL)
+ {
+ gold_assert(out_section_offsets[i] == invalid_address);
+ continue;
+ }
+ if (((shdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0)
+ && symtab->icf()->is_section_folded(this, i))
+ {
+ if (parameters->options().print_icf_sections())
+ {
+ Section_id folded =
+ symtab->icf()->get_folded_section(this, i);
+ Relobj* folded_obj =
+ reinterpret_cast<Relobj*>(folded.first);
+ gold_info(_("%s: ICF folding section '%s' in file '%s'"
+ "into '%s' in file '%s'"),
+ program_name, this->section_name(i).c_str(),
+ this->name().c_str(),
+ folded_obj->section_name(folded.second).c_str(),
+ folded_obj->name().c_str());
+ }
+ out_sections[i] = NULL;
+ out_section_offsets[i] = invalid_address;
+ continue;
+ }
+ }
+
+ // Defer layout here if input files are claimed by plugins. When gc
+ // is turned on this function is called twice. For the second call
+ // should_defer_layout should be false.
+ if (should_defer_layout && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC))
+ {
+ gold_assert(!is_gc_pass_two);
+ this->deferred_layout_.push_back(Deferred_layout(i, name,
+ pshdrs,
+ reloc_shndx[i],
+ reloc_type[i]));
+ // Put dummy values here; real values will be supplied by
+ // do_layout_deferred_sections.
+ out_sections[i] = reinterpret_cast<Output_section*>(2);
+ out_section_offsets[i] = invalid_address;
+ continue;
+ }
+
+ // During gc_pass_two if a section that was previously deferred is
+ // found, do not layout the section as layout_deferred_sections will
+ // do it later from gold.cc.
+ if (is_gc_pass_two
+ && (out_sections[i] == reinterpret_cast<Output_section*>(2)))
+ continue;
+
+ if (is_gc_pass_one)
+ {
+ // This is during garbage collection. The out_sections are
+ // assigned in the second call to this function.
+ out_sections[i] = reinterpret_cast<Output_section*>(1);
+ out_section_offsets[i] = invalid_address;
+ }
+ else
+ {
+ // When garbage collection is switched on the actual layout
+ // only happens in the second call.
+ this->layout_section(layout, i, name, shdr, reloc_shndx[i],
+ reloc_type[i]);
+ }
+ }
+
+ if (!is_gc_pass_one)
+ layout->layout_gnu_stack(seen_gnu_stack, gnu_stack_flags);
+
+ // When doing a relocatable link handle the reloc sections at the
+ // end. Garbage collection and Identical Code Folding is not
+ // turned on for relocatable code.
+ if (emit_relocs)
+ this->size_relocatable_relocs();
+
+ gold_assert(!(is_gc_or_icf) || reloc_sections.empty());
+
+ for (std::vector<unsigned int>::const_iterator p = reloc_sections.begin();
+ p != reloc_sections.end();
+ ++p)
+ {
+ unsigned int i = *p;
+ const unsigned char* pshdr;
+ pshdr = section_headers_data + i * This::shdr_size;
+ typename This::Shdr shdr(pshdr);
+
+ unsigned int data_shndx = this->adjust_shndx(shdr.get_sh_info());
+ if (data_shndx >= shnum)
+ {
+ // We already warned about this above.
+ continue;