+static bfd_boolean
+relaxable_section (asection *sec)
+{
+ return (sec->flags & SEC_DEBUGGING) == 0;
+}
+
+/* Does whatever the xtensa port does. */
+int
+avr_validate_fix_sub (fixS *fix)
+{
+ segT add_symbol_segment, sub_symbol_segment;
+
+ /* The difference of two symbols should be resolved by the assembler when
+ linkrelax is not set. If the linker may relax the section containing
+ the symbols, then an Xtensa DIFF relocation must be generated so that
+ the linker knows to adjust the difference value. */
+ if (!linkrelax || fix->fx_addsy == NULL)
+ return 0;
+
+ /* Make sure both symbols are in the same segment, and that segment is
+ "normal" and relaxable. If the segment is not "normal", then the
+ fix is not valid. If the segment is not "relaxable", then the fix
+ should have been handled earlier. */
+ add_symbol_segment = S_GET_SEGMENT (fix->fx_addsy);
+ if (! SEG_NORMAL (add_symbol_segment) ||
+ ! relaxable_section (add_symbol_segment))
+ return 0;
+
+ sub_symbol_segment = S_GET_SEGMENT (fix->fx_subsy);
+ return (sub_symbol_segment == add_symbol_segment);
+}
+
+/* TC_FORCE_RELOCATION hook */
+
+/* If linkrelax is turned on, and the symbol to relocate
+ against is in a relaxable segment, don't compute the value -
+ generate a relocation instead. */
+int
+avr_force_relocation (fixS *fix)
+{
+ if (linkrelax && fix->fx_addsy
+ && relaxable_section (S_GET_SEGMENT (fix->fx_addsy)))
+ return 1;
+
+ return generic_force_reloc (fix);
+}
+