Upstream-Status: Backport

Index: elfutils-0.146/backends/arm_init.c
===================================================================
--- elfutils-0.146.orig/backends/arm_init.c	2009-04-21 14:50:01.000000000 +0000
+++ elfutils-0.146/backends/arm_init.c	2010-04-24 10:11:13.000000000 +0000
@@ -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 @@
   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;
 }
Index: elfutils-0.146/backends/arm_regs.c
===================================================================
--- elfutils-0.146.orig/backends/arm_regs.c	2009-04-21 14:50:01.000000000 +0000
+++ elfutils-0.146/backends/arm_regs.c	2010-04-24 10:11:13.000000000 +0000
@@ -28,6 +28,7 @@
 #endif
 
 #include <string.h>
+#include <stdio.h>
 #include <dwarf.h>
 
 #define BACKEND arm_
@@ -58,7 +59,15 @@
       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 @@
       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 @@
       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;
Index: elfutils-0.146/backends/arm_retval.c
===================================================================
--- elfutils-0.146.orig/backends/arm_retval.c	2010-01-12 16:57:54.000000000 +0000
+++ elfutils-0.146/backends/arm_retval.c	2010-04-24 10:11:13.000000000 +0000
@@ -45,6 +45,13 @@
 #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 @@
 #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 @@
 	  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;
 
@@ -135,3 +160,18 @@
      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);
+}
+
Index: elfutils-0.146/libelf/elf.h
===================================================================
--- elfutils-0.146.orig/libelf/elf.h	2010-04-24 10:11:11.000000000 +0000
+++ elfutils-0.146/libelf/elf.h	2010-04-24 10:11:13.000000000 +0000
@@ -2290,6 +2290,9 @@
 #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.  */
@@ -2307,12 +2310,19 @@
 
 /* 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.  */
 
@@ -2344,12 +2354,75 @@
 #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 */
@@ -2364,6 +2437,12 @@
 					   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: elfutils-0.146/backends/libebl_arm.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ elfutils-0.146/backends/libebl_arm.h	2010-04-24 10:11:13.000000000 +0000
@@ -0,0 +1,9 @@
+#ifndef _LIBEBL_ARM_H
+#define _LIBEBL_ARM_H 1
+
+#include <libdw.h>
+
+extern int arm_return_value_location_soft(Dwarf_Die *, const Dwarf_Op **locp);
+extern int arm_return_value_location_hard(Dwarf_Die *, const Dwarf_Op **locp);
+
+#endif
