Upstream-Status: Backport

Index: elfutils-0.155/backends/arm_init.c
===================================================================
--- elfutils-0.155.orig/backends/arm_init.c
+++ elfutils-0.155/backends/arm_init.c
@@ -35,21 +35,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);
@@ -61,7 +72,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;
 }
Index: elfutils-0.155/backends/arm_regs.c
===================================================================
--- elfutils-0.155.orig/backends/arm_regs.c
+++ elfutils-0.155/backends/arm_regs.c
@@ -31,6 +31,7 @@
 #endif
 
 #include <string.h>
+#include <stdio.h>
 #include <dwarf.h>
 
 #define BACKEND arm_
@@ -61,7 +62,15 @@ arm_register_info (Ebl *ebl __attribute_
       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';
@@ -76,6 +85,9 @@ arm_register_info (Ebl *ebl __attribute_
       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:
@@ -87,11 +99,139 @@ arm_register_info (Ebl *ebl __attribute_
       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.155/backends/arm_retval.c
===================================================================
--- elfutils-0.155.orig/backends/arm_retval.c
+++ elfutils-0.155/backends/arm_retval.c
@@ -48,6 +48,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.  */
@@ -58,8 +65,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.  */
@@ -112,14 +120,31 @@ arm_return_value_location (Dwarf_Die *fu
 	  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;
 
@@ -138,3 +163,18 @@ arm_return_value_location (Dwarf_Die *fu
      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.155/libelf/elf.h
===================================================================
--- elfutils-0.155.orig/libelf/elf.h
+++ elfutils-0.155/libelf/elf.h
@@ -2281,6 +2281,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.  */
@@ -2298,12 +2301,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.  */
 
@@ -2336,12 +2346,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_NO	55
+#define R_ARM_REL32_NO	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_TLS_GOTDESC	90
 #define R_ARM_TLS_CALL		91
 #define R_ARM_TLS_DESCSEQ	92
@@ -2360,6 +2433,13 @@ 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_THM_TLS_DESCSEQ	129
 #define R_ARM_IRELATIVE		160
 #define R_ARM_RXPC25		249
Index: elfutils-0.155/backends/libebl_arm.h
===================================================================
--- /dev/null
+++ elfutils-0.155/backends/libebl_arm.h
@@ -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
