summaryrefslogtreecommitdiffstats
path: root/libgloss/sparc/fixctors.c
diff options
context:
space:
mode:
authorRanjith Kumaran <ranjith@cygnus.com>2000-03-17 22:48:54 +0000
committerRanjith Kumaran <ranjith@cygnus.com>2000-03-17 22:48:54 +0000
commit03261851a10dd2d6900a0a00a7515a0a46fb5d76 (patch)
tree7c22ac6cbbc99fd5cd1b5426853be8d4fd7bfcf1 /libgloss/sparc/fixctors.c
parentfae4c299f14fc23e2829c8656992eba21f79242a (diff)
downloadcygnal-03261851a10dd2d6900a0a00a7515a0a46fb5d76.tar.gz
cygnal-03261851a10dd2d6900a0a00a7515a0a46fb5d76.tar.bz2
cygnal-03261851a10dd2d6900a0a00a7515a0a46fb5d76.zip
20000317 sourceware import
Diffstat (limited to 'libgloss/sparc/fixctors.c')
-rw-r--r--libgloss/sparc/fixctors.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/libgloss/sparc/fixctors.c b/libgloss/sparc/fixctors.c
new file mode 100644
index 000000000..484023c7a
--- /dev/null
+++ b/libgloss/sparc/fixctors.c
@@ -0,0 +1,54 @@
+/* Code to byte-swap static constructor/destructor tables on
+ broken a.out little-endian targets. The startup code should call
+ __fix_ctors just before calling main. It is safe to use on non-broken
+ or big-endian targets. */
+
+extern long __CTOR_LIST__[];
+extern long __DTOR_LIST__[];
+
+static void
+byte_swap (long *entry)
+{
+ unsigned char *p = (unsigned char *)entry;
+ unsigned char tmp;
+
+ tmp = p[0];
+ p[0] = p[3];
+ p[3] = tmp;
+ tmp = p[1];
+ p[1] = p[2];
+ p[2] = tmp;
+}
+
+static void
+fix_table (long *table)
+{
+ long len = table[0];
+
+ /* The heuristic for deciding if a table is broken is to examine
+ the word at the start of the table, which contains the number
+ of function pointers immediately following. If the low word
+ is zero, and the high word is non-zero, it's very likely that
+ it is byte-swapped. This test will fail if the program has
+ an exact multiple of 64K static constructors or destructors, a very
+ unlikely situation. */
+ if ((len & 0xffff) == 0 && (len & 0xffff0000) != 0)
+ {
+
+ /* The table looks broken. Byte-swap all the words in the table, up
+ to a NULL entry, which marks the end of the table. */
+ do
+ {
+ byte_swap (table);
+ table++;
+ }
+ while (*table);
+ }
+}
+
+void
+__fix_ctors (void)
+{
+ fix_table (__CTOR_LIST__);
+ fix_table (__DTOR_LIST__);
+}