aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/elf32-nds32.c2
-rw-r--r--bfd/elf32-nds32.h2
-rw-r--r--gas/config/tc-nds32.c39
-rw-r--r--gas/config/tc-nds32.h3
-rw-r--r--gas/config/tc-riscv.h1
-rw-r--r--gas/write.c29
6 files changed, 31 insertions, 45 deletions
diff --git a/bfd/elf32-nds32.c b/bfd/elf32-nds32.c
index 5b43ca9..56d1d39 100644
--- a/bfd/elf32-nds32.c
+++ b/bfd/elf32-nds32.c
@@ -2522,7 +2522,7 @@ nds32_put_trampoline (void *contents, const unsigned long *template,
/* nds32_insertion_sort sorts an array with nmemb elements of size size.
This prototype is the same as qsort (). */
-void
+static void
nds32_insertion_sort (void *base, size_t nmemb, size_t size,
int (*compar) (const void *lhs, const void *rhs))
{
diff --git a/bfd/elf32-nds32.h b/bfd/elf32-nds32.h
index 0f49636..0bf1697 100644
--- a/bfd/elf32-nds32.h
+++ b/bfd/elf32-nds32.h
@@ -95,8 +95,6 @@ extern int elf32_nds32_check_relax_group (bfd *, asection *);
extern int elf32_nds32_unify_relax_group (bfd *, asection *);
extern int nds32_elf_unify_tls_model (bfd *, asection *, bfd_byte *,
struct bfd_link_info *);
-extern void nds32_insertion_sort
-(void *, size_t, size_t, int (*) (const void *, const void *));
extern int nds32_convert_32_to_16 (bfd *, uint32_t, uint16_t *, int *);
extern int nds32_convert_16_to_32 (bfd *, uint16_t, uint32_t *);
diff --git a/gas/config/tc-nds32.c b/gas/config/tc-nds32.c
index 0ab436c..228afa6 100644
--- a/gas/config/tc-nds32.c
+++ b/gas/config/tc-nds32.c
@@ -7537,45 +7537,6 @@ nds32_allow_local_subtract (expressionS *expr_l ATTRIBUTE_UNUSED,
return false;
}
-/* Sort relocation by address.
-
- We didn't use qsort () in stdlib, because quick-sort is not a stable
- sorting algorithm. Relocations at the same address (r_offset) must keep
- their relative order. For example, RELAX_ENTRY must be the very first
- relocation entry.
-
- Currently, this function implements insertion-sort. */
-
-static int
-compar_relent (const void *lhs, const void *rhs)
-{
- const arelent **l = (const arelent **) lhs;
- const arelent **r = (const arelent **) rhs;
-
- if ((*l)->address > (*r)->address)
- return 1;
- else if ((*l)->address == (*r)->address)
- return 0;
- else
- return -1;
-}
-
-/* SET_SECTION_RELOCS ()
-
- Although this macro is originally used to set a relocation for each section,
- we use it to sort relocations in the same section by the address of the
- relocation. */
-
-void
-nds32_set_section_relocs (asection *sec ATTRIBUTE_UNUSED,
- arelent **relocs, unsigned int n)
-{
- if (n <= 1)
- return;
-
- nds32_insertion_sort (relocs, n, sizeof (*relocs), compar_relent);
-}
-
long
nds32_pcrel_from_section (fixS *fixP, segT sec ATTRIBUTE_UNUSED)
{
diff --git a/gas/config/tc-nds32.h b/gas/config/tc-nds32.h
index da7e38c..85a1adb 100644
--- a/gas/config/tc-nds32.h
+++ b/gas/config/tc-nds32.h
@@ -88,7 +88,6 @@ extern void nds32_frob_file_before_fix (void);
extern void elf_nds32_final_processing (void);
extern int nds32_validate_fix_sub (struct fix *, segT);
extern int nds32_force_relocation (struct fix *);
-extern void nds32_set_section_relocs (asection *, arelent ** , unsigned int);
/* Fill in rs_align_code fragments. TODO: Review this. */
extern void nds32_handle_align (fragS *);
@@ -110,7 +109,7 @@ extern void tc_nds32_frame_initial_instructions (void);
|| TC_FORCE_RELOCATION (FIX))
#define TC_FORCE_RELOCATION(fix) nds32_force_relocation (fix)
#define TC_VALIDATE_FIX_SUB(FIX,SEG) nds32_validate_fix_sub (FIX,SEG)
-#define SET_SECTION_RELOCS(sec, relocs, n) nds32_set_section_relocs (sec, relocs, n)
+#define GAS_SORT_RELOCS 1
/* Values passed to md_apply_fix don't include the symbol value. */
#define MD_APPLY_SYM_VALUE(FIX) 0
#define HANDLE_ALIGN(f) nds32_handle_align (f)
diff --git a/gas/config/tc-riscv.h b/gas/config/tc-riscv.h
index fbe5e76..1ca02c0 100644
--- a/gas/config/tc-riscv.h
+++ b/gas/config/tc-riscv.h
@@ -78,6 +78,7 @@ extern int riscv_parse_long_option (const char *);
#define md_pre_output_hook riscv_pre_output_hook ()
extern void riscv_pre_output_hook (void);
+#define GAS_SORT_RELOCS 1
/* Let the linker resolve all the relocs due to relaxation. */
#define tc_fix_adjustable(fixp) 0
diff --git a/gas/write.c b/gas/write.c
index e2c7bf2..eaa9d21 100644
--- a/gas/write.c
+++ b/gas/write.c
@@ -1315,7 +1315,34 @@ write_relocs (bfd *abfd ATTRIBUTE_UNUSED, asection *sec,
}
r = r->next;
}
- relocs[n++] = *reloc;
+#ifdef GAS_SORT_RELOCS
+ if (n != 0 && (*reloc)->address < relocs[n - 1]->address)
+ {
+ size_t lo = 0;
+ size_t hi = n - 1;
+ bfd_vma look = (*reloc)->address;
+ while (lo < hi)
+ {
+ size_t mid = (lo + hi) / 2;
+ if (relocs[mid]->address > look)
+ hi = mid;
+ else
+ {
+ lo = mid + 1;
+ if (relocs[mid]->address == look)
+ break;
+ }
+ }
+ while (lo < hi && relocs[lo]->address == look)
+ lo++;
+ memmove (relocs + lo + 1, relocs + lo,
+ (n - lo) * sizeof (*relocs));
+ n++;
+ relocs[lo] = *reloc;
+ }
+ else
+#endif
+ relocs[n++] = *reloc;
install_reloc (sec, *reloc, fixp->fx_frag,
fixp->fx_file, fixp->fx_line);
#ifndef RELOC_EXPANSION_POSSIBLE