summaryrefslogtreecommitdiff
path: root/harmony/ltrace
diff options
context:
space:
mode:
Diffstat (limited to 'harmony/ltrace')
-rw-r--r--harmony/ltrace/APKBUILD44
-rw-r--r--harmony/ltrace/aarch-part2.patch1982
-rw-r--r--harmony/ltrace/aarch64.patch2155
-rw-r--r--harmony/ltrace/add_ppc64le.patch54
-rw-r--r--harmony/ltrace/musl.patch153
5 files changed, 4388 insertions, 0 deletions
diff --git a/harmony/ltrace/APKBUILD b/harmony/ltrace/APKBUILD
new file mode 100644
index 000000000..bd07768bf
--- /dev/null
+++ b/harmony/ltrace/APKBUILD
@@ -0,0 +1,44 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=ltrace
+pkgver=0.7.3
+pkgrel=2
+pkgdesc="Tracks runtime library calls in dynamically linked programs"
+url="http://ltrace.alioth.debian.org/"
+arch="all"
+options="!check" # Test suite has glibc stuff hardcoded.
+license="GPL-2.0+"
+makedepends="linux-headers libelf-dev autoconf automake"
+subpackages="$pkgname-doc"
+# you find latest release here, but need a login:
+# https://alioth.debian.org/frs/?group_id=30892
+source="https://dev.alpinelinux.org/archive/$pkgname/$pkgname-$pkgver.tar.bz2
+ musl.patch
+ aarch64.patch
+ add_ppc64le.patch"
+
+builddir="$srcdir/$pkgname-$pkgver"
+prepare() {
+ default_prepare
+ aclocal && autoconf && automake --add-missing --force
+}
+
+build() {
+ cd "$builddir"
+ ./configure \
+ --build=$CBUILD \
+ --host=$CHOST \
+ --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-werror
+ make
+}
+
+package() {
+ cd "$builddir"
+ make install INSTALL=install DESTDIR="$pkgdir"
+}
+
+sha512sums="a842b16dcb81da869afa0bddc755fdff0d57b35672505bf2c7164fd983b1938d28b126714128930994cc1230ced69d779456d0cfc16f4008c9b6d19f0852285d ltrace-0.7.3.tar.bz2
+c53e05471c52e161a7f7389994c6467e8f3671c5d8478546bc1897f067c62aeab848d728295f339a241a3fc186e180d47bcc2872a6335877c3813b1b62834698 musl.patch
+e6682f8c9e1e049286b6462bbab03cbdcf31c1770f649be997393cbd9b3b2ce8ada93766474e16bb604624ffe3e3d46d467bfbedecac2af31b904bb4e763d43a aarch64.patch
+987c6d18bdb559e8fe739f09cfb0b567dafcf79b2bd5db7ca32ebb205f3b1d74a8008576e4d73ea90873c1ab9bed17d96ddb7ad8752bf0a160ea0638c955eb1f add_ppc64le.patch"
diff --git a/harmony/ltrace/aarch-part2.patch b/harmony/ltrace/aarch-part2.patch
new file mode 100644
index 000000000..c40d0a797
--- /dev/null
+++ b/harmony/ltrace/aarch-part2.patch
@@ -0,0 +1,1982 @@
+From ae7249250ea650ec82bc545d4281b852020c7a6f Mon Sep 17 00:00:00 2001
+From: Petr Machata <pmachata@redhat.com>
+Date: Fri, 24 Jan 2014 00:50:06 +0100
+Subject: [PATCH 1/1] Implement aarch64 support
+
+- IFUNC support is not implemented, the rest works well. The only
+ other failure is in wide char functions, and that occurs on x86_64
+ as well.
+---
+ configure.ac | 3 +-
+ sysdeps/linux-gnu/Makefile.am | 4 +-
+ sysdeps/linux-gnu/aarch64/Makefile.am | 25 +
+ sysdeps/linux-gnu/aarch64/arch.h | 37 ++
+ sysdeps/linux-gnu/aarch64/fetch.c | 365 +++++++++++
+ sysdeps/linux-gnu/aarch64/plt.c | 38 ++
+ sysdeps/linux-gnu/aarch64/ptrace.h | 22 +
+ sysdeps/linux-gnu/aarch64/regs.c | 130 ++++
+ sysdeps/linux-gnu/aarch64/signalent.h | 52 ++
+ sysdeps/linux-gnu/aarch64/syscallent.h | 1100 ++++++++++++++++++++++++++++++++
+ sysdeps/linux-gnu/aarch64/trace.c | 83 +++
+ 11 files changed, 1857 insertions(+), 2 deletions(-)
+ create mode 100644 sysdeps/linux-gnu/aarch64/Makefile.am
+ create mode 100644 sysdeps/linux-gnu/aarch64/arch.h
+ create mode 100644 sysdeps/linux-gnu/aarch64/fetch.c
+ create mode 100644 sysdeps/linux-gnu/aarch64/plt.c
+ create mode 100644 sysdeps/linux-gnu/aarch64/ptrace.h
+ create mode 100644 sysdeps/linux-gnu/aarch64/regs.c
+ create mode 100644 sysdeps/linux-gnu/aarch64/signalent.h
+ create mode 100644 sysdeps/linux-gnu/aarch64/syscallent.h
+ create mode 100644 sysdeps/linux-gnu/aarch64/trace.c
+
+diff --git a/configure.ac b/configure.ac
+index c6e6bf0..0e9a124 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1,6 +1,6 @@
+ # -*- Autoconf -*-
+ # This file is part of ltrace.
+-# Copyright (C) 2010,2013 Petr Machata, Red Hat Inc.
++# Copyright (C) 2010,2012,2013,2014 Petr Machata, Red Hat Inc.
+ # Copyright (C) 2010,2011 Joe Damato
+ # Copyright (C) 2010 Marc Kleine-Budde
+ # Copyright (C) 2010 Zachary T Welch
+@@ -399,6 +399,7 @@ AC_CONFIG_FILES([
+ Makefile
+ sysdeps/Makefile
+ sysdeps/linux-gnu/Makefile
++ sysdeps/linux-gnu/aarch64/Makefile
+ sysdeps/linux-gnu/alpha/Makefile
+ sysdeps/linux-gnu/arm/Makefile
+ sysdeps/linux-gnu/cris/Makefile
+diff --git a/sysdeps/linux-gnu/Makefile.am b/sysdeps/linux-gnu/Makefile.am
+index ecee577..ec26162 100644
+--- a/sysdeps/linux-gnu/Makefile.am
++++ b/sysdeps/linux-gnu/Makefile.am
+@@ -1,4 +1,5 @@
+ # This file is part of ltrace.
++# Copyright (C) 2014 Petr Machata, Red Hat, Inc.
+ # Copyright (C) 2010,2012 Marc Kleine-Budde, Pengutronix
+ #
+ # This program is free software; you can redistribute it and/or
+@@ -16,7 +17,8 @@
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ # 02110-1301 USA
+
+-DIST_SUBDIRS = alpha arm cris ia64 m68k mips ppc s390 sparc x86
++DIST_SUBDIRS = aarch64 alpha arm cris ia64 m68k mips ppc s390 \
++ sparc x86
+
+ SUBDIRS = \
+ $(HOST_CPU)
+diff --git a/sysdeps/linux-gnu/aarch64/Makefile.am b/sysdeps/linux-gnu/aarch64/Makefile.am
+new file mode 100644
+index 0000000..0af4e6e
+--- /dev/null
++++ b/sysdeps/linux-gnu/aarch64/Makefile.am
+@@ -0,0 +1,25 @@
++# This file is part of ltrace.
++# Copyright (C) 2014 Petr Machata, Red Hat, Inc.
++#
++# This program is free software; you can redistribute it and/or
++# modify it under the terms of the GNU General Public License as
++# published by the Free Software Foundation; either version 2 of the
++# License, or (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful, but
++# WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++# General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++# 02110-1301 USA
++
++noinst_LTLIBRARIES = ../libcpu.la
++
++___libcpu_la_SOURCES = fetch.c plt.c regs.c trace.c
++
++noinst_HEADERS = arch.h ptrace.h signalent.h syscallent.h
++
++MAINTAINERCLEANFILES = Makefile.in
+diff --git a/sysdeps/linux-gnu/aarch64/arch.h b/sysdeps/linux-gnu/aarch64/arch.h
+new file mode 100644
+index 0000000..4137613
+--- /dev/null
++++ b/sysdeps/linux-gnu/aarch64/arch.h
+@@ -0,0 +1,37 @@
++/*
++ * This file is part of ltrace.
++ * Copyright (C) 2014 Petr Machata, Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ */
++#ifndef LTRACE_AARCH64_ARCH_H
++#define LTRACE_AARCH64_ARCH_H
++
++/* | 31 21 | 20 5 | 4 0 | *
++ * | 1 1 0 1 0 1 0 0 0 0 1 | imm16 | 0 0 0 0 0 | */
++#define BREAKPOINT_VALUE { 0xd4, 0x20, 0, 0 }
++#define BREAKPOINT_LENGTH 4
++#define DECR_PC_AFTER_BREAK 0
++
++#define LT_ELFCLASS ELFCLASS64
++#define LT_ELF_MACHINE EM_AARCH64
++
++#define ARCH_HAVE_FETCH_ARG
++#define ARCH_ENDIAN_BIG
++#define ARCH_HAVE_SIZEOF
++#define ARCH_HAVE_ALIGNOF
++
++#endif /* LTRACE_AARCH64_ARCH_H */
+diff --git a/sysdeps/linux-gnu/aarch64/fetch.c b/sysdeps/linux-gnu/aarch64/fetch.c
+new file mode 100644
+index 0000000..8779f03
+--- /dev/null
++++ b/sysdeps/linux-gnu/aarch64/fetch.c
+@@ -0,0 +1,365 @@
++/*
++ * This file is part of ltrace.
++ * Copyright (C) 2014 Petr Machata, Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ */
++
++#include <sys/ptrace.h>
++#include <asm/ptrace.h>
++#include <stdlib.h>
++#include <string.h>
++
++#include "fetch.h"
++#include "proc.h"
++#include "type.h"
++#include "value.h"
++
++int aarch64_read_gregs(struct Process *proc, struct user_pt_regs *regs);
++int aarch64_read_fregs(struct Process *proc, struct user_fpsimd_state *regs);
++
++
++struct fetch_context
++{
++ struct user_pt_regs gregs;
++ struct user_fpsimd_state fpregs;
++ arch_addr_t nsaa;
++ unsigned ngrn;
++ unsigned nsrn;
++ arch_addr_t x8;
++};
++
++static int
++context_init(struct fetch_context *context, struct Process *proc)
++{
++ if (aarch64_read_gregs(proc, &context->gregs) < 0
++ || aarch64_read_fregs(proc, &context->fpregs) < 0)
++ return -1;
++
++ context->ngrn = 0;
++ context->nsrn = 0;
++ /* XXX double cast */
++ context->nsaa = (arch_addr_t) (uintptr_t) context->gregs.sp;
++ context->x8 = 0;
++
++ return 0;
++}
++
++struct fetch_context *
++arch_fetch_arg_clone(struct Process *proc, struct fetch_context *context)
++{
++ struct fetch_context *ret = malloc(sizeof(*ret));
++ if (ret == NULL)
++ return NULL;
++ return memcpy(ret, context, sizeof(*ret));
++}
++
++static void
++fetch_next_gpr(struct fetch_context *context, unsigned char *buf)
++{
++ uint64_t u = context->gregs.regs[context->ngrn++];
++ memcpy(buf, &u, 8);
++}
++
++static int
++fetch_gpr(struct fetch_context *context, struct value *value, size_t sz)
++{
++ if (sz < 8)
++ sz = 8;
++
++ unsigned char *buf = value_reserve(value, sz);
++ if (buf == NULL)
++ return -1;
++
++ size_t i;
++ for (i = 0; i < sz; i += 8)
++ fetch_next_gpr(context, buf + i);
++
++ return 0;
++}
++
++static void
++fetch_next_sse(struct fetch_context *context, unsigned char *buf, size_t sz)
++{
++ __int128 u = context->fpregs.vregs[context->nsrn++];
++ memcpy(buf, &u, sz);
++}
++
++static int
++fetch_sse(struct fetch_context *context, struct value *value, size_t sz)
++{
++ unsigned char *buf = value_reserve(value, sz);
++ if (buf == NULL)
++ return -1;
++
++ fetch_next_sse(context, buf, sz);
++ return 0;
++}
++
++static int
++fetch_hfa(struct fetch_context *context,
++ struct value *value, struct arg_type_info *hfa_t, size_t count)
++{
++ size_t sz = type_sizeof(value->inferior, hfa_t);
++ unsigned char *buf = value_reserve(value, sz * count);
++ if (buf == NULL)
++ return -1;
++
++ size_t i;
++ for (i = 0; i < count; ++i) {
++ fetch_next_sse(context, buf, sz);
++ buf += sz;
++ }
++ return 0;
++}
++
++static int
++fetch_stack(struct fetch_context *context, struct value *value,
++ size_t align, size_t sz)
++{
++ if (align < 8)
++ align = 8;
++ size_t amount = ((sz + align - 1) / align) * align;
++
++ /* XXX double casts */
++ uintptr_t sp = (uintptr_t) context->nsaa;
++ sp = ((sp + align - 1) / align) * align;
++
++ value_in_inferior(value, (arch_addr_t) sp);
++
++ sp += amount;
++ context->nsaa = (arch_addr_t) sp;
++
++ return 0;
++}
++
++enum convert_method {
++ CVT_ERR = -1,
++ CVT_NOP = 0,
++ CVT_BYREF,
++};
++
++enum fetch_method {
++ FETCH_NOP,
++ FETCH_STACK,
++ FETCH_GPR,
++ FETCH_SSE,
++ FETCH_HFA,
++};
++
++struct fetch_script {
++ enum convert_method c;
++ enum fetch_method f;
++ size_t sz;
++ struct arg_type_info *hfa_t;
++ size_t count;
++};
++
++static struct fetch_script
++pass_arg(struct fetch_context const *context,
++ struct Process *proc, struct arg_type_info *info)
++{
++ enum fetch_method cvt = CVT_NOP;
++
++ size_t sz = type_sizeof(proc, info);
++ if (sz == (size_t) -1)
++ return (struct fetch_script) { CVT_ERR, FETCH_NOP, sz };
++
++ switch (info->type) {
++ case ARGTYPE_VOID:
++ return (struct fetch_script) { cvt, FETCH_NOP, sz };
++
++ case ARGTYPE_STRUCT:
++ case ARGTYPE_ARRAY:;
++ size_t count;
++ struct arg_type_info *hfa_t = type_get_hfa_type(info, &count);
++ if (hfa_t != NULL && count <= 4) {
++ if (context->nsrn + count <= 8)
++ return (struct fetch_script)
++ { cvt, FETCH_HFA, sz, hfa_t, count };
++ return (struct fetch_script)
++ { cvt, FETCH_STACK, sz, hfa_t, count };
++ }
++
++ if (sz <= 16) {
++ size_t count = sz / 8;
++ if (context->ngrn + count <= 8)
++ return (struct fetch_script)
++ { cvt, FETCH_GPR, sz };
++ }
++
++ cvt = CVT_BYREF;
++ sz = 8;
++ /* Fall through. */
++
++ case ARGTYPE_POINTER:
++ case ARGTYPE_INT:
++ case ARGTYPE_UINT:
++ case ARGTYPE_LONG:
++ case ARGTYPE_ULONG:
++ case ARGTYPE_CHAR:
++ case ARGTYPE_SHORT:
++ case ARGTYPE_USHORT:
++ if (context->ngrn < 8 && sz <= 8)
++ return (struct fetch_script) { cvt, FETCH_GPR, sz };
++ /* We don't support types wider than 8 bytes as of
++ * now. */
++ assert(sz <= 8);
++
++ return (struct fetch_script) { cvt, FETCH_STACK, sz };
++
++ case ARGTYPE_FLOAT:
++ case ARGTYPE_DOUBLE:
++ if (context->nsrn < 8) {
++ /* ltrace doesn't support float128. */
++ assert(sz <= 8);
++ return (struct fetch_script) { cvt, FETCH_SSE, sz };
++ }
++
++ return (struct fetch_script) { cvt, FETCH_STACK, sz };
++ }
++
++ assert(! "Failed to allocate argument.");
++ abort();
++}
++
++static int
++convert_arg(struct value *value, struct fetch_script how)
++{
++ switch (how.c) {
++ case CVT_NOP:
++ return 0;
++ case CVT_BYREF:
++ return value_pass_by_reference(value);
++ case CVT_ERR:
++ return -1;
++ }
++
++ assert(! "Don't know how to convert argument.");
++ abort();
++}
++
++static int
++fetch_arg(struct fetch_context *context,
++ struct Process *proc, struct arg_type_info *info,
++ struct value *value, struct fetch_script how)
++{
++ if (convert_arg(value, how) < 0)
++ return -1;
++
++ switch (how.f) {
++ case FETCH_NOP:
++ return 0;
++
++ case FETCH_STACK:
++ if (how.hfa_t != NULL && how.count != 0 && how.count <= 8)
++ context->nsrn = 8;
++ return fetch_stack(context, value,
++ type_alignof(proc, info), how.sz);
++
++ case FETCH_GPR:
++ return fetch_gpr(context, value, how.sz);
++
++ case FETCH_SSE:
++ return fetch_sse(context, value, how.sz);
++
++ case FETCH_HFA:
++ return fetch_hfa(context, value, how.hfa_t, how.count);
++ }
++
++ assert(! "Don't know how to fetch argument.");
++ abort();
++}
++
++struct fetch_context *
++arch_fetch_arg_init(enum tof type, struct Process *proc,
++ struct arg_type_info *ret_info)
++{
++ struct fetch_context *context = malloc(sizeof *context);
++ if (context == NULL || context_init(context, proc) < 0) {
++ fail:
++ free(context);
++ return NULL;
++ }
++
++ /* There's a provision in ARMv8 parameter passing convention
++ * for returning types that, if passed as first argument to a
++ * function, would be passed on stack. For those types, x8
++ * contains an address where the return argument should be
++ * placed. The callee doesn't need to preserve the value of
++ * x8, so we need to fetch it now.
++ *
++ * To my knowledge, there are currently no types where this
++ * holds, but the code is here, utterly untested. */
++
++ struct fetch_script how = pass_arg(context, proc, ret_info);
++ if (how.c == CVT_ERR)
++ goto fail;
++ if (how.c == CVT_NOP && how.f == FETCH_STACK) {
++ /* XXX double cast. */
++ context->x8 = (arch_addr_t) (uintptr_t) context->gregs.regs[8];
++ /* See the comment above about the assert. */
++ assert(! "Unexpected: first argument passed on stack.");
++ abort();
++ }
++
++ return context;
++}
++
++int
++arch_fetch_arg_next(struct fetch_context *context, enum tof type,
++ struct Process *proc, struct arg_type_info *info,
++ struct value *value)
++{
++ return fetch_arg(context, proc, info, value,
++ pass_arg(context, proc, info));
++}
++
++int
++arch_fetch_retval(struct fetch_context *context, enum tof type,
++ struct Process *proc, struct arg_type_info *info,
++ struct value *value)
++{
++ if (context->x8 != 0) {
++ value_in_inferior(value, context->x8);
++ return 0;
++ }
++
++ if (context_init(context, proc) < 0)
++ return -1;
++
++ return fetch_arg(context, proc, info, value,
++ pass_arg(context, proc, info));
++}
++
++void
++arch_fetch_arg_done(struct fetch_context *context)
++{
++ if (context != NULL)
++ free(context);
++}
++
++size_t
++arch_type_sizeof(struct Process *proc, struct arg_type_info *arg)
++{
++ return (size_t) -2;
++}
++
++size_t
++arch_type_alignof(struct Process *proc, struct arg_type_info *arg)
++{
++ return (size_t) -2;
++}
+diff --git a/sysdeps/linux-gnu/aarch64/plt.c b/sysdeps/linux-gnu/aarch64/plt.c
+new file mode 100644
+index 0000000..29dc4c9
+--- /dev/null
++++ b/sysdeps/linux-gnu/aarch64/plt.c
+@@ -0,0 +1,38 @@
++/*
++ * This file is part of ltrace.
++ * Copyright (C) 2014 Petr Machata, Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ */
++
++#include <gelf.h>
++
++#include "backend.h"
++#include "proc.h"
++#include "library.h"
++#include "ltrace-elf.h"
++
++arch_addr_t
++sym2addr(struct Process *proc, struct library_symbol *sym)
++{
++ return sym->enter_addr;
++}
++
++GElf_Addr
++arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela *rela)
++{
++ return lte->plt_addr + 32 + ndx * 16;
++}
+diff --git a/sysdeps/linux-gnu/aarch64/ptrace.h b/sysdeps/linux-gnu/aarch64/ptrace.h
+new file mode 100644
+index 0000000..283c314
+--- /dev/null
++++ b/sysdeps/linux-gnu/aarch64/ptrace.h
+@@ -0,0 +1,22 @@
++/*
++ * This file is part of ltrace.
++ * Copyright (C) 2014 Petr Machata, Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ */
++
++#include <sys/ptrace.h>
++#include <asm/ptrace.h>
+diff --git a/sysdeps/linux-gnu/aarch64/regs.c b/sysdeps/linux-gnu/aarch64/regs.c
+new file mode 100644
+index 0000000..06eb72b
+--- /dev/null
++++ b/sysdeps/linux-gnu/aarch64/regs.c
+@@ -0,0 +1,131 @@
++/*
++ * This file is part of ltrace.
++ * Copyright (C) 2014 Petr Machata, Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ */
++
++#include <sys/ptrace.h>
++#include <asm/ptrace.h>
++#include <linux/uio.h>
++#include <assert.h>
++#include <stdlib.h>
++#include <stdio.h>
++
++#include "backend.h"
++#include "proc.h"
++
++#define PC_OFF (32 * 4)
++
++int
++aarch64_read_gregs(struct Process *proc, struct user_pt_regs *regs)
++{
++ *regs = (struct user_pt_regs) {};
++ struct iovec iovec;
++ iovec.iov_base = regs;
++ iovec.iov_len = sizeof *regs;
++ return ptrace(PTRACE_GETREGSET, proc->pid, NT_PRSTATUS, &iovec) < 0
++ ? -1 : 0;
++}
++
++int
++aarch64_write_gregs(struct Process *proc, struct user_pt_regs *regs)
++{
++ struct iovec iovec;
++ iovec.iov_base = regs;
++ iovec.iov_len = sizeof *regs;
++ return ptrace(PTRACE_SETREGSET, proc->pid, NT_PRSTATUS, &iovec) < 0
++ ? -1 : 0;
++}
++
++int
++aarch64_read_fregs(struct Process *proc, struct user_fpsimd_state *regs)
++{
++ *regs = (struct user_fpsimd_state) {};
++ struct iovec iovec;
++ iovec.iov_base = regs;
++ iovec.iov_len = sizeof *regs;
++ return ptrace(PTRACE_GETREGSET, proc->pid, NT_FPREGSET, &iovec) < 0
++ ? -1 : 0;
++}
++
++arch_addr_t
++get_instruction_pointer(struct Process *proc)
++{
++ struct user_pt_regs regs;
++ if (aarch64_read_gregs(proc, &regs) < 0) {
++ fprintf(stderr, "get_instruction_pointer: "
++ "Couldn't read registers of %d.\n", proc->pid);
++ return 0;
++ }
++
++ /*
++ char buf[128];
++ sprintf(buf, "cat /proc/%d/maps", proc->pid);
++ system(buf);
++ */
++
++ /* XXX double cast */
++ return (arch_addr_t) (uintptr_t) regs.pc;
++}
++
++void
++set_instruction_pointer(struct Process *proc, arch_addr_t addr)
++{
++ struct user_pt_regs regs;
++ if (aarch64_read_gregs(proc, &regs) < 0) {
++ fprintf(stderr, "get_instruction_pointer: "
++ "Couldn't read registers of %d.\n", proc->pid);
++ return;
++ }
++
++ /* XXX double cast */
++ regs.pc = (uint64_t) (uintptr_t) addr;
++
++ if (aarch64_write_gregs(proc, &regs) < 0) {
++ fprintf(stderr, "get_instruction_pointer: "
++ "Couldn't write registers of %d.\n", proc->pid);
++ return;
++ }
++}
++
++arch_addr_t
++get_stack_pointer(struct Process *proc)
++{
++ struct user_pt_regs regs;
++ if (aarch64_read_gregs(proc, &regs) < 0) {
++ fprintf(stderr, "get_stack_pointer: "
++ "Couldn't read registers of %d.\n", proc->pid);
++ return 0;
++ }
++
++ /* XXX double cast */
++ return (arch_addr_t) (uintptr_t) regs.sp;
++}
++
++arch_addr_t
++get_return_addr(struct Process *proc, arch_addr_t stack_pointer)
++{
++ struct user_pt_regs regs;
++ if (aarch64_read_gregs(proc, &regs) < 0) {
++ fprintf(stderr, "get_return_addr: "
++ "Couldn't read registers of %d.\n", proc->pid);
++ return 0;
++ }
++
++ /* XXX double cast */
++ return (arch_addr_t) (uintptr_t) regs.regs[30];
++}
+diff --git a/sysdeps/linux-gnu/aarch64/signalent.h b/sysdeps/linux-gnu/aarch64/signalent.h
+new file mode 100644
+index 0000000..bf56ebc
+--- /dev/null
++++ b/sysdeps/linux-gnu/aarch64/signalent.h
+@@ -0,0 +1,52 @@
++/*
++ * This file is part of ltrace.
++ * Copyright (C) 2006 Ian Wienand
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ */
++
++ "SIG_0", /* 0 */
++ "SIGHUP", /* 1 */
++ "SIGINT", /* 2 */
++ "SIGQUIT", /* 3 */
++ "SIGILL", /* 4 */
++ "SIGTRAP", /* 5 */
++ "SIGABRT", /* 6 */
++ "SIGBUS", /* 7 */
++ "SIGFPE", /* 8 */
++ "SIGKILL", /* 9 */
++ "SIGUSR1", /* 10 */
++ "SIGSEGV", /* 11 */
++ "SIGUSR2", /* 12 */
++ "SIGPIPE", /* 13 */
++ "SIGALRM", /* 14 */
++ "SIGTERM", /* 15 */
++ "SIGSTKFLT", /* 16 */
++ "SIGCHLD", /* 17 */
++ "SIGCONT", /* 18 */
++ "SIGSTOP", /* 19 */
++ "SIGTSTP", /* 20 */
++ "SIGTTIN", /* 21 */
++ "SIGTTOU", /* 22 */
++ "SIGURG", /* 23 */
++ "SIGXCPU", /* 24 */
++ "SIGXFSZ", /* 25 */
++ "SIGVTALRM", /* 26 */
++ "SIGPROF", /* 27 */
++ "SIGWINCH", /* 28 */
++ "SIGIO", /* 29 */
++ "SIGPWR", /* 30 */
++ "SIGSYS", /* 31 */
+diff --git a/sysdeps/linux-gnu/aarch64/syscallent.h b/sysdeps/linux-gnu/aarch64/syscallent.h
+new file mode 100644
+index 0000000..aca8191
+--- /dev/null
++++ b/sysdeps/linux-gnu/aarch64/syscallent.h
+@@ -0,0 +1,1100 @@
++/*
++ * This file is part of ltrace.
++ * Copyright (C) 2014 Petr Machata, Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ */
++
++ "io_setup", /* 0 */
++ "io_destroy", /* 1 */
++ "io_submit", /* 2 */
++ "io_cancel", /* 3 */
++ "io_getevents", /* 4 */
++ "setxattr", /* 5 */
++ "lsetxattr", /* 6 */
++ "fsetxattr", /* 7 */
++ "getxattr", /* 8 */
++ "lgetxattr", /* 9 */
++ "fgetxattr", /* 10 */
++ "listxattr", /* 11 */
++ "llistxattr", /* 12 */
++ "flistxattr", /* 13 */
++ "removexattr", /* 14 */
++ "lremovexattr", /* 15 */
++ "fremovexattr", /* 16 */
++ "getcwd", /* 17 */
++ "lookup_dcookie", /* 18 */
++ "eventfd2", /* 19 */
++ "epoll_create1", /* 20 */
++ "epoll_ctl", /* 21 */
++ "epoll_pwait", /* 22 */
++ "dup", /* 23 */
++ "dup3", /* 24 */
++ "fcntl", /* 25 */
++ "inotify_init1", /* 26 */
++ "inotify_add_watch", /* 27 */
++ "inotify_rm_watch", /* 28 */
++ "ioctl", /* 29 */
++ "ioprio_set", /* 30 */
++ "ioprio_get", /* 31 */
++ "flock", /* 32 */
++ "mknodat", /* 33 */
++ "mkdirat", /* 34 */
++ "unlinkat", /* 35 */
++ "symlinkat", /* 36 */
++ "linkat", /* 37 */
++ "renameat", /* 38 */
++ "umount2", /* 39 */
++ "mount", /* 40 */
++ "pivot_root", /* 41 */
++ "nfsservctl", /* 42 */
++ "statfs", /* 43 */
++ "fstatfs", /* 44 */
++ "truncate", /* 45 */
++ "ftruncate", /* 46 */
++ "fallocate", /* 47 */
++ "faccessat", /* 48 */
++ "chdir", /* 49 */
++ "fchdir", /* 50 */
++ "chroot", /* 51 */
++ "fchmod", /* 52 */
++ "fchmodat", /* 53 */
++ "fchownat", /* 54 */
++ "fchown", /* 55 */
++ "openat", /* 56 */
++ "close", /* 57 */
++ "vhangup", /* 58 */
++ "pipe2", /* 59 */
++ "quotactl", /* 60 */
++ "getdents64", /* 61 */
++ "lseek", /* 62 */
++ "read", /* 63 */
++ "write", /* 64 */
++ "readv", /* 65 */
++ "writev", /* 66 */
++ "pread64", /* 67 */
++ "pwrite64", /* 68 */
++ "preadv", /* 69 */
++ "pwritev", /* 70 */
++ "sendfile", /* 71 */
++ "pselect6", /* 72 */
++ "ppoll", /* 73 */
++ "signalfd4", /* 74 */
++ "vmsplice", /* 75 */
++ "splice", /* 76 */
++ "tee", /* 77 */
++ "readlinkat", /* 78 */
++ "fstatat", /* 79 */
++ "fstat", /* 80 */
++ "sync", /* 81 */
++ "fsync", /* 82 */
++ "fdatasync", /* 83 */
++ "sync_file_range", /* 84 */
++ "timerfd_create", /* 85 */
++ "timerfd_settime", /* 86 */
++ "timerfd_gettime", /* 87 */
++ "utimensat", /* 88 */
++ "acct", /* 89 */
++ "capget", /* 90 */
++ "capset", /* 91 */
++ "personality", /* 92 */
++ "exit", /* 93 */
++ "exit_group", /* 94 */
++ "waitid", /* 95 */
++ "set_tid_address", /* 96 */
++ "unshare", /* 97 */
++ "futex", /* 98 */
++ "set_robust_list", /* 99 */
++ "get_robust_list", /* 100 */
++ "nanosleep", /* 101 */
++ "getitimer", /* 102 */
++ "setitimer", /* 103 */
++ "kexec_load", /* 104 */
++ "init_module", /* 105 */
++ "delete_module", /* 106 */
++ "timer_create", /* 107 */
++ "timer_gettime", /* 108 */
++ "timer_getoverrun", /* 109 */
++ "timer_settime", /* 110 */
++ "timer_delete", /* 111 */
++ "clock_settime", /* 112 */
++ "clock_gettime", /* 113 */
++ "clock_getres", /* 114 */
++ "clock_nanosleep", /* 115 */
++ "syslog", /* 116 */
++ "ptrace", /* 117 */
++ "sched_setparam", /* 118 */
++ "sched_setscheduler", /* 119 */
++ "sched_getscheduler", /* 120 */
++ "sched_getparam", /* 121 */
++ "sched_setaffinity", /* 122 */
++ "sched_getaffinity", /* 123 */
++ "sched_yield", /* 124 */
++ "sched_get_priority_max", /* 125 */
++ "sched_get_priority_min", /* 126 */
++ "sched_rr_get_interval", /* 127 */
++ "restart_syscall", /* 128 */
++ "kill", /* 129 */
++ "tkill", /* 130 */
++ "tgkill", /* 131 */
++ "sigaltstack", /* 132 */
++ "rt_sigsuspend", /* 133 */
++ "rt_sigaction", /* 134 */
++ "rt_sigprocmask", /* 135 */
++ "rt_sigpending", /* 136 */
++ "rt_sigtimedwait", /* 137 */
++ "rt_sigqueueinfo", /* 138 */
++ "rt_sigreturn", /* 139 */
++ "setpriority", /* 140 */
++ "getpriority", /* 141 */
++ "reboot", /* 142 */
++ "setregid", /* 143 */
++ "setgid", /* 144 */
++ "setreuid", /* 145 */
++ "setuid", /* 146 */
++ "setresuid", /* 147 */
++ "getresuid", /* 148 */
++ "setresgid", /* 149 */
++ "getresgid", /* 150 */
++ "setfsuid", /* 151 */
++ "setfsgid", /* 152 */
++ "times", /* 153 */
++ "setpgid", /* 154 */
++ "getpgid", /* 155 */
++ "getsid", /* 156 */
++ "setsid", /* 157 */
++ "getgroups", /* 158 */
++ "setgroups", /* 159 */
++ "uname", /* 160 */
++ "sethostname", /* 161 */
++ "setdomainname", /* 162 */
++ "getrlimit", /* 163 */
++ "setrlimit", /* 164 */
++ "getrusage", /* 165 */
++ "umask", /* 166 */
++ "prctl", /* 167 */
++ "getcpu", /* 168 */
++ "gettimeofday", /* 169 */
++ "settimeofday", /* 170 */
++ "adjtimex", /* 171 */
++ "getpid", /* 172 */
++ "getppid", /* 173 */
++ "getuid", /* 174 */
++ "geteuid", /* 175 */
++ "getgid", /* 176 */
++ "getegid", /* 177 */
++ "gettid", /* 178 */
++ "sysinfo", /* 179 */
++ "mq_open", /* 180 */
++ "mq_unlink", /* 181 */
++ "mq_timedsend", /* 182 */
++ "mq_timedreceive", /* 183 */
++ "mq_notify", /* 184 */
++ "mq_getsetattr", /* 185 */
++ "msgget", /* 186 */
++ "msgctl", /* 187 */
++ "msgrcv", /* 188 */
++ "msgsnd", /* 189 */
++ "semget", /* 190 */
++ "semctl", /* 191 */
++ "semtimedop", /* 192 */
++ "semop", /* 193 */
++ "shmget", /* 194 */
++ "shmctl", /* 195 */
++ "shmat", /* 196 */
++ "shmdt", /* 197 */
++ "socket", /* 198 */
++ "socketpair", /* 199 */
++ "bind", /* 200 */
++ "listen", /* 201 */
++ "accept", /* 202 */
++ "connect", /* 203 */
++ "getsockname", /* 204 */
++ "getpeername", /* 205 */
++ "sendto", /* 206 */
++ "recvfrom", /* 207 */
++ "setsockopt", /* 208 */
++ "getsockopt", /* 209 */
++ "shutdown", /* 210 */
++ "sendmsg", /* 211 */
++ "recvmsg", /* 212 */
++ "readahead", /* 213 */
++ "brk", /* 214 */
++ "munmap", /* 215 */
++ "mremap", /* 216 */
++ "add_key", /* 217 */
++ "request_key", /* 218 */
++ "keyctl", /* 219 */
++ "clone", /* 220 */
++ "execve", /* 221 */
++ "mmap", /* 222 */
++ "fadvise64", /* 223 */
++ "swapon", /* 224 */
++ "swapoff", /* 225 */
++ "mprotect", /* 226 */
++ "msync", /* 227 */
++ "mlock", /* 228 */
++ "munlock", /* 229 */
++ "mlockall", /* 230 */
++ "munlockall", /* 231 */
++ "mincore", /* 232 */
++ "madvise", /* 233 */
++ "remap_file_pages", /* 234 */
++ "mbind", /* 235 */
++ "get_mempolicy", /* 236 */
++ "set_mempolicy", /* 237 */
++ "migrate_pages", /* 238 */
++ "move_pages", /* 239 */
++ "rt_tgsigqueueinfo", /* 240 */
++ "perf_event_open", /* 241 */
++ "accept4", /* 242 */
++ "recvmmsg", /* 243 */
++ "arch_specific_syscall", /* 244 */
++ "245", /* 245 */
++ "246", /* 246 */
++ "247", /* 247 */
++ "248", /* 248 */
++ "249", /* 249 */
++ "250", /* 250 */
++ "251", /* 251 */
++ "252", /* 252 */
++ "253", /* 253 */
++ "254", /* 254 */
++ "255", /* 255 */
++ "256", /* 256 */
++ "257", /* 257 */
++ "258", /* 258 */
++ "259", /* 259 */
++ "wait4", /* 260 */
++ "prlimit64", /* 261 */
++ "fanotify_init", /* 262 */
++ "fanotify_mark", /* 263 */
++ "name_to_handle_at", /* 264 */
++ "open_by_handle_at", /* 265 */
++ "clock_adjtime", /* 266 */
++ "syncfs", /* 267 */
++ "setns", /* 268 */
++ "sendmmsg", /* 269 */
++ "process_vm_readv", /* 270 */
++ "process_vm_writev", /* 271 */
++ "kcmp", /* 272 */
++ "finit_module", /* 273 */
++ "syscalls", /* 274 */
++ "275", /* 275 */
++ "276", /* 276 */
++ "277", /* 277 */
++ "278", /* 278 */
++ "279", /* 279 */
++ "280", /* 280 */
++ "281", /* 281 */
++ "282", /* 282 */
++ "283", /* 283 */
++ "284", /* 284 */
++ "285", /* 285 */
++ "286", /* 286 */
++ "287", /* 287 */
++ "288", /* 288 */
++ "289", /* 289 */
++ "290", /* 290 */
++ "291", /* 291 */
++ "292", /* 292 */
++ "293", /* 293 */
++ "294", /* 294 */
++ "295", /* 295 */
++ "296", /* 296 */
++ "297", /* 297 */
++ "298", /* 298 */
++ "299", /* 299 */
++ "300", /* 300 */
++ "301", /* 301 */
++ "302", /* 302 */
++ "303", /* 303 */
++ "304", /* 304 */
++ "305", /* 305 */
++ "306", /* 306 */
++ "307", /* 307 */
++ "308", /* 308 */
++ "309", /* 309 */
++ "310", /* 310 */
++ "311", /* 311 */
++ "312", /* 312 */
++ "313", /* 313 */
++ "314", /* 314 */
++ "315", /* 315 */
++ "316", /* 316 */
++ "317", /* 317 */
++ "318", /* 318 */
++ "319", /* 319 */
++ "320", /* 320 */
++ "321", /* 321 */
++ "322", /* 322 */
++ "323", /* 323 */
++ "324", /* 324 */
++ "325", /* 325 */
++ "326", /* 326 */
++ "327", /* 327 */
++ "328", /* 328 */
++ "329", /* 329 */
++ "330", /* 330 */
++ "331", /* 331 */
++ "332", /* 332 */
++ "333", /* 333 */
++ "334", /* 334 */
++ "335", /* 335 */
++ "336", /* 336 */
++ "337", /* 337 */
++ "338", /* 338 */
++ "339", /* 339 */
++ "340", /* 340 */
++ "341", /* 341 */
++ "342", /* 342 */
++ "343", /* 343 */
++ "344", /* 344 */
++ "345", /* 345 */
++ "346", /* 346 */
++ "347", /* 347 */
++ "348", /* 348 */
++ "349", /* 349 */
++ "350", /* 350 */
++ "351", /* 351 */
++ "352", /* 352 */
++ "353", /* 353 */
++ "354", /* 354 */
++ "355", /* 355 */
++ "356", /* 356 */
++ "357", /* 357 */
++ "358", /* 358 */
++ "359", /* 359 */
++ "360", /* 360 */
++ "361", /* 361 */
++ "362", /* 362 */
++ "363", /* 363 */
++ "364", /* 364 */
++ "365", /* 365 */
++ "366", /* 366 */
++ "367", /* 367 */
++ "368", /* 368 */
++ "369", /* 369 */
++ "370", /* 370 */
++ "371", /* 371 */
++ "372", /* 372 */
++ "373", /* 373 */
++ "374", /* 374 */
++ "375", /* 375 */
++ "376", /* 376 */
++ "377", /* 377 */
++ "378", /* 378 */
++ "379", /* 379 */
++ "380", /* 380 */
++ "381", /* 381 */
++ "382", /* 382 */
++ "383", /* 383 */
++ "384", /* 384 */
++ "385", /* 385 */
++ "386", /* 386 */
++ "387", /* 387 */
++ "388", /* 388 */
++ "389", /* 389 */
++ "390", /* 390 */
++ "391", /* 391 */
++ "392", /* 392 */
++ "393", /* 393 */
++ "394", /* 394 */
++ "395", /* 395 */
++ "396", /* 396 */
++ "397", /* 397 */
++ "398", /* 398 */
++ "399", /* 399 */
++ "400", /* 400 */
++ "401", /* 401 */
++ "402", /* 402 */
++ "403", /* 403 */
++ "404", /* 404 */
++ "405", /* 405 */
++ "406", /* 406 */
++ "407", /* 407 */
++ "408", /* 408 */
++ "409", /* 409 */
++ "410", /* 410 */
++ "411", /* 411 */
++ "412", /* 412 */
++ "413", /* 413 */
++ "414", /* 414 */
++ "415", /* 415 */
++ "416", /* 416 */
++ "417", /* 417 */
++ "418", /* 418 */
++ "419", /* 419 */
++ "420", /* 420 */
++ "421", /* 421 */
++ "422", /* 422 */
++ "423", /* 423 */
++ "424", /* 424 */
++ "425", /* 425 */
++ "426", /* 426 */
++ "427", /* 427 */
++ "428", /* 428 */
++ "429", /* 429 */
++ "430", /* 430 */
++ "431", /* 431 */
++ "432", /* 432 */
++ "433", /* 433 */
++ "434", /* 434 */
++ "435", /* 435 */
++ "436", /* 436 */
++ "437", /* 437 */
++ "438", /* 438 */
++ "439", /* 439 */
++ "440", /* 440 */
++ "441", /* 441 */
++ "442", /* 442 */
++ "443", /* 443 */
++ "444", /* 444 */
++ "445", /* 445 */
++ "446", /* 446 */
++ "447", /* 447 */
++ "448", /* 448 */
++ "449", /* 449 */
++ "450", /* 450 */
++ "451", /* 451 */
++ "452", /* 452 */
++ "453", /* 453 */
++ "454", /* 454 */
++ "455", /* 455 */
++ "456", /* 456 */
++ "457", /* 457 */
++ "458", /* 458 */
++ "459", /* 459 */
++ "460", /* 460 */
++ "461", /* 461 */
++ "462", /* 462 */
++ "463", /* 463 */
++ "464", /* 464 */
++ "465", /* 465 */
++ "466", /* 466 */
++ "467", /* 467 */
++ "468", /* 468 */
++ "469", /* 469 */
++ "470", /* 470 */
++ "471", /* 471 */
++ "472", /* 472 */
++ "473", /* 473 */
++ "474", /* 474 */
++ "475", /* 475 */
++ "476", /* 476 */
++ "477", /* 477 */
++ "478", /* 478 */
++ "479", /* 479 */
++ "480", /* 480 */
++ "481", /* 481 */
++ "482", /* 482 */
++ "483", /* 483 */
++ "484", /* 484 */
++ "485", /* 485 */
++ "486", /* 486 */
++ "487", /* 487 */
++ "488", /* 488 */
++ "489", /* 489 */
++ "490", /* 490 */
++ "491", /* 491 */
++ "492", /* 492 */
++ "493", /* 493 */
++ "494", /* 494 */
++ "495", /* 495 */
++ "496", /* 496 */
++ "497", /* 497 */
++ "498", /* 498 */
++ "499", /* 499 */
++ "500", /* 500 */
++ "501", /* 501 */
++ "502", /* 502 */
++ "503", /* 503 */
++ "504", /* 504 */
++ "505", /* 505 */
++ "506", /* 506 */
++ "507", /* 507 */
++ "508", /* 508 */
++ "509", /* 509 */
++ "510", /* 510 */
++ "511", /* 511 */
++ "512", /* 512 */
++ "513", /* 513 */
++ "514", /* 514 */
++ "515", /* 515 */
++ "516", /* 516 */
++ "517", /* 517 */
++ "518", /* 518 */
++ "519", /* 519 */
++ "520", /* 520 */
++ "521", /* 521 */
++ "522", /* 522 */
++ "523", /* 523 */
++ "524", /* 524 */
++ "525", /* 525 */
++ "526", /* 526 */
++ "527", /* 527 */
++ "528", /* 528 */
++ "529", /* 529 */
++ "530", /* 530 */
++ "531", /* 531 */
++ "532", /* 532 */
++ "533", /* 533 */
++ "534", /* 534 */
++ "535", /* 535 */
++ "536", /* 536 */
++ "537", /* 537 */
++ "538", /* 538 */
++ "539", /* 539 */
++ "540", /* 540 */
++ "541", /* 541 */
++ "542", /* 542 */
++ "543", /* 543 */
++ "544", /* 544 */
++ "545", /* 545 */
++ "546", /* 546 */
++ "547", /* 547 */
++ "548", /* 548 */
++ "549", /* 549 */
++ "550", /* 550 */
++ "551", /* 551 */
++ "552", /* 552 */
++ "553", /* 553 */
++ "554", /* 554 */
++ "555", /* 555 */
++ "556", /* 556 */
++ "557", /* 557 */
++ "558", /* 558 */
++ "559", /* 559 */
++ "560", /* 560 */
++ "561", /* 561 */
++ "562", /* 562 */
++ "563", /* 563 */
++ "564", /* 564 */
++ "565", /* 565 */
++ "566", /* 566 */
++ "567", /* 567 */
++ "568", /* 568 */
++ "569", /* 569 */
++ "570", /* 570 */
++ "571", /* 571 */
++ "572", /* 572 */
++ "573", /* 573 */
++ "574", /* 574 */
++ "575", /* 575 */
++ "576", /* 576 */
++ "577", /* 577 */
++ "578", /* 578 */
++ "579", /* 579 */
++ "580", /* 580 */
++ "581", /* 581 */
++ "582", /* 582 */
++ "583", /* 583 */
++ "584", /* 584 */
++ "585", /* 585 */
++ "586", /* 586 */
++ "587", /* 587 */
++ "588", /* 588 */
++ "589", /* 589 */
++ "590", /* 590 */
++ "591", /* 591 */
++ "592", /* 592 */
++ "593", /* 593 */
++ "594", /* 594 */
++ "595", /* 595 */
++ "596", /* 596 */
++ "597", /* 597 */
++ "598", /* 598 */
++ "599", /* 599 */
++ "600", /* 600 */
++ "601", /* 601 */
++ "602", /* 602 */
++ "603", /* 603 */
++ "604", /* 604 */
++ "605", /* 605 */
++ "606", /* 606 */
++ "607", /* 607 */
++ "608", /* 608 */
++ "609", /* 609 */
++ "610", /* 610 */
++ "611", /* 611 */
++ "612", /* 612 */
++ "613", /* 613 */
++ "614", /* 614 */
++ "615", /* 615 */
++ "616", /* 616 */
++ "617", /* 617 */
++ "618", /* 618 */
++ "619", /* 619 */
++ "620", /* 620 */
++ "621", /* 621 */
++ "622", /* 622 */
++ "623", /* 623 */
++ "624", /* 624 */
++ "625", /* 625 */
++ "626", /* 626 */
++ "627", /* 627 */
++ "628", /* 628 */
++ "629", /* 629 */
++ "630", /* 630 */
++ "631", /* 631 */
++ "632", /* 632 */
++ "633", /* 633 */
++ "634", /* 634 */
++ "635", /* 635 */
++ "636", /* 636 */
++ "637", /* 637 */
++ "638", /* 638 */
++ "639", /* 639 */
++ "640", /* 640 */
++ "641", /* 641 */
++ "642", /* 642 */
++ "643", /* 643 */
++ "644", /* 644 */
++ "645", /* 645 */
++ "646", /* 646 */
++ "647", /* 647 */
++ "648", /* 648 */
++ "649", /* 649 */
++ "650", /* 650 */
++ "651", /* 651 */
++ "652", /* 652 */
++ "653", /* 653 */
++ "654", /* 654 */
++ "655", /* 655 */
++ "656", /* 656 */
++ "657", /* 657 */
++ "658", /* 658 */
++ "659", /* 659 */
++ "660", /* 660 */
++ "661", /* 661 */
++ "662", /* 662 */
++ "663", /* 663 */
++ "664", /* 664 */
++ "665", /* 665 */
++ "666", /* 666 */
++ "667", /* 667 */
++ "668", /* 668 */
++ "669", /* 669 */
++ "670", /* 670 */
++ "671", /* 671 */
++ "672", /* 672 */
++ "673", /* 673 */
++ "674", /* 674 */
++ "675", /* 675 */
++ "676", /* 676 */
++ "677", /* 677 */
++ "678", /* 678 */
++ "679", /* 679 */
++ "680", /* 680 */
++ "681", /* 681 */
++ "682", /* 682 */
++ "683", /* 683 */
++ "684", /* 684 */
++ "685", /* 685 */
++ "686", /* 686 */
++ "687", /* 687 */
++ "688", /* 688 */
++ "689", /* 689 */
++ "690", /* 690 */
++ "691", /* 691 */
++ "692", /* 692 */
++ "693", /* 693 */
++ "694", /* 694 */
++ "695", /* 695 */
++ "696", /* 696 */
++ "697", /* 697 */
++ "698", /* 698 */
++ "699", /* 699 */
++ "700", /* 700 */
++ "701", /* 701 */
++ "702", /* 702 */
++ "703", /* 703 */
++ "704", /* 704 */
++ "705", /* 705 */
++ "706", /* 706 */
++ "707", /* 707 */
++ "708", /* 708 */
++ "709", /* 709 */
++ "710", /* 710 */
++ "711", /* 711 */
++ "712", /* 712 */
++ "713", /* 713 */
++ "714", /* 714 */
++ "715", /* 715 */
++ "716", /* 716 */
++ "717", /* 717 */
++ "718", /* 718 */
++ "719", /* 719 */
++ "720", /* 720 */
++ "721", /* 721 */
++ "722", /* 722 */
++ "723", /* 723 */
++ "724", /* 724 */
++ "725", /* 725 */
++ "726", /* 726 */
++ "727", /* 727 */
++ "728", /* 728 */
++ "729", /* 729 */
++ "730", /* 730 */
++ "731", /* 731 */
++ "732", /* 732 */
++ "733", /* 733 */
++ "734", /* 734 */
++ "735", /* 735 */
++ "736", /* 736 */
++ "737", /* 737 */
++ "738", /* 738 */
++ "739", /* 739 */
++ "740", /* 740 */
++ "741", /* 741 */
++ "742", /* 742 */
++ "743", /* 743 */
++ "744", /* 744 */
++ "745", /* 745 */
++ "746", /* 746 */
++ "747", /* 747 */
++ "748", /* 748 */
++ "749", /* 749 */
++ "750", /* 750 */
++ "751", /* 751 */
++ "752", /* 752 */
++ "753", /* 753 */
++ "754", /* 754 */
++ "755", /* 755 */
++ "756", /* 756 */
++ "757", /* 757 */
++ "758", /* 758 */
++ "759", /* 759 */
++ "760", /* 760 */
++ "761", /* 761 */
++ "762", /* 762 */
++ "763", /* 763 */
++ "764", /* 764 */
++ "765", /* 765 */
++ "766", /* 766 */
++ "767", /* 767 */
++ "768", /* 768 */
++ "769", /* 769 */
++ "770", /* 770 */
++ "771", /* 771 */
++ "772", /* 772 */
++ "773", /* 773 */
++ "774", /* 774 */
++ "775", /* 775 */
++ "776", /* 776 */
++ "777", /* 777 */
++ "778", /* 778 */
++ "779", /* 779 */
++ "780", /* 780 */
++ "781", /* 781 */
++ "782", /* 782 */
++ "783", /* 783 */
++ "784", /* 784 */
++ "785", /* 785 */
++ "786", /* 786 */
++ "787", /* 787 */
++ "788", /* 788 */
++ "789", /* 789 */
++ "790", /* 790 */
++ "791", /* 791 */
++ "792", /* 792 */
++ "793", /* 793 */
++ "794", /* 794 */
++ "795", /* 795 */
++ "796", /* 796 */
++ "797", /* 797 */
++ "798", /* 798 */
++ "799", /* 799 */
++ "800", /* 800 */
++ "801", /* 801 */
++ "802", /* 802 */
++ "803", /* 803 */
++ "804", /* 804 */
++ "805", /* 805 */
++ "806", /* 806 */
++ "807", /* 807 */
++ "808", /* 808 */
++ "809", /* 809 */
++ "810", /* 810 */
++ "811", /* 811 */
++ "812", /* 812 */
++ "813", /* 813 */
++ "814", /* 814 */
++ "815", /* 815 */
++ "816", /* 816 */
++ "817", /* 817 */
++ "818", /* 818 */
++ "819", /* 819 */
++ "820", /* 820 */
++ "821", /* 821 */
++ "822", /* 822 */
++ "823", /* 823 */
++ "824", /* 824 */
++ "825", /* 825 */
++ "826", /* 826 */
++ "827", /* 827 */
++ "828", /* 828 */
++ "829", /* 829 */
++ "830", /* 830 */
++ "831", /* 831 */
++ "832", /* 832 */
++ "833", /* 833 */
++ "834", /* 834 */
++ "835", /* 835 */
++ "836", /* 836 */
++ "837", /* 837 */
++ "838", /* 838 */
++ "839", /* 839 */
++ "840", /* 840 */
++ "841", /* 841 */
++ "842", /* 842 */
++ "843", /* 843 */
++ "844", /* 844 */
++ "845", /* 845 */
++ "846", /* 846 */
++ "847", /* 847 */
++ "848", /* 848 */
++ "849", /* 849 */
++ "850", /* 850 */
++ "851", /* 851 */
++ "852", /* 852 */
++ "853", /* 853 */
++ "854", /* 854 */
++ "855", /* 855 */
++ "856", /* 856 */
++ "857", /* 857 */
++ "858", /* 858 */
++ "859", /* 859 */
++ "860", /* 860 */
++ "861", /* 861 */
++ "862", /* 862 */
++ "863", /* 863 */
++ "864", /* 864 */
++ "865", /* 865 */
++ "866", /* 866 */
++ "867", /* 867 */
++ "868", /* 868 */
++ "869", /* 869 */
++ "870", /* 870 */
++ "871", /* 871 */
++ "872", /* 872 */
++ "873", /* 873 */
++ "874", /* 874 */
++ "875", /* 875 */
++ "876", /* 876 */
++ "877", /* 877 */
++ "878", /* 878 */
++ "879", /* 879 */
++ "880", /* 880 */
++ "881", /* 881 */
++ "882", /* 882 */
++ "883", /* 883 */
++ "884", /* 884 */
++ "885", /* 885 */
++ "886", /* 886 */
++ "887", /* 887 */
++ "888", /* 888 */
++ "889", /* 889 */
++ "890", /* 890 */
++ "891", /* 891 */
++ "892", /* 892 */
++ "893", /* 893 */
++ "894", /* 894 */
++ "895", /* 895 */
++ "896", /* 896 */
++ "897", /* 897 */
++ "898", /* 898 */
++ "899", /* 899 */
++ "900", /* 900 */
++ "901", /* 901 */
++ "902", /* 902 */
++ "903", /* 903 */
++ "904", /* 904 */
++ "905", /* 905 */
++ "906", /* 906 */
++ "907", /* 907 */
++ "908", /* 908 */
++ "909", /* 909 */
++ "910", /* 910 */
++ "911", /* 911 */
++ "912", /* 912 */
++ "913", /* 913 */
++ "914", /* 914 */
++ "915", /* 915 */
++ "916", /* 916 */
++ "917", /* 917 */
++ "918", /* 918 */
++ "919", /* 919 */
++ "920", /* 920 */
++ "921", /* 921 */
++ "922", /* 922 */
++ "923", /* 923 */
++ "924", /* 924 */
++ "925", /* 925 */
++ "926", /* 926 */
++ "927", /* 927 */
++ "928", /* 928 */
++ "929", /* 929 */
++ "930", /* 930 */
++ "931", /* 931 */
++ "932", /* 932 */
++ "933", /* 933 */
++ "934", /* 934 */
++ "935", /* 935 */
++ "936", /* 936 */
++ "937", /* 937 */
++ "938", /* 938 */
++ "939", /* 939 */
++ "940", /* 940 */
++ "941", /* 941 */
++ "942", /* 942 */
++ "943", /* 943 */
++ "944", /* 944 */
++ "945", /* 945 */
++ "946", /* 946 */
++ "947", /* 947 */
++ "948", /* 948 */
++ "949", /* 949 */
++ "950", /* 950 */
++ "951", /* 951 */
++ "952", /* 952 */
++ "953", /* 953 */
++ "954", /* 954 */
++ "955", /* 955 */
++ "956", /* 956 */
++ "957", /* 957 */
++ "958", /* 958 */
++ "959", /* 959 */
++ "960", /* 960 */
++ "961", /* 961 */
++ "962", /* 962 */
++ "963", /* 963 */
++ "964", /* 964 */
++ "965", /* 965 */
++ "966", /* 966 */
++ "967", /* 967 */
++ "968", /* 968 */
++ "969", /* 969 */
++ "970", /* 970 */
++ "971", /* 971 */
++ "972", /* 972 */
++ "973", /* 973 */
++ "974", /* 974 */
++ "975", /* 975 */
++ "976", /* 976 */
++ "977", /* 977 */
++ "978", /* 978 */
++ "979", /* 979 */
++ "980", /* 980 */
++ "981", /* 981 */
++ "982", /* 982 */
++ "983", /* 983 */
++ "984", /* 984 */
++ "985", /* 985 */
++ "986", /* 986 */
++ "987", /* 987 */
++ "988", /* 988 */
++ "989", /* 989 */
++ "990", /* 990 */
++ "991", /* 991 */
++ "992", /* 992 */
++ "993", /* 993 */
++ "994", /* 994 */
++ "995", /* 995 */
++ "996", /* 996 */
++ "997", /* 997 */
++ "998", /* 998 */
++ "999", /* 999 */
++ "1000", /* 1000 */
++ "1001", /* 1001 */
++ "1002", /* 1002 */
++ "1003", /* 1003 */
++ "1004", /* 1004 */
++ "1005", /* 1005 */
++ "1006", /* 1006 */
++ "1007", /* 1007 */
++ "1008", /* 1008 */
++ "1009", /* 1009 */
++ "1010", /* 1010 */
++ "1011", /* 1011 */
++ "1012", /* 1012 */
++ "1013", /* 1013 */
++ "1014", /* 1014 */
++ "1015", /* 1015 */
++ "1016", /* 1016 */
++ "1017", /* 1017 */
++ "1018", /* 1018 */
++ "1019", /* 1019 */
++ "1020", /* 1020 */
++ "1021", /* 1021 */
++ "1022", /* 1022 */
++ "1023", /* 1023 */
++ "open", /* 1024 */
++ "link", /* 1025 */
++ "unlink", /* 1026 */
++ "mknod", /* 1027 */
++ "chmod", /* 1028 */
++ "chown", /* 1029 */
++ "mkdir", /* 1030 */
++ "rmdir", /* 1031 */
++ "lchown", /* 1032 */
++ "access", /* 1033 */
++ "rename", /* 1034 */
++ "readlink", /* 1035 */
++ "symlink", /* 1036 */
++ "utimes", /* 1037 */
++ "stat", /* 1038 */
++ "lstat", /* 1039 */
++ "pipe", /* 1040 */
++ "dup2", /* 1041 */
++ "epoll_create", /* 1042 */
++ "inotify_init", /* 1043 */
++ "eventfd", /* 1044 */
++ "signalfd", /* 1045 */
++ "sendfile", /* 1046 */
++ "ftruncate", /* 1047 */
++ "truncate", /* 1048 */
++ "stat", /* 1049 */
++ "lstat", /* 1050 */
++ "fstat", /* 1051 */
++ "fcntl", /* 1052 */
++ "fadvise64", /* 1053 */
++ "newfstatat", /* 1054 */
++ "fstatfs", /* 1055 */
++ "statfs", /* 1056 */
++ "lseek", /* 1057 */
++ "mmap", /* 1058 */
++ "alarm", /* 1059 */
++ "getpgrp", /* 1060 */
++ "pause", /* 1061 */
++ "time", /* 1062 */
++ "utime", /* 1063 */
++ "creat", /* 1064 */
++ "getdents", /* 1065 */
++ "futimesat", /* 1066 */
++ "select", /* 1067 */
++ "poll", /* 1068 */
++ "epoll_wait", /* 1069 */
++ "ustat", /* 1070 */
++ "vfork", /* 1071 */
++ "oldwait4", /* 1072 */
++ "recv", /* 1073 */
++ "send", /* 1074 */
++ "bdflush", /* 1075 */
++ "umount", /* 1076 */
++ "uselib", /* 1077 */
++ "_sysctl", /* 1078 */
++ "fork", /* 1079 */
+diff --git a/sysdeps/linux-gnu/aarch64/trace.c b/sysdeps/linux-gnu/aarch64/trace.c
+new file mode 100644
+index 0000000..5544b51
+--- /dev/null
++++ b/sysdeps/linux-gnu/aarch64/trace.c
+@@ -0,0 +1,84 @@
++/*
++ * This file is part of ltrace.
++ * Copyright (C) 2014 Petr Machata, Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ */
++
++#include <sys/ptrace.h>
++#include <sys/types.h>
++#include <sys/wait.h>
++#include <asm/ptrace.h>
++#include <string.h>
++#include <stdio.h>
++#include <errno.h>
++
++#include "backend.h"
++#include "proc.h"
++
++void
++get_arch_dep(struct Process *proc)
++{
++}
++
++int aarch64_read_gregs(struct Process *proc, struct user_pt_regs *regs);
++
++/* The syscall instruction is:
++ * | 31 21 | 20 5 | 4 0 |
++ * | 1 1 0 1 0 1 0 0 | 0 0 0 | imm16 | 0 0 0 0 1 | */
++#define SVC_MASK 0xffe0001f
++#define SVC_VALUE 0xd4000001
++
++int
++syscall_p(struct Process *proc, int status, int *sysnum)
++{
++ if (WIFSTOPPED(status)
++ && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
++
++ struct user_pt_regs regs;
++ if (aarch64_read_gregs(proc, &regs) < 0) {
++ fprintf(stderr, "syscall_p: "
++ "Couldn't read registers of %d.\n", proc->pid);
++ return -1;
++ }
++
++ errno = 0;
++ unsigned long insn = (unsigned long) ptrace(PTRACE_PEEKTEXT,
++ proc->pid,
++ regs.pc - 4, 0);
++ if (insn == -1UL && errno != 0) {
++ fprintf(stderr, "syscall_p: "
++ "Couldn't peek into %d: %s\n", proc->pid,
++ strerror(errno));
++ return -1;
++ }
++
++ insn &= 0xffffffffUL;
++ if ((insn & SVC_MASK) == SVC_VALUE) {
++ *sysnum = regs.regs[8];
++
++ size_t d1 = proc->callstack_depth - 1;
++ if (proc->callstack_depth > 0
++ && proc->callstack[d1].is_syscall
++ && proc->callstack[d1].c_un.syscall == *sysnum)
++ return 2;
++
++ return 1;
++ }
++ }
++
++ return 0;
++}
+--
+1.9.1
+
diff --git a/harmony/ltrace/aarch64.patch b/harmony/ltrace/aarch64.patch
new file mode 100644
index 000000000..a89c3073a
--- /dev/null
+++ b/harmony/ltrace/aarch64.patch
@@ -0,0 +1,2155 @@
+From 982cbca34b2b49a158086ff5f43eb9bba89edead Mon Sep 17 00:00:00 2001
+From: Petr Machata <pmachata@redhat.com>
+Date: Wed, 6 Feb 2013 15:46:04 +0100
+Subject: [PATCH] Move get_hfa_type from IA64 backend to type.c, name it
+ type_get_hfa_type
+
+---
+ sysdeps/linux-gnu/ia64/fetch.c | 48 ++++++++----------------------------------
+ type.c | 36 +++++++++++++++++++++++++++++++
+ type.h | 11 +++++++++-
+ 3 files changed, 55 insertions(+), 40 deletions(-)
+
+diff --git a/sysdeps/linux-gnu/ia64/fetch.c b/sysdeps/linux-gnu/ia64/fetch.c
+index e90dbed..171c7a2 100644
+--- a/sysdeps/linux-gnu/ia64/fetch.c
++++ b/sysdeps/linux-gnu/ia64/fetch.c
+@@ -1,6 +1,6 @@
+ /*
+ * This file is part of ltrace.
+- * Copyright (C) 2012 Petr Machata, Red Hat Inc.
++ * Copyright (C) 2012,2013 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2008,2009 Juan Cespedes
+ * Copyright (C) 2006 Steve Fink
+ * Copyright (C) 2006 Ian Wienand
+@@ -249,37 +249,6 @@ allocate_float(struct fetch_context *ctx, struct process *proc,
+ return 0;
+ }
+
+-static enum arg_type
+-get_hfa_type(struct arg_type_info *info, size_t *countp)
+-{
+- size_t n = type_aggregate_size(info);
+- if (n == (size_t)-1)
+- return ARGTYPE_VOID;
+-
+- enum arg_type type = ARGTYPE_VOID;
+- *countp = 0;
+-
+- while (n-- > 0) {
+- struct arg_type_info *emt = type_element(info, n);
+-
+- enum arg_type emt_type = emt->type;
+- size_t emt_count = 1;
+- if (emt_type == ARGTYPE_STRUCT || emt_type == ARGTYPE_ARRAY)
+- emt_type = get_hfa_type(emt, &emt_count);
+-
+- if (type == ARGTYPE_VOID) {
+- if (emt_type != ARGTYPE_FLOAT
+- && emt_type != ARGTYPE_DOUBLE)
+- return ARGTYPE_VOID;
+- type = emt_type;
+- }
+- if (emt_type != type)
+- return ARGTYPE_VOID;
+- *countp += emt_count;
+- }
+- return type;
+-}
+-
+ static int
+ allocate_hfa(struct fetch_context *ctx, struct process *proc,
+ struct arg_type_info *info, struct value *valuep,
+@@ -380,10 +349,11 @@ allocate_ret(struct fetch_context *ctx, struct process *proc,
+ * floating-point registers, beginning with f8. */
+ if (info->type == ARGTYPE_STRUCT || info->type == ARGTYPE_ARRAY) {
+ size_t hfa_size;
+- enum arg_type hfa_type = get_hfa_type(info, &hfa_size);
+- if (hfa_type != ARGTYPE_VOID && hfa_size <= 8)
++ struct arg_type_info *hfa_info
++ = type_get_hfa_type(info, &hfa_size);
++ if (hfa_info != NULL && hfa_size <= 8)
+ return allocate_hfa(ctx, proc, info, valuep,
+- hfa_type, hfa_size);
++ hfa_info->type, hfa_size);
+ }
+
+ /* Integers and pointers are passed in r8. 128-bit integers
+@@ -409,7 +379,7 @@ arch_fetch_arg_next(struct fetch_context *ctx, enum tof type,
+ struct arg_type_info *info, struct value *valuep)
+ {
+ switch (info->type) {
+- enum arg_type hfa_type;
++ struct arg_type_info *hfa_info;
+ size_t hfa_size;
+
+ case ARGTYPE_VOID:
+@@ -421,10 +391,10 @@ arch_fetch_arg_next(struct fetch_context *ctx, enum tof type,
+ return allocate_float(ctx, proc, info, valuep, 1);
+
+ case ARGTYPE_STRUCT:
+- hfa_type = get_hfa_type(info, &hfa_size);
+- if (hfa_type != ARGTYPE_VOID)
++ hfa_info = type_get_hfa_type(info, &hfa_size);
++ if (hfa_info != NULL)
+ return allocate_hfa(ctx, proc, info, valuep,
+- hfa_type, hfa_size);
++ hfa_info->type, hfa_size);
+ /* Fall through. */
+ case ARGTYPE_CHAR:
+ case ARGTYPE_SHORT:
+diff --git a/type.c b/type.c
+index 11b4ce1..d5bc98f 100644
+--- a/type.c
++++ b/type.c
+@@ -564,3 +564,39 @@ type_get_fp_equivalent(struct arg_type_info *info)
+ }
+ abort();
+ }
++
++struct arg_type_info *
++type_get_hfa_type(struct arg_type_info *info, size_t *countp)
++{
++ assert(info != NULL);
++ if (info->type != ARGTYPE_STRUCT
++ && info->type != ARGTYPE_ARRAY)
++ return NULL;
++
++ size_t n = type_aggregate_size(info);
++ if (n == (size_t)-1)
++ return NULL;
++
++ struct arg_type_info *ret = NULL;
++ *countp = 0;
++
++ while (n-- > 0) {
++ struct arg_type_info *emt = type_element(info, n);
++
++ size_t emt_count = 1;
++ if (emt->type == ARGTYPE_STRUCT || emt->type == ARGTYPE_ARRAY)
++ emt = type_get_hfa_type(emt, &emt_count);
++ if (emt == NULL)
++ return NULL;
++ if (ret == NULL) {
++ if (emt->type != ARGTYPE_FLOAT
++ && emt->type != ARGTYPE_DOUBLE)
++ return NULL;
++ ret = emt;
++ }
++ if (emt->type != ret->type)
++ return NULL;
++ *countp += emt_count;
++ }
++ return ret;
++}
+diff --git a/type.h b/type.h
+index b92c1af..3210677 100644
+--- a/type.h
++++ b/type.h
+@@ -1,6 +1,6 @@
+ /*
+ * This file is part of ltrace.
+- * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
++ * Copyright (C) 2011,2012,2013 Petr Machata, Red Hat Inc.
+ * Copyright (C) 1997-2009 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+@@ -142,4 +142,13 @@ int type_is_signed(enum arg_type type);
+ * type. */
+ struct arg_type_info *type_get_fp_equivalent(struct arg_type_info *info);
+
++/* If INFO is homogeneous floating-point aggregate, return the
++ * corresponding floating point type, and set *COUNTP to number of
++ * fields of the structure. Otherwise return NULL. INFO is a HFA if
++ * it's an aggregate whose each field is either a HFA, or a
++ * floating-point type. */
++struct arg_type_info *type_get_hfa_type(struct arg_type_info *info,
++ size_t *countp);
++
++
+ #endif /* TYPE_H */
+--
+1.9.1
+
+From ae7249250ea650ec82bc545d4281b852020c7a6f Mon Sep 17 00:00:00 2001
+From: Petr Machata <pmachata@redhat.com>
+Date: Fri, 24 Jan 2014 00:50:06 +0100
+Subject: [PATCH 1/1] Implement aarch64 support
+
+- IFUNC support is not implemented, the rest works well. The only
+ other failure is in wide char functions, and that occurs on x86_64
+ as well.
+---
+ configure.ac | 3 +-
+ sysdeps/linux-gnu/Makefile.am | 4 +-
+ sysdeps/linux-gnu/aarch64/Makefile.am | 25 +
+ sysdeps/linux-gnu/aarch64/arch.h | 37 ++
+ sysdeps/linux-gnu/aarch64/fetch.c | 365 +++++++++++
+ sysdeps/linux-gnu/aarch64/plt.c | 38 ++
+ sysdeps/linux-gnu/aarch64/ptrace.h | 22 +
+ sysdeps/linux-gnu/aarch64/regs.c | 130 ++++
+ sysdeps/linux-gnu/aarch64/signalent.h | 52 ++
+ sysdeps/linux-gnu/aarch64/syscallent.h | 1100 ++++++++++++++++++++++++++++++++
+ sysdeps/linux-gnu/aarch64/trace.c | 83 +++
+ 11 files changed, 1857 insertions(+), 2 deletions(-)
+ create mode 100644 sysdeps/linux-gnu/aarch64/Makefile.am
+ create mode 100644 sysdeps/linux-gnu/aarch64/arch.h
+ create mode 100644 sysdeps/linux-gnu/aarch64/fetch.c
+ create mode 100644 sysdeps/linux-gnu/aarch64/plt.c
+ create mode 100644 sysdeps/linux-gnu/aarch64/ptrace.h
+ create mode 100644 sysdeps/linux-gnu/aarch64/regs.c
+ create mode 100644 sysdeps/linux-gnu/aarch64/signalent.h
+ create mode 100644 sysdeps/linux-gnu/aarch64/syscallent.h
+ create mode 100644 sysdeps/linux-gnu/aarch64/trace.c
+
+diff --git a/configure.ac b/configure.ac
+index c6e6bf0..0e9a124 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1,6 +1,6 @@
+ # -*- Autoconf -*-
+ # This file is part of ltrace.
+-# Copyright (C) 2010,2013 Petr Machata, Red Hat Inc.
++# Copyright (C) 2010,2012,2013,2014 Petr Machata, Red Hat Inc.
+ # Copyright (C) 2010,2011 Joe Damato
+ # Copyright (C) 2010 Marc Kleine-Budde
+ # Copyright (C) 2010 Zachary T Welch
+@@ -399,6 +399,7 @@ AC_CONFIG_FILES([
+ Makefile
+ sysdeps/Makefile
+ sysdeps/linux-gnu/Makefile
++ sysdeps/linux-gnu/aarch64/Makefile
+ sysdeps/linux-gnu/alpha/Makefile
+ sysdeps/linux-gnu/arm/Makefile
+ sysdeps/linux-gnu/cris/Makefile
+diff --git a/sysdeps/linux-gnu/Makefile.am b/sysdeps/linux-gnu/Makefile.am
+index ecee577..ec26162 100644
+--- a/sysdeps/linux-gnu/Makefile.am
++++ b/sysdeps/linux-gnu/Makefile.am
+@@ -1,4 +1,5 @@
+ # This file is part of ltrace.
++# Copyright (C) 2014 Petr Machata, Red Hat, Inc.
+ # Copyright (C) 2010,2012 Marc Kleine-Budde, Pengutronix
+ #
+ # This program is free software; you can redistribute it and/or
+@@ -16,7 +17,8 @@
+ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ # 02110-1301 USA
+
+-DIST_SUBDIRS = alpha arm cris ia64 m68k mips ppc s390 sparc x86
++DIST_SUBDIRS = aarch64 alpha arm cris ia64 m68k mips ppc s390 \
++ sparc x86
+
+ SUBDIRS = \
+ $(HOST_CPU)
+diff --git a/sysdeps/linux-gnu/aarch64/Makefile.am b/sysdeps/linux-gnu/aarch64/Makefile.am
+new file mode 100644
+index 0000000..0af4e6e
+--- /dev/null
++++ b/sysdeps/linux-gnu/aarch64/Makefile.am
+@@ -0,0 +1,25 @@
++# This file is part of ltrace.
++# Copyright (C) 2014 Petr Machata, Red Hat, Inc.
++#
++# This program is free software; you can redistribute it and/or
++# modify it under the terms of the GNU General Public License as
++# published by the Free Software Foundation; either version 2 of the
++# License, or (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful, but
++# WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++# General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++# 02110-1301 USA
++
++noinst_LTLIBRARIES = ../libcpu.la
++
++___libcpu_la_SOURCES = fetch.c plt.c regs.c trace.c
++
++noinst_HEADERS = arch.h ptrace.h signalent.h syscallent.h
++
++MAINTAINERCLEANFILES = Makefile.in
+diff --git a/sysdeps/linux-gnu/aarch64/arch.h b/sysdeps/linux-gnu/aarch64/arch.h
+new file mode 100644
+index 0000000..4137613
+--- /dev/null
++++ b/sysdeps/linux-gnu/aarch64/arch.h
+@@ -0,0 +1,37 @@
++/*
++ * This file is part of ltrace.
++ * Copyright (C) 2014 Petr Machata, Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ */
++#ifndef LTRACE_AARCH64_ARCH_H
++#define LTRACE_AARCH64_ARCH_H
++
++/* | 31 21 | 20 5 | 4 0 | *
++ * | 1 1 0 1 0 1 0 0 0 0 1 | imm16 | 0 0 0 0 0 | */
++#define BREAKPOINT_VALUE { 0xd4, 0x20, 0, 0 }
++#define BREAKPOINT_LENGTH 4
++#define DECR_PC_AFTER_BREAK 0
++
++#define LT_ELFCLASS ELFCLASS64
++#define LT_ELF_MACHINE EM_AARCH64
++
++#define ARCH_HAVE_FETCH_ARG
++#define ARCH_ENDIAN_BIG
++#define ARCH_HAVE_SIZEOF
++#define ARCH_HAVE_ALIGNOF
++
++#endif /* LTRACE_AARCH64_ARCH_H */
+diff --git a/sysdeps/linux-gnu/aarch64/fetch.c b/sysdeps/linux-gnu/aarch64/fetch.c
+new file mode 100644
+index 0000000..8779f03
+--- /dev/null
++++ b/sysdeps/linux-gnu/aarch64/fetch.c
+@@ -0,0 +1,365 @@
++/*
++ * This file is part of ltrace.
++ * Copyright (C) 2014 Petr Machata, Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ */
++
++#include <sys/ptrace.h>
++#include <asm/ptrace.h>
++#include <stdlib.h>
++#include <string.h>
++
++#include "fetch.h"
++#include "proc.h"
++#include "type.h"
++#include "value.h"
++
++int aarch64_read_gregs(struct Process *proc, struct user_pt_regs *regs);
++int aarch64_read_fregs(struct Process *proc, struct user_fpsimd_state *regs);
++
++
++struct fetch_context
++{
++ struct user_pt_regs gregs;
++ struct user_fpsimd_state fpregs;
++ arch_addr_t nsaa;
++ unsigned ngrn;
++ unsigned nsrn;
++ arch_addr_t x8;
++};
++
++static int
++context_init(struct fetch_context *context, struct Process *proc)
++{
++ if (aarch64_read_gregs(proc, &context->gregs) < 0
++ || aarch64_read_fregs(proc, &context->fpregs) < 0)
++ return -1;
++
++ context->ngrn = 0;
++ context->nsrn = 0;
++ /* XXX double cast */
++ context->nsaa = (arch_addr_t) (uintptr_t) context->gregs.sp;
++ context->x8 = 0;
++
++ return 0;
++}
++
++struct fetch_context *
++arch_fetch_arg_clone(struct Process *proc, struct fetch_context *context)
++{
++ struct fetch_context *ret = malloc(sizeof(*ret));
++ if (ret == NULL)
++ return NULL;
++ return memcpy(ret, context, sizeof(*ret));
++}
++
++static void
++fetch_next_gpr(struct fetch_context *context, unsigned char *buf)
++{
++ uint64_t u = context->gregs.regs[context->ngrn++];
++ memcpy(buf, &u, 8);
++}
++
++static int
++fetch_gpr(struct fetch_context *context, struct value *value, size_t sz)
++{
++ if (sz < 8)
++ sz = 8;
++
++ unsigned char *buf = value_reserve(value, sz);
++ if (buf == NULL)
++ return -1;
++
++ size_t i;
++ for (i = 0; i < sz; i += 8)
++ fetch_next_gpr(context, buf + i);
++
++ return 0;
++}
++
++static void
++fetch_next_sse(struct fetch_context *context, unsigned char *buf, size_t sz)
++{
++ __int128 u = context->fpregs.vregs[context->nsrn++];
++ memcpy(buf, &u, sz);
++}
++
++static int
++fetch_sse(struct fetch_context *context, struct value *value, size_t sz)
++{
++ unsigned char *buf = value_reserve(value, sz);
++ if (buf == NULL)
++ return -1;
++
++ fetch_next_sse(context, buf, sz);
++ return 0;
++}
++
++static int
++fetch_hfa(struct fetch_context *context,
++ struct value *value, struct arg_type_info *hfa_t, size_t count)
++{
++ size_t sz = type_sizeof(value->inferior, hfa_t);
++ unsigned char *buf = value_reserve(value, sz * count);
++ if (buf == NULL)
++ return -1;
++
++ size_t i;
++ for (i = 0; i < count; ++i) {
++ fetch_next_sse(context, buf, sz);
++ buf += sz;
++ }
++ return 0;
++}
++
++static int
++fetch_stack(struct fetch_context *context, struct value *value,
++ size_t align, size_t sz)
++{
++ if (align < 8)
++ align = 8;
++ size_t amount = ((sz + align - 1) / align) * align;
++
++ /* XXX double casts */
++ uintptr_t sp = (uintptr_t) context->nsaa;
++ sp = ((sp + align - 1) / align) * align;
++
++ value_in_inferior(value, (arch_addr_t) sp);
++
++ sp += amount;
++ context->nsaa = (arch_addr_t) sp;
++
++ return 0;
++}
++
++enum convert_method {
++ CVT_ERR = -1,
++ CVT_NOP = 0,
++ CVT_BYREF,
++};
++
++enum fetch_method {
++ FETCH_NOP,
++ FETCH_STACK,
++ FETCH_GPR,
++ FETCH_SSE,
++ FETCH_HFA,
++};
++
++struct fetch_script {
++ enum convert_method c;
++ enum fetch_method f;
++ size_t sz;
++ struct arg_type_info *hfa_t;
++ size_t count;
++};
++
++static struct fetch_script
++pass_arg(struct fetch_context const *context,
++ struct Process *proc, struct arg_type_info *info)
++{
++ enum fetch_method cvt = CVT_NOP;
++
++ size_t sz = type_sizeof(proc, info);
++ if (sz == (size_t) -1)
++ return (struct fetch_script) { CVT_ERR, FETCH_NOP, sz };
++
++ switch (info->type) {
++ case ARGTYPE_VOID:
++ return (struct fetch_script) { cvt, FETCH_NOP, sz };
++
++ case ARGTYPE_STRUCT:
++ case ARGTYPE_ARRAY:;
++ size_t count;
++ struct arg_type_info *hfa_t = type_get_hfa_type(info, &count);
++ if (hfa_t != NULL && count <= 4) {
++ if (context->nsrn + count <= 8)
++ return (struct fetch_script)
++ { cvt, FETCH_HFA, sz, hfa_t, count };
++ return (struct fetch_script)
++ { cvt, FETCH_STACK, sz, hfa_t, count };
++ }
++
++ if (sz <= 16) {
++ size_t count = sz / 8;
++ if (context->ngrn + count <= 8)
++ return (struct fetch_script)
++ { cvt, FETCH_GPR, sz };
++ }
++
++ cvt = CVT_BYREF;
++ sz = 8;
++ /* Fall through. */
++
++ case ARGTYPE_POINTER:
++ case ARGTYPE_INT:
++ case ARGTYPE_UINT:
++ case ARGTYPE_LONG:
++ case ARGTYPE_ULONG:
++ case ARGTYPE_CHAR:
++ case ARGTYPE_SHORT:
++ case ARGTYPE_USHORT:
++ if (context->ngrn < 8 && sz <= 8)
++ return (struct fetch_script) { cvt, FETCH_GPR, sz };
++ /* We don't support types wider than 8 bytes as of
++ * now. */
++ assert(sz <= 8);
++
++ return (struct fetch_script) { cvt, FETCH_STACK, sz };
++
++ case ARGTYPE_FLOAT:
++ case ARGTYPE_DOUBLE:
++ if (context->nsrn < 8) {
++ /* ltrace doesn't support float128. */
++ assert(sz <= 8);
++ return (struct fetch_script) { cvt, FETCH_SSE, sz };
++ }
++
++ return (struct fetch_script) { cvt, FETCH_STACK, sz };
++ }
++
++ assert(! "Failed to allocate argument.");
++ abort();
++}
++
++static int
++convert_arg(struct value *value, struct fetch_script how)
++{
++ switch (how.c) {
++ case CVT_NOP:
++ return 0;
++ case CVT_BYREF:
++ return value_pass_by_reference(value);
++ case CVT_ERR:
++ return -1;
++ }
++
++ assert(! "Don't know how to convert argument.");
++ abort();
++}
++
++static int
++fetch_arg(struct fetch_context *context,
++ struct Process *proc, struct arg_type_info *info,
++ struct value *value, struct fetch_script how)
++{
++ if (convert_arg(value, how) < 0)
++ return -1;
++
++ switch (how.f) {
++ case FETCH_NOP:
++ return 0;
++
++ case FETCH_STACK:
++ if (how.hfa_t != NULL && how.count != 0 && how.count <= 8)
++ context->nsrn = 8;
++ return fetch_stack(context, value,
++ type_alignof(proc, info), how.sz);
++
++ case FETCH_GPR:
++ return fetch_gpr(context, value, how.sz);
++
++ case FETCH_SSE:
++ return fetch_sse(context, value, how.sz);
++
++ case FETCH_HFA:
++ return fetch_hfa(context, value, how.hfa_t, how.count);
++ }
++
++ assert(! "Don't know how to fetch argument.");
++ abort();
++}
++
++struct fetch_context *
++arch_fetch_arg_init(enum tof type, struct Process *proc,
++ struct arg_type_info *ret_info)
++{
++ struct fetch_context *context = malloc(sizeof *context);
++ if (context == NULL || context_init(context, proc) < 0) {
++ fail:
++ free(context);
++ return NULL;
++ }
++
++ /* There's a provision in ARMv8 parameter passing convention
++ * for returning types that, if passed as first argument to a
++ * function, would be passed on stack. For those types, x8
++ * contains an address where the return argument should be
++ * placed. The callee doesn't need to preserve the value of
++ * x8, so we need to fetch it now.
++ *
++ * To my knowledge, there are currently no types where this
++ * holds, but the code is here, utterly untested. */
++
++ struct fetch_script how = pass_arg(context, proc, ret_info);
++ if (how.c == CVT_ERR)
++ goto fail;
++ if (how.c == CVT_NOP && how.f == FETCH_STACK) {
++ /* XXX double cast. */
++ context->x8 = (arch_addr_t) (uintptr_t) context->gregs.regs[8];
++ /* See the comment above about the assert. */
++ assert(! "Unexpected: first argument passed on stack.");
++ abort();
++ }
++
++ return context;
++}
++
++int
++arch_fetch_arg_next(struct fetch_context *context, enum tof type,
++ struct Process *proc, struct arg_type_info *info,
++ struct value *value)
++{
++ return fetch_arg(context, proc, info, value,
++ pass_arg(context, proc, info));
++}
++
++int
++arch_fetch_retval(struct fetch_context *context, enum tof type,
++ struct Process *proc, struct arg_type_info *info,
++ struct value *value)
++{
++ if (context->x8 != 0) {
++ value_in_inferior(value, context->x8);
++ return 0;
++ }
++
++ if (context_init(context, proc) < 0)
++ return -1;
++
++ return fetch_arg(context, proc, info, value,
++ pass_arg(context, proc, info));
++}
++
++void
++arch_fetch_arg_done(struct fetch_context *context)
++{
++ if (context != NULL)
++ free(context);
++}
++
++size_t
++arch_type_sizeof(struct Process *proc, struct arg_type_info *arg)
++{
++ return (size_t) -2;
++}
++
++size_t
++arch_type_alignof(struct Process *proc, struct arg_type_info *arg)
++{
++ return (size_t) -2;
++}
+diff --git a/sysdeps/linux-gnu/aarch64/plt.c b/sysdeps/linux-gnu/aarch64/plt.c
+new file mode 100644
+index 0000000..29dc4c9
+--- /dev/null
++++ b/sysdeps/linux-gnu/aarch64/plt.c
+@@ -0,0 +1,38 @@
++/*
++ * This file is part of ltrace.
++ * Copyright (C) 2014 Petr Machata, Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ */
++
++#include <gelf.h>
++
++#include "backend.h"
++#include "proc.h"
++#include "library.h"
++#include "ltrace-elf.h"
++
++arch_addr_t
++sym2addr(struct Process *proc, struct library_symbol *sym)
++{
++ return sym->enter_addr;
++}
++
++GElf_Addr
++arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela *rela)
++{
++ return lte->plt_addr + 32 + ndx * 16;
++}
+diff --git a/sysdeps/linux-gnu/aarch64/ptrace.h b/sysdeps/linux-gnu/aarch64/ptrace.h
+new file mode 100644
+index 0000000..283c314
+--- /dev/null
++++ b/sysdeps/linux-gnu/aarch64/ptrace.h
+@@ -0,0 +1,22 @@
++/*
++ * This file is part of ltrace.
++ * Copyright (C) 2014 Petr Machata, Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ */
++
++#include <sys/ptrace.h>
++#include <asm/ptrace.h>
+diff --git a/sysdeps/linux-gnu/aarch64/regs.c b/sysdeps/linux-gnu/aarch64/regs.c
+new file mode 100644
+index 0000000..06eb72b
+--- /dev/null
++++ b/sysdeps/linux-gnu/aarch64/regs.c
+@@ -0,0 +1,131 @@
++/*
++ * This file is part of ltrace.
++ * Copyright (C) 2014 Petr Machata, Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ */
++
++#include <sys/ptrace.h>
++#include <asm/ptrace.h>
++#include <linux/uio.h>
++#include <assert.h>
++#include <stdlib.h>
++#include <stdio.h>
++
++#include "backend.h"
++#include "proc.h"
++
++#define PC_OFF (32 * 4)
++
++int
++aarch64_read_gregs(struct Process *proc, struct user_pt_regs *regs)
++{
++ *regs = (struct user_pt_regs) {};
++ struct iovec iovec;
++ iovec.iov_base = regs;
++ iovec.iov_len = sizeof *regs;
++ return ptrace(PTRACE_GETREGSET, proc->pid, NT_PRSTATUS, &iovec) < 0
++ ? -1 : 0;
++}
++
++int
++aarch64_write_gregs(struct Process *proc, struct user_pt_regs *regs)
++{
++ struct iovec iovec;
++ iovec.iov_base = regs;
++ iovec.iov_len = sizeof *regs;
++ return ptrace(PTRACE_SETREGSET, proc->pid, NT_PRSTATUS, &iovec) < 0
++ ? -1 : 0;
++}
++
++int
++aarch64_read_fregs(struct Process *proc, struct user_fpsimd_state *regs)
++{
++ *regs = (struct user_fpsimd_state) {};
++ struct iovec iovec;
++ iovec.iov_base = regs;
++ iovec.iov_len = sizeof *regs;
++ return ptrace(PTRACE_GETREGSET, proc->pid, NT_FPREGSET, &iovec) < 0
++ ? -1 : 0;
++}
++
++arch_addr_t
++get_instruction_pointer(struct Process *proc)
++{
++ struct user_pt_regs regs;
++ if (aarch64_read_gregs(proc, &regs) < 0) {
++ fprintf(stderr, "get_instruction_pointer: "
++ "Couldn't read registers of %d.\n", proc->pid);
++ return 0;
++ }
++
++ /*
++ char buf[128];
++ sprintf(buf, "cat /proc/%d/maps", proc->pid);
++ system(buf);
++ */
++
++ /* XXX double cast */
++ return (arch_addr_t) (uintptr_t) regs.pc;
++}
++
++void
++set_instruction_pointer(struct Process *proc, arch_addr_t addr)
++{
++ struct user_pt_regs regs;
++ if (aarch64_read_gregs(proc, &regs) < 0) {
++ fprintf(stderr, "get_instruction_pointer: "
++ "Couldn't read registers of %d.\n", proc->pid);
++ return;
++ }
++
++ /* XXX double cast */
++ regs.pc = (uint64_t) (uintptr_t) addr;
++
++ if (aarch64_write_gregs(proc, &regs) < 0) {
++ fprintf(stderr, "get_instruction_pointer: "
++ "Couldn't write registers of %d.\n", proc->pid);
++ return;
++ }
++}
++
++arch_addr_t
++get_stack_pointer(struct Process *proc)
++{
++ struct user_pt_regs regs;
++ if (aarch64_read_gregs(proc, &regs) < 0) {
++ fprintf(stderr, "get_stack_pointer: "
++ "Couldn't read registers of %d.\n", proc->pid);
++ return 0;
++ }
++
++ /* XXX double cast */
++ return (arch_addr_t) (uintptr_t) regs.sp;
++}
++
++arch_addr_t
++get_return_addr(struct Process *proc, arch_addr_t stack_pointer)
++{
++ struct user_pt_regs regs;
++ if (aarch64_read_gregs(proc, &regs) < 0) {
++ fprintf(stderr, "get_return_addr: "
++ "Couldn't read registers of %d.\n", proc->pid);
++ return 0;
++ }
++
++ /* XXX double cast */
++ return (arch_addr_t) (uintptr_t) regs.regs[30];
++}
+diff --git a/sysdeps/linux-gnu/aarch64/signalent.h b/sysdeps/linux-gnu/aarch64/signalent.h
+new file mode 100644
+index 0000000..bf56ebc
+--- /dev/null
++++ b/sysdeps/linux-gnu/aarch64/signalent.h
+@@ -0,0 +1,52 @@
++/*
++ * This file is part of ltrace.
++ * Copyright (C) 2006 Ian Wienand
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ */
++
++ "SIG_0", /* 0 */
++ "SIGHUP", /* 1 */
++ "SIGINT", /* 2 */
++ "SIGQUIT", /* 3 */
++ "SIGILL", /* 4 */
++ "SIGTRAP", /* 5 */
++ "SIGABRT", /* 6 */
++ "SIGBUS", /* 7 */
++ "SIGFPE", /* 8 */
++ "SIGKILL", /* 9 */
++ "SIGUSR1", /* 10 */
++ "SIGSEGV", /* 11 */
++ "SIGUSR2", /* 12 */
++ "SIGPIPE", /* 13 */
++ "SIGALRM", /* 14 */
++ "SIGTERM", /* 15 */
++ "SIGSTKFLT", /* 16 */
++ "SIGCHLD", /* 17 */
++ "SIGCONT", /* 18 */
++ "SIGSTOP", /* 19 */
++ "SIGTSTP", /* 20 */
++ "SIGTTIN", /* 21 */
++ "SIGTTOU", /* 22 */
++ "SIGURG", /* 23 */
++ "SIGXCPU", /* 24 */
++ "SIGXFSZ", /* 25 */
++ "SIGVTALRM", /* 26 */
++ "SIGPROF", /* 27 */
++ "SIGWINCH", /* 28 */
++ "SIGIO", /* 29 */
++ "SIGPWR", /* 30 */
++ "SIGSYS", /* 31 */
+diff --git a/sysdeps/linux-gnu/aarch64/syscallent.h b/sysdeps/linux-gnu/aarch64/syscallent.h
+new file mode 100644
+index 0000000..aca8191
+--- /dev/null
++++ b/sysdeps/linux-gnu/aarch64/syscallent.h
+@@ -0,0 +1,1100 @@
++/*
++ * This file is part of ltrace.
++ * Copyright (C) 2014 Petr Machata, Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ */
++
++ "io_setup", /* 0 */
++ "io_destroy", /* 1 */
++ "io_submit", /* 2 */
++ "io_cancel", /* 3 */
++ "io_getevents", /* 4 */
++ "setxattr", /* 5 */
++ "lsetxattr", /* 6 */
++ "fsetxattr", /* 7 */
++ "getxattr", /* 8 */
++ "lgetxattr", /* 9 */
++ "fgetxattr", /* 10 */
++ "listxattr", /* 11 */
++ "llistxattr", /* 12 */
++ "flistxattr", /* 13 */
++ "removexattr", /* 14 */
++ "lremovexattr", /* 15 */
++ "fremovexattr", /* 16 */
++ "getcwd", /* 17 */
++ "lookup_dcookie", /* 18 */
++ "eventfd2", /* 19 */
++ "epoll_create1", /* 20 */
++ "epoll_ctl", /* 21 */
++ "epoll_pwait", /* 22 */
++ "dup", /* 23 */
++ "dup3", /* 24 */
++ "fcntl", /* 25 */
++ "inotify_init1", /* 26 */
++ "inotify_add_watch", /* 27 */
++ "inotify_rm_watch", /* 28 */
++ "ioctl", /* 29 */
++ "ioprio_set", /* 30 */
++ "ioprio_get", /* 31 */
++ "flock", /* 32 */
++ "mknodat", /* 33 */
++ "mkdirat", /* 34 */
++ "unlinkat", /* 35 */
++ "symlinkat", /* 36 */
++ "linkat", /* 37 */
++ "renameat", /* 38 */
++ "umount2", /* 39 */
++ "mount", /* 40 */
++ "pivot_root", /* 41 */
++ "nfsservctl", /* 42 */
++ "statfs", /* 43 */
++ "fstatfs", /* 44 */
++ "truncate", /* 45 */
++ "ftruncate", /* 46 */
++ "fallocate", /* 47 */
++ "faccessat", /* 48 */
++ "chdir", /* 49 */
++ "fchdir", /* 50 */
++ "chroot", /* 51 */
++ "fchmod", /* 52 */
++ "fchmodat", /* 53 */
++ "fchownat", /* 54 */
++ "fchown", /* 55 */
++ "openat", /* 56 */
++ "close", /* 57 */
++ "vhangup", /* 58 */
++ "pipe2", /* 59 */
++ "quotactl", /* 60 */
++ "getdents64", /* 61 */
++ "lseek", /* 62 */
++ "read", /* 63 */
++ "write", /* 64 */
++ "readv", /* 65 */
++ "writev", /* 66 */
++ "pread64", /* 67 */
++ "pwrite64", /* 68 */
++ "preadv", /* 69 */
++ "pwritev", /* 70 */
++ "sendfile", /* 71 */
++ "pselect6", /* 72 */
++ "ppoll", /* 73 */
++ "signalfd4", /* 74 */
++ "vmsplice", /* 75 */
++ "splice", /* 76 */
++ "tee", /* 77 */
++ "readlinkat", /* 78 */
++ "fstatat", /* 79 */
++ "fstat", /* 80 */
++ "sync", /* 81 */
++ "fsync", /* 82 */
++ "fdatasync", /* 83 */
++ "sync_file_range", /* 84 */
++ "timerfd_create", /* 85 */
++ "timerfd_settime", /* 86 */
++ "timerfd_gettime", /* 87 */
++ "utimensat", /* 88 */
++ "acct", /* 89 */
++ "capget", /* 90 */
++ "capset", /* 91 */
++ "personality", /* 92 */
++ "exit", /* 93 */
++ "exit_group", /* 94 */
++ "waitid", /* 95 */
++ "set_tid_address", /* 96 */
++ "unshare", /* 97 */
++ "futex", /* 98 */
++ "set_robust_list", /* 99 */
++ "get_robust_list", /* 100 */
++ "nanosleep", /* 101 */
++ "getitimer", /* 102 */
++ "setitimer", /* 103 */
++ "kexec_load", /* 104 */
++ "init_module", /* 105 */
++ "delete_module", /* 106 */
++ "timer_create", /* 107 */
++ "timer_gettime", /* 108 */
++ "timer_getoverrun", /* 109 */
++ "timer_settime", /* 110 */
++ "timer_delete", /* 111 */
++ "clock_settime", /* 112 */
++ "clock_gettime", /* 113 */
++ "clock_getres", /* 114 */
++ "clock_nanosleep", /* 115 */
++ "syslog", /* 116 */
++ "ptrace", /* 117 */
++ "sched_setparam", /* 118 */
++ "sched_setscheduler", /* 119 */
++ "sched_getscheduler", /* 120 */
++ "sched_getparam", /* 121 */
++ "sched_setaffinity", /* 122 */
++ "sched_getaffinity", /* 123 */
++ "sched_yield", /* 124 */
++ "sched_get_priority_max", /* 125 */
++ "sched_get_priority_min", /* 126 */
++ "sched_rr_get_interval", /* 127 */
++ "restart_syscall", /* 128 */
++ "kill", /* 129 */
++ "tkill", /* 130 */
++ "tgkill", /* 131 */
++ "sigaltstack", /* 132 */
++ "rt_sigsuspend", /* 133 */
++ "rt_sigaction", /* 134 */
++ "rt_sigprocmask", /* 135 */
++ "rt_sigpending", /* 136 */
++ "rt_sigtimedwait", /* 137 */
++ "rt_sigqueueinfo", /* 138 */
++ "rt_sigreturn", /* 139 */
++ "setpriority", /* 140 */
++ "getpriority", /* 141 */
++ "reboot", /* 142 */
++ "setregid", /* 143 */
++ "setgid", /* 144 */
++ "setreuid", /* 145 */
++ "setuid", /* 146 */
++ "setresuid", /* 147 */
++ "getresuid", /* 148 */
++ "setresgid", /* 149 */
++ "getresgid", /* 150 */
++ "setfsuid", /* 151 */
++ "setfsgid", /* 152 */
++ "times", /* 153 */
++ "setpgid", /* 154 */
++ "getpgid", /* 155 */
++ "getsid", /* 156 */
++ "setsid", /* 157 */
++ "getgroups", /* 158 */
++ "setgroups", /* 159 */
++ "uname", /* 160 */
++ "sethostname", /* 161 */
++ "setdomainname", /* 162 */
++ "getrlimit", /* 163 */
++ "setrlimit", /* 164 */
++ "getrusage", /* 165 */
++ "umask", /* 166 */
++ "prctl", /* 167 */
++ "getcpu", /* 168 */
++ "gettimeofday", /* 169 */
++ "settimeofday", /* 170 */
++ "adjtimex", /* 171 */
++ "getpid", /* 172 */
++ "getppid", /* 173 */
++ "getuid", /* 174 */
++ "geteuid", /* 175 */
++ "getgid", /* 176 */
++ "getegid", /* 177 */
++ "gettid", /* 178 */
++ "sysinfo", /* 179 */
++ "mq_open", /* 180 */
++ "mq_unlink", /* 181 */
++ "mq_timedsend", /* 182 */
++ "mq_timedreceive", /* 183 */
++ "mq_notify", /* 184 */
++ "mq_getsetattr", /* 185 */
++ "msgget", /* 186 */
++ "msgctl", /* 187 */
++ "msgrcv", /* 188 */
++ "msgsnd", /* 189 */
++ "semget", /* 190 */
++ "semctl", /* 191 */
++ "semtimedop", /* 192 */
++ "semop", /* 193 */
++ "shmget", /* 194 */
++ "shmctl", /* 195 */
++ "shmat", /* 196 */
++ "shmdt", /* 197 */
++ "socket", /* 198 */
++ "socketpair", /* 199 */
++ "bind", /* 200 */
++ "listen", /* 201 */
++ "accept", /* 202 */
++ "connect", /* 203 */
++ "getsockname", /* 204 */
++ "getpeername", /* 205 */
++ "sendto", /* 206 */
++ "recvfrom", /* 207 */
++ "setsockopt", /* 208 */
++ "getsockopt", /* 209 */
++ "shutdown", /* 210 */
++ "sendmsg", /* 211 */
++ "recvmsg", /* 212 */
++ "readahead", /* 213 */
++ "brk", /* 214 */
++ "munmap", /* 215 */
++ "mremap", /* 216 */
++ "add_key", /* 217 */
++ "request_key", /* 218 */
++ "keyctl", /* 219 */
++ "clone", /* 220 */
++ "execve", /* 221 */
++ "mmap", /* 222 */
++ "fadvise64", /* 223 */
++ "swapon", /* 224 */
++ "swapoff", /* 225 */
++ "mprotect", /* 226 */
++ "msync", /* 227 */
++ "mlock", /* 228 */
++ "munlock", /* 229 */
++ "mlockall", /* 230 */
++ "munlockall", /* 231 */
++ "mincore", /* 232 */
++ "madvise", /* 233 */
++ "remap_file_pages", /* 234 */
++ "mbind", /* 235 */
++ "get_mempolicy", /* 236 */
++ "set_mempolicy", /* 237 */
++ "migrate_pages", /* 238 */
++ "move_pages", /* 239 */
++ "rt_tgsigqueueinfo", /* 240 */
++ "perf_event_open", /* 241 */
++ "accept4", /* 242 */
++ "recvmmsg", /* 243 */
++ "arch_specific_syscall", /* 244 */
++ "245", /* 245 */
++ "246", /* 246 */
++ "247", /* 247 */
++ "248", /* 248 */
++ "249", /* 249 */
++ "250", /* 250 */
++ "251", /* 251 */
++ "252", /* 252 */
++ "253", /* 253 */
++ "254", /* 254 */
++ "255", /* 255 */
++ "256", /* 256 */
++ "257", /* 257 */
++ "258", /* 258 */
++ "259", /* 259 */
++ "wait4", /* 260 */
++ "prlimit64", /* 261 */
++ "fanotify_init", /* 262 */
++ "fanotify_mark", /* 263 */
++ "name_to_handle_at", /* 264 */
++ "open_by_handle_at", /* 265 */
++ "clock_adjtime", /* 266 */
++ "syncfs", /* 267 */
++ "setns", /* 268 */
++ "sendmmsg", /* 269 */
++ "process_vm_readv", /* 270 */
++ "process_vm_writev", /* 271 */
++ "kcmp", /* 272 */
++ "finit_module", /* 273 */
++ "syscalls", /* 274 */
++ "275", /* 275 */
++ "276", /* 276 */
++ "277", /* 277 */
++ "278", /* 278 */
++ "279", /* 279 */
++ "280", /* 280 */
++ "281", /* 281 */
++ "282", /* 282 */
++ "283", /* 283 */
++ "284", /* 284 */
++ "285", /* 285 */
++ "286", /* 286 */
++ "287", /* 287 */
++ "288", /* 288 */
++ "289", /* 289 */
++ "290", /* 290 */
++ "291", /* 291 */
++ "292", /* 292 */
++ "293", /* 293 */
++ "294", /* 294 */
++ "295", /* 295 */
++ "296", /* 296 */
++ "297", /* 297 */
++ "298", /* 298 */
++ "299", /* 299 */
++ "300", /* 300 */
++ "301", /* 301 */
++ "302", /* 302 */
++ "303", /* 303 */
++ "304", /* 304 */
++ "305", /* 305 */
++ "306", /* 306 */
++ "307", /* 307 */
++ "308", /* 308 */
++ "309", /* 309 */
++ "310", /* 310 */
++ "311", /* 311 */
++ "312", /* 312 */
++ "313", /* 313 */
++ "314", /* 314 */
++ "315", /* 315 */
++ "316", /* 316 */
++ "317", /* 317 */
++ "318", /* 318 */
++ "319", /* 319 */
++ "320", /* 320 */
++ "321", /* 321 */
++ "322", /* 322 */
++ "323", /* 323 */
++ "324", /* 324 */
++ "325", /* 325 */
++ "326", /* 326 */
++ "327", /* 327 */
++ "328", /* 328 */
++ "329", /* 329 */
++ "330", /* 330 */
++ "331", /* 331 */
++ "332", /* 332 */
++ "333", /* 333 */
++ "334", /* 334 */
++ "335", /* 335 */
++ "336", /* 336 */
++ "337", /* 337 */
++ "338", /* 338 */
++ "339", /* 339 */
++ "340", /* 340 */
++ "341", /* 341 */
++ "342", /* 342 */
++ "343", /* 343 */
++ "344", /* 344 */
++ "345", /* 345 */
++ "346", /* 346 */
++ "347", /* 347 */
++ "348", /* 348 */
++ "349", /* 349 */
++ "350", /* 350 */
++ "351", /* 351 */
++ "352", /* 352 */
++ "353", /* 353 */
++ "354", /* 354 */
++ "355", /* 355 */
++ "356", /* 356 */
++ "357", /* 357 */
++ "358", /* 358 */
++ "359", /* 359 */
++ "360", /* 360 */
++ "361", /* 361 */
++ "362", /* 362 */
++ "363", /* 363 */
++ "364", /* 364 */
++ "365", /* 365 */
++ "366", /* 366 */
++ "367", /* 367 */
++ "368", /* 368 */
++ "369", /* 369 */
++ "370", /* 370 */
++ "371", /* 371 */
++ "372", /* 372 */
++ "373", /* 373 */
++ "374", /* 374 */
++ "375", /* 375 */
++ "376", /* 376 */
++ "377", /* 377 */
++ "378", /* 378 */
++ "379", /* 379 */
++ "380", /* 380 */
++ "381", /* 381 */
++ "382", /* 382 */
++ "383", /* 383 */
++ "384", /* 384 */
++ "385", /* 385 */
++ "386", /* 386 */
++ "387", /* 387 */
++ "388", /* 388 */
++ "389", /* 389 */
++ "390", /* 390 */
++ "391", /* 391 */
++ "392", /* 392 */
++ "393", /* 393 */
++ "394", /* 394 */
++ "395", /* 395 */
++ "396", /* 396 */
++ "397", /* 397 */
++ "398", /* 398 */
++ "399", /* 399 */
++ "400", /* 400 */
++ "401", /* 401 */
++ "402", /* 402 */
++ "403", /* 403 */
++ "404", /* 404 */
++ "405", /* 405 */
++ "406", /* 406 */
++ "407", /* 407 */
++ "408", /* 408 */
++ "409", /* 409 */
++ "410", /* 410 */
++ "411", /* 411 */
++ "412", /* 412 */
++ "413", /* 413 */
++ "414", /* 414 */
++ "415", /* 415 */
++ "416", /* 416 */
++ "417", /* 417 */
++ "418", /* 418 */
++ "419", /* 419 */
++ "420", /* 420 */
++ "421", /* 421 */
++ "422", /* 422 */
++ "423", /* 423 */
++ "424", /* 424 */
++ "425", /* 425 */
++ "426", /* 426 */
++ "427", /* 427 */
++ "428", /* 428 */
++ "429", /* 429 */
++ "430", /* 430 */
++ "431", /* 431 */
++ "432", /* 432 */
++ "433", /* 433 */
++ "434", /* 434 */
++ "435", /* 435 */
++ "436", /* 436 */
++ "437", /* 437 */
++ "438", /* 438 */
++ "439", /* 439 */
++ "440", /* 440 */
++ "441", /* 441 */
++ "442", /* 442 */
++ "443", /* 443 */
++ "444", /* 444 */
++ "445", /* 445 */
++ "446", /* 446 */
++ "447", /* 447 */
++ "448", /* 448 */
++ "449", /* 449 */
++ "450", /* 450 */
++ "451", /* 451 */
++ "452", /* 452 */
++ "453", /* 453 */
++ "454", /* 454 */
++ "455", /* 455 */
++ "456", /* 456 */
++ "457", /* 457 */
++ "458", /* 458 */
++ "459", /* 459 */
++ "460", /* 460 */
++ "461", /* 461 */
++ "462", /* 462 */
++ "463", /* 463 */
++ "464", /* 464 */
++ "465", /* 465 */
++ "466", /* 466 */
++ "467", /* 467 */
++ "468", /* 468 */
++ "469", /* 469 */
++ "470", /* 470 */
++ "471", /* 471 */
++ "472", /* 472 */
++ "473", /* 473 */
++ "474", /* 474 */
++ "475", /* 475 */
++ "476", /* 476 */
++ "477", /* 477 */
++ "478", /* 478 */
++ "479", /* 479 */
++ "480", /* 480 */
++ "481", /* 481 */
++ "482", /* 482 */
++ "483", /* 483 */
++ "484", /* 484 */
++ "485", /* 485 */
++ "486", /* 486 */
++ "487", /* 487 */
++ "488", /* 488 */
++ "489", /* 489 */
++ "490", /* 490 */
++ "491", /* 491 */
++ "492", /* 492 */
++ "493", /* 493 */
++ "494", /* 494 */
++ "495", /* 495 */
++ "496", /* 496 */
++ "497", /* 497 */
++ "498", /* 498 */
++ "499", /* 499 */
++ "500", /* 500 */
++ "501", /* 501 */
++ "502", /* 502 */
++ "503", /* 503 */
++ "504", /* 504 */
++ "505", /* 505 */
++ "506", /* 506 */
++ "507", /* 507 */
++ "508", /* 508 */
++ "509", /* 509 */
++ "510", /* 510 */
++ "511", /* 511 */
++ "512", /* 512 */
++ "513", /* 513 */
++ "514", /* 514 */
++ "515", /* 515 */
++ "516", /* 516 */
++ "517", /* 517 */
++ "518", /* 518 */
++ "519", /* 519 */
++ "520", /* 520 */
++ "521", /* 521 */
++ "522", /* 522 */
++ "523", /* 523 */
++ "524", /* 524 */
++ "525", /* 525 */
++ "526", /* 526 */
++ "527", /* 527 */
++ "528", /* 528 */
++ "529", /* 529 */
++ "530", /* 530 */
++ "531", /* 531 */
++ "532", /* 532 */
++ "533", /* 533 */
++ "534", /* 534 */
++ "535", /* 535 */
++ "536", /* 536 */
++ "537", /* 537 */
++ "538", /* 538 */
++ "539", /* 539 */
++ "540", /* 540 */
++ "541", /* 541 */
++ "542", /* 542 */
++ "543", /* 543 */
++ "544", /* 544 */
++ "545", /* 545 */
++ "546", /* 546 */
++ "547", /* 547 */
++ "548", /* 548 */
++ "549", /* 549 */
++ "550", /* 550 */
++ "551", /* 551 */
++ "552", /* 552 */
++ "553", /* 553 */
++ "554", /* 554 */
++ "555", /* 555 */
++ "556", /* 556 */
++ "557", /* 557 */
++ "558", /* 558 */
++ "559", /* 559 */
++ "560", /* 560 */
++ "561", /* 561 */
++ "562", /* 562 */
++ "563", /* 563 */
++ "564", /* 564 */
++ "565", /* 565 */
++ "566", /* 566 */
++ "567", /* 567 */
++ "568", /* 568 */
++ "569", /* 569 */
++ "570", /* 570 */
++ "571", /* 571 */
++ "572", /* 572 */
++ "573", /* 573 */
++ "574", /* 574 */
++ "575", /* 575 */
++ "576", /* 576 */
++ "577", /* 577 */
++ "578", /* 578 */
++ "579", /* 579 */
++ "580", /* 580 */
++ "581", /* 581 */
++ "582", /* 582 */
++ "583", /* 583 */
++ "584", /* 584 */
++ "585", /* 585 */
++ "586", /* 586 */
++ "587", /* 587 */
++ "588", /* 588 */
++ "589", /* 589 */
++ "590", /* 590 */
++ "591", /* 591 */
++ "592", /* 592 */
++ "593", /* 593 */
++ "594", /* 594 */
++ "595", /* 595 */
++ "596", /* 596 */
++ "597", /* 597 */
++ "598", /* 598 */
++ "599", /* 599 */
++ "600", /* 600 */
++ "601", /* 601 */
++ "602", /* 602 */
++ "603", /* 603 */
++ "604", /* 604 */
++ "605", /* 605 */
++ "606", /* 606 */
++ "607", /* 607 */
++ "608", /* 608 */
++ "609", /* 609 */
++ "610", /* 610 */
++ "611", /* 611 */
++ "612", /* 612 */
++ "613", /* 613 */
++ "614", /* 614 */
++ "615", /* 615 */
++ "616", /* 616 */
++ "617", /* 617 */
++ "618", /* 618 */
++ "619", /* 619 */
++ "620", /* 620 */
++ "621", /* 621 */
++ "622", /* 622 */
++ "623", /* 623 */
++ "624", /* 624 */
++ "625", /* 625 */
++ "626", /* 626 */
++ "627", /* 627 */
++ "628", /* 628 */
++ "629", /* 629 */
++ "630", /* 630 */
++ "631", /* 631 */
++ "632", /* 632 */
++ "633", /* 633 */
++ "634", /* 634 */
++ "635", /* 635 */
++ "636", /* 636 */
++ "637", /* 637 */
++ "638", /* 638 */
++ "639", /* 639 */
++ "640", /* 640 */
++ "641", /* 641 */
++ "642", /* 642 */
++ "643", /* 643 */
++ "644", /* 644 */
++ "645", /* 645 */
++ "646", /* 646 */
++ "647", /* 647 */
++ "648", /* 648 */
++ "649", /* 649 */
++ "650", /* 650 */
++ "651", /* 651 */
++ "652", /* 652 */
++ "653", /* 653 */
++ "654", /* 654 */
++ "655", /* 655 */
++ "656", /* 656 */
++ "657", /* 657 */
++ "658", /* 658 */
++ "659", /* 659 */
++ "660", /* 660 */
++ "661", /* 661 */
++ "662", /* 662 */
++ "663", /* 663 */
++ "664", /* 664 */
++ "665", /* 665 */
++ "666", /* 666 */
++ "667", /* 667 */
++ "668", /* 668 */
++ "669", /* 669 */
++ "670", /* 670 */
++ "671", /* 671 */
++ "672", /* 672 */
++ "673", /* 673 */
++ "674", /* 674 */
++ "675", /* 675 */
++ "676", /* 676 */
++ "677", /* 677 */
++ "678", /* 678 */
++ "679", /* 679 */
++ "680", /* 680 */
++ "681", /* 681 */
++ "682", /* 682 */
++ "683", /* 683 */
++ "684", /* 684 */
++ "685", /* 685 */
++ "686", /* 686 */
++ "687", /* 687 */
++ "688", /* 688 */
++ "689", /* 689 */
++ "690", /* 690 */
++ "691", /* 691 */
++ "692", /* 692 */
++ "693", /* 693 */
++ "694", /* 694 */
++ "695", /* 695 */
++ "696", /* 696 */
++ "697", /* 697 */
++ "698", /* 698 */
++ "699", /* 699 */
++ "700", /* 700 */
++ "701", /* 701 */
++ "702", /* 702 */
++ "703", /* 703 */
++ "704", /* 704 */
++ "705", /* 705 */
++ "706", /* 706 */
++ "707", /* 707 */
++ "708", /* 708 */
++ "709", /* 709 */
++ "710", /* 710 */
++ "711", /* 711 */
++ "712", /* 712 */
++ "713", /* 713 */
++ "714", /* 714 */
++ "715", /* 715 */
++ "716", /* 716 */
++ "717", /* 717 */
++ "718", /* 718 */
++ "719", /* 719 */
++ "720", /* 720 */
++ "721", /* 721 */
++ "722", /* 722 */
++ "723", /* 723 */
++ "724", /* 724 */
++ "725", /* 725 */
++ "726", /* 726 */
++ "727", /* 727 */
++ "728", /* 728 */
++ "729", /* 729 */
++ "730", /* 730 */
++ "731", /* 731 */
++ "732", /* 732 */
++ "733", /* 733 */
++ "734", /* 734 */
++ "735", /* 735 */
++ "736", /* 736 */
++ "737", /* 737 */
++ "738", /* 738 */
++ "739", /* 739 */
++ "740", /* 740 */
++ "741", /* 741 */
++ "742", /* 742 */
++ "743", /* 743 */
++ "744", /* 744 */
++ "745", /* 745 */
++ "746", /* 746 */
++ "747", /* 747 */
++ "748", /* 748 */
++ "749", /* 749 */
++ "750", /* 750 */
++ "751", /* 751 */
++ "752", /* 752 */
++ "753", /* 753 */
++ "754", /* 754 */
++ "755", /* 755 */
++ "756", /* 756 */
++ "757", /* 757 */
++ "758", /* 758 */
++ "759", /* 759 */
++ "760", /* 760 */
++ "761", /* 761 */
++ "762", /* 762 */
++ "763", /* 763 */
++ "764", /* 764 */
++ "765", /* 765 */
++ "766", /* 766 */
++ "767", /* 767 */
++ "768", /* 768 */
++ "769", /* 769 */
++ "770", /* 770 */
++ "771", /* 771 */
++ "772", /* 772 */
++ "773", /* 773 */
++ "774", /* 774 */
++ "775", /* 775 */
++ "776", /* 776 */
++ "777", /* 777 */
++ "778", /* 778 */
++ "779", /* 779 */
++ "780", /* 780 */
++ "781", /* 781 */
++ "782", /* 782 */
++ "783", /* 783 */
++ "784", /* 784 */
++ "785", /* 785 */
++ "786", /* 786 */
++ "787", /* 787 */
++ "788", /* 788 */
++ "789", /* 789 */
++ "790", /* 790 */
++ "791", /* 791 */
++ "792", /* 792 */
++ "793", /* 793 */
++ "794", /* 794 */
++ "795", /* 795 */
++ "796", /* 796 */
++ "797", /* 797 */
++ "798", /* 798 */
++ "799", /* 799 */
++ "800", /* 800 */
++ "801", /* 801 */
++ "802", /* 802 */
++ "803", /* 803 */
++ "804", /* 804 */
++ "805", /* 805 */
++ "806", /* 806 */
++ "807", /* 807 */
++ "808", /* 808 */
++ "809", /* 809 */
++ "810", /* 810 */
++ "811", /* 811 */
++ "812", /* 812 */
++ "813", /* 813 */
++ "814", /* 814 */
++ "815", /* 815 */
++ "816", /* 816 */
++ "817", /* 817 */
++ "818", /* 818 */
++ "819", /* 819 */
++ "820", /* 820 */
++ "821", /* 821 */
++ "822", /* 822 */
++ "823", /* 823 */
++ "824", /* 824 */
++ "825", /* 825 */
++ "826", /* 826 */
++ "827", /* 827 */
++ "828", /* 828 */
++ "829", /* 829 */
++ "830", /* 830 */
++ "831", /* 831 */
++ "832", /* 832 */
++ "833", /* 833 */
++ "834", /* 834 */
++ "835", /* 835 */
++ "836", /* 836 */
++ "837", /* 837 */
++ "838", /* 838 */
++ "839", /* 839 */
++ "840", /* 840 */
++ "841", /* 841 */
++ "842", /* 842 */
++ "843", /* 843 */
++ "844", /* 844 */
++ "845", /* 845 */
++ "846", /* 846 */
++ "847", /* 847 */
++ "848", /* 848 */
++ "849", /* 849 */
++ "850", /* 850 */
++ "851", /* 851 */
++ "852", /* 852 */
++ "853", /* 853 */
++ "854", /* 854 */
++ "855", /* 855 */
++ "856", /* 856 */
++ "857", /* 857 */
++ "858", /* 858 */
++ "859", /* 859 */
++ "860", /* 860 */
++ "861", /* 861 */
++ "862", /* 862 */
++ "863", /* 863 */
++ "864", /* 864 */
++ "865", /* 865 */
++ "866", /* 866 */
++ "867", /* 867 */
++ "868", /* 868 */
++ "869", /* 869 */
++ "870", /* 870 */
++ "871", /* 871 */
++ "872", /* 872 */
++ "873", /* 873 */
++ "874", /* 874 */
++ "875", /* 875 */
++ "876", /* 876 */
++ "877", /* 877 */
++ "878", /* 878 */
++ "879", /* 879 */
++ "880", /* 880 */
++ "881", /* 881 */
++ "882", /* 882 */
++ "883", /* 883 */
++ "884", /* 884 */
++ "885", /* 885 */
++ "886", /* 886 */
++ "887", /* 887 */
++ "888", /* 888 */
++ "889", /* 889 */
++ "890", /* 890 */
++ "891", /* 891 */
++ "892", /* 892 */
++ "893", /* 893 */
++ "894", /* 894 */
++ "895", /* 895 */
++ "896", /* 896 */
++ "897", /* 897 */
++ "898", /* 898 */
++ "899", /* 899 */
++ "900", /* 900 */
++ "901", /* 901 */
++ "902", /* 902 */
++ "903", /* 903 */
++ "904", /* 904 */
++ "905", /* 905 */
++ "906", /* 906 */
++ "907", /* 907 */
++ "908", /* 908 */
++ "909", /* 909 */
++ "910", /* 910 */
++ "911", /* 911 */
++ "912", /* 912 */
++ "913", /* 913 */
++ "914", /* 914 */
++ "915", /* 915 */
++ "916", /* 916 */
++ "917", /* 917 */
++ "918", /* 918 */
++ "919", /* 919 */
++ "920", /* 920 */
++ "921", /* 921 */
++ "922", /* 922 */
++ "923", /* 923 */
++ "924", /* 924 */
++ "925", /* 925 */
++ "926", /* 926 */
++ "927", /* 927 */
++ "928", /* 928 */
++ "929", /* 929 */
++ "930", /* 930 */
++ "931", /* 931 */
++ "932", /* 932 */
++ "933", /* 933 */
++ "934", /* 934 */
++ "935", /* 935 */
++ "936", /* 936 */
++ "937", /* 937 */
++ "938", /* 938 */
++ "939", /* 939 */
++ "940", /* 940 */
++ "941", /* 941 */
++ "942", /* 942 */
++ "943", /* 943 */
++ "944", /* 944 */
++ "945", /* 945 */
++ "946", /* 946 */
++ "947", /* 947 */
++ "948", /* 948 */
++ "949", /* 949 */
++ "950", /* 950 */
++ "951", /* 951 */
++ "952", /* 952 */
++ "953", /* 953 */
++ "954", /* 954 */
++ "955", /* 955 */
++ "956", /* 956 */
++ "957", /* 957 */
++ "958", /* 958 */
++ "959", /* 959 */
++ "960", /* 960 */
++ "961", /* 961 */
++ "962", /* 962 */
++ "963", /* 963 */
++ "964", /* 964 */
++ "965", /* 965 */
++ "966", /* 966 */
++ "967", /* 967 */
++ "968", /* 968 */
++ "969", /* 969 */
++ "970", /* 970 */
++ "971", /* 971 */
++ "972", /* 972 */
++ "973", /* 973 */
++ "974", /* 974 */
++ "975", /* 975 */
++ "976", /* 976 */
++ "977", /* 977 */
++ "978", /* 978 */
++ "979", /* 979 */
++ "980", /* 980 */
++ "981", /* 981 */
++ "982", /* 982 */
++ "983", /* 983 */
++ "984", /* 984 */
++ "985", /* 985 */
++ "986", /* 986 */
++ "987", /* 987 */
++ "988", /* 988 */
++ "989", /* 989 */
++ "990", /* 990 */
++ "991", /* 991 */
++ "992", /* 992 */
++ "993", /* 993 */
++ "994", /* 994 */
++ "995", /* 995 */
++ "996", /* 996 */
++ "997", /* 997 */
++ "998", /* 998 */
++ "999", /* 999 */
++ "1000", /* 1000 */
++ "1001", /* 1001 */
++ "1002", /* 1002 */
++ "1003", /* 1003 */
++ "1004", /* 1004 */
++ "1005", /* 1005 */
++ "1006", /* 1006 */
++ "1007", /* 1007 */
++ "1008", /* 1008 */
++ "1009", /* 1009 */
++ "1010", /* 1010 */
++ "1011", /* 1011 */
++ "1012", /* 1012 */
++ "1013", /* 1013 */
++ "1014", /* 1014 */
++ "1015", /* 1015 */
++ "1016", /* 1016 */
++ "1017", /* 1017 */
++ "1018", /* 1018 */
++ "1019", /* 1019 */
++ "1020", /* 1020 */
++ "1021", /* 1021 */
++ "1022", /* 1022 */
++ "1023", /* 1023 */
++ "open", /* 1024 */
++ "link", /* 1025 */
++ "unlink", /* 1026 */
++ "mknod", /* 1027 */
++ "chmod", /* 1028 */
++ "chown", /* 1029 */
++ "mkdir", /* 1030 */
++ "rmdir", /* 1031 */
++ "lchown", /* 1032 */
++ "access", /* 1033 */
++ "rename", /* 1034 */
++ "readlink", /* 1035 */
++ "symlink", /* 1036 */
++ "utimes", /* 1037 */
++ "stat", /* 1038 */
++ "lstat", /* 1039 */
++ "pipe", /* 1040 */
++ "dup2", /* 1041 */
++ "epoll_create", /* 1042 */
++ "inotify_init", /* 1043 */
++ "eventfd", /* 1044 */
++ "signalfd", /* 1045 */
++ "sendfile", /* 1046 */
++ "ftruncate", /* 1047 */
++ "truncate", /* 1048 */
++ "stat", /* 1049 */
++ "lstat", /* 1050 */
++ "fstat", /* 1051 */
++ "fcntl", /* 1052 */
++ "fadvise64", /* 1053 */
++ "newfstatat", /* 1054 */
++ "fstatfs", /* 1055 */
++ "statfs", /* 1056 */
++ "lseek", /* 1057 */
++ "mmap", /* 1058 */
++ "alarm", /* 1059 */
++ "getpgrp", /* 1060 */
++ "pause", /* 1061 */
++ "time", /* 1062 */
++ "utime", /* 1063 */
++ "creat", /* 1064 */
++ "getdents", /* 1065 */
++ "futimesat", /* 1066 */
++ "select", /* 1067 */
++ "poll", /* 1068 */
++ "epoll_wait", /* 1069 */
++ "ustat", /* 1070 */
++ "vfork", /* 1071 */
++ "oldwait4", /* 1072 */
++ "recv", /* 1073 */
++ "send", /* 1074 */
++ "bdflush", /* 1075 */
++ "umount", /* 1076 */
++ "uselib", /* 1077 */
++ "_sysctl", /* 1078 */
++ "fork", /* 1079 */
+diff --git a/sysdeps/linux-gnu/aarch64/trace.c b/sysdeps/linux-gnu/aarch64/trace.c
+new file mode 100644
+index 0000000..5544b51
+--- /dev/null
++++ b/sysdeps/linux-gnu/aarch64/trace.c
+@@ -0,0 +1,84 @@
++/*
++ * This file is part of ltrace.
++ * Copyright (C) 2014 Petr Machata, Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA
++ */
++
++#include <sys/ptrace.h>
++#include <sys/types.h>
++#include <sys/wait.h>
++#include <asm/ptrace.h>
++#include <string.h>
++#include <stdio.h>
++#include <errno.h>
++
++#include "backend.h"
++#include "proc.h"
++
++void
++get_arch_dep(struct Process *proc)
++{
++}
++
++int aarch64_read_gregs(struct Process *proc, struct user_pt_regs *regs);
++
++/* The syscall instruction is:
++ * | 31 21 | 20 5 | 4 0 |
++ * | 1 1 0 1 0 1 0 0 | 0 0 0 | imm16 | 0 0 0 0 1 | */
++#define SVC_MASK 0xffe0001f
++#define SVC_VALUE 0xd4000001
++
++int
++syscall_p(struct Process *proc, int status, int *sysnum)
++{
++ if (WIFSTOPPED(status)
++ && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
++
++ struct user_pt_regs regs;
++ if (aarch64_read_gregs(proc, &regs) < 0) {
++ fprintf(stderr, "syscall_p: "
++ "Couldn't read registers of %d.\n", proc->pid);
++ return -1;
++ }
++
++ errno = 0;
++ unsigned long insn = (unsigned long) ptrace(PTRACE_PEEKTEXT,
++ proc->pid,
++ regs.pc - 4, 0);
++ if (insn == -1UL && errno != 0) {
++ fprintf(stderr, "syscall_p: "
++ "Couldn't peek into %d: %s\n", proc->pid,
++ strerror(errno));
++ return -1;
++ }
++
++ insn &= 0xffffffffUL;
++ if ((insn & SVC_MASK) == SVC_VALUE) {
++ *sysnum = regs.regs[8];
++
++ size_t d1 = proc->callstack_depth - 1;
++ if (proc->callstack_depth > 0
++ && proc->callstack[d1].is_syscall
++ && proc->callstack[d1].c_un.syscall == *sysnum)
++ return 2;
++
++ return 1;
++ }
++ }
++
++ return 0;
++}
+--
+1.9.1
+
diff --git a/harmony/ltrace/add_ppc64le.patch b/harmony/ltrace/add_ppc64le.patch
new file mode 100644
index 000000000..32efa8b52
--- /dev/null
+++ b/harmony/ltrace/add_ppc64le.patch
@@ -0,0 +1,54 @@
+--- ltrace-0.7.3.orig/configure.ac
++++ ltrace-0.7.3/configure.ac
+@@ -43,7 +43,7 @@
+ arm*|sa110) HOST_CPU="arm" ;;
+ cris*) HOST_CPU="cris" ;;
+ mips*) HOST_CPU="mips" ;;
+- powerpc|powerpc64) HOST_CPU="ppc" ;;
++ powerpc|powerpc64|powerpc64le) HOST_CPU="ppc" ;;
+ sun4u|sparc64) HOST_CPU="sparc" ;;
+ s390x) HOST_CPU="s390" ;;
+ i?86|x86_64) HOST_CPU="x86" ;;
+@@ -159,7 +159,7 @@
+ arm*|sa110) UNWIND_ARCH="arm" ;;
+ i?86) UNWIND_ARCH="x86" ;;
+ powerpc) UNWIND_ARCH="ppc32" ;;
+- powerpc64) UNWIND_ARCH="ppc64" ;;
++ powerpc64|powerpc64le) UNWIND_ARCH="ppc64" ;;
+ mips*) UNWIND_ARCH="mips" ;;
+ *) UNWIND_ARCH="${host_cpu}" ;;
+ esac
+--- ltrace-0.7.3.orig/sysdeps/linux-gnu/ppc/ptrace.h
++++ ltrace-0.7.3/sysdeps/linux-gnu/ppc/ptrace.h
+@@ -18,4 +18,5 @@
+ * 02110-1301 USA
+ */
+
++#include <asm/ptrace.h>
+ #include <sys/ptrace.h>
+--- ltrace-0.7.3.orig/sysdeps/linux-gnu/ppc/regs.c
++++ ltrace-0.7.3/sysdeps/linux-gnu/ppc/regs.c
+@@ -26,7 +26,9 @@
+ #include <sys/ptrace.h>
+ #include <asm/ptrace.h>
+ #include <errno.h>
++#ifdef HAVE_ERROR_H
+ #include <error.h>
++#endif
+
+ #include "proc.h"
+ #include "common.h"
+@@ -47,8 +49,11 @@
+ void
+ set_instruction_pointer(Process *proc, void *addr)
+ {
+- if (ptrace(PTRACE_POKEUSER, proc->pid, sizeof(long)*PT_NIP, addr) != 0)
+- error(0, errno, "set_instruction_pointer");
++ if (ptrace(PTRACE_POKEUSER, proc->pid, sizeof(long)*PT_NIP, addr) != 0){
++ strerror(0, errno, "set_instruction_pointer");
++ report_global_error("%s: set_instruction_pointer",
++ strerror(errno));
++ }
+ }
+
+ void *
diff --git a/harmony/ltrace/musl.patch b/harmony/ltrace/musl.patch
new file mode 100644
index 000000000..2dc909c95
--- /dev/null
+++ b/harmony/ltrace/musl.patch
@@ -0,0 +1,153 @@
+--- ./configure.ac.orig
++++ ./configure.ac
+@@ -34,6 +34,7 @@
+ case "${host_os}" in
+ linux-gnu*) HOST_OS="linux-gnu" ;;
+ linux-uclibc*) HOST_OS="linux-gnu" ;;
++ linux-musl*) HOST_OS="linux-gnu" ;;
+ *) AC_MSG_ERROR([unkown host-os ${host_os}]) ;;
+ esac
+ AC_SUBST(HOST_OS)
+@@ -234,6 +235,7 @@
+ sys/param.h \
+ sys/time.h \
+ unistd.h \
++ error.h \
+ ])
+
+ # Checks for typedefs, structures, and compiler characteristics.
+diff --git a/expr.c b/expr.c
+index 32860fd..374c549 100644
+--- a/expr.c
++++ b/expr.c
+@@ -19,9 +19,12 @@
+ */
+
+ #include <string.h>
++#include <stdio.h>
+ #include <assert.h>
+ #include <errno.h>
++#ifdef HAVE_ERROR_H
+ #include <error.h>
++#endif
+ #include <stdlib.h>
+
+ #include "expr.h"
+@@ -330,8 +333,11 @@ expr_self(void)
+ static struct expr_node *node = NULL;
+ if (node == NULL) {
+ node = malloc(sizeof(*node));
+- if (node == NULL)
+- error(1, errno, "malloc expr_self");
++ if (node == NULL) {
++ fprintf(stderr, "%s: malloc expr_self\n",
++ strerror(errno));
++ exit(1);
++ }
+ expr_init_self(node);
+ }
+ return node;
+diff --git a/glob.c b/glob.c
+index 075c867..06fec47 100644
+--- a/glob.c
++++ b/glob.c
+@@ -180,7 +180,7 @@ glob_to_regex(const char *glob, char **retp)
+ goto fail;
+ }
+ *retp = buf;
+- return REG_NOERROR;
++ return 0;
+ }
+
+ int
+@@ -188,7 +188,7 @@ globcomp(regex_t *preg, const char *glob, int cflags)
+ {
+ char *regex = NULL;
+ int status = glob_to_regex(glob, &regex);
+- if (status != REG_NOERROR)
++ if (status != 0)
+ return status;
+ assert(regex != NULL);
+ status = regcomp(preg, regex, cflags);
+diff --git a/options.c b/options.c
+index 1e19dc7..1dc5e1e 100644
+--- a/options.c
++++ b/options.c
+@@ -204,7 +204,7 @@ compile_libname(const char *expr, const char *a_lib, int lib_re_p,
+
+ regex_t lib_re;
+ int status = (lib_re_p ? regcomp : globcomp)(&lib_re, lib, 0);
+- if (status != REG_NOERROR) {
++ if (status != 0) {
+ char buf[100];
+ regerror(status, &lib_re, buf, sizeof buf);
+ fprintf(stderr, "Rule near '%s' will be ignored: %s.\n",
+diff --git a/read_config_file.c b/read_config_file.c
+index e247436..73528fe 100644
+--- a/read_config_file.c
++++ b/read_config_file.c
+@@ -27,7 +27,9 @@
+ #include <stdlib.h>
+ #include <ctype.h>
+ #include <errno.h>
++#ifdef HAVE_ERROR_H
+ #include <error.h>
++#endif
+ #include <assert.h>
+
+ #include "common.h"
+@@ -1258,8 +1260,12 @@ void
+ init_global_config(void)
+ {
+ struct arg_type_info *info = malloc(2 * sizeof(*info));
+- if (info == NULL)
+- error(1, errno, "malloc in init_global_config");
++ if (info == NULL) {
++ report_error(filename, line_no,
++ "%s: malloc in init_global_config",
++ strerror(errno));
++ exit(1);
++ }
+
+ memset(info, 0, 2 * sizeof(*info));
+ info[0].type = ARGTYPE_POINTER;
+diff --git a/zero.c b/zero.c
+index bc119ee..e685f59 100644
+--- a/zero.c
++++ b/zero.c
+@@ -18,8 +18,11 @@
+ * 02110-1301 USA
+ */
+
++#ifdef HAVE_ERROR_H
+ #include <error.h>
++#endif
+ #include <errno.h>
++#include <string.h>
+
+ #include "zero.h"
+ #include "common.h"
+@@ -96,8 +99,11 @@ expr_node_zero(void)
+ static struct expr_node *node = NULL;
+ if (node == NULL) {
+ node = malloc(sizeof(*node));
+- if (node == NULL)
+- error(1, errno, "malloc expr_node_zero");
++ if (node == NULL) {
++ report_global_error("%s: malloc expr_node_zero",
++ strerror(errno));
++ exit(1);
++ }
+ expr_init_cb1(node, &zero1_callback,
+ expr_self(), 0, (void *)-1);
+ }
+--- ./proc.h.orig
++++ ./proc.h
+@@ -26,6 +26,7 @@
+ #include "config.h"
+
+ #include <sys/time.h>
++#include <unistd.h>
+
+ #if defined(HAVE_LIBUNWIND)
+ # include <libunwind.h>