+// Process the GOT and PLT entries from the existing output file.
+
+template<int size, bool big_endian>
+void
+Sized_incremental_binary<size, big_endian>::do_process_got_plt(
+ Symbol_table* symtab,
+ Layout* layout)
+{
+ Incremental_got_plt_reader<big_endian> got_plt_reader(this->got_plt_reader());
+ Sized_target<size, big_endian>* target =
+ parameters->sized_target<size, big_endian>();
+
+ // Get the number of symbols in the main symbol table and in the
+ // incremental symbol table. The difference between the two counts
+ // is the index of the first forced-local or global symbol in the
+ // main symbol table.
+ unsigned int symtab_count =
+ this->main_symtab_loc_.data_size / elfcpp::Elf_sizes<size>::sym_size;
+ unsigned int isym_count = this->symtab_reader_.symbol_count();
+ unsigned int first_global = symtab_count - isym_count;
+
+ // Tell the target how big the GOT and PLT sections are.
+ unsigned int got_count = got_plt_reader.get_got_entry_count();
+ unsigned int plt_count = got_plt_reader.get_plt_entry_count();
+ Output_data_got_base* got =
+ target->init_got_plt_for_update(symtab, layout, got_count, plt_count);
+
+ // Read the GOT entries from the base file and build the outgoing GOT.
+ for (unsigned int i = 0; i < got_count; ++i)
+ {
+ unsigned int got_type = got_plt_reader.get_got_type(i);
+ if ((got_type & 0x7f) == 0x7f)
+ {
+ // This is the second entry of a pair.
+ got->reserve_slot(i);
+ continue;
+ }
+ unsigned int symndx = got_plt_reader.get_got_symndx(i);
+ if (got_type & 0x80)
+ {
+ // This is an entry for a local symbol. Ignore this entry if
+ // the object file was replaced.
+ unsigned int input_index = got_plt_reader.get_got_input_index(i);
+ gold_debug(DEBUG_INCREMENTAL,
+ "GOT entry %d, type %02x: (local symbol)",
+ i, got_type & 0x7f);
+ Sized_relobj_incr<size, big_endian>* obj =
+ this->input_object(input_index);
+ if (obj != NULL)
+ target->reserve_local_got_entry(i, obj, symndx, got_type & 0x7f);
+ }
+ else
+ {
+ // This is an entry for a global symbol. GOT_DESC is the symbol
+ // table index.
+ // FIXME: This should really be a fatal error (corrupt input).
+ gold_assert(symndx >= first_global && symndx < symtab_count);
+ Symbol* sym = this->global_symbol(symndx - first_global);
+ // Add the GOT entry only if the symbol is still referenced.
+ if (sym != NULL && sym->in_reg())
+ {
+ gold_debug(DEBUG_INCREMENTAL,
+ "GOT entry %d, type %02x: %s",
+ i, got_type, sym->name());
+ target->reserve_global_got_entry(i, sym, got_type);
+ }
+ }
+ }
+
+ // Read the PLT entries from the base file and pass each to the target.
+ for (unsigned int i = 0; i < plt_count; ++i)
+ {
+ unsigned int plt_desc = got_plt_reader.get_plt_desc(i);
+ // FIXME: This should really be a fatal error (corrupt input).
+ gold_assert(plt_desc >= first_global && plt_desc < symtab_count);
+ Symbol* sym = this->global_symbol(plt_desc - first_global);
+ // Add the PLT entry only if the symbol is still referenced.
+ if (sym != NULL && sym->in_reg())
+ {
+ gold_debug(DEBUG_INCREMENTAL,
+ "PLT entry %d: %s",
+ i, sym->name());
+ target->register_global_plt_entry(symtab, layout, i, sym);
+ }
+ }
+}
+
+// Emit COPY relocations from the existing output file.
+
+template<int size, bool big_endian>
+void
+Sized_incremental_binary<size, big_endian>::do_emit_copy_relocs(
+ Symbol_table* symtab)
+{
+ Sized_target<size, big_endian>* target =
+ parameters->sized_target<size, big_endian>();
+
+ for (typename Copy_relocs::iterator p = this->copy_relocs_.begin();
+ p != this->copy_relocs_.end();
+ ++p)
+ {
+ if (!(*p).symbol->is_copied_from_dynobj())
+ target->emit_copy_reloc(symtab, (*p).symbol, (*p).output_section,
+ (*p).offset);
+ }
+}
+
+// Apply incremental relocations for symbols whose values have changed.
+
+template<int size, bool big_endian>
+void
+Sized_incremental_binary<size, big_endian>::do_apply_incremental_relocs(
+ const Symbol_table* symtab,
+ Layout* layout,
+ Output_file* of)
+{
+ typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
+ typedef typename elfcpp::Elf_types<size>::Elf_Swxword Addend;
+ Incremental_symtab_reader<big_endian> isymtab(this->symtab_reader());
+ Incremental_relocs_reader<size, big_endian> irelocs(this->relocs_reader());
+ unsigned int nglobals = isymtab.symbol_count();
+ const unsigned int incr_reloc_size = irelocs.reloc_size;
+
+ Relocate_info<size, big_endian> relinfo;
+ relinfo.symtab = symtab;
+ relinfo.layout = layout;
+ relinfo.object = NULL;
+ relinfo.reloc_shndx = 0;
+ relinfo.reloc_shdr = NULL;
+ relinfo.data_shndx = 0;
+ relinfo.data_shdr = NULL;
+
+ Sized_target<size, big_endian>* target =
+ parameters->sized_target<size, big_endian>();
+
+ for (unsigned int i = 0; i < nglobals; i++)
+ {
+ const Symbol* gsym = this->global_symbol(i);
+
+ // If the symbol is not referenced from any unchanged input files,
+ // we do not need to reapply any of its relocations.
+ if (gsym == NULL)
+ continue;
+
+ // If the symbol is defined in an unchanged file, we do not need to
+ // reapply any of its relocations.
+ if (gsym->source() == Symbol::FROM_OBJECT
+ && gsym->object()->is_incremental())
+ continue;
+
+ gold_debug(DEBUG_INCREMENTAL,
+ "Applying incremental relocations for global symbol %s [%d]",
+ gsym->name(), i);
+
+ // Follow the linked list of input symbol table entries for this symbol.
+ // We don't bother to figure out whether the symbol table entry belongs
+ // to a changed or unchanged file because it's easier just to apply all
+ // the relocations -- although we might scribble over an area that has
+ // been reallocated, we do this before copying any new data into the
+ // output file.
+ unsigned int offset = isymtab.get_list_head(i);
+ while (offset > 0)
+ {
+ Incremental_global_symbol_reader<big_endian> sym_info =
+ this->inputs_reader().global_symbol_reader_at_offset(offset);
+ unsigned int r_base = sym_info.reloc_offset();
+ unsigned int r_count = sym_info.reloc_count();
+
+ // Apply each relocation for this symbol table entry.
+ for (unsigned int j = 0; j < r_count;
+ ++j, r_base += incr_reloc_size)
+ {
+ unsigned int r_type = irelocs.get_r_type(r_base);
+ unsigned int r_shndx = irelocs.get_r_shndx(r_base);
+ Address r_offset = irelocs.get_r_offset(r_base);
+ Addend r_addend = irelocs.get_r_addend(r_base);
+ Output_section* os = this->output_section(r_shndx);
+ Address address = os->address();
+ off_t section_offset = os->offset();
+ size_t view_size = os->data_size();
+ unsigned char* const view = of->get_output_view(section_offset,
+ view_size);
+
+ gold_debug(DEBUG_INCREMENTAL,
+ " %08lx: %s + %d: type %d addend %ld",
+ (long)(section_offset + r_offset),
+ os->name(),
+ (int)r_offset,
+ r_type,
+ (long)r_addend);
+
+ target->apply_relocation(&relinfo, r_offset, r_type, r_addend,
+ gsym, view, address, view_size);
+
+ // FIXME: Do something more efficient if write_output_view
+ // ever becomes more than a no-op.
+ of->write_output_view(section_offset, view_size, view);
+ }
+ offset = sym_info.next_offset();
+ }
+ }
+}
+