aboutsummaryrefslogtreecommitdiff
path: root/gold
diff options
context:
space:
mode:
Diffstat (limited to 'gold')
-rw-r--r--gold/ChangeLog6
-rw-r--r--gold/x86_64.cc62
2 files changed, 67 insertions, 1 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index 6df30ff..244692f 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,5 +1,11 @@
2008-04-07 Ian Lance Taylor <iant@google.com>
+ * x86_64.cc (Target_x86_64::Scan): Change from struct to class.
+ Add issued_non_pic_error_ field. Declare check_non_pic.
+ (Target_x86_64::Scan::check_non_pic): New function.
+ (Target_x86_64::Scan::local): Call check_non_pic as appropriate.
+ (Target_x86_64::Scan::global): Likewise.
+
* output.cc (Output_reloc<SHT_REL>::local_section_offset): Add
addend parameter. Change caller. Handle merge sections.
(Output_reloc<SHT_REL>::symbol_value): Change parameter type from
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index 973787f..f3844176 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -150,8 +150,13 @@ class Target_x86_64 : public Sized_target<64, false>
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_x86_64* target,
@@ -170,12 +175,19 @@ class Target_x86_64 : public Sized_target<64, false>
const elfcpp::Rela<64, false>& reloc, unsigned int r_type,
Symbol* gsym);
+ private:
static void
unsupported_reloc_local(Sized_relobj<64, false>*, unsigned int r_type);
static void
unsupported_reloc_global(Sized_relobj<64, false>*, unsigned int r_type,
Symbol*);
+
+ 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.
@@ -802,6 +814,48 @@ Target_x86_64::Scan::unsupported_reloc_local(Sized_relobj<64, false>* object,
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. The GNU linker
+// only issues a non-PIC error for an allocated read-only section.
+// Here we know the section is allocated, but we don't know that it is
+// read-only. But we check for all the relocation types which the
+// glibc dynamic linker supports, so it seems appropriate to issue an
+// error even if the section is not read-only.
+
+void
+Target_x86_64::Scan::check_non_pic(Relobj* object, unsigned int r_type)
+{
+ switch (r_type)
+ {
+ // These are the relocation types supported by glibc for x86_64.
+ case elfcpp::R_X86_64_RELATIVE:
+ case elfcpp::R_X86_64_GLOB_DAT:
+ case elfcpp::R_X86_64_JUMP_SLOT:
+ case elfcpp::R_X86_64_DTPMOD64:
+ case elfcpp::R_X86_64_DTPOFF64:
+ case elfcpp::R_X86_64_TPOFF64:
+ case elfcpp::R_X86_64_64:
+ case elfcpp::R_X86_64_32:
+ case elfcpp::R_X86_64_PC32:
+ case elfcpp::R_X86_64_COPY:
+ return;
+
+ default:
+ // 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;
+
+ case elfcpp::R_X86_64_NONE:
+ gold_unreachable();
+ }
+}
+
// Scan a relocation for a local symbol.
inline void
@@ -852,6 +906,8 @@ Target_x86_64::Scan::local(const General_options&,
// because that is always a 64-bit relocation.
if (parameters->options().output_is_position_independent())
{
+ this->check_non_pic(object, r_type);
+
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
if (lsym.get_st_type() != elfcpp::STT_SECTION)
{
@@ -915,6 +971,8 @@ Target_x86_64::Scan::local(const General_options&,
object->local_got_offset(r_sym, GOT_TYPE_STANDARD), 0);
else
{
+ this->check_non_pic(object, r_type);
+
gold_assert(lsym.get_st_type() != elfcpp::STT_SECTION);
rela_dyn->add_local(
object, r_sym, r_type, got,
@@ -1100,6 +1158,7 @@ Target_x86_64::Scan::global(const General_options& options,
}
else
{
+ this->check_non_pic(object, r_type);
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
rela_dyn->add_global(gsym, r_type, output_section, object,
data_shndx, reloc.get_r_offset(),
@@ -1130,6 +1189,7 @@ Target_x86_64::Scan::global(const General_options& options,
}
else
{
+ this->check_non_pic(object, r_type);
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
rela_dyn->add_global(gsym, r_type, output_section, object,
data_shndx, reloc.get_r_offset(),