diff -Nur binutils-2.16.1/bfd/elf.c binutils-2.16.1-patched/bfd/elf.c
--- binutils-2.16.1/bfd/elf.c	2005-05-30 00:00:10.000000000 +0200
+++ binutils-2.16.1-patched/bfd/elf.c	2006-02-13 12:00:51.000000000 +0100
@@ -727,10 +727,16 @@
     flags |= SEC_DATA;
   if ((hdr->sh_flags & SHF_MERGE) != 0)
     {
+      /* turn this off because diablo can't handle it */
+#if 0
       flags |= SEC_MERGE;
       newsect->entsize = hdr->sh_entsize;
       if ((hdr->sh_flags & SHF_STRINGS) != 0)
 	flags |= SEC_STRINGS;
+#else
+      flags &= ~(SEC_MERGE | SEC_STRINGS);
+      hdr->sh_flags &= ~(SHF_MERGE | SHF_STRINGS);
+#endif
     }
   if (hdr->sh_flags & SHF_GROUP)
     if (!setup_group (abfd, hdr, newsect))
@@ -2582,10 +2588,16 @@
     this_hdr->sh_flags |= SHF_EXECINSTR;
   if ((asect->flags & SEC_MERGE) != 0)
     {
+      /* turn this off because diablo can't handle it */
+#if 0
       this_hdr->sh_flags |= SHF_MERGE;
       this_hdr->sh_entsize = asect->entsize;
       if ((asect->flags & SEC_STRINGS) != 0)
 	this_hdr->sh_flags |= SHF_STRINGS;
+#else
+      this_hdr->sh_flags &= ~(SHF_MERGE | SHF_STRINGS);
+      asect->flags &= ~(SEC_MERGE | SEC_STRINGS);
+#endif
     }
   if ((asect->flags & SEC_GROUP) == 0 && elf_group_name (asect) != NULL)
     this_hdr->sh_flags |= SHF_GROUP;
diff -Nur binutils-2.16.1/bfd/elf-eh-frame.c binutils-2.16.1-patched/bfd/elf-eh-frame.c
--- binutils-2.16.1/bfd/elf-eh-frame.c	2005-02-20 15:59:06.000000000 +0100
+++ binutils-2.16.1-patched/bfd/elf-eh-frame.c	2006-02-13 12:00:51.000000000 +0100
@@ -401,6 +401,7 @@
   htab = elf_hash_table (info);
   hdr_info = &htab->eh_info;
 
+  goto free_no_table;
   /* Read the frame unwind information from abfd.  */
 
   REQUIRE (bfd_malloc_and_get_section (abfd, sec, &ehbuf));
diff -Nur binutils-2.16.1/gas/config/obj-elf.c binutils-2.16.1-patched/gas/config/obj-elf.c
--- binutils-2.16.1/gas/config/obj-elf.c	2005-02-22 13:58:35.000000000 +0100
+++ binutils-2.16.1-patched/gas/config/obj-elf.c	2006-02-13 12:00:51.000000000 +0100
@@ -1423,6 +1423,8 @@
   demand_empty_rest_of_line ();
 }
 
+extern int size_expression;
+
 static void
 obj_elf_size (int ignore ATTRIBUTE_UNUSED)
 {
@@ -1444,7 +1446,10 @@
       return;
     }
   input_line_pointer++;
+
+  size_expression=1;
   expression (&exp);
+  size_expression=0;
   if (exp.X_op == O_absent)
     {
       as_bad (_("missing expression in .size directive"));
@@ -1546,6 +1551,7 @@
   demand_empty_rest_of_line ();
 }
 
+
 static void
 obj_elf_ident (int ignore ATTRIBUTE_UNUSED)
 {
diff -Nur binutils-2.16.1/gas/config/tc-arm.c binutils-2.16.1-patched/gas/config/tc-arm.c
--- binutils-2.16.1/gas/config/tc-arm.c	2005-05-17 21:51:33.000000000 +0200
+++ binutils-2.16.1-patched/gas/config/tc-arm.c	2006-02-13 12:00:51.000000000 +0100
@@ -45,6 +45,7 @@
 #include "dw2gencfi.h"
 #endif
 
+extern int prev_was_data;
 /* XXX Set this to 1 after the next binutils release.  */
 #define WARN_DEPRECATED 0
 
@@ -12352,6 +12353,10 @@
       opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
       *p = c;
 
+      /* NEEDED FOR DIABLO: add code symbols */
+      if (prev_was_data!=2) symbol_new ("$t", now_seg, (valueT) frag_now_fix (), frag_now);
+      prev_was_data=2;
+
       if (opcode)
 	{
 	  /* Check that this instruction is supported for this CPU.  */
@@ -12378,6 +12383,10 @@
       opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
       *p = c;
 
+      /* NEEDED FOR DIABLO: add code symbols */
+      if (prev_was_data!=0) symbol_new ("$a", now_seg, (valueT) frag_now_fix (), frag_now);
+      prev_was_data=0;
+      
       if (opcode)
 	{
 	  /* Check that this instruction is supported for this CPU.  */
@@ -13437,7 +13446,7 @@
       || fixP->fx_r_type == BFD_RELOC_ARM_TARGET2)
     return 0;
 
-  return 1;
+  return 0;
 }
 
 const char *
@@ -13481,6 +13490,10 @@
       return;
     }
 
+      /* NEEDED FOR DIABLO: add data symbols */
+      if (prev_was_data!=1) symbol_new ("$d", now_seg, (valueT) frag_now_fix (), frag_now);
+      prev_was_data=1;
+
 #ifdef md_cons_align
   md_cons_align (nbytes);
 #endif
diff -Nur binutils-2.16.1/gas/config/tc-i386.c binutils-2.16.1-patched/gas/config/tc-i386.c
--- binutils-2.16.1/gas/config/tc-i386.c	2005-04-13 19:58:42.000000000 +0200
+++ binutils-2.16.1-patched/gas/config/tc-i386.c	2006-02-13 12:00:51.000000000 +0100
@@ -63,6 +63,8 @@
 #endif
 #endif
 
+extern int prev_was_data;
+
 static INLINE unsigned int mode_from_disp_size PARAMS ((unsigned int));
 static INLINE int fits_in_signed_byte PARAMS ((offsetT));
 static INLINE int fits_in_unsigned_byte PARAMS ((offsetT));
@@ -1297,7 +1299,8 @@
       || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
     return 0;
 #endif
-  return 1;
+  /* Needed by DIABLO */
+  return 0;
 }
 
 static int intel_float_operand PARAMS ((const char *mnemonic));
@@ -1367,6 +1370,8 @@
   int j;
   char mnemonic[MAX_MNEM_SIZE];
 
+  if (prev_was_data!=0) symbol_new ("$a", now_seg, (valueT) frag_now_fix (), frag_now);
+  prev_was_data=0;
   /* Initialize globals.  */
   memset (&i, '\0', sizeof (i));
   for (j = 0; j < MAX_OPERANDS; j++)
diff -Nur binutils-2.16.1/gas/config/tc-ia64.c binutils-2.16.1-patched/gas/config/tc-ia64.c
--- binutils-2.16.1/gas/config/tc-ia64.c	2005-05-28 23:52:38.000000000 +0200
+++ binutils-2.16.1-patched/gas/config/tc-ia64.c	2006-02-13 12:00:51.000000000 +0100
@@ -720,6 +720,8 @@
 
 #define ENCODED_PSP_OFFSET(OFFSET) (((OFFSET) + 16) / 4)
 
+extern int prev_was_data;
+
 typedef void (*vbyte_func) PARAMS ((int, char *, char *));
 
 /* Forward declarations:  */
@@ -10575,6 +10577,8 @@
   if (!idesc)
     goto done;
 
+  if (prev_was_data!=0) symbol_new ("$a", now_seg, (valueT) frag_now_fix (), frag_now);
+  prev_was_data=0;
   /* Handle the dynamic ops we can handle now:  */
   if (idesc->type == IA64_TYPE_DYN)
     {
diff -Nur binutils-2.16.1/gas/config/tc-mips.c binutils-2.16.1-patched/gas/config/tc-mips.c
--- binutils-2.16.1/gas/config/tc-mips.c	2005-06-12 20:07:03.000000000 +0200
+++ binutils-2.16.1-patched/gas/config/tc-mips.c	2006-02-13 12:00:51.000000000 +0100
@@ -110,6 +110,7 @@
 #endif
 
 extern int target_big_endian;
+extern int prev_was_data;
 
 /* The name of the readonly data section.  */
 #define RDATA_SECTION_NAME (OUTPUT_FLAVOR == bfd_target_ecoff_flavour \
@@ -1616,6 +1617,9 @@
   bfd_reloc_code_real_type unused_reloc[3]
     = {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED};
 
+  if (prev_was_data!=0) symbol_new ("$a", now_seg, (valueT) frag_now_fix (), frag_now);
+  prev_was_data=0;
+  
   imm_expr.X_op = O_absent;
   imm2_expr.X_op = O_absent;
   offset_expr.X_op = O_absent;
@@ -11998,6 +12002,10 @@
       return;
     }
 
+  if (prev_was_data!=1) symbol_new ("$d", now_seg, (valueT) frag_now_fix (), frag_now);
+  prev_was_data=1;
+  if (prev_was_data!=1) symbol_new ("$d", now_seg, (valueT) frag_now_fix (), frag_now);
+  prev_was_data=1;
   label = insn_labels != NULL ? insn_labels->label : NULL;
   mips_emit_delays ();
   if (auto_align)
@@ -12739,7 +12747,7 @@
     return 0;
 #endif
 
-  return 1;
+  return 0;
 }
 
 /* Translate internal representation of relocation info to BFD target
diff -Nur binutils-2.16.1/gas/config/tc-ppc.c binutils-2.16.1-patched/gas/config/tc-ppc.c
--- binutils-2.16.1/gas/config/tc-ppc.c	2005-03-02 14:24:01.000000000 +0100
+++ binutils-2.16.1-patched/gas/config/tc-ppc.c	2006-05-05 10:54:21.000000000 +0200
@@ -2083,6 +2083,8 @@
 
 /* This routine is called for each instruction to be assembled.  */
 
+extern int prev_was_data;
+
 void
 md_assemble (str)
      char *str;
@@ -2103,6 +2105,8 @@
   bfd_reloc_code_real_type reloc;
 #endif
 
+  if (prev_was_data!=0) symbol_new ("$a", now_seg, (valueT) frag_now_fix (), frag_now);
+  prev_was_data=0;
   /* Get the opcode.  */
   for (s = str; *s != '\0' && ! ISSPACE (*s); s++)
     ;
@@ -4672,7 +4676,8 @@
 ppc_pe_fix_adjustable (fix)
      fixS *fix;
 {
-  return fix->fx_r_type != BFD_RELOC_PPC_TOC16;
+/*  return fix->fx_r_type != BFD_RELOC_PPC_TOC16;*/
+  return 0;
 }
 
 #endif
@@ -5477,15 +5482,16 @@
 ppc_fix_adjustable (fix)
      fixS *fix;
 {
-  return (fix->fx_r_type != BFD_RELOC_16_GOTOFF
-	  && fix->fx_r_type != BFD_RELOC_LO16_GOTOFF
-	  && fix->fx_r_type != BFD_RELOC_HI16_GOTOFF
-	  && fix->fx_r_type != BFD_RELOC_HI16_S_GOTOFF
-	  && fix->fx_r_type != BFD_RELOC_GPREL16
-	  && fix->fx_r_type != BFD_RELOC_VTABLE_INHERIT
-	  && fix->fx_r_type != BFD_RELOC_VTABLE_ENTRY
-	  && !(fix->fx_r_type >= BFD_RELOC_PPC_TLS
-	       && fix->fx_r_type <= BFD_RELOC_PPC64_DTPREL16_HIGHESTA));
+  return 0;
+/*  return (fix->fx_r_type != BFD_RELOC_16_GOTOFF*/
+/*          && fix->fx_r_type != BFD_RELOC_LO16_GOTOFF*/
+/*          && fix->fx_r_type != BFD_RELOC_HI16_GOTOFF*/
+/*          && fix->fx_r_type != BFD_RELOC_HI16_S_GOTOFF*/
+/*          && fix->fx_r_type != BFD_RELOC_GPREL16*/
+/*          && fix->fx_r_type != BFD_RELOC_VTABLE_INHERIT*/
+/*          && fix->fx_r_type != BFD_RELOC_VTABLE_ENTRY*/
+/*          && !(fix->fx_r_type >= BFD_RELOC_PPC_TLS*/
+/*               && fix->fx_r_type <= BFD_RELOC_PPC64_DTPREL16_HIGHESTA));*/
 }
 #endif
 
diff -Nur binutils-2.16.1/gas/config/tc-sh.c binutils-2.16.1-patched/gas/config/tc-sh.c
--- binutils-2.16.1/gas/config/tc-sh.c	2005-02-23 13:28:05.000000000 +0100
+++ binutils-2.16.1-patched/gas/config/tc-sh.c	2006-02-13 12:00:51.000000000 +0100
@@ -37,6 +37,8 @@
 #include "dwarf2dbg.h"
 #include "dw2gencfi.h"
 
+extern int prev_was_data;
+
 typedef struct
   {
     sh_arg_type type;
@@ -2740,6 +2742,9 @@
   unsigned int size = 0;
   char *initial_str = str;
 
+  if (prev_was_data!=0) symbol_new ("$a", now_seg, (valueT) frag_now_fix (), frag_now);
+  prev_was_data=0;
+
 #ifdef HAVE_SH64
   if (sh64_isa_mode == sh64_isa_shmedia)
     {
diff -Nur binutils-2.16.1/gas/expr.c binutils-2.16.1-patched/gas/expr.c
--- binutils-2.16.1/gas/expr.c	2005-03-03 18:22:12.000000000 +0100
+++ binutils-2.16.1-patched/gas/expr.c	2006-02-13 12:00:51.000000000 +0100
@@ -1650,6 +1650,7 @@
 
 /* Parse an expression.  */
 
+int size_expression=0;
 segT
 expr (int rankarg,		/* Larger # is higher rank.  */
       expressionS *resultP	/* Deliver result here.  */)
@@ -1760,6 +1761,21 @@
 	       && (SEG_NORMAL (rightseg)
 		   || right.X_add_symbol == resultP->X_add_symbol))
 	{
+	   /* NEEDED FOR DIABLO: add special symbols for address substractions */
+	   if (!size_expression)
+	   {
+	      const char * left_name=S_GET_NAME(resultP->X_add_symbol); 
+	      const char * right_name=S_GET_NAME(right.X_add_symbol); 
+	      char * new_sym_name=malloc(strlen(left_name)+strlen(right_name)+strlen("$diablo:@-@")+1);
+
+	      strcpy(new_sym_name,"$diablo:");
+	      strcat(new_sym_name,left_name);
+	      strcat(new_sym_name,"@-@");
+	      strcat(new_sym_name,right_name);
+	      symbol_new (new_sym_name, now_seg, (valueT) frag_now_fix (), frag_now);
+	      symbol_mark_used_in_reloc (resultP->X_add_symbol);
+	      symbol_mark_used_in_reloc (right.X_add_symbol);
+	   }
 	  resultP->X_add_number -= right.X_add_number;
 	  resultP->X_add_number += (S_GET_VALUE (resultP->X_add_symbol)
 				    - S_GET_VALUE (right.X_add_symbol));
@@ -1854,6 +1870,21 @@
 	    resultP->X_add_number += right.X_add_number;
 	  else if (op_left == O_subtract)
 	    {
+	       if (!size_expression)
+	       {
+		  const char * left_name=S_GET_NAME(resultP->X_add_symbol); 
+		  const char * right_name=S_GET_NAME(right.X_add_symbol); 
+		  char * new_sym_name=malloc(strlen(left_name)+strlen(right_name)+strlen("$diablo:@-@")+1);
+		  symbol_mark_used_in_reloc (resultP->X_add_symbol);
+		  symbol_mark_used_in_reloc (right.X_add_symbol);
+
+		  strcpy(new_sym_name,"$diablo:");
+		  strcat(new_sym_name,left_name);
+		  strcat(new_sym_name,"@-@");
+		  strcat(new_sym_name,right_name);
+		  symbol_new (new_sym_name, now_seg, (valueT) frag_now_fix (), frag_now);
+	       }
+
 	      resultP->X_add_number -= right.X_add_number;
 	      if (retval == rightseg && SEG_NORMAL (retval))
 		{
diff -Nur binutils-2.16.1/gas/read.c binutils-2.16.1-patched/gas/read.c
--- binutils-2.16.1/gas/read.c	2005-04-13 19:58:41.000000000 +0200
+++ binutils-2.16.1-patched/gas/read.c	2006-02-13 12:00:51.000000000 +0100
@@ -211,6 +211,10 @@
 #endif
 #endif
 
+/* NEEDED for diablo: -1 means there was no previous data or code symbol, 0
+ * means previous was code, 1 means previous was data */
+int prev_was_data=-1;
+
 static void do_align (int, char *, int, int);
 static void s_align (int, int);
 static void s_altmacro (int);
@@ -3427,12 +3431,19 @@
 void
 cons (int size)
 {
+  /* NEEDED FOR DIABLO: add data symbols */
+  if (prev_was_data!=1) symbol_new ("$d", now_seg, (valueT) frag_now_fix (), frag_now);
+    prev_was_data=1;
+
   cons_worker (size, 0);
 }
 
 void
 s_rva (int size)
 {
+  /* NEEDED FOR DIABLO: add data symbols */
+  if (prev_was_data!=1) symbol_new ("$d", now_seg, (valueT) frag_now_fix (), frag_now);
+    prev_was_data=1;
   cons_worker (size, 1);
 }
 
@@ -4137,6 +4148,9 @@
   md_flush_pending_output ();
 #endif
 
+  /* NEEDED FOR DIABLO: add data symbols */
+  if (prev_was_data!=1) symbol_new ("$d", now_seg, (valueT) frag_now_fix (), frag_now);
+    prev_was_data=1;
   do
     {
       /* input_line_pointer->1st char of a flonum (we hope!).  */
diff -Nur binutils-2.16.1/ld/ldlang.c binutils-2.16.1-patched/ld/ldlang.c
--- binutils-2.16.1/ld/ldlang.c	2005-03-22 16:32:36.000000000 +0100
+++ binutils-2.16.1-patched/ld/ldlang.c	2006-02-13 12:00:51.000000000 +0100
@@ -1366,6 +1366,8 @@
       if (! first && (output->bfd_section->flags & SEC_READONLY) == 0)
 	flags &= ~ SEC_READONLY;
 
+      /* turn off section merging, Diablo can't handle it */
+#if 0
       /* Keep SEC_MERGE and SEC_STRINGS only if they are the same.  */
       if (! first
 	  && ((output->bfd_section->flags & (SEC_MERGE | SEC_STRINGS))
@@ -1381,6 +1383,10 @@
 
       if (flags & SEC_MERGE)
 	output->bfd_section->entsize = section->entsize;
+#else
+      output->bfd_section->flags |= flags;
+      flags &= ~(SEC_MERGE | SEC_STRINGS);
+#endif
 
       /* If SEC_READONLY is not set in the input section, then clear
 	 it from the output section.  */
