aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gold/ChangeLog6
-rw-r--r--gold/sparc.cc109
2 files changed, 114 insertions, 1 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index 1f60009..b290666 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -27,6 +27,12 @@
2008-04-16 David S. Miller <davem@davemloft.net>
+ * sparc.cc (Target_sparc::Scan): Change from struct to class.
+ Add issued_non_pic_error_ field. Declare check_non_pic.
+ (Target_sparc::Scan::check_non_pic): New function.
+ (Target_sparc::Scan::local): Call check_non_pic as appropriate.
+ (Target_sparc::Scan::global): Likewise.
+
* configure.ac (FN_PTRS_IN_SO_WITHOUT_PIC): Add sparc64.
* configure: Rebuild.
diff --git a/gold/sparc.cc b/gold/sparc.cc
index 68c3cb7..1ae48c3 100644
--- a/gold/sparc.cc
+++ b/gold/sparc.cc
@@ -150,8 +150,13 @@ class Target_sparc : public Sized_target<size, big_endian>
private:
// The class which scans relocations.
- struct Scan
+ class Scan
{
+ public:
+ Scan()
+ : issued_non_pic_error_(false)
+ { }
+
inline void
local(const General_options& options, Symbol_table* symtab,
Layout* layout, Target_sparc* target,
@@ -170,6 +175,7 @@ class Target_sparc : public Sized_target<size, big_endian>
const elfcpp::Rela<size, big_endian>& reloc, unsigned int r_type,
Symbol* gsym);
+ private:
static void
unsupported_reloc_local(Sized_relobj<size, big_endian>*,
unsigned int r_type);
@@ -181,6 +187,12 @@ class Target_sparc : public Sized_target<size, big_endian>
static void
generate_tls_call(Symbol_table* symtab, Layout* layout,
Target_sparc* target);
+
+ void
+ check_non_pic(Relobj*, unsigned int r_type);
+
+ // Whether we have issued an error about a non-PIC compilation.
+ bool issued_non_pic_error_;
};
// The class which implements relocation.
@@ -1460,6 +1472,97 @@ Target_sparc<size, big_endian>::Scan::unsupported_reloc_local(
object->name().c_str(), r_type);
}
+// We are about to emit a dynamic relocation of type R_TYPE. If the
+// dynamic linker does not support it, issue an error.
+
+template<int size, bool big_endian>
+void
+Target_sparc<size, big_endian>::Scan::check_non_pic(Relobj* object, unsigned int r_type)
+{
+ gold_assert(r_type != elfcpp::R_SPARC_NONE);
+
+ if (size == 64)
+ {
+ switch (r_type)
+ {
+ // These are the relocation types supported by glibc for sparc 64-bit.
+ case elfcpp::R_SPARC_RELATIVE:
+ case elfcpp::R_SPARC_COPY:
+ case elfcpp::R_SPARC_64:
+ case elfcpp::R_SPARC_GLOB_DAT:
+ case elfcpp::R_SPARC_JMP_SLOT:
+ case elfcpp::R_SPARC_TLS_DTPMOD64:
+ case elfcpp::R_SPARC_TLS_DTPOFF64:
+ case elfcpp::R_SPARC_TLS_TPOFF64:
+ case elfcpp::R_SPARC_TLS_LE_HIX22:
+ case elfcpp::R_SPARC_TLS_LE_LOX10:
+ case elfcpp::R_SPARC_8:
+ case elfcpp::R_SPARC_16:
+ case elfcpp::R_SPARC_DISP8:
+ case elfcpp::R_SPARC_DISP16:
+ case elfcpp::R_SPARC_DISP32:
+ case elfcpp::R_SPARC_WDISP30:
+ case elfcpp::R_SPARC_LO10:
+ case elfcpp::R_SPARC_HI22:
+ case elfcpp::R_SPARC_OLO10:
+ case elfcpp::R_SPARC_H44:
+ case elfcpp::R_SPARC_M44:
+ case elfcpp::R_SPARC_L44:
+ case elfcpp::R_SPARC_HH22:
+ case elfcpp::R_SPARC_HM10:
+ case elfcpp::R_SPARC_LM22:
+ case elfcpp::R_SPARC_UA16:
+ case elfcpp::R_SPARC_UA32:
+ case elfcpp::R_SPARC_UA64:
+ return;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ switch (r_type)
+ {
+ // These are the relocation types supported by glibc for sparc 32-bit.
+ case elfcpp::R_SPARC_RELATIVE:
+ case elfcpp::R_SPARC_COPY:
+ case elfcpp::R_SPARC_GLOB_DAT:
+ case elfcpp::R_SPARC_32:
+ case elfcpp::R_SPARC_JMP_SLOT:
+ case elfcpp::R_SPARC_TLS_DTPMOD32:
+ case elfcpp::R_SPARC_TLS_DTPOFF32:
+ case elfcpp::R_SPARC_TLS_TPOFF32:
+ case elfcpp::R_SPARC_TLS_LE_HIX22:
+ case elfcpp::R_SPARC_TLS_LE_LOX10:
+ case elfcpp::R_SPARC_8:
+ case elfcpp::R_SPARC_16:
+ case elfcpp::R_SPARC_DISP8:
+ case elfcpp::R_SPARC_DISP16:
+ case elfcpp::R_SPARC_DISP32:
+ case elfcpp::R_SPARC_LO10:
+ case elfcpp::R_SPARC_WDISP30:
+ case elfcpp::R_SPARC_HI22:
+ case elfcpp::R_SPARC_UA16:
+ case elfcpp::R_SPARC_UA32:
+ return;
+
+ default:
+ break;
+ }
+ }
+
+ // This prevents us from issuing more than one error per reloc
+ // section. But we can still wind up issuing more than one
+ // error per object file.
+ if (this->issued_non_pic_error_)
+ return;
+ object->error(_("requires unsupported dynamic reloc; "
+ "recompile with -fPIC"));
+ this->issued_non_pic_error_ = true;
+ return;
+}
+
// Scan a relocation for a local symbol.
template<int size, bool big_endian>
@@ -1533,6 +1636,8 @@ Target_sparc<size, big_endian>::Scan::local(
if (parameters->options().output_is_position_independent())
{
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+
+ check_non_pic(object, r_type);
if (lsym.get_st_type() != elfcpp::STT_SECTION)
{
unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
@@ -1830,6 +1935,7 @@ Target_sparc<size, big_endian>::Scan::global(
else
{
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ check_non_pic(object, r_type);
rela_dyn->add_global(gsym, orig_r_type, output_section, object,
data_shndx, reloc.get_r_offset(),
reloc.get_r_addend());
@@ -1895,6 +2001,7 @@ Target_sparc<size, big_endian>::Scan::global(
{
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ check_non_pic(object, r_type);
if (gsym->is_from_dynobj()
|| gsym->is_undefined()
|| gsym->is_preemptible())