+ // When determining whether a reference to a symbol needs a dynamic
+ // relocation, we need to know several things about the reference.
+ // These flags may be or'ed together.
+ enum Reference_flags
+ {
+ // Reference to the symbol's absolute address.
+ ABSOLUTE_REF = 1,
+ // A non-PIC reference.
+ NON_PIC_REF = 2,
+ // A function call.
+ FUNCTION_CALL = 4
+ };
+
+ // Given a direct absolute or pc-relative static relocation against
+ // the global symbol, this function returns whether a dynamic relocation
+ // is needed.
+
+ bool
+ needs_dynamic_reloc(int flags) const
+ {
+ // No dynamic relocations in a static link!
+ if (parameters->doing_static_link())
+ return false;
+
+ // A reference to a weak undefined symbol from an executable should be
+ // statically resolved to 0, and does not need a dynamic relocation.
+ // This matches gnu ld behavior.
+ if (this->is_weak_undefined() && !parameters->options().shared())
+ return false;
+
+ // A reference to an absolute symbol does not need a dynamic relocation.
+ if (this->is_absolute())
+ return false;
+
+ // An absolute reference within a position-independent output file
+ // will need a dynamic relocation.
+ if ((flags & ABSOLUTE_REF)
+ && parameters->options().output_is_position_independent())
+ return true;
+
+ // A function call that can branch to a local PLT entry does not need
+ // a dynamic relocation. A non-pic pc-relative function call in a
+ // shared library cannot use a PLT entry.
+ if ((flags & FUNCTION_CALL)
+ && this->has_plt_offset()
+ && !((flags & NON_PIC_REF) && parameters->options().shared()))
+ return false;
+
+ // A reference to any PLT entry in a non-position-independent executable
+ // does not need a dynamic relocation.
+ if (!parameters->options().output_is_position_independent()
+ && this->has_plt_offset())
+ return false;
+
+ // A reference to a symbol defined in a dynamic object or to a
+ // symbol that is preemptible will need a dynamic relocation.
+ if (this->is_from_dynobj()
+ || this->is_undefined()
+ || this->is_preemptible())
+ return true;
+
+ // For all other cases, return FALSE.
+ return false;
+ }
+
+ // Given a direct absolute static relocation against
+ // the global symbol, where a dynamic relocation is needed, this
+ // function returns whether a relative dynamic relocation can be used.
+ // The caller must determine separately whether the static relocation
+ // is compatible with a relative relocation.
+
+ bool
+ can_use_relative_reloc(bool is_function_call) const
+ {
+ // A function call that can branch to a local PLT entry can
+ // use a RELATIVE relocation.
+ if (is_function_call && this->has_plt_offset())
+ return true;
+
+ // A reference to a symbol defined in a dynamic object or to a
+ // symbol that is preemptible can not use a RELATIVE relocaiton.
+ if (this->is_from_dynobj()
+ || this->is_undefined()
+ || this->is_preemptible())
+ return false;
+
+ // For all other cases, return TRUE.
+ return true;
+ }
+
+ // Return the output section where this symbol is defined. Return
+ // NULL if the symbol has an absolute value.
+ Output_section*
+ output_section() const;
+
+ // Set the symbol's output section. This is used for symbols
+ // defined in scripts. This should only be called after the symbol
+ // table has been finalized.
+ void
+ set_output_section(Output_section*);
+