This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [nonworking patch] gold/arm: define $a/$d markers in .plt
On Tue, Apr 17, 2012 at 4:24 PM, Cary Coutant <ccoutant@google.com> wrote:
> I think your patch is pretty close to working. The problem is that
> Symbol_table::sized_write_globals() only visits symbols in the global
> symbol table, so it never sees the ones in forced_locals_ that weren't
> also added to the global table. I think you need a separate
> generated_locals_ list, change Symbol_table::sized_finalize() to
> iterate over that list the same way it does over forced_locals_, and
> add a loop to Symbol_table::sized_write_globals() to iterate over the
> generated_locals_ list to write them out.
Here's my attempt at that. It produces three new symbol table entries.
But they are nameless and SHN_UNDEF instead of the names and sections
they should have.
Thanks,
Roland
diff --git a/gold/arm.cc b/gold/arm.cc
index dc6e64a..063aa57 100644
--- a/gold/arm.cc
+++ b/gold/arm.cc
@@ -7223,8 +7223,27 @@ class Output_data_plt_arm : public Output_section_data
get_plt_entry_size()
{ return sizeof(plt_entry); }
+ // Define marker symbols at the start of the PLT so that
+ // objdump will know to disassemble it as ARM instructions.
+ void
+ add_marker_symbols(Output_section* os, Symbol_table* symtab)
+ {
+ this->add_marker_symbol(os, symtab, 0, false);
+ this->add_marker_symbol(os, symtab, 16, true);
+ this->add_marker_symbol(os, symtab, 20, false);
+ }
+
protected:
void
+ add_marker_symbol(Output_section* os, Symbol_table* symtab,
+ Arm_address offset, bool is_data)
+ {
+ symtab->define_local_in_output_data(is_data ? "$d" : "$a",
+ Symbol_table::PREDEFINED, os,
+ offset, 0, elfcpp::STT_NOTYPE, false);
+ }
+
+ void
do_adjust_output_section(Output_section* os);
// Write to a map file.
@@ -7430,10 +7449,13 @@
Target_arm<big_endian>::make_plt_entry(Symbol_table* symtab, Layout*
layout,
this->got_section(symtab, layout);
this->plt_ = new Output_data_plt_arm<big_endian>(layout, this->got_plt_);
- layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
- (elfcpp::SHF_ALLOC
- | elfcpp::SHF_EXECINSTR),
+
+ Output_section* os = layout->add_output_section_data
+ (".plt", elfcpp::SHT_PROGBITS,
+ (elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR),
this->plt_, ORDER_PLT, false);
+
+ this->plt_->add_marker_symbols(os, symtab);
}
this->plt_->add_entry(gsym);
}
diff --git a/gold/symtab.cc b/gold/symtab.cc
index 1edb88d..29a170f 100644
--- a/gold/symtab.cc
+++ b/gold/symtab.cc
@@ -1,6 +1,6 @@
// symtab.cc -- the gold symbol table
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2006,2007,2008,2009,2010,2011,2012 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -532,7 +532,7 @@ Symbol_table::Symbol_table(unsigned int count,
const Version_script_info& version_script)
: saw_undefined_(0), offset_(0), table_(count), namepool_(),
forwarders_(), commons_(), tls_commons_(), small_commons_(),
- large_commons_(), forced_locals_(), warnings_(),
+ large_commons_(), forced_locals_(), generated_locals_(), warnings_(),
version_script_(version_script), gc_(NULL), icf_(NULL)
{
namepool_.reserve(count);
@@ -1934,6 +1934,81 @@ Symbol_table::do_define_in_output_data(
}
}
+// Define a special local symbol based on an Output_data.
+
+Symbol*
+Symbol_table::define_local_in_output_data(const char* name,
+ Defined defined, Output_data* od,
+ uint64_t value, uint64_t symsize,
+ elfcpp::STT type,
+ bool offset_is_from_end)
+{
+ if (parameters->target().get_size() == 32)
+ {
+#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
+ return this->do_define_local_in_output_data<32>(name, defined, od,
+ value, symsize, type,
+ offset_is_from_end);
+#else
+ gold_unreachable();
+#endif
+ }
+ else if (parameters->target().get_size() == 64)
+ {
+#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
+ return this->do_define_local_in_output_data<64>(name, defined, od,
+ value, symsize, type,
+ offset_is_from_end);
+#else
+ gold_unreachable();
+#endif
+ }
+ else
+ gold_unreachable();
+}
+
+// Define a special local symbol based on an Output_data, sized version.
+
+template<int size>
+Sized_symbol<size>*
+Symbol_table::do_define_local_in_output_data(
+ const char* name, Defined defined, Output_data* od,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
+ typename elfcpp::Elf_types<size>::Elf_WXword symsize,
+ elfcpp::STT type, bool offset_is_from_end)
+{
+ Sized_symbol<size>* sym;
+
+ const Target& target = parameters->target();
+ if (!target.has_make_symbol())
+ sym = new Sized_symbol<size>();
+ else
+ {
+ if (parameters->target().is_big_endian())
+ {
+ Sized_target<size, true>* sized_target =
+ parameters->sized_target<size, true>();
+ sym = sized_target->make_symbol();
+ }
+ else
+ {
+ Sized_target<size, false>* sized_target =
+ parameters->sized_target<size, false>();
+ sym = sized_target->make_symbol();
+ }
+
+ if (sym == NULL)
+ return NULL;
+ }
+
+ sym->init_output_data(name, NULL, od, value, symsize, type,
+ elfcpp::STB_LOCAL, elfcpp::STV_DEFAULT, 0,
+ offset_is_from_end, defined == PREDEFINED);
+ sym->set_is_forced_local();
+ this->generated_locals_.push_back(sym);
+ return sym;
+}
+
// Define a symbol based on an Output_segment.
Symbol*
@@ -2515,6 +2590,21 @@ Symbol_table::sized_finalize(off_t off, Stringpool* pool,
}
}
+ // Next do all the symbols which have been generated as local.
+ // They too must appear before all global symbols.
+ for (Forced_locals::iterator p = this->generated_locals_.begin();
+ p != this->generated_locals_.end();
+ ++p)
+ {
+ Symbol* sym = *p;
+ gold_assert(sym->is_forced_local());
+ if (this->sized_finalize_symbol<size>(sym))
+ {
+ this->add_to_final_symtab<size>(sym, pool, &index, &off);
+ ++*plocal_symcount;
+ }
+ }
+
// Now do all the remaining symbols.
for (Symbol_table_type::iterator p = this->table_.begin();
p != this->table_.end();
@@ -2824,6 +2914,37 @@ Symbol_table::sized_write_globals(const
Stringpool* sympool,
else
dynamic_view = of->get_output_view(this->dynamic_offset_, dynamic_size);
+ // Next do all the symbols which have been generated as local.
+ // They too must appear before all global symbols.
+ if (0)
+ for (Forced_locals::const_iterator p = this->generated_locals_.begin();
+ p != this->generated_locals_.end();
+ ++p)
+ {
+ Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(*p);
+ unsigned int sym_index = sym->symtab_index();
+ unsigned int shndx = sym->output_data()->out_shndx();
+ typename elfcpp::Elf_types<size>::Elf_Addr sym_value = sym->value();
+
+ gold_assert(sym->binding() == elfcpp::STB_LOCAL);
+
+ if (shndx >= elfcpp::SHN_LORESERVE)
+ {
+ if (sym_index != -1U)
+ symtab_xindex->add(sym_index, shndx);
+ shndx = elfcpp::SHN_XINDEX;
+ }
+
+ if (sym_index != -1U)
+ {
+ gold_assert(sym_index < output_count);
+ unsigned char* ps = psyms + (sym_index * sym_size);
+ this->sized_write_symbol<size, big_endian>(sym, sym_value, shndx,
+ elfcpp::STB_LOCAL,
+ sympool, ps);
+ }
+ }
+
for (Symbol_table_type::const_iterator p = this->table_.begin();
p != this->table_.end();
++p)
diff --git a/gold/symtab.h b/gold/symtab.h
index feed245..fae194a 100644
--- a/gold/symtab.h
+++ b/gold/symtab.h
@@ -1,6 +1,6 @@
// symtab.h -- the gold symbol table -*- C++ -*-
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+// Copyright 2006,2007,2008,2009,2010,2011,2012 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -1393,6 +1393,12 @@ class Symbol_table
unsigned char nonvis, bool only_if_ref,
bool force_override);
+ // Define a special local symbol based on an Output_data.
+ Symbol*
+ define_local_in_output_data(const char* name, Defined,
+ Output_data*, uint64_t value, uint64_t symsize,
+ elfcpp::STT type, bool offset_is_from_end);
+
// Define a set of symbols in output sections. If ONLY_IF_REF is
// true, only define them if they are referenced.
void
@@ -1716,6 +1722,15 @@ class Symbol_table
elfcpp::STV visibility, unsigned char nonvis,
bool offset_is_from_end, bool only_if_ref);
+ // Define a local symbol in an Output_data, sized version.
+ template<int size>
+ Sized_symbol<size>*
+ do_define_local_in_output_data(
+ const char* name, Defined, Output_data*,
+ typename elfcpp::Elf_types<size>::Elf_Addr value,
+ typename elfcpp::Elf_types<size>::Elf_WXword symsize,
+ elfcpp::STT type, bool offset_is_from_end);
+
// Define a symbol in an Output_segment, sized version.
template<int size>
Sized_symbol<size>*
@@ -1872,6 +1887,8 @@ class Symbol_table
// expect there to be very many of them, so we keep a list of them
// rather than walking the whole table to find them.
Forced_locals forced_locals_;
+ // A list of symbols that were generated as local.
+ Forced_locals generated_locals_;
// Manage symbol warnings.
Warnings warnings_;
// Manage potential One Definition Rule (ODR) violations.