This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Additional support for arm.


Hi,

Here is a patch that adds additional support for the arm backend.

One of the things it does it add support to see the difference
between hard and soft floating point operations.  Currently this
is done by selecting a different return_value_location hook,
which probably isn't a good long term solution, but the only
way I can see without having to change all the backends.

Most of this patch was written by
Eugeniy Meshcheryakov <eugeniy.meshcheryakov@googlemail.com>
with some minor changes from me.


Kurt

diff --git a/backends/arm_init.c b/backends/arm_init.c
index 15c0ee6..be35da1 100644
--- a/backends/arm_init.c
+++ b/backends/arm_init.c
@@ -32,21 +32,32 @@
 #define RELOC_PREFIX	R_ARM_
 #include "libebl_CPU.h"
 
+#include "libebl_arm.h"
+
 /* This defines the common reloc hooks based on arm_reloc.def.  */
 #include "common-reloc.c"
 
 
 const char *
 arm_init (elf, machine, eh, ehlen)
-     Elf *elf __attribute__ ((unused));
+     Elf *elf;
      GElf_Half machine __attribute__ ((unused));
      Ebl *eh;
      size_t ehlen;
 {
+  int soft_float = 0;
+
   /* Check whether the Elf_BH object has a sufficent size.  */
   if (ehlen < sizeof (Ebl))
     return NULL;
 
+  if (elf) {
+    GElf_Ehdr ehdr_mem;
+    GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
+    if (ehdr && (ehdr->e_flags & EF_ARM_SOFT_FLOAT))
+      soft_float = 1;
+  }
+
   /* We handle it.  */
   eh->name = "ARM";
   arm_init_reloc (eh);
@@ -58,7 +69,10 @@ arm_init (elf, machine, eh, ehlen)
   HOOK (eh, core_note);
   HOOK (eh, auxv_info);
   HOOK (eh, check_object_attribute);
-  HOOK (eh, return_value_location);
+  if (soft_float)
+    eh->return_value_location = arm_return_value_location_soft;
+  else
+    eh->return_value_location = arm_return_value_location_hard;
 
   return MODVERSION;
 }
diff --git a/backends/arm_regs.c b/backends/arm_regs.c
index 0a9536d..1abce3b 100644
--- a/backends/arm_regs.c
+++ b/backends/arm_regs.c
@@ -28,6 +28,7 @@
 #endif
 
 #include <string.h>
+#include <stdio.h>
 #include <dwarf.h>
 
 #define BACKEND arm_
@@ -58,7 +59,15 @@ arm_register_info (Ebl *ebl __attribute__ ((unused)),
       namelen = 2;
       break;
 
-    case 10 ... 12:
+    case 10 ... 11:
+      name[0] = 'r';
+      name[1] = '1';
+      name[2] = regno % 10 + '0';
+      namelen = 3;
+      break;
+
+    case 12:
+      *type = DW_ATE_unsigned;
       name[0] = 'r';
       name[1] = '1';
       name[2] = regno % 10 + '0';
@@ -73,6 +82,9 @@ arm_register_info (Ebl *ebl __attribute__ ((unused)),
       break;
 
     case 16 + 0 ... 16 + 7:
+      /* AADWARF says that there are no registers in that range,
+       * but gcc maps FPA registers here
+       */
       regno += 96 - 16;
       /* Fall through.  */
     case 96 + 0 ... 96 + 7:
@@ -84,11 +96,139 @@ arm_register_info (Ebl *ebl __attribute__ ((unused)),
       namelen = 2;
       break;
 
+    case 64 + 0 ... 64 + 9:
+      *setname = "VFP";
+      *bits = 32;
+      *type = DW_ATE_float;
+      name[0] = 's';
+      name[1] = regno - 64 + '0';
+      namelen = 2;
+      break;
+
+    case 64 + 10 ... 64 + 31:
+      *setname = "VFP";
+      *bits = 32;
+      *type = DW_ATE_float;
+      name[0] = 's';
+      name[1] = (regno - 64) / 10 + '0';
+      name[2] = (regno - 64) % 10 + '0';
+      namelen = 3;
+      break;
+
+    case 104 + 0 ... 104 + 7:
+      /* XXX TODO:
+       * This can be either intel wireless MMX general purpose/control
+       * registers or xscale accumulator, which have different usage.
+       * We only have the intel wireless MMX here now.
+       * The name needs to be changed for the xscale accumulator too. */
+      *setname = "MMX";
+      *type = DW_ATE_unsigned;
+      *bits = 32;
+      memcpy(name, "wcgr", 4);
+      name[4] = regno - 104 + '0';
+      namelen = 5;
+      break;
+
+    case 112 + 0 ... 112 + 9:
+      *setname = "MMX";
+      *type = DW_ATE_unsigned;
+      *bits = 64;
+      name[0] = 'w';
+      name[1] = 'r';
+      name[2] = regno - 112 + '0';
+      namelen = 3;
+      break;
+
+    case 112 + 10 ... 112 + 15:
+      *setname = "MMX";
+      *type = DW_ATE_unsigned;
+      *bits = 64;
+      name[0] = 'w';
+      name[1] = 'r';
+      name[2] = '1';
+      name[3] = regno - 112 - 10 + '0';
+      namelen = 4;
+      break;
+
     case 128:
+      *setname = "special";
       *type = DW_ATE_unsigned;
       return stpcpy (name, "spsr") + 1 - name;
 
+    case 129:
+      *setname = "special";
+      *type = DW_ATE_unsigned;
+      return stpcpy(name, "spsr_fiq") + 1 - name;
+
+    case 130:
+      *setname = "special";
+      *type = DW_ATE_unsigned;
+      return stpcpy(name, "spsr_irq") + 1 - name;
+
+    case 131:
+      *setname = "special";
+      *type = DW_ATE_unsigned;
+      return stpcpy(name, "spsr_abt") + 1 - name;
+
+    case 132:
+      *setname = "special";
+      *type = DW_ATE_unsigned;
+      return stpcpy(name, "spsr_und") + 1 - name;
+
+    case 133:
+      *setname = "special";
+      *type = DW_ATE_unsigned;
+      return stpcpy(name, "spsr_svc") + 1 - name;
+
+    case 144 ... 150:
+      *setname = "integer";
+      *type = DW_ATE_signed;
+      *bits = 32;
+      return sprintf(name, "r%d_usr", regno - 144 + 8) + 1;
+
+    case 151 ... 157:
+      *setname = "integer";
+      *type = DW_ATE_signed;
+      *bits = 32;
+      return sprintf(name, "r%d_fiq", regno - 151 + 8) + 1;
+
+    case 158 ... 159:
+      *setname = "integer";
+      *type = DW_ATE_signed;
+      *bits = 32;
+      return sprintf(name, "r%d_irq", regno - 158 + 13) + 1;
+
+    case 160 ... 161:
+      *setname = "integer";
+      *type = DW_ATE_signed;
+      *bits = 32;
+      return sprintf(name, "r%d_abt", regno - 160 + 13) + 1;
+
+    case 162 ... 163:
+      *setname = "integer";
+      *type = DW_ATE_signed;
+      *bits = 32;
+      return sprintf(name, "r%d_und", regno - 162 + 13) + 1;
+
+    case 164 ... 165:
+      *setname = "integer";
+      *type = DW_ATE_signed;
+      *bits = 32;
+      return sprintf(name, "r%d_svc", regno - 164 + 13) + 1;
+
+    case 192 ... 199:
+     *setname = "MMX";
+      *bits = 32;
+      *type = DW_ATE_unsigned;
+      name[0] = 'w';
+      name[1] = 'c';
+      name[2] = regno - 192 + '0';
+      namelen = 3;
+      break;
+
     case 256 + 0 ... 256 + 9:
+      /* XXX TODO: Neon also uses those registers and can contain
+       * both float and integers */
       *setname = "VFP";
       *type = DW_ATE_float;
       *bits = 64;
diff --git a/backends/arm_retval.c b/backends/arm_retval.c
index 4ffc6e7..94101db 100644
--- a/backends/arm_retval.c
+++ b/backends/arm_retval.c
@@ -45,6 +45,13 @@ static const Dwarf_Op loc_intreg[] =
 #define nloc_intreg	1
 #define nloc_intregs(n)	(2 * (n))
 
+/* f1  */ /* XXX TODO: f0 can also have number 96 if program was compiled with -mabi=aapcs */
+static const Dwarf_Op loc_fpreg[] =
+  {
+    { .atom = DW_OP_reg16 },
+  };
+#define nloc_fpreg  1
+
 /* The return value is a structure and is actually stored in stack space
    passed in a hidden argument by the caller.  But, the compiler
    helpfully returns the address of that space in r0.  */
@@ -55,8 +62,9 @@ static const Dwarf_Op loc_aggregate[] =
 #define nloc_aggregate 1
 
 
-int
-arm_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+static int
+arm_return_value_location_ (Dwarf_Die *functypedie, const Dwarf_Op **locp,
+		            int soft_float)
 {
   /* Start with the function's type, and get the DW_AT_type attribute,
      which is the type of the return value.  */
@@ -109,14 +117,31 @@ arm_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
 	  else
 	    return -1;
 	}
+      if (tag == DW_TAG_base_type)
+	{
+	  Dwarf_Word encoding;
+	  if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
+	                       &attr_mem), &encoding) != 0)
+	    return -1;
+
+	  if ((encoding == DW_ATE_float) && !soft_float)
+	    {
+	      *locp = loc_fpreg;
+	      if (size <= 8)
+		return nloc_fpreg;
+	      goto aggregate;
+	    }
+	}
       if (size <= 16)
 	{
 	intreg:
 	  *locp = loc_intreg;
 	  return size <= 4 ? nloc_intreg : nloc_intregs ((size + 3) / 4);
 	}
+      /* fall through. */
 
     aggregate:
+      /* XXX TODO sometimes aggregates are returned in r0 (-mabi=aapcs) */
       *locp = loc_aggregate;
       return nloc_aggregate;
 
@@ -136,3 +161,18 @@ arm_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
      DWARF and might be valid.  */
   return -2;
 }
+
+/* return location for -mabi=apcs-gnu -msoft-float */
+int
+arm_return_value_location_soft (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+   return arm_return_value_location_ (functypedie, locp, 1);
+}
+
+/* return location for -mabi=apcs-gnu -mhard-float (current default) */
+int
+arm_return_value_location_hard (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+   return arm_return_value_location_ (functypedie, locp, 0);
+}
+
diff --git a/libelf/elf.h b/libelf/elf.h
index ce6de07..6fc6871 100644
--- a/libelf/elf.h
+++ b/libelf/elf.h
@@ -2243,6 +2243,9 @@ typedef Elf32_Addr Elf32_Conflict;
 #define EF_ARM_EABI_VER4	0x04000000
 #define EF_ARM_EABI_VER5	0x05000000
 
+/* EI_OSABI values */
+#define ELFOSABI_ARM_AEABI    64      /* Contains symbol versioning. */
+
 /* Additional symbol types for Thumb.  */
 #define STT_ARM_TFUNC		STT_LOPROC /* A Thumb function.  */
 #define STT_ARM_16BIT		STT_HIPROC /* A Thumb label.  */
@@ -2260,12 +2263,19 @@ typedef Elf32_Addr Elf32_Conflict;
 
 /* Processor specific values for the Phdr p_type field.  */
 #define PT_ARM_EXIDX		(PT_LOPROC + 1)	/* ARM unwind segment.  */
+#define PT_ARM_UNWIND		PT_ARM_EXIDX
 
 /* Processor specific values for the Shdr sh_type field.  */
 #define SHT_ARM_EXIDX		(SHT_LOPROC + 1) /* ARM unwind section.  */
 #define SHT_ARM_PREEMPTMAP	(SHT_LOPROC + 2) /* Preemption details.  */
 #define SHT_ARM_ATTRIBUTES	(SHT_LOPROC + 3) /* ARM attributes section.  */
 
+/* Processor specific values for the Dyn d_tag field.  */
+#define DT_ARM_RESERVED1	(DT_LOPROC + 0)
+#define DT_ARM_SYMTABSZ		(DT_LOPROC + 1)
+#define DT_ARM_PREEMTMAB	(DT_LOPROC + 2)
+#define DT_ARM_RESERVED2	(DT_LOPROC + 3)
+#define DT_ARM_NUM		4
 
 /* ARM relocs.  */
 
@@ -2297,12 +2307,75 @@ typedef Elf32_Addr Elf32_Conflict;
 #define R_ARM_GOTPC		25	/* 32 bit PC relative offset to GOT */
 #define R_ARM_GOT32		26	/* 32 bit GOT entry */
 #define R_ARM_PLT32		27	/* 32 bit PLT address */
+#define R_ARM_CALL		28
+#define R_ARM_JUMP24		29
+#define R_ARM_THM_JUMP24	30
+#define R_ARM_BASE_ABS		31
 #define R_ARM_ALU_PCREL_7_0	32
 #define R_ARM_ALU_PCREL_15_8	33
 #define R_ARM_ALU_PCREL_23_15	34
 #define R_ARM_LDR_SBREL_11_0	35
 #define R_ARM_ALU_SBREL_19_12	36
 #define R_ARM_ALU_SBREL_27_20	37
+#define R_ARM_TARGET1		38
+#define R_ARM_SBREL31		39
+#define R_ARM_V4BX		40
+#define R_ARM_TARGET2		41
+#define R_ARM_PREL31		42
+#define R_ARM_MOVW_ABS_NC	43
+#define R_ARM_MOVT_ABS		44
+#define R_ARM_MOVW_PREL_NC	45
+#define R_ARM_MOVT_PREL		46
+#define R_ARM_THM_MOVW_ABS_NC	47
+#define R_ARM_THM_MOVT_ABS	48
+#define R_ARM_THM_MOVW_PREL_NC	49
+#define R_ARM_THM_MOVT_PREL	50
+#define R_ARM_THM_JUMP19	51
+#define R_ARM_THM_JUMP6		52
+#define R_ARM_THM_ALU_PREL_11_0	53
+#define R_ARM_THM_PC12		54
+#define R_ARM_ABS32_NOI		55
+#define R_ARM_REL32_NOI		56
+#define R_ARM_ALU_PC_G0_NC	57
+#define R_ARM_ALU_PC_G0		58
+#define R_ARM_ALU_PC_G1_NC	59
+#define R_ARM_ALU_PC_G1		60
+#define R_ARM_ALU_PC_G2		61
+#define R_ARM_LDR_PC_G1		62
+#define R_ARM_LDR_PC_G2		63
+#define R_ARM_LDRS_PC_G0	64
+#define R_ARM_LDRS_PC_G1	65
+#define R_ARM_LDRS_PC_G2	66
+#define R_ARM_LDC_PC_G0		67
+#define R_ARM_LDC_PC_G1		68
+#define R_ARM_LDC_PC_G2		69
+#define R_ARM_ALU_SB_G0_NC	70
+#define R_ARM_ALU_SB_G0		71
+#define R_ARM_ALU_SB_G1_NC	72
+#define R_ARM_ALU_SB_G1		73
+#define R_ARM_ALU_SB_G2		74
+#define R_ARM_LDR_SB_G0		75
+#define R_ARM_LDR_SB_G1		76
+#define R_ARM_LDR_SB_G2		77
+#define R_ARM_LDRS_SB_G0	78
+#define R_ARM_LDRS_SB_G1	79
+#define R_ARM_LDRS_SB_G2	80
+#define R_ARM_LDC_G0		81
+#define R_ARM_LDC_G1		82
+#define R_ARM_LDC_G2		83
+#define R_ARM_MOVW_BREL_NC	84
+#define R_ARM_MOVT_BREL		85
+#define R_ARM_MOVW_BREL		86
+#define R_ARM_THM_MOVW_BREL_NC	87
+#define R_ARM_THM_MOVT_BREL	88
+#define R_ARM_THM_MOVW_BREL	89
+/* 90-93 unallocated */
+#define R_ARM_PLT32_ABS		94
+#define R_ARM_GOT_ABS		95
+#define R_ARM_GOT_PREL		96
+#define R_ARM_GOT_BREL12	97
+#define R_ARM_GOTOFF12		98
+#define R_ARM_GOTRELAX		99
 #define R_ARM_GNU_VTENTRY	100
 #define R_ARM_GNU_VTINHERIT	101
 #define R_ARM_THM_PC11		102	/* thumb unconditional branch */
@@ -2317,6 +2390,12 @@ typedef Elf32_Addr Elf32_Conflict;
 					   static TLS block offset */
 #define R_ARM_TLS_LE32		108	/* 32 bit offset relative to static
 					   TLS block */
+#define R_ARM_TLS_LDO12		109
+#define R_ARM_TLS_LE12		110
+#define R_ARM_TLS_IE12GP	111
+/* 112 - 127 private range */
+#define R_ARM_ME_TOO		128	/* obsolete */
+
 #define R_ARM_RXPC25		249
 #define R_ARM_RSBREL32		250
 #define R_ARM_THM_RPC22		251

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]