Author: markj
Date: Sun Dec 29 21:46:50 2019
New Revision: 356187
URL: https://svnweb.freebsd.org/changeset/base/356187

Log:
  Add libdtrace support for arm64 USDT probes.
  
  arm64 is still lacking a fasttrap implementation, which is required to
  actually enable userland probes, but this at least allows USDT probes to
  be linked into userland applications.
  
  Submitted by: Klaus Küchemann <macipho...@googlemail.com> (original)
  MFC after:    2 weeks
  Differential Revision:        https://reviews.freebsd.org/D22360

Modified:
  head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c

Modified: head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c
==============================================================================
--- head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c        Sun Dec 
29 21:46:00 2019        (r356186)
+++ head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c        Sun Dec 
29 21:46:50 2019        (r356187)
@@ -229,9 +229,10 @@ prepare_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof,
 
                for (j = 0; j < nrel; j++) {
 #if defined(__aarch64__)
-/* XXX */
-                       printf("%s:%s(%d): aarch64 not implemented\n",
-                           __FUNCTION__, __FILE__, __LINE__);
+                       rel->r_offset = s->dofs_offset +
+                           dofr[j].dofr_offset;
+                       rel->r_info = ELF32_R_INFO(count + dep->de_global,
+                           R_ARM_REL32);
 #elif defined(__arm__)
 /* XXX */
                        printf("%s:%s(%d): arm not implemented\n",
@@ -425,7 +426,10 @@ prepare_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof,
 
                for (j = 0; j < nrel; j++) {
 #if defined(__aarch64__)
-/* XXX */
+                       rel->r_offset = s->dofs_offset +
+                           dofr[j].dofr_offset;
+                       rel->r_info = ELF64_R_INFO(count + dep->de_global,
+                           R_AARCH64_PREL64);
 #elif defined(__arm__)
 /* XXX */
 #elif defined(__mips__)
@@ -541,6 +545,8 @@ dump_elf32(dtrace_hdl_t *dtp, const dof_hdr_t *dof, in
        elf_file.ehdr.e_machine = EM_SPARC;
 #elif defined(__i386) || defined(__amd64)
        elf_file.ehdr.e_machine = EM_386;
+#elif defined(__aarch64__)
+       elf_file.ehdr.e_machine = EM_AARCH64;
 #endif
        elf_file.ehdr.e_version = EV_CURRENT;
        elf_file.ehdr.e_shoff = sizeof (Elf32_Ehdr);
@@ -687,6 +693,8 @@ dump_elf64(dtrace_hdl_t *dtp, const dof_hdr_t *dof, in
        elf_file.ehdr.e_machine = EM_SPARCV9;
 #elif defined(__i386) || defined(__amd64)
        elf_file.ehdr.e_machine = EM_AMD64;
+#elif defined(__aarch64__)
+       elf_file.ehdr.e_machine = EM_AARCH64;
 #endif
        elf_file.ehdr.e_version = EV_CURRENT;
        elf_file.ehdr.e_shoff = sizeof (Elf64_Ehdr);
@@ -802,14 +810,66 @@ dt_symtab_lookup(Elf_Data *data_sym, int start, int en
 }
 
 #if defined(__aarch64__)
-/* XXX */
+#define        DT_OP_NOP               0xd503201f
+#define        DT_OP_RET               0xd65f03c0
+#define        DT_OP_CALL26            0x94000000
+#define        DT_OP_JUMP26            0x14000000
+
 static int
 dt_modtext(dtrace_hdl_t *dtp, char *p, int isenabled, GElf_Rela *rela,
     uint32_t *off)
 {
-       printf("%s:%s(%d): aarch64 not implemented\n", __FUNCTION__, __FILE__,
-           __LINE__);
-       return (-1);
+       uint32_t *ip;
+
+       /*
+        * Ensure that the offset is aligned on an instruction boundary.
+        */
+       if ((rela->r_offset & (sizeof (uint32_t) - 1)) != 0)
+               return (-1);
+
+       /*
+        * We only know about some specific relocation types.
+        * We also recognize relocation type NONE, since that gets used for
+        * relocations of USDT probes, and we might be re-processing a file.
+        */
+       if (GELF_R_TYPE(rela->r_info) != R_AARCH64_CALL26 &&
+           GELF_R_TYPE(rela->r_info) != R_AARCH64_JUMP26 &&
+           GELF_R_TYPE(rela->r_info) != R_AARCH64_NONE)
+               return (-1);
+
+       ip = (uint32_t *)(p + rela->r_offset);
+
+       /*
+        * We may have already processed this object file in an earlier linker
+        * invocation. Check to see if the present instruction sequence matches
+        * the one we would install below.
+        */
+       if (ip[0] == DT_OP_NOP || ip[0] == DT_OP_RET)
+               return (0);
+
+       /*
+        * We only expect call instructions with a displacement of 0, or a jump
+        * instruction acting as a tail call.
+        */
+       if (ip[0] != DT_OP_CALL26 && ip[0] != DT_OP_JUMP26) {
+               dt_dprintf("found %x instead of a call or jmp instruction at "
+                   "%llx\n", ip[0], (u_longlong_t)rela->r_offset);
+               return (-1);
+       }
+
+       /*
+        * On arm64, we do not have to differentiate between regular probes and
+        * is-enabled probes.  Both cases are encoded as a regular branch for
+        * non-tail call locations, and a jump for tail call locations.  Calls
+        * are to be converted into a no-op whereas jumps should become a
+        * return.
+        */
+       if (ip[0] == DT_OP_CALL26)
+               ip[0] = DT_OP_NOP;
+       else
+               ip[0] = DT_OP_RET;
+
+       return (0);
 }
 #elif defined(__arm__)
 /* XXX */
@@ -1254,6 +1314,8 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *e
                emachine1 = emachine2 = EM_SPARCV9;
 #elif defined(__i386) || defined(__amd64)
                emachine1 = emachine2 = EM_AMD64;
+#elif defined(__aarch64__)
+               emachine1 = emachine2 = EM_AARCH64;
 #endif
                symsize = sizeof (Elf64_Sym);
        } else {
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to