[prev in list] [next in list] [prev in thread] [next in thread] 

List:       binutils
Subject:    bfd_arch_info.fill vs ARM (bug 13616)
From:       Roland McGrath <mcgrathr () google ! com>
Date:       2012-01-31 21:03:20
Message-ID: x57jmx93y487.fsf () frobland ! mtv ! corp ! google ! com
[Download RAW message or body]

I took a crack at adding the ARM support for fixing bug 13616.  But I think
the new hook's signature passes insufficient information for all cases.
It's easy to get right for 32-bit ARM.  But the hook has no way to know
whether the preceding code was ARM or Thumb.

I'm not even really sure how you're supposed to determine that.  Best I can
figure is you're supposed to look at the symbol table for symbols named
"$a" or "$t" in that section, the highest-addressed of those indicating
which mode was being assembled at the end of the section.

Whatever the details, it seems certain it will require that the hook get at
least the asection pointer.


Thanks,
Roland


--- a/bfd/cpu-arm.c
+++ b/bfd/cpu-arm.c
@@ -123,9 +123,72 @@ scan (const struct bfd_arch_info *info, 
   return FALSE;
 }
 
+#define ARM_NOP 	0xe1a00000
+#define THUMB_NOP 	0x46c0
+#define THUMB_NOP_W 	0xf3af8000
+
+/* Fill the buffer with zero, or with nop instruction if CODE is TRUE.  */
+static void *
+bfd_arch_arm_fill (bfd_size_type count,
+                   bfd_boolean is_bigendian,
+                   bfd_boolean code)
+{
+  if (!code)
+    return bfd_arch_default_fill (count, is_bigendian, code);
+  else
+    {
+      void *fill = bfd_malloc (count);
+      if (fill != NULL)
+        {
+          bfd_byte *p = fill;
+          while (count >= 4)
+            {
+              (is_bigendian ? bfd_putb32 : bfd_putl32) (ARM_NOP, p);
+              p += 4;
+              count -= 4;
+            }
+          memset (p, 0, count);
+        }
+      return fill;
+    }
+}
+
+#if 0
+static void *
+bfd_arch_thumb_fill (bfd_size_type count,
+                     bfd_boolean is_bigendian,
+                     bfd_boolean code)
+{
+  if (!code)
+    return bfd_arch_default_fill (count, is_bigendian, code);
+  else
+    {
+      void *fill = bfd_malloc (count);
+      if (fill != NULL)
+        {
+          bfd_byte *p = fill;
+          while (count >= 4)
+            {
+              (is_bigendian ? bfd_putb32 : bfd_putl32) (THUMB_NOP_W, p);
+              p += 4;
+              count -= 4;
+            }
+          while (count >= 2)
+            {
+              (is_bigendian ? bfd_putb16 : bfd_putl16) (THUMB_NOP, p);
+              p += 2;
+              count -= 2;
+            }
+          memset (p, 0, count);
+        }
+      return fill;
+    }
+}
+#endif
+
 #define N(number, print, default, next)  \
 {  32, 32, 8, bfd_arch_arm, number, "arm", print, 4, default, compatible, \
-   scan, bfd_arch_default_fill, next }
+   scan, bfd_arch_arm_fill, next }
 
 static const bfd_arch_info_type arch_info_struct[] =
 {

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic