Squashed 'third_party/elfutils/' content from commit 555e15e

Change-Id: I61cde98949e47e5c8c09c33260de17f30921be79
git-subtree-dir: third_party/elfutils
git-subtree-split: 555e15ebe8bf1eb33d00747173cfc80cc65648a4
diff --git a/backends/ChangeLog b/backends/ChangeLog
new file mode 100644
index 0000000..098bed7
--- /dev/null
+++ b/backends/ChangeLog
@@ -0,0 +1,1116 @@
+2018-02-09  Joshua Watt  <JPEWhacker@gmail.com>
+
+	* aarch64_retval.c (aarch64_return_value_location): Use FALLTHROUGH
+	macro instead of comment.
+	* alpha_retval.c (alpha_return_value_location): Likewise.
+	* arm_regs.c (arm_register_info): Likewise.
+	* arm_retval.c (arm_return_value_location): Likewise.
+	* i386_regs.c (i386_register_info): Likewise.
+	* i386_retval.c (i386_return_value_location): Likewise.
+	* ia64_retval.c (ia64_return_value_location): Likewise.
+	* linux-core-note.c (core_note): Likewise.
+	* m68k_retval.c (m68k_return_value_location): Likewise.
+	* ppc64_retval.c (ppc64_return_value_location): Likewise.
+	* ppc_regs.c (ppc_register_info): Likewise.
+	* ppc_retval.c (ppc_return_value_location): Likewise.
+	* s390_retval.c (s390_return_value_location): Likewise.
+	* sh_retval.c (sh_return_value_location): Likewise.
+	* sparc_retval.c (sparc_return_value_location): Likewise.
+	* tilegx_retval.c (tilegx_return_value_location): Likewise.
+	* x86_64_regs.c (x86_64_register_info): Likewise.
+	* x86_64_retval.c (x86_64_return_value_location): Likewise.
+
+2017-10-24  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (m68k_corenote_no_Wpacked_not_aligned): New variable.
+
+2017-08-18  Ulf Hermann <ulf.hermann@qt.io>
+
+	* linux-core-note.c: Use attribute_packed.
+
+2017-04-27  Ulf Hermann <ulf.hermann@qt.io>
+
+	* Makefile.am: Use dso_LDFLAGS.
+
+2017-07-27  Mark Wielaard  <mark@klomp.org>
+
+	* sparc_reloc.def: GOTDATA_OP_HIX22, GOTDATA_OP_LOX10 and
+	GOTDATA_OP can be used in ET_REL files.
+
+2017-07-19  Gustavo Romero <gromero@linux.vnet.ibm.com>
+
+	* ppc_corenote.c: Add offsets for ppc64 HTM SPRs: thfar, tfiar,
+	and texasr.
+	* ppc_regs.c: Add names for ppc64 HTM SPRs mappings.
+
+2017-07-20  Mark Wielaard  <mark@klomp.org>
+
+	* aarch64_init.c (aarch64_init): Hook data_marker_symbol.
+	* aarch64_symbol.c (aarch64_data_marker_symbol): New function.
+	* arm_init.c (arm_init): Hook data_marker_symbol.
+	* arm_symbol.c (aarch64_data_marker_symbol): New function.
+
+2017-07-18  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (cpu_bpf): Always define.
+	* bpf_init.c (disasm): Always hook.
+	* bpf_regs.c: Include bpf.h instead of linux/bpf.h. Don't define
+	MAX_BPF_REG.
+
+2017-02-17  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* Makefile.am: Add libeu.
+	(libebl_%so): Link with --no-undefined,-z,defs,-z,relro
+	and libeu.a.
+
+2017-06-17  Mark Wielaard  <mark@klomp.org>
+
+	* s390_initreg.c: Swap sys/ptrace.h and asm/ptrace.h include order.
+
+2017-06-15  Andreas Schwab  <schwab@linux-m68k.org>
+
+	* ppc_symbol.c (ppc_machine_flag_check): New function.
+	* ppc_init.c (ppc_init): Hook it.
+
+2017-05-30  Mark Wielaard  <mark@klomp.org>
+
+	* ppc64_unwind.c: New file.
+	* ppc64_init.c (pcc64_init): Hook unwind.
+	* Makefile.am (ppc64_SRCS): Add ppc64_unwind.c
+
+2017-04-06  Mark Wielaard  <mark@klomp.org>
+
+	* i386_unwind.c: New file.
+	* i386_init.c: Hook i386_unwind.
+	* Makefile.am (i386_SRCS): Add i386_unwind.c
+
+2017-02-09  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* aarch64_unwind.c: New file
+	* Makefile.am (aarch64_SRCS): Add aarch64_unwind.c
+	* aarch64_init.c (aarch64_init): Hook aarch64_unwind
+
+2017-02-09  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* x86_64_unwind.c: New file
+	* Makefile.am (x86_64_SRCS): Add x86_64_unwind.c
+	* x86_64_init.c (x86_64_init): Hook x86_64_unwind
+
+2017-04-20  Ulf Hermann <ulf.hermann@qt.io>
+
+	* aarch64_initreg.c: Compile register initialization only on linux.
+	* arm_initreg.c: Likewise.
+	* ppc_initreg.c: Likewise.
+	* s390_initreg.c: Likewise.
+	* x86_64_initreg.c: Likewise.
+
+2017-02-15  Mark Wielaard  <mark@klomp.org>
+
+	* ppc64_init.c (ppc64_init): Add check_object_attribute HOOK.
+	* ppc_attrs.c (ppc_check_object_attribute): Add Single-precision hard
+	float.
+
+2016-11-02  Mark Wielaard  <mjw@redhat.com>
+
+	* i386_regs.c (i386_register_info): Add fallthrough comment.
+	* i386_retval.c (i386_return_value_location): Move fallthrough
+	comment.
+	* linux-core-note.c (core_note): Adjust fallthrough comment.
+	* m68k_retval.c (m68k_return_value_location): Move fallthrough
+	comment.
+	* ppc_regs.c (ppc_register_info): Add fallthrough comment.
+	* x86_64_regs.c (x86_64_register_info): Likewise.
+
+2016-08-09  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* sparc_attrs.c (sparc_check_object_attribute): Fix the
+	calculation of GNU_SParc_HWCAPS and GNU_SParc_HWCAPS2 values as
+	comma-separated list of hw capability names.
+
+2016-07-10  Andreas Schwab  <schwab@linux-m68k.org>
+
+	* m68k_corenote.c (ALIGN_PRSTATUS): Define.
+	* linux-core-note.c (struct EBLHOOK(prstatus)): Set alignment to
+	ALIGN_PRSTATUS if defined.
+
+2016-06-28  Richard Henderson <rth@redhat.com>
+
+	* Makefile.am (modules): Add bpf.
+	(libebl_pic): Add libebl_bpf_pic.a.
+	(am_libebl_bpf_pic_a_OBJECTS): New.
+	* bpf_init.c, bpf_regs.c, bpf_reloc.def: New files.
+	* common-reloc.c (copy_reloc_p): Honor NO_COPY_RELOC.
+	(init_reloc): Likewise.
+
+2016-05-20  Andreas Schwab  <schwab@linux-m68k.org>
+
+	* Makefile.am (modules): Add m68k.
+	(libebl_pic): Add libebl_m68k_pic.a.
+	(m68k_SRCS, libebl_m68k_pic_a_SOURCES)
+	(am_libebl_m68k_pic_a_OBJECTS): Define.
+	* m68k_init.c: New file.
+	* m68k_symbol.c: New file.
+	* m68k_regs.c: New file.
+	* m68k_retval.c: New file.
+	* m68k_corenote.c: New file.
+	* m68k_reloc.def: New file.
+	* linux-core-note.c (ALIGN_INT): Only define if not defined.
+
+2016-02-26  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* sparc_initreg.c (EBLHOOK): Provide a dummy
+	sparc_set_initial_registers_tid for sparc32.  This fixes the build
+	in sparcv9-*-* targets.
+
+2016-02-26  Andreas Schwab  <schwab@suse.de>
+
+	* ppc_symbol.c (ppc_dynamic_tag_name): Add DT_PPC_OPT.
+	(ppc_dynamic_tag_check): Likewise.
+
+2015-12-28  Mark Wielaard  <mjw@redhat.com>
+
+	* i386_reloc.def: Add GOT32X.
+	* x86_64_reloc.def: Add GOTPCRELX and REX_GOTPCRELX.
+
+2016-02-12  Mark Wielaard  <mjw@redhat.com>
+
+	* aarch64_corenote.c (aarch64_syscall_items): New Ebl_Core_Item[].
+	(EXTRA_NOTES): Add NT_ARM_SYSTEM_CALL.
+	* eblcorenotetypename.c (ebl_core_note_type_name):
+	Add ARM_SYSTEM_CALL.
+
+2015-12-08  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* sparc_init.c (sparc_init): Hook sparc_set_initial_registers_tid.
+	* sparc_initreg.c: New file.
+	* Makefile.am (sparc_SRCS): Added sparc_initreg.c.
+
+2015-12-08  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* sparc_corenote.c: Header comment typo fixed.
+	(PRSTATUS_REGSET_ITEMS): Defined, so the PC can be fetched from
+	core files.
+	* Makefile.am (sparc_SRCS): Added sparc_cfi.c
+	* sparc_cfi.c: New file.
+	* sparc_init.c (sparc_init): Set eh->frame_nregs, eh->ra_offset
+	and hook sparc_abi_cfi.
+
+2015-10-21  Chih-Hung Hsieh  <chh@google.com>
+
+	* ia64_retval.c (hfa_type): Move nested function 'hfa' to file scope.
+	* aarch64_regs.c (aarch64_register_info): Move nested function 'regtype'
+	to file scope.
+
+2015-10-16  Mark Wielaard  <mjw@redhat.com>
+
+	* ppc_symbol.c (ppc_check_special_symbol): Also allow _SDA_BASE_
+	in .data section.
+
+2015-10-05  Josh Stone  <jistone@redhat.com>
+
+	* Makefile.am (libebl_%.so): Add AM_V_at and AM_V_CCLD silencers.
+
+2015-10-06  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* sparc_attrs.c: New file.
+	* Makefile.am (sparc_SRCS): Added sparc_attrs.c
+	* sparc_init.c (sparc_init): Hook sparc_check_object_attribute.
+
+2015-10-02  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* sparc_init.c (RELOC_TYPE_ID): Defined.
+	* common-reloc.c (reloc_type_name): Apply target-specific
+	relocation ID extractors if defined.
+	(reloc_type_check): Likewise.
+	(reloc_valid_use): Likewise.
+
+2015-10-02  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* sparc_reloc.def: Added relocation types WDISP10, JMP_IREL and
+	IRELATIVE.
+
+2015-09-22  Mark Wielaard  <mjw@redhat.com>
+
+	* arm_attrs.c: Remove old-style function definitions.
+	* linux-core-note.c: Likewise.
+	* ppc_attrs.c: Likewise.
+
+2015-09-04  Chih-Hung Hsieh  <chh@google.com>
+
+	* aarch64_init.c (aarch64_init): Replace K&R function definition
+	with ansi-C definitions.
+	* alpha_init.c (alpha_init): Likewise.
+	* arm_init.c (arm_init): Likewise.
+	* i386_init.c (i386_init): Likewise.
+	* ia64_init.c (ia64_init): Likewise.
+	* ppc64_init.c (ppc64_init): Likewise.
+	* ppc_init.c (ppc_init): Likewise.
+	* s390_init.c (s390_init): Likewise.
+	* sh_init.c (sh_init): Likewise.
+	* sparc_init.c (sparc_init): Likewise.
+	* tilegx_init.c (tilegx_init): Likewise.
+	* x86_64_init.c (x86_64_init): Likewise.
+
+2015-09-03  Mark Wielaard  <mjw@redhat.com>
+
+	* sparc_regs.c (sparc_register_info): Use ebl->class not ebl->machine.
+
+2015-06-26  Pino Toscano  <toscano.pino@tiscali.it>
+
+	* i386_initreg.c: Reduce scope of some includes to match their usage.
+
+2015-04-28  Mark Wielaard  <mjw@redhat.com>
+
+	* aarch64_reloc.def: Drop "64" from TLS_DTPMOD64, TLS_DTPREL64 and
+	TLS_TPREL64.
+
+2015-04-01  H.J. Lu  <hjl.tools@gmail.com>
+
+	* Makefile.am (x86_64_SRCS): Add x32_corenote.c.
+	* linux-core-note.c (PR_REG): New.
+	(PRPSINFO_UID_T): Likewise.
+	(ALIGN_PRPSINFO_UID_T): Likewise.
+	(TYPE_PRPSINFO_UID_T): Likewise.
+	(PRPSINFO_GID_T): Likewise.
+	(ALIGN_PRPSINFO_GID_T): Likewise.
+	(TYPE_PRPSINFO_GID_T): Likewise.
+	(pr_reg): Replace ULONG with PR_REG.
+	(pr_uid): Replace UID_T with PRPSINFO_UID_T.
+	(uid): Likewise.
+	(pr_gid): Replace GID_T with PRPSINFO_GID_T.
+	(gid): Likewise.
+	* x32_corenote.c: New file.
+	* x86_64_corenote.c (BITS): New.  Support x32.
+	(BACKEND): Support x32.
+	(ULONG): Likewise.
+	(ALIGN_ULONG): Likewise.
+	(TYPE_ULONG): Likewise.
+	(PRPSINFO_UID_T): New.
+	(ALIGN_PRPSINFO_UID_T): Likewise.
+	(TYPE_PRPSINFO_UID_T): Likewise.
+	(PRPSINFO_GID_T): Likewise.
+	(ALIGN_PRPSINFO_GID_T): Likewise.
+	(TYPE_PRPSINFO_GID_T): Likewise.
+	(PR_REG): Likewise.
+	(ALIGN_PR_REG): Likewise.
+	* x86_64_init.c (x32_core_note): New.
+	(x86_64_init): Set eh->core_note to x32_core_note for x32.
+
+2015-03-23  Mark Wielaard  <mjw@redhat.com>
+
+	* aarch64_symbol.c (aarch64_check_special_symbol): Accept
+	_GLOBAL_OFFSET_TABLE_ pointing anywhere in .got.
+
+2015-03-09  Mark Wielaard  <mjw@redhat.com>
+
+	* aarch64_reloc.def (COPY): Add DYN.
+	* arm_reloc.def (COPY): Likewise.
+	* i386_reloc.def (COPY): Likewise.
+	* ia64_reloc.def (COPY): Likewise.
+	* ppc64_reloc.def (COPY): Likewise.
+	* ppc_reloc.def (COPY): Likewise.
+	* s390_reloc.def (COPY): Likewise.
+	* sh_reloc.def (COPY): Likewise.
+	* sparc_reloc.def (COPY): Likewise.
+	* tilegx_reloc.def (COPY): Likewise.
+	* x86_64_reloc.def (COPY): Likewise.
+
+2015-02-23  Petr Machata  <pmachata@redhat.com>
+
+	* arm_symbol.c (arm_symbol_type_name): New function.
+	* arm_init.c (arm_init): Initialize the hook.
+
+2014-12-30  Mark Wielaard  <mjw@redhat.com>
+
+	* ppc_symbol.c (find_dyn_got): Check sh_entsize is not zero.
+
+2014-12-18  Ulrich Drepper  <drepper@gmail.com>
+
+	* Makefile.am: Suppress output of textrel_check command.
+
+2014-11-22  Mark Wielaard  <mjw@redhat.com>
+
+	* ppc64_symbol.c (ppc64_bss_plt_p): Remove ehdr argument.
+	* ppc_symbol.c (find_dyn_got): Likewise. Use elf_getphdrnum.
+	(ppc_check_special_symbol): Call find_dyn_got without ehdr.
+	(ppc_bss_plt_p): Remove ehdr argument.
+
+2014-11-17  Mark Wielaard  <mjw@redhat.com>
+
+	* ppc64_init.c (ppc64_init): Check section name is not NULL.
+
+2014-10-06  Mark Wielaard  <mjw@redhat.com>
+
+	* libebl_CPU.h (dwarf_peel_type): Removed.
+	(dwarf_peeled_die_type): Use libdw dwarf_peel_type.
+
+2014-07-18  Kyle McMartin  <kyle@redhat.com>
+	    Mark Wielaard  <mjw@redhat.com>
+
+	* aarch64_initreg.c: Check HAVE_SYS_USER_REGS.
+	(aarch64_set_initial_registers_tid): Use user_regs_struct and
+	user_fpsimd_struct.
+	* arm_initreg.c: Check HAVE_SYS_USER_REGS.
+	(arm_set_initial_registers_tid): Use user_regs_struct in compat mode.
+
+2014-07-04  Menanteau Guy  <menantea@linux.vnet.ibm.com>
+	    Mark Wielaard  <mjw@redhat.com>
+
+	* ppc64_init.c (ppc64_init): Hook check_st_other_bits.
+	* ppc64_reloc.def: TLSGD, TLSLD, TOCSAVE, ADDR16_HIGH, ADDR16_HIGHA,
+	TPREL16_HIGH, TPREL16_HIGHA, DTPREL16_HIGH, DTPREL16_HIGHA, JMP_IREL,
+	IRELATIVE, REL16, REL16_LO, REL16_HI and REL16_HA.
+	* ppc64_symbol.c (ppc64_dynamic_tag_name): Recognize DT_PPC64_OPT.
+	(ppc64_dynamic_tag_check): Likewise.
+	(ppc64_check_st_other_bits): New function.
+
+2014-07-04  Mark Wielaard  <mjw@redhat.com>
+
+	* aarch64_retval.c (aarch64_return_value_location): Handle
+	DW_ATE_boolean.
+
+2014-06-18  Mark Wielaard  <mjw@redhat.com>
+
+	* libebl_CPU.h (dwarf_peel_type): Remove DW_TAG_mutable_type
+	handling.
+
+2014-06-17  Mark Wielaard  <mjw@redhat.com>
+
+	* arm_init.c (arm_init): Set func_addr_mask.
+
+2014-06-20  Petr Machata  <pmachata@redhat.com>
+
+	* alpha_retval.c (alpha_return_value_location): Call
+	dwarf_peeled_die_type instead of inlining equivalent code.
+	* arm_retval.c (arm_return_value_location): Likewise.
+	* i386_retval.c (i386_return_value_location): Likewise.
+	* ia64_retval.c (ia64_return_value_location): Likewise.
+	* ppc64_retval.c (ppc64_return_value_location): Likewise.
+	* ppc_retval.c (ppc_return_value_location): Likewise.
+	* s390_retval.c (s390_return_value_location): Likewise.
+	* sh_retval.c (sh_return_value_location): Likewise.
+	* sparc_retval.c (sparc_return_value_location): Likewise.
+	* tilegx_retval.c (tilegx_return_value_location): Likewise.
+	* x86_64_retval.c (x86_64_return_value_location): Likewise.
+
+2014-05-19  Mark Wielaard  <mjw@redhat.com>
+
+	* arm_init.c (arm_init): Hook check_reloc_target_type.
+	* arm_symbol.c (arm_check_reloc_target_type): New function.
+	* ia64_init.c (ia64_init): Hook check_reloc_target_type.
+	* ia64_symbol.c (ia64_check_reloc_target_type): New function.
+
+2014-04-22  Kurt Roeckx  <kurt@roeckx.be>
+
+	* i386_initreg.c: Make Linux only.
+	* x86_64_initreg.c: Make Linux only.
+
+2014-04-13  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am: Remove libelf and libdw definitions when MUDFLAP
+	is defined. Remove libmudflap from LINK line.
+
+2014-04-09  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (aarch64_SRCS): Add aarch64_initreg.c.
+	* aarch64_corenote.c (prstatus_regs): Mark pc_register.
+	* aarch64_init.c: Assign frame_nregs. Hook set_initial_registers_tid.
+	* aarch64_initreg: New file.
+
+2014-03-28  Jean Pihet  <jean.pihet@linaro.org>
+
+	* arm_initreg.c (arm_set_initial_registers_tid): Handle compat mode.
+	ARM compatible code running on AARCH64.
+
+2014-03-19  Mark Wielaard  <mjw@redhat.com>
+
+	* aarch64_reloc.def: AARCH64_ABS32 and AARCH64_ABS64 are also valid
+	in ET_REL.
+
+2014-01-30  Petr Machata  <pmachata@redhat.com>
+
+	* aarch64_regs.c (aarch64_register_info.regtype): Make this
+	variadic printf-like function.  Call one vsnprintf instead of two
+	snprintf's.
+	(regtyper, regtypen): Drop.
+	(aarch64_register_info): Adjust callers.
+
+2014-01-26  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (arm_SRCS): Add arm_initreg.c.
+	* arm_init.c (arm_init): Define frame_nregs and hook
+	set_initial_registers_tid.
+	* arm_initreg.c: New file.
+
+2014-01-25  Mark Wielaard  <mjw@redhat.com>
+
+	* arm_cfi.c (arm_abi_cfi): Restore SP (r13) from CFA.
+
+2014-01-24  Mark Wielaard  <mjw@redhat.com>
+
+	* arm_reloc.def: Update list.
+
+2014-01-22  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (aarch64_regs_no_Wformat): Removed.
+	* aarch64_regs.c (regtype): Add bool nr argument. snprintf arg
+	when nr is true.
+	(regtyper): New function.
+	(regtypen): Likewise.
+	(aarch64_register_info): Call either regtyper or regtypen not
+	regtype directly.
+
+2014-01-14  Mark Wielaard  <mjw@redhat.com>
+
+	* aarch64_symbol.c (aarch64_check_special_symbol): Check shdr is
+	not NULL before usage.
+
+2014-01-04  Mark Wielaard  <mjw@redhat.com>
+
+	* ppc64_symbol.c (ppc64_machine_flag_check): New function.
+	* ppc64_init.c (ppc64_init): Hook machine_flag_check.
+
+2014-01-03  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (aarch64_SRCS): Add aarch64_cfi.c.
+	* aarch64_cfi.c: New file.
+	* aarch64_init.c (aarch64_init): Hook abi_cfi.
+	* aarch64_regs.c (aarch64_register_info): Set *prefix to "".
+
+2013-12-19  Mark Wielaard  <mjw@redhat.com>
+
+	* aarch64_init.c (aarch64_init): Hook check_special_symbol.
+	* aarch64_symbol.c (aarch64_check_special_symbol): New function.
+
+2013-12-18  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (ppc64_SRCS): Add ppc64_resolve_sym.c.
+	* ppc64_resolve_sym.c: New file.
+	* ppc64_init.c: Hook resolve_sym_value and find function descriptor
+	table.
+
+2013-12-18  Mark Wielaard  <mjw@redhat.com>
+
+	* s390_initreg.c (s390_set_initial_registers_tid): Use union
+	to avoid type-punning when assigning a double to a Dwarf_Word.
+
+2013-12-18  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	unwinder: s390 and s390x
+	* Makefile.am (s390_SRCS): Add s390_initreg.c and s390_unwind.c.
+	* s390_corenote.c (prstatus_regs): Set PC_REGISTER.  Reindent all the
+	entries.
+	* s390_init.c (s390_init): Initialize frame_nregs,
+	set_initial_registers_tid, normalize_pc and unwind.
+	* s390_initreg.c: New file.
+	* s390_unwind.c: New file.
+
+2013-12-15  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	unwinder: ppc and ppc64
+	* Makefile.am (ppc_SRCS, ppc64_SRCS): Add ppc_initreg.c.
+	* ppc64_init.c (ppc64_init): Initialize also frame_nregs,
+	set_initial_registers_tid and dwarf_to_regno.
+	* ppc_corenote.c (PRSTATUS_REGSET_ITEMS) <nip>: Set PC_REGISTER.
+	* ppc_init.c (ppc64_init): Initialize also frame_nregs,
+	set_initial_registers_tid and dwarf_to_regno.
+	* ppc_initreg.c: New file.
+
+2013-11-25  Petr Machata  <pmachata@redhat.com>
+
+	* Makefile.am (modules): Add aarch64.
+	(libebl_pic): Add libebl_aarch64_pic.a.
+	(aarch64_SRCS): New variable.
+	(libebl_aarch64_pic_a_SOURCES): Likewise.
+	(am_libebl_aarch64_pic_a_OBJECTS): Likewise.
+	(aarch64_regs_no_Wformat): Likewise.
+	* aarch64_corenote.c, aarch64_init.c: New files.
+	* aarch64_regs.c, aarch64_reloc.def: Likewise.
+	* aarch64_retval.c, aarch64_symbol.c: Likewise.
+	* libebl_CPU.h (dwarf_peel_type): New function.
+	(dwarf_peeled_die_type): Likewise.
+
+2013-11-07  Jan Kratochvil  <jan.kratochvil@redhat.com>
+	    Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (i386_SRCS): Add i386_initreg.c.
+	(x86_64_SRCS): Add x86_64_initreg.c.
+	* i386_initreg.c: New file.
+	* i386_init.c (i386_init): Initialize frame_nregs and
+	set_initial_registers_tid.
+	* x86_64_initreg.c: New file.
+	* x86_64_init.c (x86_64_init): Initialize frame_nregs and
+	set_initial_registers_tid.
+
+2013-10-06  Mark Wielaard  <mjw@redhat.com>
+
+	* ppc_cfi.c (ppc_abi_cfi): Use DW_CFA_val_offset for reg1, not
+	DW_CFA_val_expression.
+
+2013-08-29  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (arm_SRCS): Add arm_cfi.c.
+	* arm_cfi.c: New file.
+	* arm_init.c (arm_init): Initialize abi_cfi.
+
+2013-08-27  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* Makefile.am (ppc_SRCS, ppc64_SRCS): Add ppc_cfi.c.
+	(s390_SRCS): Add s390_cfi.c.
+	* ppc64_init.c (ppc64_init): Initialize abi_cfi.
+	* ppc_cfi.c: New file.
+	* ppc_init.c (ppc_init): Initialize abi_cfi.
+	* s390_cfi.c: New file.
+	* s390_init.c (s390_init): Initialize abi_cfi.
+
+2013-08-28  Mark Wielaard  <mjw@redhat.com>
+
+	* arm_regs.c (arm_register_info): Set *prefix to "".
+	* ppc_regs.c (ppc_register_info): Likewise.
+	* sh_regs.c (sh_register_info): Likewise.
+
+2013-04-24  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am: Use AM_CPPFLAGS instead of INCLUDES.
+
+2013-02-06  Mark Wielaard  <mjw@redhat.com>
+
+	* libebl_CPU.h (DWARF_TAG_OR_RETURN): New macro.
+	* backends/alpha_retval.c (alpha_return_value_location): Use new
+	DWARF_TAG_OR_RETURN macro instead of dwarf_tag ().
+	* backends/arm_retval.c (arm_return_value_location): Likewise.
+	* backends/i386_retval.c (i386_return_value_location): Likewise.
+	* backends/ia64_retval.c (hfa_type): Likewise.
+	(ia64_return_value_location): Likewise.
+	* backends/ppc64_retval.c (ppc64_return_value_location): Likewise.
+	* backends/ppc_retval.c (ppc_return_value_location): Likewise.
+	* backends/s390_retval.c (s390_return_value_location): Likewise.
+	* backends/sh_retval.c (sh_return_value_location): Likewise.
+	* backends/sparc_retval.c (sparc_return_value_location): Likewise.
+	* backends/tilegx_retval.c (tilegx_return_value_location): Likewise.
+	* backends/x86_64_retval.c (x86_64_return_value_location): Likewise.
+
+2013-01-29  Jan Kratochvil  <jan.kratochvil@redhat.com>
+	    Roland McGrath <roland@hack.frob.com>
+
+	* Makefile.am (s390_SRCS): Add s390_corenote.c and s390x_corenote.c.
+	* linux-core-note.c (ALIGN_PR_REG): New definitions.
+	(struct EBLHOOK(prstatus)): Change field pr_reg to anonymous struct with
+	ALIGN_PR_REG.
+	(EXTRA_ITEMS): New macro.
+	* s390_corenote.c: New file.
+	* s390_init.c (s390x_core_note): New declaration.
+	(s390_init): Install s390x_core_note and s390_core_note.
+	* s390x_corenote.c: New file.
+
+2013-01-30  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* arm_corenote.c (vfp_items): Remove zero COUNT initializer.
+
+2012-10-12  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* linux-core-note.c (prstatus_items): Rename groups of sigpend and
+	sighold to signal2 and signal3.
+
+2012-09-24  Petr Machata  <pmachata@redhat.com>
+
+	* arm_corenote.c (vfp_items, vfp_regs): New const variables.
+	(EXTRA_NOTES): Use it for NT_ARM_VFP.
+	* linux-core-note.c (EXTRA_REGSET_ITEMS): New macro.
+
+2012-09-17  Petr Machata  <pmachata@redhat.com>
+
+	* arm_corenote.c (FPREGSET_SIZE): Change to 116.
+
+2012-08-22  Jeff Kenton  <jkenton@tilera.com>
+
+	* Makefile.am (modules): Add tilegx.
+	(libebl_pic): Add libebl_tilegx_pic.a.
+	(tilegx_SRCS): New variable.
+	(libebl_tilegx_pic_a_SOURCES): Likewise.
+	(am_libebl_tilegx_pic_a_OBJECTS): Likewise.
+	* tilegx_corenote.c: New file.
+	* tilegx_regs.c: New file.
+	* tilegx_reloc.def: New file.
+	* tilegx_init.c: New file.
+	* tilegx_retval.c: New file.
+	* tilegx_symbol.c: New file.
+
+2011-03-09  Mark Wielaard  <mjw@redhat.com>
+
+	* alpha_init.c (alpha_init): Initialize check_st_other_bits hook.
+	* alpha_symbol.c (alpha_check_st_other_bits): New function.
+
+2011-03-09  Roland McGrath  <roland@redhat.com>
+
+	* alpha_symbol.c (alpha_check_special_symbol): New function.
+	* alpha_init.c (alpha_init): Initialize hook.
+
+2010-11-08  Roland McGrath  <roland@redhat.com>
+
+	* i386_retval.c (loc_intreg): Typo fix.
+	Reported by Thorsten Glaser <tg@mirbsd.de>.
+
+2010-04-10  Matt Fleming  <matt@console-pimps.org>
+
+	* sh_corenote.c: New file.
+	* sh_regs.c: New file.
+	* sh_retval.c: New file.
+	* sh_symbol.c (sh_machine_flag_check): New function.
+	* Makefile.am (sh_SRCS): Add new files.
+	* sh_init.c (sh_init): Add initializers.
+
+2010-04-07  Roland McGrath  <roland@redhat.com>
+
+	* arm_reloc.def: Accept PC24 and ABS32 in EXEC|DYN too.
+
+2010-03-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* x86_64_reloc.def: Add entries for R_X86_64_SIZE32 and
+	R_X86_64_SIZE64.
+
+2010-02-18  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (libebl_%.so): Use multi-target pattern rule instead of
+	intermediate dependency file for libebl_%.map, working around apparent
+	make -j timing-sensitive bugs.
+
+2010-02-15  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am: Use config/eu.am for common stuff.
+
+2010-01-05  Roland McGrath  <roland@redhat.com>
+
+	* arm_retval.c (arm_return_value_location): Use dwarf_aggregate_size.
+	* ia64_retval.c (ia64_return_value_location): Likewise.
+	* ppc_retval.c (ppc_return_value_location): Likewise.
+	* ppc64_retval.c (ppc64_return_value_location): Likewise.
+	* sparc_retval.c (sparc_return_value_location): Likewise.
+
+	* ppc64_retval.c (ppc64_return_value_location):
+	Use vr2 for DW_TAG_array_type with DW_AT_GNU_vector.
+	* ppc_retval.c (ppc_return_value_location): Likewise.
+
+2010-01-04  Roland McGrath  <roland@redhat.com>
+
+	* linux-core-note.c (vmcoreinfo_items): New static const variable.
+	(EBLHOOK(core_note)): Update arguments for new protocol.
+	Validate the name as "CORE" or "LINUX" for known n_type cases.
+	Handle name "VMCOREINFO" n_type=0 with vmcoreinfo_items.
+	* i386_corenote.c (EXTRA_NOTES): Update parameter usage.
+	* x86_corenote.c (EXTRA_NOTES_IOPERM): Likewise.
+
+2009-09-10  Mark Wielaard  <mjw@redhat.com>
+
+	* sparc_retval.c: Fix license header.
+
+2009-08-07  Roland McGrath  <roland@redhat.com>
+
+	* x86_64_reloc.def: Add PC64, GOTOFF64, GOTPC32, GOTPC32_TLSDESC,
+	TLSDESC_CALL, TLSDESC.
+
+2009-07-08  Roland McGrath  <roland@redhat.com>
+
+	* x86_64_cfi.c (x86_64_abi_cfi): New file.
+	* Makefile.am (x86_64_SRCS): Add it.
+	* x86_64_init.c (x86_64_init): Add initializer.
+
+	* i386_cfi.c (i386_abi_cfi): New file.
+	* Makefile.am (i386_SRCS): Add it.
+	* i386_init.c (i386_init): Initialize abi_cfi hook.
+
+2009-06-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* i386_reloc.def: Add IRELATIVE entry.
+	* x86_64_reloc.def: Likewise.
+
+2009-04-16  Roland McGrath  <roland@redhat.com>
+
+	* arm_regs.c (arm_register_info): Handle VFP registers.
+
+	* i386_corenote.c (EXTRA_NOTES): NT_PRXFPREG -> NT_PRXFPREG
+
+2009-04-14  Roland McGrath  <roland@redhat.com>
+
+	* arm_retval.c: New file.
+	* arm_attrs.c: New file.
+	* Makefile.am (arm_SRCS): Add them.
+	* arm_symbol.c (arm_segment_type_name): New function.
+	(arm_section_type_name): New function.
+	(arm_machine_flag_check): New function.
+	* arm_init.c (arm_init): Initialize those hooks.
+
+	* arm_regs.c: New file.
+	* arm_corenote.c: New file.
+	* arm_auxv.c: New file.
+	* Makefile.am (arm_SRCS): Add them.
+	* arm_init.c (arm_init): Initialize core_note, register_info,
+	and auxv_info hooks.
+
+	* ia64_symbol.c (ia64_section_type_name): Remove "SHT_" prefixes.
+
+2009-04-01  Roland McGrath  <roland@redhat.com>
+
+	* sparc_reloc.def: Update table.
+	Data from Dave Miller <davem@davemloft.net>.
+
+2009-02-15  Roland McGrath  <roland@redhat.com>
+
+	* ppc_attrs.c (ppc_check_object_attribute): Handle tag
+	GNU_Power_ABI_Struct_Return.
+
+2008-10-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* i386_reloc.def: Fix entries for TLS_GOTDESC, TLS_DESC_CALL, and
+	TLS_DESC.
+
+2008-08-01  Roland McGrath  <roland@redhat.com>
+
+	* x86_corenote.c: New file.
+	* Makefile.am (noinst_HEADERS): Add it.
+	* i386_corenote.c: Include it, use EXTRA_NOTES_IOPERM in EXTRA_NOTES.
+	* x86_64_corenote.c: Likewise.
+
+	* linux-core-note.c (prstatus_items): Use 'B' instead of 'b'
+	for sigpend and sighold.
+
+2008-07-04  Roland McGrath  <roland@redhat.com>
+
+	* i386_syscall.c: New file.
+	* x86_64_syscall.c: New file.
+	* ppc_syscall.c: New file.
+	* Makefile.am (i386_SRCS, x86_64_SRCS, ppc_SRCS, ppc64_SRCS): Add them.
+	* i386_init.c (i386_init): Initialize syscall_abi hook.
+	* x86_64_init.c (x86_64_init): Likewise.
+	* ppc_init.c (ppc_init): Likewise.
+	* ppc64_init.c (ppc64_init): Likewise.
+
+	* ppc_corenote.c (PRSTATUS_REGSET_ITEMS): Add nip.
+	Fix offset calculation for 64-bit case.
+
+2008-04-04  Roland McGrath  <roland@redhat.com>
+
+	* alpha_symbol.c (alpha_check_special_section): New function.
+	* alpha_init.c (alpha_init): Initialize check_special_section hook.
+
+2008-03-31  Roland McGrath  <roland@redhat.com>
+
+	* sparc_symbol.c (sparc_symbol_type_name): New function.
+	(sparc_dynamic_tag_name): New function.
+	(sparc_dynamic_tag_check): New function.
+	* sparc_init.c (sparc_init): Initialize those hooks.
+
+	* sparc_symbol.c (sparc_check_special_section): New function.
+	* sparc_init.c (sparc_init): Initialize check_special_section hook.
+
+2008-02-20  Roland McGrath  <roland@redhat.com>
+
+	* ppc_attrs.c: New file.
+	* Makefile.am (ppc_SRCS, ppc64_SRCS): Add it.
+	* ppc_init.c (ppc_init): Initialize check_object_attribute hook.
+
+2008-02-14  Roland McGrath  <roland@redhat.com>
+
+	* alpha_auxv.c: New file.
+	* Makefile.am (alpha_SRCS): Add it.
+	* alpha_init.c (alpha_init): Initialize auxv_info hook.
+
+2008-02-08  Roland McGrath  <roland@redhat.com>
+
+	* ppc_corenote.c (spe_regs): New const variable.
+	(EXTRA_NOTES): Use it for NT_PPC_SPE.
+
+2008-01-02  Roland McGrath  <roland@redhat.com>
+
+	* i386_corenote.c (tls_items): New const table.
+	(tls_info): New function, uses it.
+	(EXTRA_NOTES): Use it to handle NT_386_TLS.
+
+2008-01-08  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Add x86-64 disassembler.
+	* x86_64_init.c (x86_64_init): Hook up disassembler.
+
+2007-12-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Add x86 disassembler.
+	* i386_init.c (i386_init): Hook up disassembler.
+
+2007-12-15  Roland McGrath  <roland@redhat.com>
+
+	* ppc_regs.c (ppc_register_info): Return "spefscr", not "spr512".
+
+2007-10-18  Roland McGrath  <roland@redhat.com>
+
+	* ppc_regs.c (ppc_register_info): Assign 67 to "vscr".
+	Return "vector" and 32 bits for vscr and vrsave.
+	* ppc_corenote.c (altivec_regs): New variable.
+	(EXTRA_NOTES): New macro, handle NT_PPC_VMX.
+
+	* linux-core-note.c (EXTRA_REGSET): New macro.
+	Remove NT_PRXFPREG case.  Instead, use EXTRA_NOTES if defined.
+	* i386_corenote.c (EXTRA_NOTES): Define it.
+
+2007-10-09  Roland McGrath  <roland@redhat.com>
+
+	* sparc_auxv.c: New file.
+	* Makefile.am (sparc_SRCS): Add it.
+	* sparc_init.c (sparc_init): Initialize auxv_info hook.
+
+2007-10-08  Roland McGrath  <roland@redhat.com>
+
+	* linux-core-note.c (TIMEVAL_FIELD): New macro.
+	(prstatus_items): Use it.
+	* sparc_corenote.c: New file.
+	* sparc64_corenote.c: New file.
+	* Makefile.am (sparc_SRCS): Add them.
+	* sparc_init.c (sparc_init): Initialize core_note hook.
+
+	* sparc_symbol.c (sparc_machine_flag_check): New function.
+	* sparc_init.c (sparc_init): Use it.
+
+2007-09-27  Roland McGrath  <roland@redhat.com>
+
+	* alpha_retval.c: Use dwarf_attr_integrate and dwarf_hasattr_integrate.
+	* i386_retval.c: Likewise.
+	* ia64_retval.c: Likewise.
+	* ppc64_retval.c: Likewise.
+	* ppc_retval.c: Likewise.
+	* s390_retval.c: Likewise.
+	* sparc_retval.c: Likewise.
+	* x86_64_retval.c: Likewise.
+
+2007-10-31  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: More dependencies for the libebl_* libraries.
+
+2007-08-23  Roland McGrath  <roland@redhat.com>
+
+	* x86_64_regs.c (x86_64_register_info): Put %rflags in "integer" set.
+
+2007-08-22  Roland McGrath  <roland@redhat.com>
+
+	* linux-core-note.c (prstatus_items): Add .group initializers.
+	(prpsinfo_items): Likewise.
+	* x86_64_corenote.c (PRSTATUS_REGSET_ITEMS): Likewise.
+	* i386_corenote.c (PRSTATUS_REGSET_ITEMS): Likewise.
+	* ppc_corenote.c (PRSTATUS_REGSET_ITEMS): Likewise.
+
+2007-08-20  Roland McGrath  <roland@redhat.com>
+
+	* ppc_symbol.c (ppc_check_special_symbol): For _GLOBAL_OFFSET_TABLE_
+	when DT_PPC_GOT is not found, anywhere in the section is valid.
+
+2007-08-19  Roland McGrath  <roland@redhat.com>
+
+	* i386_auxv.c: New file.
+	* Makefile.am (i386_SRCS, x86_64_SRCS): Add it.
+	* ppc_auxv.c: New file.
+	* Makefile.am (ppc_SRCS, ppc64_SRCS): Add it.
+	* i386_init.c (i386_init): Initialize auxv_info hook.
+	* x86_64_init.c (x86_64_init): Likewise.
+	* ppc_init.c (ppc_init): Likewise.
+	* ppc64_init.c (ppc64_init): Likewise.
+
+	* alpha_corenote.c: New file.
+	* Makefile.am (alpha_SRCS): Add it.
+	* alpha_init.c (alpha_init): Initialize core_note hook.
+
+	* ppc_corenote.c: New file.
+	* ppc64_corenote.c: New file.
+	* Makefile.am (ppc_SRCS, ppc64_SRCS): Add them.
+	* ppc_init.c (ppc_init): Initialize core_note hook.
+	* ppc64_init.c (ppc64_init): Likewise.
+
+	* linux-core-note.c: New file.
+	* Makefile.am (noinst_HEADERS): Add it.
+	* i386_corenote.c: Rewritten.
+	* x86_64_corenote.c: Likewise.
+
+2007-05-23  Roland McGrath  <roland@redhat.com>
+
+	* alpha_regs.c (alpha_register_info): fp -> s6
+
+2007-04-26  Roland McGrath  <roland@redhat.com>
+
+	* alpha_symbol.c (alpha_machine_section_flag_check): New function.
+	* alpha_init.c (alpha_init): Initialize hook.
+
+	* alpha_regs.c: New file.
+	* Makefile.am (alpha_SRCS): Add it.
+	* alpha_init.c (alpha_init): Initialize register_info hook.
+
+2007-04-22  Roland McGrath  <roland@redhat.com>
+
+	* ppc_regs.c (ppc_register_info): Use some names instead of sprNNN:
+	mq, xer, lr, ctr, dsisr, dar, dec, vrsave.
+	Set *BITS to 64 for FPU registers.
+
+	* i386_regs.c (i386_register_info): Set *BITS to 16 for fctrl, fstat.
+	* x86_64_regs.c (x86_64_register_info): Likewise for fcw, fsw.
+
+2007-04-01  Roland McGrath  <roland@redhat.com>
+
+	* x86_64_regs.c (x86_64_register_info): Add more registers from newer
+	ABI spec.
+
+2007-01-11  Roland McGrath  <roland@redhat.com>
+
+	* ia64_symbol.c (ia64_machine_section_flag_check): New function.
+	* ia64_init.c (ia64_init): Use it.
+
+	* ia64_symbol.c (ia64_section_type_name): Typo fix in string.
+
+2006-10-09  Roland McGrath  <roland@redhat.com>
+
+	* ia64_symbol.c (ia64_reloc_simple_type): Treat SECREL types as simple.
+
+2006-08-29  Roland McGrath  <roland@redhat.com>
+
+	* sparc_retval.c: New file.
+	* Makefile.am (sparc_SRCS): Add it.
+	* sparc_init.c (sparc_init): Initialize return_value_location hook.
+
+2006-08-22  Roland McGrath  <roland@redhat.com>
+
+	* i386_regs.c (i386_register_name): Renamed i386_register_info.
+	Take new args, yield more info.
+	* i386_init.c (i386_init): Update initializer.
+	* ia64_regs.c (ia64_register_name): Likewise.
+	* ia64_init.c (ia64_init): Likewise.
+	* ppc_regs.c (ppc_register_name): Likewise.
+	* ppc64_init.c (ppc64_init): Likewise.
+	* ppc_init.c (ppc_init): Likewise.
+	* s390_regs.c (s390_register_name): Likewise.
+	* s390_init.c (s390_init): Likewise.
+	* sparc_regs.c (sparc_register_name): Likewise.
+	* sparc_init.c (sparc_init): Likewise.
+	* x86_64_regs.c (x86_64_register_name): Likewise.
+	* x86_64_init.c (x86_64_init): Likewise.
+
+2006-08-08  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (%.os): Don't depend on %.o, since we don't actually
+	need static object for anything here.  This rule is the only source of
+	.deps/ files.
+
+2006-06-23  Stepan Kasal  <skasal@redhat.com>
+
+	* Makefile.am (PACKAGE_VERSION): Remove superfluous definition.
+
+2006-08-03  Roland McGrath  <roland@redhat.com>
+
+	* sparc_regs.c (sparc_register_name): List 32 FPU regs only for
+	EM_SPARC.  EM_SPARC32PLUS also has 64.
+
+2006-07-21  Roland McGrath  <roland@redhat.com>
+
+	* i386_regs.c (i386_register_name): Fix return value when using stpcpy.
+	* ppc_regs.c (ppc_register_name): Likewise.
+	* s390_regs.c (s390_register_name): Likewise.
+
+	* ia64_retval.c: New file.
+	* Makefile.am (ia64_SRCS): Add it.
+	* ia64_init.c (ia64_init): Install return_value_location hook.
+
+	* ia64_regs.c: New file.
+	* Makefile.am (ia64_SRCS): Add it.
+	* ia64_init.c (ia64_init): Install register_name hook.
+
+2006-07-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* alpha_init.c: Initialize sysvhash_entrysize.
+	* s390_init.c: Likewise.
+
+2006-07-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* common-reloc.c (relative_reloc_p): New function.
+	(init_reloc): Hook it up.
+	* ia64_reloc.def: Define NO_RELATIVE_RELOC.
+
+2006-06-13  Roland McGrath  <roland@redhat.com>
+
+	* ppc64_retval.c: Remove SVR4_STRUCT_RETURN braino.
+
+2006-06-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* common-reloc.c (none_reloc_p): New function.
+	(init_reloc): Hook it up.
+
+2006-02-22  Roland McGrath  <roland@redhat.com>
+
+	* ppc64_retval.c (SVR4_STRUCT_RETURN): New macro.
+	(ppc64_return_value_location): Use registers for aggregate conditional
+	on that.
+	* ppc_retval.c (SVR4_STRUCT_RETURN): New macro.
+	(ppc_return_value_location): Use registers for aggregate conditional
+	on that.
+
+2006-01-12  Roland McGrath  <roland@redhat.com>
+
+	* s390_retval.c: New file.
+	* Makefile.am (s390_SRCS): Add it.
+	* s390_init.c (s390_init): Install return_value_location hook.
+
+2006-01-11  Roland McGrath  <roland@redhat.com>
+
+	* s390_regs.c: New file.
+	* Makefile.am (s390_SRCS): Add it.
+	* s390_init.c (s390_init): Install register_name hook.
+
+	* s390_reloc.def: Update bits per
+	Martin Schwidefsky <schwidefsky@de.ibm.com>.
+
+2005-12-10  Ulrich Drepper
+
+	* common-reloc.c (R_NAME): Generate string correctly.
+
+2005-12-05  Roland McGrath  <roland@redhat.com>
+
+	* i386_regs.c (i386_register_name): Use a table for the first 8 regs.
+	* x86_64_regs.c (x86_64_register_name): Likewise.
+
+2005-11-25  Roland McGrath  <roland@redhat.com>
+
+	* i386_regs.c (i386_register_name): Return 0, not 1, for gaps.
+
+	* i386_regs.c: New file.
+	* ppc_regs.c: New file.
+	* sparc_regs.c: New file.
+	* x86_64_regs.c: New file.
+	* Makefile.am
+	(i386_SRCS, x86_64_SRCS, ppc_SRCS, ppc64_SRCS, sparc_SRCS): Add them.
+	* i386_init.c: Initialize register_name hook.
+	* ppc_init.c: Likewise.
+	* ppc64_init.c: Likewise.
+	* sparc_init.c: Likewise.
+	* x86_64_init.c: Likewise.
+
+2005-11-19  Roland McGrath  <roland@redhat.com>
+
+	* ppc64_reloc.def: REL30 -> ADDR30.
+
+2005-11-18  Roland McGrath  <roland@redhat.com>
+
+	* alpha_init.c: Use HOOK macro.
+	* arm_init.c: Likewise.
+	* i386_init.c: Likewise.
+	* ia64_init.c: Likewise.
+	* ppc64_init.c: Likewise.
+	* ppc_init.c: Likewise.
+	* s390_init.c: Likewise.
+	* sh_init.c: Likewise.
+	* sparc_init.c: Likewise.
+	* x86_64_init.c: Likewise.
+
+2005-11-17  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (uninstall): Don't try to remove $(pkgincludedir).
+	(CLEANFILES): Add libebl_$(m).so.
+
+	* ppc_reloc.def: Update bits per Alan Modra <amodra@bigpond.net.au>.
+	* ppc64_reloc.def: Likewise.
+
+2005-11-15  Roland McGrath  <roland@redhat.com>
+
+	* Contents moved here from ../libebl.
diff --git a/backends/Makefile.am b/backends/Makefile.am
new file mode 100644
index 0000000..2c62add
--- /dev/null
+++ b/backends/Makefile.am
@@ -0,0 +1,169 @@
+## Process this file with automake to create Makefile.in
+##
+## Copyright (C) 2000-2010, 2013, 2014 Red Hat, Inc.
+## Copyright (C) 2012 Tilera Corporation
+## This file is part of elfutils.
+##
+## This file is free software; you can redistribute it and/or modify
+## it under the terms of either
+##
+##   * the GNU Lesser General Public License as published by the Free
+##     Software Foundation; either version 3 of the License, or (at
+##     your option) any later version
+##
+## or
+##
+##   * 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
+##
+## or both in parallel, as here.
+##
+## elfutils 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 copies of the GNU General Public License and
+## the GNU Lesser General Public License along with this program.  If
+## not, see <http://www.gnu.org/licenses/>.
+include $(top_srcdir)/config/eu.am
+AM_CPPFLAGS += -I$(top_srcdir)/libebl -I$(top_srcdir)/libasm \
+	   -I$(top_srcdir)/libelf -I$(top_srcdir)/libdw
+
+
+modules = i386 sh x86_64 ia64 alpha arm aarch64 sparc ppc ppc64 s390 \
+	  tilegx m68k bpf
+libebl_pic = libebl_i386_pic.a libebl_sh_pic.a libebl_x86_64_pic.a    \
+	     libebl_ia64_pic.a libebl_alpha_pic.a libebl_arm_pic.a    \
+	     libebl_aarch64_pic.a libebl_sparc_pic.a libebl_ppc_pic.a \
+	     libebl_ppc64_pic.a libebl_s390_pic.a libebl_tilegx_pic.a \
+	     libebl_m68k_pic.a libebl_bpf_pic.a
+noinst_LIBRARIES = $(libebl_pic)
+noinst_DATA = $(libebl_pic:_pic.a=.so)
+
+
+libelf = ../libelf/libelf.so
+libdw = ../libdw/libdw.so
+libeu = ../lib/libeu.a
+
+i386_SRCS = i386_init.c i386_symbol.c i386_corenote.c i386_cfi.c \
+	    i386_retval.c i386_regs.c i386_auxv.c i386_syscall.c \
+	    i386_initreg.c i386_unwind.c
+cpu_i386 = ../libcpu/libcpu_i386.a
+libebl_i386_pic_a_SOURCES = $(i386_SRCS)
+am_libebl_i386_pic_a_OBJECTS = $(i386_SRCS:.c=.os)
+
+sh_SRCS = sh_init.c sh_symbol.c sh_corenote.c sh_regs.c sh_retval.c
+libebl_sh_pic_a_SOURCES = $(sh_SRCS)
+am_libebl_sh_pic_a_OBJECTS = $(sh_SRCS:.c=.os)
+
+x86_64_SRCS = x86_64_init.c x86_64_symbol.c x86_64_corenote.c x86_64_cfi.c \
+	      x86_64_retval.c x86_64_regs.c i386_auxv.c x86_64_syscall.c \
+	      x86_64_initreg.c x86_64_unwind.c x32_corenote.c
+cpu_x86_64 = ../libcpu/libcpu_x86_64.a
+libebl_x86_64_pic_a_SOURCES = $(x86_64_SRCS)
+am_libebl_x86_64_pic_a_OBJECTS = $(x86_64_SRCS:.c=.os)
+
+ia64_SRCS = ia64_init.c ia64_symbol.c ia64_regs.c ia64_retval.c
+libebl_ia64_pic_a_SOURCES = $(ia64_SRCS)
+am_libebl_ia64_pic_a_OBJECTS = $(ia64_SRCS:.c=.os)
+
+alpha_SRCS = alpha_init.c alpha_symbol.c alpha_retval.c alpha_regs.c \
+	     alpha_corenote.c alpha_auxv.c
+libebl_alpha_pic_a_SOURCES = $(alpha_SRCS)
+am_libebl_alpha_pic_a_OBJECTS = $(alpha_SRCS:.c=.os)
+
+arm_SRCS = arm_init.c arm_symbol.c arm_regs.c arm_corenote.c \
+	   arm_auxv.c arm_attrs.c arm_retval.c arm_cfi.c arm_initreg.c
+libebl_arm_pic_a_SOURCES = $(arm_SRCS)
+am_libebl_arm_pic_a_OBJECTS = $(arm_SRCS:.c=.os)
+
+aarch64_SRCS = aarch64_init.c aarch64_regs.c aarch64_symbol.c	\
+	       aarch64_corenote.c aarch64_retval.c aarch64_cfi.c \
+	       aarch64_initreg.c aarch64_unwind.c
+libebl_aarch64_pic_a_SOURCES = $(aarch64_SRCS)
+am_libebl_aarch64_pic_a_OBJECTS = $(aarch64_SRCS:.c=.os)
+
+sparc_SRCS = sparc_init.c sparc_symbol.c sparc_regs.c sparc_retval.c \
+	     sparc_corenote.c sparc64_corenote.c sparc_auxv.c sparc_attrs.c \
+             sparc_cfi.c sparc_initreg.c
+libebl_sparc_pic_a_SOURCES = $(sparc_SRCS)
+am_libebl_sparc_pic_a_OBJECTS = $(sparc_SRCS:.c=.os)
+
+ppc_SRCS = ppc_init.c ppc_symbol.c ppc_retval.c ppc_regs.c \
+	   ppc_corenote.c ppc_auxv.c ppc_attrs.c ppc_syscall.c \
+	   ppc_cfi.c ppc_initreg.c
+libebl_ppc_pic_a_SOURCES = $(ppc_SRCS)
+am_libebl_ppc_pic_a_OBJECTS = $(ppc_SRCS:.c=.os)
+
+ppc64_SRCS = ppc64_init.c ppc64_symbol.c ppc64_retval.c \
+	     ppc64_corenote.c ppc_regs.c ppc_auxv.c ppc_attrs.c ppc_syscall.c \
+	     ppc_cfi.c ppc_initreg.c ppc64_unwind.c ppc64_resolve_sym.c
+libebl_ppc64_pic_a_SOURCES = $(ppc64_SRCS)
+am_libebl_ppc64_pic_a_OBJECTS = $(ppc64_SRCS:.c=.os)
+
+s390_SRCS = s390_init.c s390_symbol.c s390_regs.c s390_retval.c \
+	    s390_corenote.c s390x_corenote.c s390_cfi.c s390_initreg.c \
+	    s390_unwind.c
+libebl_s390_pic_a_SOURCES = $(s390_SRCS)
+am_libebl_s390_pic_a_OBJECTS = $(s390_SRCS:.c=.os)
+
+tilegx_SRCS = tilegx_init.c tilegx_symbol.c tilegx_regs.c \
+              tilegx_retval.c tilegx_corenote.c
+libebl_tilegx_pic_a_SOURCES = $(tilegx_SRCS)
+am_libebl_tilegx_pic_a_OBJECTS = $(tilegx_SRCS:.c=.os)
+
+m68k_SRCS = m68k_init.c m68k_symbol.c m68k_regs.c \
+	    m68k_retval.c m68k_corenote.c
+libebl_m68k_pic_a_SOURCES = $(m68k_SRCS)
+am_libebl_m68k_pic_a_OBJECTS = $(m68k_SRCS:.c=.os)
+
+# m68k prstatus core notes are described by a packed structure
+# which has not naturally aligned fields. Since we don't access
+# these fields directly, but take their offset to be used later
+# to extract the data through elfxx_xlatetom/memmove, this isn't
+# an issue.
+m68k_corenote_no_Wpacked_not_aligned = yes
+
+bpf_SRCS = bpf_init.c bpf_regs.c
+cpu_bpf = ../libcpu/libcpu_bpf.a
+libebl_bpf_pic_a_SOURCES = $(bpf_SRCS)
+am_libebl_bpf_pic_a_OBJECTS = $(bpf_SRCS:.c=.os)
+
+
+libebl_%.so libebl_%.map: libebl_%_pic.a $(libelf) $(libdw) $(libeu)
+	@rm -f $(@:.so=.map)
+	$(AM_V_at)echo 'ELFUTILS_$(PACKAGE_VERSION) { global: $*_init; local: *; };' \
+	  > $(@:.so=.map)
+	$(AM_V_CCLD)$(LINK) $(dso_LDFLAGS) -o $(@:.map=.so) \
+		-Wl,--whole-archive $< $(cpu_$*) -Wl,--no-whole-archive \
+		-Wl,--version-script,$(@:.so=.map),--no-undefined \
+		-Wl,--as-needed $(libelf) $(libdw) $(libeu)
+	@$(textrel_check)
+
+libebl_i386.so: $(cpu_i386)
+libebl_x86_64.so: $(cpu_x86_64)
+libebl_bpf.so: $(cpu_bpf)
+
+install: install-am install-ebl-modules
+install-ebl-modules:
+	$(mkinstalldirs) $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)
+	for m in $(modules); do \
+	  $(INSTALL_PROGRAM) libebl_$${m}.so $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)/libebl_$${m}-$(PACKAGE_VERSION).so; \
+	  ln -fs libebl_$${m}-$(PACKAGE_VERSION).so $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)/libebl_$${m}.so; \
+	done
+
+uninstall: uninstall-am
+	for m in $(modules); do \
+	  rm -f $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)/libebl_$${m}-$(PACKAGE_VERSION).so; \
+	  rm -f $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)/libebl_$${m}.so; \
+	done
+	rmdir --ignore-fail-on-non-empty $(DESTDIR)$(libdir)/$(LIBEBL_SUBDIR)
+
+noinst_HEADERS = libebl_CPU.h common-reloc.c linux-core-note.c x86_corenote.c
+EXTRA_DIST = $(foreach m,$(modules),$($(m)_SRCS)) $(modules:=_reloc.def)
+
+CLEANFILES += $(foreach m,$(modules),\
+			libebl_$(m).map libebl_$(m).so \
+			$(am_libebl_$(m)_pic_a_OBJECTS))
diff --git a/backends/aarch64_cfi.c b/backends/aarch64_cfi.c
new file mode 100644
index 0000000..acbb9b6
--- /dev/null
+++ b/backends/aarch64_cfi.c
@@ -0,0 +1,82 @@
+/* arm ABI-specified defaults for DWARF CFI.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#define BACKEND aarch64_
+#include "libebl_CPU.h"
+
+
+/* ABI-specified state of DWARF CFI based on:
+
+   "DWARF for the ARM 64 bit architecture (AArch64) 1.0"
+http://infocenter.arm.com/help/topic/com.arm.doc.ihi0057b/IHI0057B_aadwarf64.pdf
+
+   "Procedure Call Standard for the ARM 64 bit Architecture 1.0"
+http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
+*/
+
+int
+aarch64_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info)
+{
+  static const uint8_t abi_cfi[] =
+    {
+      /* The initial Canonical Frame Address is the value of the
+         Stack Pointer (r31) as setup in the previous frame. */
+      DW_CFA_def_cfa, ULEB128_7 (30), ULEB128_7 (0),
+
+#define SV(n) DW_CFA_same_value, ULEB128_7 (n)
+      /* Callee-saved regs r19-r28.  */
+      SV (19), SV (20), SV (21), SV (22), SV (23),
+      SV (24), SV (25), SV (26), SV (27), SV (28),
+
+      /* The Frame Pointer (FP, r29) and Link Register (LR, r30).  */
+      SV (29), SV (30),
+
+      /* Callee-saved fpregs v8-v15.  v0 == 64.  */
+      SV (72), SV (73), SV (74), SV (75),
+      SV (76), SV (77), SV (78), SV (79),
+#undef SV
+
+      /* XXX Note: registers intentionally unused by the program,
+	 for example as a consequence of the procedure call standard
+	 should be initialized as if by DW_CFA_same_value.  */
+    };
+
+  abi_info->initial_instructions = abi_cfi;
+  abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
+  abi_info->data_alignment_factor = -4;
+
+  abi_info->return_address_register = 30; /* lr.  */
+
+  return 0;
+}
diff --git a/backends/aarch64_corenote.c b/backends/aarch64_corenote.c
new file mode 100644
index 0000000..905a4b8
--- /dev/null
+++ b/backends/aarch64_corenote.c
@@ -0,0 +1,172 @@
+/* AArch64 specific core note handling.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#define BACKEND aarch64_
+#include "libebl_CPU.h"
+
+#define	ULONG			uint64_t
+#define PID_T			int32_t
+#define	UID_T			uint32_t
+#define	GID_T			uint32_t
+#define ALIGN_ULONG		8
+#define ALIGN_PID_T		4
+#define ALIGN_UID_T		4
+#define ALIGN_GID_T		4
+#define TYPE_ULONG		ELF_T_XWORD
+#define TYPE_PID_T		ELF_T_SWORD
+#define TYPE_UID_T		ELF_T_WORD
+#define TYPE_GID_T		ELF_T_WORD
+
+#define PRSTATUS_REGS_SIZE	(34 * 8)
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+    { .offset = 0, .regno = 0, .count = 32, .bits = 64 }, /* x0..x30, sp */
+  };
+
+#define PRSTATUS_REGSET_ITEMS						\
+  {									\
+    .name = "pc", .type = ELF_T_XWORD, .format = 'x',			\
+    .offset = (offsetof (struct EBLHOOK(prstatus), pr_reg)		\
+	       + PRSTATUS_REGS_SIZE - 16),				\
+    .group = "register",						\
+    .pc_register = true							\
+  },									\
+  {									\
+    .name = "pstate", .type = ELF_T_XWORD, .format = 'x',		\
+    .offset = (offsetof (struct EBLHOOK(prstatus), pr_reg)		\
+	       + PRSTATUS_REGS_SIZE - 8),				\
+    .group = "register"							\
+  }
+
+static const Ebl_Register_Location aarch64_fpregset_regs[] =
+  {
+    { .offset = 0, .regno = 64, .count = 32, .bits = 128 }, /* v0..v31 */
+  };
+
+static const Ebl_Core_Item aarch64_fpregset_items[] =
+  {
+    {
+      .name = "fpsr", .type = ELF_T_WORD, .format = 'x',
+      .offset = 512, .group = "register"
+    },
+    {
+      .name = "fpcr", .type = ELF_T_WORD, .format = 'x',
+      .offset = 516, .group = "register"
+    }
+  };
+
+static const Ebl_Core_Item aarch64_tls_items[] =
+  {
+    {
+      .name = "tls", .type = ELF_T_XWORD, .format = 'x',
+      .offset = 0, .group = "register"
+    }
+  };
+
+static const Ebl_Core_Item aarch64_syscall_items [] =
+  {
+    {
+      .name = "syscall", .type = ELF_T_WORD, .format = 'x',
+      .offset = 0, .group = "register"
+    }
+  };
+
+#define AARCH64_HWBP_REG(KIND, N)					\
+    {									\
+      .name = "DBG" KIND "VR" #N "_EL1", .type = ELF_T_XWORD, .format = 'x', \
+      .offset = 8 + N * 16, .group = "register"				\
+    },									\
+    {									\
+      .name = "DBG" KIND "CR" #N "_EL1", .type = ELF_T_WORD, .format = 'x', \
+      .offset = 16 + N * 16, .group = "register"			\
+    }
+
+#define AARCH64_BP_WP_GROUP(KIND, NAME)					\
+  static const Ebl_Core_Item NAME[] =					\
+    {									\
+      {									\
+	.name = "dbg_info", .type = ELF_T_WORD, .format = 'x',		\
+	.offset = 0, .group = "control"					\
+      },								\
+      /* N.B.: 4 bytes of padding here.  */				\
+									\
+      AARCH64_HWBP_REG(KIND, 0),					\
+      AARCH64_HWBP_REG(KIND, 1),					\
+      AARCH64_HWBP_REG(KIND, 2),					\
+      AARCH64_HWBP_REG(KIND, 3),					\
+      AARCH64_HWBP_REG(KIND, 4),					\
+      AARCH64_HWBP_REG(KIND, 5),					\
+      AARCH64_HWBP_REG(KIND, 6),					\
+      AARCH64_HWBP_REG(KIND, 7),					\
+      AARCH64_HWBP_REG(KIND, 8),					\
+      AARCH64_HWBP_REG(KIND, 9),					\
+      AARCH64_HWBP_REG(KIND, 10),					\
+      AARCH64_HWBP_REG(KIND, 11),					\
+      AARCH64_HWBP_REG(KIND, 12),					\
+      AARCH64_HWBP_REG(KIND, 13),					\
+      AARCH64_HWBP_REG(KIND, 14),					\
+      AARCH64_HWBP_REG(KIND, 15),					\
+									\
+      /* The DBGBVR+DBGBCR pair only takes 12 bytes.  There are 4 bytes	\
+	 of padding at the end of each pair.  The item formatter in	\
+	 readelf can skip those, but the missing 4 bytes at the end of	\
+	 the whole block cause it to assume the whole item bunch	\
+	 repeats, so it loops around to read more.  Insert an explicit	\
+	 (but invisible) padding word.  */				\
+      {									\
+	.name = "", .type = ELF_T_WORD, .format = 'h',			\
+	.offset = 260, .group = "register"				\
+      }									\
+    }
+
+AARCH64_BP_WP_GROUP ("B", aarch64_hw_bp_items);
+AARCH64_BP_WP_GROUP ("W", aarch64_hw_wp_items);
+
+#undef AARCH64_BP_WP_GROUP
+#undef AARCH64_HWBP_REG
+
+#define EXTRA_NOTES							\
+  EXTRA_REGSET_ITEMS (NT_FPREGSET, 528,					\
+		      aarch64_fpregset_regs, aarch64_fpregset_items)	\
+  EXTRA_ITEMS (NT_ARM_TLS, 8, aarch64_tls_items)			\
+  EXTRA_ITEMS (NT_ARM_HW_BREAK, 264, aarch64_hw_bp_items)		\
+  EXTRA_ITEMS (NT_ARM_HW_WATCH, 264, aarch64_hw_wp_items)		\
+  EXTRA_ITEMS (NT_ARM_SYSTEM_CALL, 4, aarch64_syscall_items)
+
+#include "linux-core-note.c"
diff --git a/backends/aarch64_init.c b/backends/aarch64_init.c
new file mode 100644
index 0000000..fad923f
--- /dev/null
+++ b/backends/aarch64_init.c
@@ -0,0 +1,70 @@
+/* Initialization of AArch64 specific backend library.
+   Copyright (C) 2013, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		aarch64_
+#define RELOC_PREFIX	R_AARCH64_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on aarch64_reloc.def.  */
+#include "common-reloc.c"
+
+
+const char *
+aarch64_init (Elf *elf __attribute__ ((unused)),
+	      GElf_Half machine __attribute__ ((unused)),
+	      Ebl *eh,
+	      size_t ehlen)
+{
+  /* Check whether the Elf_BH object has a sufficent size.  */
+  if (ehlen < sizeof (Ebl))
+    return NULL;
+
+  /* We handle it.  */
+  eh->name = "AARCH64";
+  aarch64_init_reloc (eh);
+  HOOK (eh, register_info);
+  HOOK (eh, core_note);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, return_value_location);
+  HOOK (eh, check_special_symbol);
+  HOOK (eh, data_marker_symbol);
+  HOOK (eh, abi_cfi);
+
+  /* X0-X30 (31 regs) + SP + 1 Reserved + ELR, 30 Reserved regs (34-43)
+     + V0-V31 (32 regs, least significant 64 bits only)
+     + ALT_FRAME_RETURN_COLUMN (used when LR isn't used) = 97 DWARF regs. */
+  eh->frame_nregs = 97;
+  HOOK (eh, set_initial_registers_tid);
+  HOOK (eh, unwind);
+
+  return MODVERSION;
+}
diff --git a/backends/aarch64_initreg.c b/backends/aarch64_initreg.c
new file mode 100644
index 0000000..daf6f37
--- /dev/null
+++ b/backends/aarch64_initreg.c
@@ -0,0 +1,92 @@
+/* Fetch live process registers from TID.
+   Copyright (C) 2013, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "system.h"
+#include <assert.h>
+#if defined(__aarch64__) && defined(__linux__)
+# include <linux/uio.h>
+# include <sys/user.h>
+# include <sys/ptrace.h>
+/* Deal with old glibc defining user_pt_regs instead of user_regs_struct.  */
+# ifndef HAVE_SYS_USER_REGS
+#  define user_regs_struct user_pt_regs
+#  define user_fpsimd_struct user_fpsimd_state
+# endif
+#endif
+
+#define BACKEND aarch64_
+#include "libebl_CPU.h"
+
+bool
+aarch64_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
+			  ebl_tid_registers_t *setfunc __attribute__ ((unused)),
+				void *arg __attribute__ ((unused)))
+{
+#if !defined(__aarch64__) || !defined(__linux__)
+  return false;
+#else /* __aarch64__ */
+
+  /* General registers.  */
+  struct user_regs_struct gregs;
+  struct iovec iovec;
+  iovec.iov_base = &gregs;
+  iovec.iov_len = sizeof (gregs);
+  if (ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, &iovec) != 0)
+    return false;
+
+  /* X0..X30 plus SP.  */
+  if (! setfunc (0, 32, (Dwarf_Word *) &gregs.regs[0], arg))
+    return false;
+
+  /* PC.  */
+  if (! setfunc (-1, 1, (Dwarf_Word *) &gregs.pc, arg))
+    return false;
+
+  /* ELR cannot be found.  */
+
+  /* FP registers (only 64bits are used).  */
+  struct user_fpsimd_struct fregs;
+  iovec.iov_base = &fregs;
+  iovec.iov_len = sizeof (fregs);
+  if (ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, &iovec) != 0)
+    return false;
+
+  Dwarf_Word dwarf_fregs[32];
+  for (int r = 0; r < 32; r++)
+    dwarf_fregs[r] = fregs.vregs[r] & 0xFFFFFFFF;
+
+  if (! setfunc (64, 32, dwarf_fregs, arg))
+    return false;
+
+  return true;
+#endif /* __aarch64__ */
+}
diff --git a/backends/aarch64_regs.c b/backends/aarch64_regs.c
new file mode 100644
index 0000000..23014bf
--- /dev/null
+++ b/backends/aarch64_regs.c
@@ -0,0 +1,108 @@
+/* Register names and numbers for AArch64 DWARF.
+   Copyright (C) 2013, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <dwarf.h>
+#include <stdarg.h>
+
+#define BACKEND aarch64_
+#include "libebl_CPU.h"
+
+__attribute__ ((format (printf, 7, 8)))
+static ssize_t
+do_regtype (const char *setname, int type,
+           const char **setnamep, int *typep,
+           char *name, size_t namelen, const char *fmt, ...)
+{
+  *setnamep = setname;
+  *typep = type;
+
+  va_list ap;
+  va_start (ap, fmt);
+  int s = vsnprintf (name, namelen, fmt, ap);
+  va_end(ap);
+
+  if (s < 0 || (unsigned) s >= namelen)
+    return -1;
+  return s + 1;
+}
+
+ssize_t
+aarch64_register_info (Ebl *ebl __attribute__ ((unused)),
+		       int regno, char *name, size_t namelen,
+		       const char **prefix, const char **setnamep,
+		       int *bits, int *typep)
+{
+  if (name == NULL)
+    return 128;
+
+
+  *prefix = "";
+  *bits = 64;
+
+#define regtype(setname, type, ...) \
+    do_regtype(setname, type, setnamep, typep, name, namelen, __VA_ARGS__)
+
+  switch (regno)
+    {
+    case 0 ... 30:
+      return regtype ("integer", DW_ATE_signed, "x%d", regno);
+
+    case 31:
+      return regtype ("integer", DW_ATE_address, "sp");
+
+    case 32:
+      return 0;
+
+    case 33:
+      return regtype ("integer", DW_ATE_address, "elr");
+
+    case 34 ... 63:
+      return 0;
+
+    case 64 ... 95:
+      /* FP/SIMD register file supports a variety of data types--it
+	 can be thought of as a register holding a single integer or
+	 floating-point value, or a vector of 8-, 16-, 32- or 64-bit
+	 integers.  128-bit quad-word is the only singular value that
+	 covers the whole register, so mark the register thus.  */
+      *bits = 128;
+      return regtype ("FP/SIMD", DW_ATE_unsigned, "v%d", regno - 64);
+
+    case 96 ... 127:
+      return 0;
+
+    default:
+      return -1;
+    }
+}
diff --git a/backends/aarch64_reloc.def b/backends/aarch64_reloc.def
new file mode 100644
index 0000000..f894687
--- /dev/null
+++ b/backends/aarch64_reloc.def
@@ -0,0 +1,157 @@
+/* List the relocation types for AArch64.  -*- C -*-
+   Copyright (C) 2013, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (ABS64,		REL|EXEC|DYN)
+RELOC_TYPE (ABS32,		REL|EXEC|DYN)
+RELOC_TYPE (COPY,		EXEC|DYN)
+RELOC_TYPE (GLOB_DAT,		EXEC|DYN)
+RELOC_TYPE (JUMP_SLOT,		EXEC|DYN)
+RELOC_TYPE (RELATIVE,		EXEC|DYN)
+RELOC_TYPE (TLS_DTPMOD,		EXEC|DYN)
+RELOC_TYPE (TLS_DTPREL,		EXEC|DYN)
+RELOC_TYPE (TLS_TPREL,		EXEC|DYN)
+RELOC_TYPE (TLSDESC,		EXEC|DYN)
+
+/* R_AARCH64_NONE records that the section containing the place to be
+   relocated depends on the section defining the symbol mentioned in
+   the relocation directive[.]  (ARM IHI 0056B).  */
+RELOC_TYPE (NONE,		REL)
+
+RELOC_TYPE (ABS16,		REL)
+RELOC_TYPE (PREL64,		REL)
+RELOC_TYPE (PREL32,		REL)
+RELOC_TYPE (PREL16,		REL)
+RELOC_TYPE (MOVW_UABS_G0,	REL)
+RELOC_TYPE (MOVW_UABS_G0_NC,	REL)
+RELOC_TYPE (MOVW_UABS_G1,	REL)
+RELOC_TYPE (MOVW_UABS_G1_NC,	REL)
+RELOC_TYPE (MOVW_UABS_G2,	REL)
+RELOC_TYPE (MOVW_UABS_G2_NC,	REL)
+RELOC_TYPE (MOVW_UABS_G3,	REL)
+RELOC_TYPE (MOVW_SABS_G0,	REL)
+RELOC_TYPE (MOVW_SABS_G1,	REL)
+RELOC_TYPE (MOVW_SABS_G2,	REL)
+RELOC_TYPE (LD_PREL_LO19,	REL)
+RELOC_TYPE (ADR_PREL_LO21,	REL)
+RELOC_TYPE (ADR_PREL_PG_HI21,	REL)
+RELOC_TYPE (ADR_PREL_PG_HI21_NC, REL)
+RELOC_TYPE (ADD_ABS_LO12_NC,	REL)
+RELOC_TYPE (LDST8_ABS_LO12_NC,	REL)
+RELOC_TYPE (LDST16_ABS_LO12_NC,	REL)
+RELOC_TYPE (LDST32_ABS_LO12_NC,	REL)
+RELOC_TYPE (LDST64_ABS_LO12_NC,	REL)
+RELOC_TYPE (LDST128_ABS_LO12_NC, REL)
+RELOC_TYPE (TSTBR14,		REL)
+RELOC_TYPE (CONDBR19,		REL)
+RELOC_TYPE (JUMP26,		REL)
+RELOC_TYPE (CALL26,		REL)
+RELOC_TYPE (MOVW_PREL_G0,	REL)
+RELOC_TYPE (MOVW_PREL_G0_NC,	REL)
+RELOC_TYPE (MOVW_PREL_G1,	REL)
+RELOC_TYPE (MOVW_PREL_G1_NC,	REL)
+RELOC_TYPE (MOVW_PREL_G2,	REL)
+RELOC_TYPE (MOVW_PREL_G2_NC,	REL)
+RELOC_TYPE (MOVW_PREL_G3,	REL)
+RELOC_TYPE (MOVW_GOTOFF_G0,	REL)
+RELOC_TYPE (MOVW_GOTOFF_G0_NC,	REL)
+RELOC_TYPE (MOVW_GOTOFF_G1,	REL)
+RELOC_TYPE (MOVW_GOTOFF_G1_NC,	REL)
+RELOC_TYPE (MOVW_GOTOFF_G2,	REL)
+RELOC_TYPE (MOVW_GOTOFF_G2_NC,	REL)
+RELOC_TYPE (MOVW_GOTOFF_G3,	REL)
+RELOC_TYPE (GOTREL64,		REL)
+RELOC_TYPE (GOTREL32,		REL)
+RELOC_TYPE (GOT_LD_PREL19,	REL)
+RELOC_TYPE (LD64_GOTOFF_LO15,	REL)
+RELOC_TYPE (ADR_GOT_PAGE,	REL)
+RELOC_TYPE (LD64_GOT_LO12_NC,	REL)
+RELOC_TYPE (LD64_GOTPAGE_LO15,	REL)
+RELOC_TYPE (TLSGD_ADR_PREL21,	REL)
+RELOC_TYPE (TLSGD_ADR_PAGE21,	REL)
+RELOC_TYPE (TLSGD_ADD_LO12_NC,	REL)
+RELOC_TYPE (TLSGD_MOVW_G1,	REL)
+RELOC_TYPE (TLSGD_MOVW_G0_NC,	REL)
+RELOC_TYPE (TLSLD_ADR_PREL21,	REL)
+RELOC_TYPE (TLSLD_ADR_PAGE21,	REL)
+RELOC_TYPE (TLSLD_ADD_LO12_NC,	REL)
+RELOC_TYPE (TLSLD_MOVW_G1,	REL)
+RELOC_TYPE (TLSLD_MOVW_G0_NC,	REL)
+RELOC_TYPE (TLSLD_LD_PREL19,	REL)
+RELOC_TYPE (TLSLD_MOVW_DTPREL_G2,	REL)
+RELOC_TYPE (TLSLD_MOVW_DTPREL_G1,	REL)
+RELOC_TYPE (TLSLD_MOVW_DTPREL_G1_NC,	REL)
+RELOC_TYPE (TLSLD_MOVW_DTPREL_G0,	REL)
+RELOC_TYPE (TLSLD_MOVW_DTPREL_G0_NC,	REL)
+RELOC_TYPE (TLSLD_ADD_DTPREL_HI12,	REL)
+RELOC_TYPE (TLSLD_ADD_DTPREL_LO12,	REL)
+RELOC_TYPE (TLSLD_ADD_DTPREL_LO12_NC,	REL)
+RELOC_TYPE (TLSLD_LDST8_DTPREL_LO12,	REL)
+RELOC_TYPE (TLSLD_LDST8_DTPREL_LO12_NC,	REL)
+RELOC_TYPE (TLSLD_LDST16_DTPREL_LO12,	REL)
+RELOC_TYPE (TLSLD_LDST16_DTPREL_LO12_NC, REL)
+RELOC_TYPE (TLSLD_LDST32_DTPREL_LO12,	REL)
+RELOC_TYPE (TLSLD_LDST32_DTPREL_LO12_NC, REL)
+RELOC_TYPE (TLSLD_LDST64_DTPREL_LO12,	REL)
+RELOC_TYPE (TLSLD_LDST64_DTPREL_LO12_NC, REL)
+RELOC_TYPE (TLSLD_LDST128_DTPREL_LO12,	REL)
+RELOC_TYPE (TLSLD_LDST128_DTPREL_LO12_NC, REL)
+RELOC_TYPE (TLSIE_MOVW_GOTTPREL_G1,	REL)
+RELOC_TYPE (TLSIE_MOVW_GOTTPREL_G0_NC,	REL)
+RELOC_TYPE (TLSIE_ADR_GOTTPREL_PAGE21,	REL)
+RELOC_TYPE (TLSIE_LD64_GOTTPREL_LO12_NC, REL)
+RELOC_TYPE (TLSIE_LD_GOTTPREL_PREL19,	REL)
+RELOC_TYPE (TLSLE_MOVW_TPREL_G2,	REL)
+RELOC_TYPE (TLSLE_MOVW_TPREL_G1,	REL)
+RELOC_TYPE (TLSLE_MOVW_TPREL_G1_NC,	REL)
+RELOC_TYPE (TLSLE_MOVW_TPREL_G0,	REL)
+RELOC_TYPE (TLSLE_MOVW_TPREL_G0_NC,	REL)
+RELOC_TYPE (TLSLE_ADD_TPREL_HI12,	REL)
+RELOC_TYPE (TLSLE_ADD_TPREL_LO12,	REL)
+RELOC_TYPE (TLSLE_ADD_TPREL_LO12_NC,	REL)
+RELOC_TYPE (TLSLE_LDST8_TPREL_LO12,	REL)
+RELOC_TYPE (TLSLE_LDST8_TPREL_LO12_NC,	REL)
+RELOC_TYPE (TLSLE_LDST16_TPREL_LO12,	REL)
+RELOC_TYPE (TLSLE_LDST16_TPREL_LO12_NC,	REL)
+RELOC_TYPE (TLSLE_LDST32_TPREL_LO12,	REL)
+RELOC_TYPE (TLSLE_LDST32_TPREL_LO12_NC,	REL)
+RELOC_TYPE (TLSLE_LDST64_TPREL_LO12,	REL)
+RELOC_TYPE (TLSLE_LDST64_TPREL_LO12_NC,	REL)
+RELOC_TYPE (TLSLE_LDST128_TPREL_LO12,	REL)
+RELOC_TYPE (TLSLE_LDST128_TPREL_LO12_NC, REL)
+RELOC_TYPE (TLSDESC_LD_PREL19,		REL)
+RELOC_TYPE (TLSDESC_ADR_PREL21,		REL)
+RELOC_TYPE (TLSDESC_ADR_PAGE21,		REL)
+RELOC_TYPE (TLSDESC_LD64_LO12,		REL)
+RELOC_TYPE (TLSDESC_ADD_LO12,		REL)
+RELOC_TYPE (TLSDESC_OFF_G1,		REL)
+RELOC_TYPE (TLSDESC_OFF_G0_NC,		REL)
+RELOC_TYPE (TLSDESC_LDR,		REL)
+RELOC_TYPE (TLSDESC_ADD,		REL)
+RELOC_TYPE (TLSDESC_CALL,		REL)
diff --git a/backends/aarch64_retval.c b/backends/aarch64_retval.c
new file mode 100644
index 0000000..1308340
--- /dev/null
+++ b/backends/aarch64_retval.c
@@ -0,0 +1,376 @@
+/* Function return value location for Linux/AArch64 ABI.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <inttypes.h>
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND aarch64_
+#include "libebl_CPU.h"
+
+static int
+skip_until (Dwarf_Die *child, int tag)
+{
+  int i;
+  while (DWARF_TAG_OR_RETURN (child) != tag)
+    if ((i = dwarf_siblingof (child, child)) != 0)
+      /* If there are no members, then this is not a HFA.  Errors
+	 are propagated.  */
+      return i;
+  return 0;
+}
+
+static int
+dwarf_bytesize_aux (Dwarf_Die *die, Dwarf_Word *sizep)
+{
+  int bits;
+  if (((bits = 8 * dwarf_bytesize (die)) < 0
+       && (bits = dwarf_bitsize (die)) < 0)
+      || bits % 8 != 0)
+    return -1;
+
+  *sizep = bits / 8;
+  return 0;
+}
+
+/* HFA (Homogeneous Floating-point Aggregate) is an aggregate type
+   whose members are all of the same floating-point type, which is
+   then base type of this HFA.  Instead of being floating-point types
+   directly, members can instead themselves be HFA.  Such HFA fields
+   are handled as if their type were HFA base type.
+
+   This function returns 0 if TYPEDIE is HFA, 1 if it is not, or -1 if
+   there were errors.  In the former case, *SIZEP contains byte size
+   of the base type (e.g. 8 for IEEE double).  *COUNT is set to the
+   number of leaf members of the HFA.  */
+static int hfa_type (Dwarf_Die *ftypedie, int tag,
+		     Dwarf_Word *sizep, Dwarf_Word *countp);
+
+/* Return 0 if MEMBDIE refers to a member with a floating-point or HFA
+   type, or 1 if it's not.  Return -1 for errors.  The meaning of the
+   remaining arguments is as documented at hfa_type.  */
+static int
+member_is_fp (Dwarf_Die *membdie, Dwarf_Word *sizep, Dwarf_Word *countp)
+{
+  Dwarf_Die typedie;
+  int tag = dwarf_peeled_die_type (membdie, &typedie);
+  switch (tag)
+    {
+    case DW_TAG_base_type:;
+      Dwarf_Word encoding;
+      Dwarf_Attribute attr_mem;
+      if (dwarf_attr_integrate (&typedie, DW_AT_encoding, &attr_mem) == NULL
+	  || dwarf_formudata (&attr_mem, &encoding) != 0)
+	return -1;
+
+      switch (encoding)
+	{
+	case DW_ATE_complex_float:
+	  *countp = 2;
+	  break;
+
+	case DW_ATE_float:
+	  *countp = 1;
+	  break;
+
+	default:
+	  return 1;
+	}
+
+      if (dwarf_bytesize_aux (&typedie, sizep) < 0)
+	return -1;
+
+      *sizep /= *countp;
+      return 0;
+
+    case DW_TAG_structure_type:
+    case DW_TAG_union_type:
+    case DW_TAG_array_type:
+      return hfa_type (&typedie, tag, sizep, countp);
+    }
+
+  return 1;
+}
+
+static int
+hfa_type (Dwarf_Die *ftypedie, int tag, Dwarf_Word *sizep, Dwarf_Word *countp)
+{
+  assert (tag == DW_TAG_structure_type || tag == DW_TAG_class_type
+	  || tag == DW_TAG_union_type || tag == DW_TAG_array_type);
+
+  int i;
+  if (tag == DW_TAG_array_type)
+    {
+      Dwarf_Word tot_size;
+      if (dwarf_aggregate_size (ftypedie, &tot_size) < 0)
+	return -1;
+
+      /* For vector types, we don't care about the underlying
+	 type, but only about the vector type itself.  */
+      bool vec;
+      Dwarf_Attribute attr_mem;
+      if (dwarf_formflag (dwarf_attr_integrate (ftypedie, DW_AT_GNU_vector,
+						&attr_mem), &vec) == 0
+	  && vec)
+	{
+	  *sizep = tot_size;
+	  *countp = 1;
+
+	  return 0;
+	}
+
+      if ((i = member_is_fp (ftypedie, sizep, countp)) == 0)
+	{
+	  *countp = tot_size / *sizep;
+	  return 0;
+	}
+
+      return i;
+    }
+
+  /* Find first DW_TAG_member and determine its type.  */
+  Dwarf_Die member;
+  if ((i = dwarf_child (ftypedie, &member) != 0))
+    return i;
+
+  if ((i = skip_until (&member, DW_TAG_member)) != 0)
+    return i;
+
+  *countp = 0;
+  if ((i = member_is_fp (&member, sizep, countp)) != 0)
+    return i;
+
+  while ((i = dwarf_siblingof (&member, &member)) == 0
+	 && (i = skip_until (&member, DW_TAG_member)) == 0)
+    {
+      Dwarf_Word size, count;
+      if ((i = member_is_fp (&member, &size, &count)) != 0)
+	return i;
+
+      if (*sizep != size)
+	return 1;
+
+      *countp += count;
+    }
+
+  /* At this point we already have at least one FP member, which means
+     FTYPEDIE is an HFA.  So either return 0, or propagate error.  */
+  return i < 0 ? i : 0;
+}
+
+static int
+pass_in_gpr (const Dwarf_Op **locp, Dwarf_Word size)
+{
+  static const Dwarf_Op loc[] =
+    {
+      { .atom = DW_OP_reg0 }, { .atom = DW_OP_piece, .number = 8 },
+      { .atom = DW_OP_reg1 }, { .atom = DW_OP_piece, .number = 8 }
+    };
+
+  *locp = loc;
+  return size <= 8 ? 1 : 4;
+}
+
+static int
+pass_by_ref (const Dwarf_Op **locp)
+{
+  static const Dwarf_Op loc[] = { { .atom = DW_OP_breg0 } };
+
+  *locp = loc;
+  return 1;
+}
+
+static int
+pass_hfa (const Dwarf_Op **locp, Dwarf_Word size, Dwarf_Word count)
+{
+  assert (count >= 1 && count <= 4);
+  assert (size == 2 || size == 4 || size == 8 || size == 16);
+
+#define DEFINE_FPREG(NAME, SIZE)		\
+  static const Dwarf_Op NAME[] = {		\
+    { .atom = DW_OP_regx, .number = 64 },	\
+    { .atom = DW_OP_piece, .number = SIZE },	\
+    { .atom = DW_OP_regx, .number = 65 },	\
+    { .atom = DW_OP_piece, .number = SIZE },	\
+    { .atom = DW_OP_regx, .number = 66 },	\
+    { .atom = DW_OP_piece, .number = SIZE },	\
+    { .atom = DW_OP_regx, .number = 67 },	\
+    { .atom = DW_OP_piece, .number = SIZE }	\
+  }
+
+  switch (size)
+    {
+    case 2:;
+      DEFINE_FPREG (loc_hfa_2, 2);
+      *locp = loc_hfa_2;
+      break;
+
+    case 4:;
+      DEFINE_FPREG (loc_hfa_4, 4);
+      *locp = loc_hfa_4;
+      break;
+
+    case 8:;
+      DEFINE_FPREG (loc_hfa_8, 8);
+      *locp = loc_hfa_8;
+      break;
+
+    case 16:;
+      DEFINE_FPREG (loc_hfa_16, 16);
+      *locp = loc_hfa_16;
+      break;
+    }
+#undef DEFINE_FPREG
+
+  return count == 1 ? 1 : 2 * count;
+}
+
+static int
+pass_in_simd (const Dwarf_Op **locp)
+{
+  /* This is like passing single-element HFA.  Size doesn't matter, so
+     pretend it's for example double.  */
+  return pass_hfa (locp, 8, 1);
+}
+
+int
+aarch64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die typedie;
+  int tag = dwarf_peeled_die_type (functypedie, &typedie);
+  if (tag <= 0)
+    return tag;
+
+  Dwarf_Word size = (Dwarf_Word)-1;
+
+  /* If the argument type is a Composite Type that is larger than 16
+     bytes, then the argument is copied to memory allocated by the
+     caller and the argument is replaced by a pointer to the copy.  */
+  if (tag == DW_TAG_structure_type || tag == DW_TAG_union_type
+      || tag == DW_TAG_class_type || tag == DW_TAG_array_type)
+    {
+      Dwarf_Word base_size, count;
+      switch (hfa_type (&typedie, tag, &base_size, &count))
+	{
+	default:
+	  return -1;
+
+	case 0:
+	  assert (count > 0);
+	  if (count <= 4)
+	    return pass_hfa (locp, base_size, count);
+	  FALLTHROUGH;
+
+	case 1:
+	  /* Not a HFA.  */
+	  if (dwarf_aggregate_size (&typedie, &size) < 0)
+	    return -1;
+	  if (size > 16)
+	    return pass_by_ref (locp);
+	}
+    }
+
+  if (tag == DW_TAG_base_type
+      || tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+    {
+      if (dwarf_bytesize_aux (&typedie, &size) < 0)
+	{
+	  if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+	    size = 8;
+	  else
+	    return -1;
+	}
+
+      Dwarf_Attribute attr_mem;
+      if (tag == DW_TAG_base_type)
+	{
+	  Dwarf_Word encoding;
+	  if (dwarf_formudata (dwarf_attr_integrate (&typedie, DW_AT_encoding,
+						     &attr_mem),
+			       &encoding) != 0)
+	    return -1;
+
+	  switch (encoding)
+	    {
+	      /* If the argument is a Half-, Single-, Double- or Quad-
+		 precision Floating-point [...] the argument is allocated
+		 to the least significant bits of register v[NSRN].  */
+	    case DW_ATE_float:
+	      switch (size)
+		{
+		case 2: /* half */
+		case 4: /* sigle */
+		case 8: /* double */
+		case 16: /* quad */
+		  return pass_in_simd (locp);
+
+		default:
+		  return -2;
+		}
+
+	    case DW_ATE_complex_float:
+	      switch (size)
+		{
+		case 8: /* float _Complex */
+		case 16: /* double _Complex */
+		case 32: /* long double _Complex */
+		  return pass_hfa (locp, size / 2, 2);
+
+		default:
+		  return -2;
+		}
+
+	      /* If the argument is an Integral or Pointer Type, the
+		 size of the argument is less than or equal to 8 bytes
+		 [...] the argument is copied to the least significant
+		 bits in x[NGRN].  */
+	    case DW_ATE_boolean:
+	    case DW_ATE_signed:
+	    case DW_ATE_unsigned:
+	    case DW_ATE_unsigned_char:
+	    case DW_ATE_signed_char:
+	      return pass_in_gpr (locp, size);
+	    }
+
+	  return -2;
+	}
+      else
+	return pass_in_gpr (locp, size);
+    }
+
+  *locp = NULL;
+  return 0;
+}
diff --git a/backends/aarch64_symbol.c b/backends/aarch64_symbol.c
new file mode 100644
index 0000000..da3382e
--- /dev/null
+++ b/backends/aarch64_symbol.c
@@ -0,0 +1,104 @@
+/* AArch64 specific symbolic name handling.
+   Copyright (C) 2013, 2015, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <stddef.h>
+#include <string.h>
+
+#define BACKEND		aarch64_
+#include "libebl_CPU.h"
+
+
+/* Check for the simple reloc types.  */
+Elf_Type
+aarch64_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+{
+  switch (type)
+    {
+    case R_AARCH64_ABS64:
+      return ELF_T_XWORD;
+    case R_AARCH64_ABS32:
+      return ELF_T_WORD;
+    case R_AARCH64_ABS16:
+      return ELF_T_HALF;
+
+    default:
+      return ELF_T_NUM;
+    }
+}
+
+/* If this is the _GLOBAL_OFFSET_TABLE_ symbol, then it should point in
+   the .got even if there is a .got.plt section.
+   https://sourceware.org/ml/libc-ports/2013-06/msg00057.html
+   https://bugzilla.redhat.com/show_bug.cgi?id=1201778
+ */
+bool
+aarch64_check_special_symbol (Elf *elf, GElf_Ehdr *ehdr, const GElf_Sym *sym,
+                              const char *name, const GElf_Shdr *destshdr)
+{
+  if (name != NULL
+      && strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
+    {
+      const char *sname = elf_strptr (elf, ehdr->e_shstrndx, destshdr->sh_name);
+      if (sname != NULL
+	  && (strcmp (sname, ".got") == 0 || strcmp (sname, ".got.plt") == 0))
+	{
+	  Elf_Scn *scn = NULL;
+	  while ((scn = elf_nextscn (elf, scn)) != NULL)
+	    {
+	      GElf_Shdr shdr_mem;
+	      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+	      if (shdr != NULL)
+		{
+		  sname = elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name);
+		  if (sname != NULL && strcmp (sname, ".got") == 0)
+		    return (sym->st_value >= shdr->sh_addr
+			    && sym->st_value < shdr->sh_addr + shdr->sh_size);
+		}
+	    }
+	}
+    }
+
+  return false;
+}
+
+/* A data mapping symbol is a symbol with "$d" name or "$d.<any...>" name,
+   STT_NOTYPE, STB_LOCAL and st_size of zero. The indicate the stat of a
+   sequence of data items.  */
+bool
+aarch64_data_marker_symbol (const GElf_Sym *sym, const char *sname)
+{
+  return (sym != NULL && sname != NULL
+	  && sym->st_size == 0 && GELF_ST_BIND (sym->st_info) == STB_LOCAL
+	  && GELF_ST_TYPE (sym->st_info) == STT_NOTYPE
+	  && (strcmp (sname, "$d") == 0 || strncmp (sname, "$d.", 3) == 0));
+}
diff --git a/backends/aarch64_unwind.c b/backends/aarch64_unwind.c
new file mode 100644
index 0000000..e0a7e96
--- /dev/null
+++ b/backends/aarch64_unwind.c
@@ -0,0 +1,83 @@
+/* Get previous frame state for an existing frame state.
+   Copyright (C) 2016 The Qt Company Ltd.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND aarch64_
+#define FP_REG 29
+#define LR_REG 30
+#define SP_REG 31
+#define FP_OFFSET 0
+#define LR_OFFSET 8
+#define SP_OFFSET 16
+
+#include "libebl_CPU.h"
+
+/* There was no CFI. Maybe we happen to have a frame pointer and can unwind from that?  */
+
+bool
+EBLHOOK(unwind) (Ebl *ebl __attribute__ ((unused)), Dwarf_Addr pc __attribute__ ((unused)),
+                 ebl_tid_registers_t *setfunc, ebl_tid_registers_get_t *getfunc,
+                 ebl_pid_memory_read_t *readfunc, void *arg,
+                 bool *signal_framep __attribute__ ((unused)))
+{
+  Dwarf_Word fp, lr, sp;
+
+  if (!getfunc(LR_REG, 1, &lr, arg))
+    return false;
+
+  if (lr == 0 || !setfunc(-1, 1, &lr, arg))
+    return false;
+
+  if (!getfunc(FP_REG, 1, &fp, arg))
+    fp = 0;
+
+  if (!getfunc(SP_REG, 1, &sp, arg))
+    sp = 0;
+
+  Dwarf_Word newLr, newFp, newSp;
+
+  if (!readfunc(fp + LR_OFFSET, &newLr, arg))
+    newLr = 0;
+
+  if (!readfunc(fp + FP_OFFSET, &newFp, arg))
+    newFp = 0;
+
+  newSp = fp + SP_OFFSET;
+
+  // These are not fatal if they don't work. They will just prevent unwinding at the next frame.
+  setfunc(LR_REG, 1, &newLr, arg);
+  setfunc(FP_REG, 1, &newFp, arg);
+  setfunc(SP_REG, 1, &newSp, arg);
+
+  // If the fp is invalid, we might still have a valid lr.
+  // But if the fp is valid, then the stack should be moving in the right direction.
+  return fp == 0 || newSp > sp;
+}
diff --git a/backends/alpha_auxv.c b/backends/alpha_auxv.c
new file mode 100644
index 0000000..83e7199
--- /dev/null
+++ b/backends/alpha_auxv.c
@@ -0,0 +1,49 @@
+/* Alpha-specific auxv handling.
+   Copyright (C) 2008 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND alpha_
+#include "libebl_CPU.h"
+
+int
+EBLHOOK(auxv_info) (GElf_Xword a_type, const char **name, const char **format)
+{
+  if (a_type != AT_HWCAP)
+    return 0;
+
+  *name = "HWCAP";
+  *format = "b"
+    "bwx\0" "fix\0" "cix\0" "0x08\0"
+    "0x10\0" "0x20\0" "0x40\0" "0x80\0"
+    "max\0" "precise_trap\0"
+    "\0";
+  return 1;
+}
diff --git a/backends/alpha_corenote.c b/backends/alpha_corenote.c
new file mode 100644
index 0000000..6190df3
--- /dev/null
+++ b/backends/alpha_corenote.c
@@ -0,0 +1,70 @@
+/* PowerPC specific core note handling.
+   Copyright (C) 2007 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#define BACKEND	alpha_
+#include "libebl_CPU.h"
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+    { .offset = 0, .regno = 0, .count = 31, .bits = 64 }, /* r0-r30 */
+    { .offset = 32 * 8, .regno = 64, .count = 1, .bits = 64 }, /* pc */
+    { .offset = 33 * 8, .regno = 66, .count = 1, .bits = 64 }, /* unique */
+  };
+#define PRSTATUS_REGS_SIZE	(33 * 8)
+
+static const Ebl_Register_Location fpregset_regs[] =
+  {
+    { .offset = 0, .regno = 32, .count = 32, .bits = 64 }, /* f0-f30, fpcr */
+  };
+#define FPREGSET_SIZE		(32 * 8)
+
+#define ULONG			uint64_t
+#define ALIGN_ULONG		8
+#define TYPE_ULONG		ELF_T_XWORD
+#define TYPE_LONG		ELF_T_SXWORD
+#define PID_T			int32_t
+#define	UID_T			uint32_t
+#define	GID_T			uint32_t
+#define ALIGN_PID_T		4
+#define ALIGN_UID_T		4
+#define ALIGN_GID_T		4
+#define TYPE_PID_T		ELF_T_SWORD
+#define TYPE_UID_T		ELF_T_WORD
+#define TYPE_GID_T		ELF_T_WORD
+
+#include "linux-core-note.c"
diff --git a/backends/alpha_init.c b/backends/alpha_init.c
new file mode 100644
index 0000000..25c5b32
--- /dev/null
+++ b/backends/alpha_init.c
@@ -0,0 +1,69 @@
+/* Initialization of Alpha specific backend library.
+   Copyright (C) 2002-2011 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		alpha_
+#define RELOC_PREFIX	R_ALPHA_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on alpha_reloc.def.  */
+#include "common-reloc.c"
+
+
+const char *
+alpha_init (Elf *elf __attribute__ ((unused)),
+	    GElf_Half machine __attribute__ ((unused)),
+	    Ebl *eh,
+	    size_t ehlen)
+{
+  /* Check whether the Elf_BH object has a sufficent size.  */
+  if (ehlen < sizeof (Ebl))
+    return NULL;
+
+  /* We handle it.  */
+  eh->name = "Alpha";
+  alpha_init_reloc (eh);
+  HOOK (eh, dynamic_tag_name);
+  HOOK (eh, dynamic_tag_check);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, return_value_location);
+  HOOK (eh, machine_section_flag_check);
+  HOOK (eh, check_special_section);
+  HOOK (eh, check_special_symbol);
+  HOOK (eh, check_st_other_bits);
+  HOOK (eh, register_info);
+  HOOK (eh, core_note);
+  HOOK (eh, auxv_info);
+  eh->sysvhash_entrysize = sizeof (Elf64_Xword);
+
+  return MODVERSION;
+}
diff --git a/backends/alpha_regs.c b/backends/alpha_regs.c
new file mode 100644
index 0000000..436af3b
--- /dev/null
+++ b/backends/alpha_regs.c
@@ -0,0 +1,164 @@
+/* Register names and numbers for Alpha DWARF.
+   Copyright (C) 2007 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND alpha_
+#include "libebl_CPU.h"
+
+ssize_t
+alpha_register_info (Ebl *ebl __attribute__ ((unused)),
+		     int regno, char *name, size_t namelen,
+		     const char **prefix, const char **setname,
+		     int *bits, int *type)
+{
+  if (name == NULL)
+    return 67;
+
+  if (regno < 0 || regno > 66 || namelen < 7)
+    return -1;
+
+  *prefix = "$";
+
+  *bits = 64;
+  *type = DW_ATE_signed;
+  *setname = "integer";
+  if (regno >= 32 && regno < 64)
+    {
+      *setname = "FPU";
+      *type = DW_ATE_float;
+    }
+
+  switch (regno)
+    {
+    case 0:
+      name[0] = 'v';
+      name[1] = '0';
+      namelen = 2;
+      break;
+
+    case 1 ... 8:
+      name[0] = 't';
+      name[1] = regno - 1 + '0';
+      namelen = 2;
+      break;
+
+    case 9 ... 15:
+      name[0] = 's';
+      name[1] = regno - 9 + '0';
+      namelen = 2;
+      break;
+
+    case 16 ... 21:
+      name[0] = 'a';
+      name[1] = regno - 16 + '0';
+      namelen = 2;
+      break;
+
+    case 22 ... 23:
+      name[0] = 't';
+      name[1] = regno - 22 + '8';
+      namelen = 2;
+      break;
+
+    case 24 ... 25:
+      name[0] = 't';
+      name[1] = '1';
+      name[2] = regno - 24 + '0';
+      namelen = 3;
+      break;
+
+    case 26:
+      *type = DW_ATE_address;
+      return stpcpy (name, "ra") + 1 - name;
+
+    case 27:
+      return stpcpy (name, "t12") + 1 - name;
+
+    case 28:
+      return stpcpy (name, "at") + 1 - name;
+
+    case 29:
+      *type = DW_ATE_address;
+      return stpcpy (name, "gp") + 1 - name;
+
+    case 30:
+      *type = DW_ATE_address;
+      return stpcpy (name, "sp") + 1 - name;
+
+    case 31:
+      return stpcpy (name, "zero") + 1 - name;
+
+    case 32 ... 32 + 9:
+      name[0] = 'f';
+      name[1] = regno - 32 + '0';
+      namelen = 2;
+      break;
+
+    case 32 + 10 ... 32 + 19:
+      name[0] = 'f';
+      name[1] = '1';
+      name[2] = regno - 32 - 10 + '0';
+      namelen = 3;
+      break;
+
+    case 32 + 20 ... 32 + 29:
+      name[0] = 'f';
+      name[1] = '2';
+      name[2] = regno - 32 - 20 + '0';
+      namelen = 3;
+      break;
+
+    case 32 + 30:
+      return stpcpy (name, "f30") + 1 - name;
+
+    case 32 + 31:
+      *type = DW_ATE_unsigned;
+      return stpcpy (name, "fpcr") + 1 - name;
+
+    case 64:
+      *type = DW_ATE_address;
+      return stpcpy (name, "pc") + 1 - name;
+
+    case 66:
+      *type = DW_ATE_address;
+      return stpcpy (name, "unique") + 1 - name;
+
+    default:
+      *setname = NULL;
+      return 0;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
diff --git a/backends/alpha_reloc.def b/backends/alpha_reloc.def
new file mode 100644
index 0000000..ed7e5c3
--- /dev/null
+++ b/backends/alpha_reloc.def
@@ -0,0 +1,63 @@
+/* List the relocation types for alpha.  -*- C -*-
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,		0)
+RELOC_TYPE (REFLONG,		REL|EXEC|DYN)
+RELOC_TYPE (REFQUAD,		REL|EXEC|DYN)
+RELOC_TYPE (GPREL32,		REL)
+RELOC_TYPE (LITERAL,		REL)
+RELOC_TYPE (LITUSE,		REL)
+RELOC_TYPE (GPDISP,		REL)
+RELOC_TYPE (BRADDR,		REL)
+RELOC_TYPE (HINT,		REL)
+RELOC_TYPE (SREL16,		REL)
+RELOC_TYPE (SREL32,		REL)
+RELOC_TYPE (SREL64,		REL)
+RELOC_TYPE (GPRELHIGH,		REL)
+RELOC_TYPE (GPRELLOW,		REL)
+RELOC_TYPE (GPREL16,		REL)
+RELOC_TYPE (COPY,		0)
+RELOC_TYPE (GLOB_DAT,		EXEC|DYN)
+RELOC_TYPE (JMP_SLOT,		EXEC|DYN)
+RELOC_TYPE (RELATIVE,		EXEC|DYN)
+RELOC_TYPE (TLS_GD_HI,		REL)
+RELOC_TYPE (TLSGD,		REL)
+RELOC_TYPE (TLS_LDM,		REL)
+RELOC_TYPE (DTPMOD64,		REL|EXEC|DYN)
+RELOC_TYPE (GOTDTPREL,		REL)
+RELOC_TYPE (DTPREL64,		REL|EXEC|DYN)
+RELOC_TYPE (DTPRELHI,		REL)
+RELOC_TYPE (DTPRELLO,		REL)
+RELOC_TYPE (DTPREL16,		REL)
+RELOC_TYPE (GOTTPREL,		REL)
+RELOC_TYPE (TPREL64,		REL|EXEC|DYN)
+RELOC_TYPE (TPRELHI,		REL)
+RELOC_TYPE (TPRELLO,		REL)
+RELOC_TYPE (TPREL16,		REL)
diff --git a/backends/alpha_retval.c b/backends/alpha_retval.c
new file mode 100644
index 0000000..d9bae3b
--- /dev/null
+++ b/backends/alpha_retval.c
@@ -0,0 +1,150 @@
+/* Function return value location for Alpha ELF ABI.
+   Copyright (C) 2005, 2007, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND alpha_
+#include "libebl_CPU.h"
+
+
+/* $0.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg0 }
+  };
+#define nloc_intreg	1
+
+/* $f0, or pair $f0, $f1.  */
+static const Dwarf_Op loc_fpreg[] =
+  {
+    { .atom = DW_OP_regx, .number = 32 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_regx, .number = 33 }, { .atom = DW_OP_piece, .number = 4 },
+  };
+#define nloc_fpreg	1
+#define nloc_fpregpair	4
+
+/* The return value is a structure and is actually stored in stack space
+   passed in a hidden argument by the caller.  But, the compiler
+   helpfully returns the address of that space in $0.  */
+static const Dwarf_Op loc_aggregate[] =
+  {
+    { .atom = DW_OP_breg0, .number = 0 }
+  };
+#define nloc_aggregate 1
+
+int
+alpha_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die die_mem, *typedie = &die_mem;
+  int tag = dwarf_peeled_die_type (functypedie, typedie);
+  if (tag <= 0)
+    return tag;
+
+  switch (tag)
+    {
+    case -1:
+      return -1;
+
+    case DW_TAG_subrange_type:
+      if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
+	{
+	  Dwarf_Attribute attr_mem, *attr;
+	  attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+	  typedie = dwarf_formref_die (attr, &die_mem);
+	  tag = DWARF_TAG_OR_RETURN (typedie);
+	}
+      FALLTHROUGH;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    case DW_TAG_pointer_type:
+    case DW_TAG_ptr_to_member_type:
+      {
+	Dwarf_Attribute attr_mem;
+	Dwarf_Word size;
+	if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+						   &attr_mem), &size) != 0)
+	  {
+	    if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+	      size = 8;
+	    else
+	      return -1;
+	  }
+	if (tag == DW_TAG_base_type)
+	  {
+	    Dwarf_Word encoding;
+	    if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
+						       &attr_mem),
+				 &encoding) != 0)
+	      return -1;
+
+	    *locp = loc_fpreg;
+	    if (encoding == DW_ATE_float)
+	      {
+		if (size <= 8)
+		  return nloc_fpreg;
+		goto aggregate;
+	      }
+	    if (encoding == DW_ATE_complex_float)
+	      {
+		if (size <= 8 * 2)
+		  return nloc_fpregpair;
+		goto aggregate;
+	      }
+	  }
+	if (size <= 8)
+	  {
+	    *locp = loc_intreg;
+	    return nloc_intreg;
+	  }
+      }
+
+      FALLTHROUGH;
+
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+    case DW_TAG_string_type:
+    case DW_TAG_array_type:
+    aggregate:
+      *locp = loc_aggregate;
+      return nloc_aggregate;
+    }
+
+  /* XXX We don't have a good way to return specific errors from ebl calls.
+     This value means we do not understand the type, but it is well-formed
+     DWARF and might be valid.  */
+  return -2;
+}
diff --git a/backends/alpha_symbol.c b/backends/alpha_symbol.c
new file mode 100644
index 0000000..657d9ee
--- /dev/null
+++ b/backends/alpha_symbol.c
@@ -0,0 +1,156 @@
+/* Alpha specific symbolic name handling.
+   Copyright (C) 2002-2011 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <stddef.h>
+#include <string.h>
+
+#define BACKEND		alpha_
+#include "libebl_CPU.h"
+
+
+const char *
+alpha_dynamic_tag_name (int64_t tag, char *buf __attribute__ ((unused)),
+			size_t len __attribute__ ((unused)))
+{
+  switch (tag)
+    {
+    case DT_ALPHA_PLTRO:
+      return "ALPHA_PLTRO";
+    default:
+      break;
+    }
+  return NULL;
+}
+
+bool
+alpha_dynamic_tag_check (int64_t tag)
+{
+  return tag == DT_ALPHA_PLTRO;
+}
+
+/* Check for the simple reloc types.  */
+Elf_Type
+alpha_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+{
+  switch (type)
+    {
+    case R_ALPHA_REFLONG:
+      return ELF_T_WORD;
+    case R_ALPHA_REFQUAD:
+      return ELF_T_XWORD;
+    default:
+      return ELF_T_NUM;
+    }
+}
+
+
+/* Check whether SHF_MASKPROC flags are valid.  */
+bool
+alpha_machine_section_flag_check (GElf_Xword sh_flags)
+{
+  return (sh_flags &~ (SHF_ALPHA_GPREL)) == 0;
+}
+
+bool
+alpha_check_special_section (Ebl *ebl,
+			     int ndx __attribute__ ((unused)),
+			     const GElf_Shdr *shdr,
+			     const char *sname __attribute__ ((unused)))
+{
+  if ((shdr->sh_flags
+       & (SHF_WRITE | SHF_EXECINSTR)) == (SHF_WRITE | SHF_EXECINSTR)
+      && shdr->sh_addr != 0)
+    {
+      /* This is ordinarily flagged, but is valid for an old-style PLT.
+
+	 Look for the SHT_DYNAMIC section and the DT_PLTGOT tag in it.
+	 Its d_ptr should match the .plt section's sh_addr.  */
+
+      Elf_Scn *scn = NULL;
+      while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+	{
+	  GElf_Shdr scn_shdr;
+	  if (likely (gelf_getshdr (scn, &scn_shdr) != NULL)
+	      && scn_shdr.sh_type == SHT_DYNAMIC
+	      && scn_shdr.sh_entsize != 0)
+	    {
+	      GElf_Addr pltgot = 0;
+	      Elf_Data *data = elf_getdata (scn, NULL);
+	      if (data != NULL)
+		for (size_t i = 0; i < data->d_size / scn_shdr.sh_entsize; ++i)
+		  {
+		    GElf_Dyn dyn;
+		    if (unlikely (gelf_getdyn (data, i, &dyn) == NULL))
+		      break;
+		    if (dyn.d_tag == DT_PLTGOT)
+		      pltgot = dyn.d_un.d_ptr;
+		    else if (dyn.d_tag == DT_ALPHA_PLTRO && dyn.d_un.d_val != 0)
+		      return false; /* This PLT should not be writable.  */
+		  }
+	      return pltgot == shdr->sh_addr;
+	    }
+	}
+    }
+
+  return false;
+}
+
+/* Check whether given symbol's st_value and st_size are OK despite failing
+   normal checks.  */
+bool
+alpha_check_special_symbol (Elf *elf __attribute__ ((unused)),
+			    GElf_Ehdr *ehdr __attribute__ ((unused)),
+			    const GElf_Sym *sym __attribute__ ((unused)),
+			    const char *name,
+			    const GElf_Shdr *destshdr __attribute__ ((unused)))
+{
+  if (name == NULL)
+    return false;
+
+  if (strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
+    /* On Alpha any place in the section is valid.  */
+    return true;
+
+  return false;
+}
+
+/* Check whether only valid bits are set on the st_other symbol flag.
+   Standard ST_VISIBILITY have already been masked off.  */
+bool
+alpha_check_st_other_bits (unsigned char st_other)
+{
+  return ((((st_other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_NOPV)
+	   || ((st_other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_STD_GPLOAD))
+	  && (st_other &~ STO_ALPHA_STD_GPLOAD) == 0);
+}
diff --git a/backends/arm_attrs.c b/backends/arm_attrs.c
new file mode 100644
index 0000000..6842b77
--- /dev/null
+++ b/backends/arm_attrs.c
@@ -0,0 +1,241 @@
+/* Object attribute tags for ARM.
+   Copyright (C) 2009 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND arm_
+#include "libebl_CPU.h"
+
+#define KNOWN_VALUES(...) do				\
+  {							\
+    static const char *table[] = { __VA_ARGS__ };	\
+    if (value < sizeof table / sizeof table[0])		\
+      *value_name = table[value];			\
+  } while (0)
+
+bool
+arm_check_object_attribute (Ebl *ebl __attribute__ ((unused)),
+			    const char *vendor, int tag, uint64_t value,
+			    const char **tag_name, const char **value_name)
+{
+  if (!strcmp (vendor, "aeabi"))
+    switch (tag)
+      {
+      case 4:
+	*tag_name = "CPU_raw_name";
+	return true;
+      case 5:
+	*tag_name = "CPU_name";
+	return true;
+      case 6:
+	*tag_name = "CPU_arch";
+	KNOWN_VALUES ("Pre-v4",
+		      "v4",
+		      "v4T",
+		      "v5T",
+		      "v5TE",
+		      "v5TEJ",
+		      "v6",
+		      "v6KZ",
+		      "v6T2",
+		      "v6K",
+		      "v7",
+		      "v6-M",
+		      "v6S-M");
+	return true;
+      case 7:
+	*tag_name = "CPU_arch_profile";
+	switch (value)
+	  {
+	  case 'A':
+	    *value_name = "Application";
+	    break;
+	  case 'R':
+	    *value_name = "Realtime";
+	    break;
+	  case 'M':
+	    *value_name = "Microcontroller";
+	    break;
+	  }
+	return true;
+      case 8:
+	*tag_name = "ARM_ISA_use";
+	KNOWN_VALUES ("No", "Yes");
+	return true;
+      case 9:
+	*tag_name = "THUMB_ISA_use";
+	KNOWN_VALUES ("No", "Thumb-1", "Thumb-2");
+	return true;
+      case 10:
+	*tag_name = "VFP_arch";
+	KNOWN_VALUES ("No", "VFPv1", "VFPv2", "VFPv3", "VFPv3-D16");
+	return true;
+      case 11:
+	*tag_name = "WMMX_arch";
+	KNOWN_VALUES ("No", "WMMXv1", "WMMXv2");
+	return true;
+      case 12:
+	*tag_name = "Advanced_SIMD_arch";
+	KNOWN_VALUES ("No", "NEONv1");
+	return true;
+      case 13:
+	*tag_name = "PCS_config";
+	KNOWN_VALUES ("None",
+		      "Bare platform",
+		      "Linux application",
+		      "Linux DSO",
+		      "PalmOS 2004",
+		      "PalmOS (reserved)",
+		      "SymbianOS 2004",
+		      "SymbianOS (reserved)");
+	return true;
+      case 14:
+	*tag_name = "ABI_PCS_R9_use";
+	KNOWN_VALUES ("V6", "SB", "TLS", "Unused");
+	return true;
+      case 15:
+	*tag_name = "ABI_PCS_RW_data";
+	KNOWN_VALUES ("Absolute", "PC-relative", "SB-relative", "None");
+	return true;
+      case 16:
+	*tag_name = "ABI_PCS_RO_data";
+	KNOWN_VALUES ("Absolute", "PC-relative", "None");
+	return true;
+      case 17:
+	*tag_name = "ABI_PCS_GOT_use";
+	KNOWN_VALUES ("None", "direct", "GOT-indirect");
+	return true;
+      case 18:
+	*tag_name = "ABI_PCS_wchar_t";
+	return true;
+      case 19:
+	*tag_name = "ABI_FP_rounding";
+	KNOWN_VALUES ("Unused", "Needed");
+	return true;
+      case 20:
+	*tag_name = "ABI_FP_denormal";
+	KNOWN_VALUES ("Unused", "Needed", "Sign only");
+	return true;
+      case 21:
+	*tag_name = "ABI_FP_exceptions";
+	KNOWN_VALUES ("Unused", "Needed");
+	return true;
+      case 22:
+	*tag_name = "ABI_FP_user_exceptions";
+	KNOWN_VALUES ("Unused", "Needed");
+	return true;
+      case 23:
+	*tag_name = "ABI_FP_number_model";
+	KNOWN_VALUES ("Unused", "Finite", "RTABI", "IEEE 754");
+	return true;
+      case 24:
+	*tag_name = "ABI_align8_needed";
+	KNOWN_VALUES ("No", "Yes", "4-byte");
+	return true;
+      case 25:
+	*tag_name = "ABI_align8_preserved";
+	KNOWN_VALUES ("No", "Yes, except leaf SP", "Yes");
+	return true;
+      case 26:
+	*tag_name = "ABI_enum_size";
+	KNOWN_VALUES ("Unused", "small", "int", "forced to int");
+	return true;
+      case 27:
+	*tag_name = "ABI_HardFP_use";
+	KNOWN_VALUES ("as VFP_arch", "SP only", "DP only", "SP and DP");
+	return true;
+      case 28:
+	*tag_name = "ABI_VFP_args";
+	KNOWN_VALUES ("AAPCS", "VFP registers", "custom");
+	return true;
+      case 29:
+	*tag_name = "ABI_WMMX_args";
+	KNOWN_VALUES ("AAPCS", "WMMX registers", "custom");
+	return true;
+      case 30:
+	*tag_name = "ABI_optimization_goals";
+	KNOWN_VALUES ("None",
+		      "Prefer Speed",
+		      "Aggressive Speed",
+		      "Prefer Size",
+		      "Aggressive Size",
+		      "Prefer Debug",
+		      "Aggressive Debug");
+	return true;
+      case 31:
+	*tag_name = "ABI_FP_optimization_goals";
+	KNOWN_VALUES ("None",
+		      "Prefer Speed",
+		      "Aggressive Speed",
+		      "Prefer Size",
+		      "Aggressive Size",
+		      "Prefer Accuracy",
+		      "Aggressive Accuracy");
+	return true;
+      case 34:
+	*tag_name = "CPU_unaligned_access";
+	KNOWN_VALUES ("None", "v6");
+	return true;
+      case 36:
+	*tag_name = "VFP_HP_extension";
+	KNOWN_VALUES ("Not Allowed", "Allowed");
+	return true;
+      case 38:
+	*tag_name = "ABI_FP_16bit_format";
+	KNOWN_VALUES ("None", "IEEE 754", "Alternative Format");
+	return true;
+      case 64:
+	*tag_name = "nodefaults";
+	return true;
+      case 65:
+	*tag_name = "also_compatible_with";
+	return true;
+      case 66:
+	*tag_name = "T2EE_use";
+	KNOWN_VALUES ("Not Allowed", "Allowed");
+	return true;
+      case 67:
+	*tag_name = "conformance";
+	return true;
+      case 68:
+	*tag_name = "Virtualization_use";
+	KNOWN_VALUES ("Not Allowed", "Allowed");
+	return true;
+      case 70:
+	*tag_name = "MPextension_use";
+	KNOWN_VALUES ("Not Allowed", "Allowed");
+	return true;
+      }
+
+  return false;
+}
diff --git a/backends/arm_auxv.c b/backends/arm_auxv.c
new file mode 100644
index 0000000..3282baf
--- /dev/null
+++ b/backends/arm_auxv.c
@@ -0,0 +1,49 @@
+/* ARM-specific auxv handling.
+   Copyright (C) 2009 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND arm_
+#include "libebl_CPU.h"
+
+int
+EBLHOOK(auxv_info) (GElf_Xword a_type, const char **name, const char **format)
+{
+  if (a_type != AT_HWCAP)
+    return 0;
+
+  *name = "HWCAP";
+  *format = "b"
+    "swp\0" "half\0" "thumb\0" "26bit\0"
+    "fast-mult\0" "fpa\0" "vfp\0" "edsp\0"
+    "java\0" "iwmmxt\0"
+    "\0";
+  return 1;
+}
diff --git a/backends/arm_cfi.c b/backends/arm_cfi.c
new file mode 100644
index 0000000..971a1fc
--- /dev/null
+++ b/backends/arm_cfi.c
@@ -0,0 +1,90 @@
+/* arm ABI-specified defaults for DWARF CFI.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#define BACKEND arm_
+#include "libebl_CPU.h"
+
+
+/* ABI-specified state of DWARF CFI based on:
+
+   "DWARF for the ARM Architecture ABI r2.09"
+http://infocenter.arm.com/help/topic/com.arm.doc.ihi0040b/IHI0040B_aadwarf.pdf
+
+   "Procedure Call Standard for the ARM Architecture ABI r2.09"
+http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042e/IHI0042E_aapcs.pdf
+*/
+
+int
+arm_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info)
+{
+  static const uint8_t abi_cfi[] =
+    {
+      /* The initial Canonical Frame Address is the value of the
+         Stack Pointer (r13) as setup in the previous frame. */
+      DW_CFA_def_cfa, ULEB128_7 (13), ULEB128_7 (0),
+
+      /* The Stack Pointer (r13) is restored from CFA address by default.  */
+      DW_CFA_val_offset, ULEB128_7 (13), ULEB128_7 (0),
+
+#define SV(n) DW_CFA_same_value, ULEB128_7 (n)
+      /* Callee-saved regs r4-r8, r10, r11.  */
+      SV (4), SV (5), SV (6), SV (7), SV (8), SV (10), SV (11),
+
+      /* The link register contains the return address setup by caller.  */
+      SV (14),
+      DW_CFA_register, ULEB128_7 (15), ULEB128_7 (14), /* pc = lr */
+#undef SV
+
+      /* VFP S16-S31/D8-D15/Q4-Q7 are callee saved.
+         And uleb128 encoded with two bytes.  */
+#define ULEB128_8_2(x) ((x & 0x7f) | 0x80), 0x02
+#define SV(n) DW_CFA_same_value, ULEB128_8_2 (n)
+      SV (264), SV (265), SV (266), SV (267),
+      SV (268), SV (269), SV (270), SV (271),
+
+      /* XXX Note: registers intentionally unused by the program,
+	 for example as a consequence of the procedure call standard
+	 should be initialized as if by DW_CFA_same_value.  */
+    };
+#undef ULEB128_8_2
+#undef SV
+
+  abi_info->initial_instructions = abi_cfi;
+  abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
+  abi_info->data_alignment_factor = 4;
+
+  abi_info->return_address_register = 15; /* pc.  */
+
+  return 0;
+}
diff --git a/backends/arm_corenote.c b/backends/arm_corenote.c
new file mode 100644
index 0000000..c5d8d88
--- /dev/null
+++ b/backends/arm_corenote.c
@@ -0,0 +1,94 @@
+/* ARM specific core note handling.
+   Copyright (C) 2009, 2012 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#define BACKEND arm_
+#include "libebl_CPU.h"
+
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+    { .offset = 0, .regno = 0, .count = 16, .bits = 32 },	/* r0..r15 */
+    { .offset = 16 * 4, .regno = 128, .count = 1, .bits = 32 }, /* cpsr */
+  };
+#define PRSTATUS_REGS_SIZE	(18 * 4)
+
+#define PRSTATUS_REGSET_ITEMS						      \
+  {									      \
+    .name = "orig_r0", .type = ELF_T_SWORD, .format = 'd',		      \
+    .offset = offsetof (struct EBLHOOK(prstatus), pr_reg) + (4 * 17),	      \
+    .group = "register"	       			  	       	 	      \
+  }
+
+static const Ebl_Register_Location fpregset_regs[] =
+  {
+    { .offset = 0, .regno = 96, .count = 8, .bits = 96 }, /* f0..f7 */
+  };
+#define FPREGSET_SIZE	116
+
+#define	ULONG			uint32_t
+#define PID_T			int32_t
+#define	UID_T			uint16_t
+#define	GID_T			uint16_t
+#define ALIGN_ULONG		4
+#define ALIGN_PID_T		4
+#define ALIGN_UID_T		2
+#define ALIGN_GID_T		2
+#define TYPE_ULONG		ELF_T_WORD
+#define TYPE_PID_T		ELF_T_SWORD
+#define TYPE_UID_T		ELF_T_HALF
+#define TYPE_GID_T		ELF_T_HALF
+
+#define ARM_VFPREGS_SIZE ( 32 * 8 /*fpregs*/ + 4 /*fpscr*/ )
+static const Ebl_Register_Location vfp_regs[] =
+  {
+    { .offset = 0, .regno = 256, .count = 32, .bits = 64 }, /* fpregs */
+  };
+
+static const Ebl_Core_Item vfp_items[] =
+  {
+    {
+      .name = "fpscr", .group = "register",
+      .offset = 0,
+      .type = ELF_T_WORD, .format = 'x',
+    },
+  };
+
+#define	EXTRA_NOTES \
+  EXTRA_REGSET_ITEMS (NT_ARM_VFP, ARM_VFPREGS_SIZE, vfp_regs, vfp_items)
+
+#include "linux-core-note.c"
diff --git a/backends/arm_init.c b/backends/arm_init.c
new file mode 100644
index 0000000..f2b1b11
--- /dev/null
+++ b/backends/arm_init.c
@@ -0,0 +1,77 @@
+/* Initialization of Arm specific backend library.
+   Copyright (C) 2002, 2005, 2009, 2013, 2014, 2015, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		arm_
+#define RELOC_PREFIX	R_ARM_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on arm_reloc.def.  */
+#include "common-reloc.c"
+
+
+const char *
+arm_init (Elf *elf __attribute__ ((unused)),
+	  GElf_Half machine __attribute__ ((unused)),
+	  Ebl *eh,
+	  size_t ehlen)
+{
+  /* Check whether the Elf_BH object has a sufficent size.  */
+  if (ehlen < sizeof (Ebl))
+    return NULL;
+
+  /* We handle it.  */
+  eh->name = "ARM";
+  arm_init_reloc (eh);
+  HOOK (eh, segment_type_name);
+  HOOK (eh, section_type_name);
+  HOOK (eh, machine_flag_check);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, register_info);
+  HOOK (eh, core_note);
+  HOOK (eh, auxv_info);
+  HOOK (eh, check_object_attribute);
+  HOOK (eh, return_value_location);
+  HOOK (eh, abi_cfi);
+  HOOK (eh, check_reloc_target_type);
+  HOOK (eh, symbol_type_name);
+  HOOK (eh, data_marker_symbol);
+
+  /* We only unwind the core integer registers.  */
+  eh->frame_nregs = 16;
+  HOOK (eh, set_initial_registers_tid);
+
+  /* Bit zero encodes whether an function address is THUMB or ARM. */
+  eh->func_addr_mask = ~(GElf_Addr)1;
+
+  return MODVERSION;
+}
diff --git a/backends/arm_initreg.c b/backends/arm_initreg.c
new file mode 100644
index 0000000..efcabaf
--- /dev/null
+++ b/backends/arm_initreg.c
@@ -0,0 +1,94 @@
+/* Fetch live process registers from TID.
+   Copyright (C) 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef __linux__
+#if defined __arm__
+# include <sys/types.h>
+# include <sys/user.h>
+# include <sys/ptrace.h>
+#endif
+
+#ifdef __aarch64__
+# include <linux/uio.h>
+# include <sys/user.h>
+# include <sys/ptrace.h>
+/* Deal with old glibc defining user_pt_regs instead of user_regs_struct.  */
+# ifndef HAVE_SYS_USER_REGS
+#  define user_regs_struct user_pt_regs
+# endif
+#endif
+#endif
+
+#define BACKEND arm_
+#include "libebl_CPU.h"
+
+bool
+arm_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
+			  ebl_tid_registers_t *setfunc __attribute__ ((unused)),
+			       void *arg __attribute__ ((unused)))
+{
+#if !defined(__linux__) || (!defined __arm__ && !defined __aarch64__)
+  return false;
+#else	/* __arm__ || __aarch64__ */
+#if defined __arm__
+  struct user_regs user_regs;
+  if (ptrace (PTRACE_GETREGS, tid, NULL, &user_regs) != 0)
+    return false;
+
+  Dwarf_Word dwarf_regs[16];
+  /* R0..R12 SP LR PC */
+  for (int i = 0; i < 16; i++)
+    dwarf_regs[i] = user_regs.uregs[i];
+
+  return setfunc (0, 16, dwarf_regs, arg);
+#elif defined __aarch64__
+  /* Compat mode: arm compatible code running on aarch64 */
+  int i;
+  struct user_regs_struct gregs;
+  struct iovec iovec;
+  iovec.iov_base = &gregs;
+  iovec.iov_len = sizeof (gregs);
+  if (ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, &iovec) != 0)
+    return false;
+
+  Dwarf_Word dwarf_regs[16];
+  /* R0..R12 SP LR PC, encoded as 32 bit quantities */
+  uint32_t *u32_ptr = (uint32_t *) &gregs.regs[0];
+  for (i = 0; i < 16; i++)
+    dwarf_regs[i] = u32_ptr[i];
+
+  return setfunc (0, 16, dwarf_regs, arg);
+#else
+# error "source file error, it cannot happen"
+#endif
+#endif
+}
diff --git a/backends/arm_regs.c b/backends/arm_regs.c
new file mode 100644
index 0000000..a46a4c9
--- /dev/null
+++ b/backends/arm_regs.c
@@ -0,0 +1,120 @@
+/* Register names and numbers for ARM DWARF.
+   Copyright (C) 2009 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND arm_
+#include "libebl_CPU.h"
+
+ssize_t
+arm_register_info (Ebl *ebl __attribute__ ((unused)),
+		   int regno, char *name, size_t namelen,
+		   const char **prefix, const char **setname,
+		   int *bits, int *type)
+{
+  if (name == NULL)
+    return 320;
+
+  if (regno < 0 || regno > 320 || namelen < 5)
+    return -1;
+
+  *prefix = "";
+  *bits = 32;
+  *type = DW_ATE_signed;
+  *setname = "integer";
+
+  switch (regno)
+    {
+    case 0 ... 9:
+      name[0] = 'r';
+      name[1] = regno + '0';
+      namelen = 2;
+      break;
+
+    case 10 ... 12:
+      name[0] = 'r';
+      name[1] = '1';
+      name[2] = regno % 10 + '0';
+      namelen = 3;
+      break;
+
+    case 13 ... 15:
+      *type = DW_ATE_address;
+      name[0] = "slp"[regno - 13];
+      name[1] = "prc"[regno - 13];
+      namelen = 2;
+      break;
+
+    case 16 + 0 ... 16 + 7:
+      regno += 96 - 16;
+      FALLTHROUGH;
+    case 96 + 0 ... 96 + 7:
+      *setname = "FPA";
+      *type = DW_ATE_float;
+      *bits = 96;
+      name[0] = 'f';
+      name[1] = regno - 96 + '0';
+      namelen = 2;
+      break;
+
+    case 128:
+      *type = DW_ATE_unsigned;
+      return stpcpy (name, "spsr") + 1 - name;
+
+    case 256 + 0 ... 256 + 9:
+      *setname = "VFP";
+      *type = DW_ATE_float;
+      *bits = 64;
+      name[0] = 'd';
+      name[1] = regno - 256 + '0';
+      namelen = 2;
+      break;
+
+    case 256 + 10 ... 256 + 31:
+      *setname = "VFP";
+      *type = DW_ATE_float;
+      *bits = 64;
+      name[0] = 'd';
+      name[1] = (regno - 256) / 10 + '0';
+      name[2] = (regno - 256) % 10 + '0';
+      namelen = 3;
+      break;
+
+    default:
+      *setname = NULL;
+      return 0;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
diff --git a/backends/arm_reloc.def b/backends/arm_reloc.def
new file mode 100644
index 0000000..113648e
--- /dev/null
+++ b/backends/arm_reloc.def
@@ -0,0 +1,157 @@
+/* List the relocation types for arm.  -*- C -*-
+   Copyright (C) 2005-2010, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,		REL) /* It really is used in ET_REL on ARM.  */
+RELOC_TYPE (PC24,		REL|EXEC|DYN)
+RELOC_TYPE (ABS32,		REL|EXEC|DYN)
+RELOC_TYPE (REL32,		REL)
+RELOC_TYPE (PC13,		REL)
+RELOC_TYPE (ABS16,		REL)
+RELOC_TYPE (ABS12,		REL)
+RELOC_TYPE (THM_ABS5,		REL)
+RELOC_TYPE (ABS8,		REL)
+RELOC_TYPE (SBREL32,		REL)
+RELOC_TYPE (THM_PC22,		REL)
+RELOC_TYPE (THM_PC8,		REL)
+RELOC_TYPE (AMP_VCALL9,		REL)
+RELOC_TYPE (TLS_DESC,		EXEC|DYN)
+RELOC_TYPE (THM_SWI8,		REL)
+RELOC_TYPE (XPC25,		REL)
+RELOC_TYPE (THM_XPC22,		REL)
+RELOC_TYPE (TLS_DTPMOD32,	EXEC|DYN)
+RELOC_TYPE (TLS_DTPOFF32,	EXEC|DYN)
+RELOC_TYPE (TLS_TPOFF32,	EXEC|DYN)
+RELOC_TYPE (COPY,		EXEC|DYN)
+RELOC_TYPE (GLOB_DAT,		EXEC|DYN)
+RELOC_TYPE (JUMP_SLOT,		EXEC|DYN)
+RELOC_TYPE (RELATIVE,		EXEC|DYN)
+RELOC_TYPE (GOTOFF,		REL)
+RELOC_TYPE (GOTPC,		REL)
+RELOC_TYPE (GOT32,		REL)
+RELOC_TYPE (PLT32,		REL)
+RELOC_TYPE (CALL,		REL)
+RELOC_TYPE (JUMP24,		REL)
+RELOC_TYPE (THM_JUMP24,		REL)
+RELOC_TYPE (BASE_ABS,		REL)
+RELOC_TYPE (ALU_PCREL_7_0,	REL)
+RELOC_TYPE (ALU_PCREL_15_8,	REL)
+RELOC_TYPE (ALU_PCREL_23_15,	REL)
+RELOC_TYPE (LDR_SBREL_11_0,	REL)
+RELOC_TYPE (ALU_SBREL_19_12,	REL)
+RELOC_TYPE (ALU_SBREL_27_20,	REL)
+RELOC_TYPE (TARGET1,		REL)
+RELOC_TYPE (SBREL31,		REL)
+RELOC_TYPE (V4BX,		REL)
+RELOC_TYPE (TARGET2,		REL)
+RELOC_TYPE (PREL31,		REL)
+RELOC_TYPE (MOVW_ABS_NC,	REL)
+RELOC_TYPE (MOVT_ABS,		REL)
+RELOC_TYPE (MOVW_PREL_NC,	REL)
+RELOC_TYPE (MOVT_PREL,		REL)
+RELOC_TYPE (THM_MOVW_ABS_NC,	REL)
+RELOC_TYPE (THM_MOVT_ABS,	REL)
+RELOC_TYPE (THM_MOVW_PREL_NC,	REL)
+RELOC_TYPE (THM_MOVT_PREL,	REL)
+RELOC_TYPE (THM_JUMP19,		REL)
+RELOC_TYPE (THM_JUMP6,		REL)
+RELOC_TYPE (THM_ALU_PREL_11_0,	REL)
+RELOC_TYPE (THM_PC12,		REL)
+RELOC_TYPE (ABS32_NOI,		REL)
+RELOC_TYPE (REL32_NOI,		REL)
+RELOC_TYPE (ALU_PC_G0_NC,	REL)
+RELOC_TYPE (ALU_PC_G0,		REL)
+RELOC_TYPE (ALU_PC_G1_NC,	REL)
+RELOC_TYPE (ALU_PC_G1,		REL)
+RELOC_TYPE (ALU_PC_G2,		REL)
+RELOC_TYPE (LDR_PC_G1,		REL)
+RELOC_TYPE (LDR_PC_G2,		REL)
+RELOC_TYPE (LDRS_PC_G0,		REL)
+RELOC_TYPE (LDRS_PC_G1,		REL)
+RELOC_TYPE (LDRS_PC_G2,		REL)
+RELOC_TYPE (LDC_PC_G0,		REL)
+RELOC_TYPE (LDC_PC_G1,		REL)
+RELOC_TYPE (LDC_PC_G2,		REL)
+RELOC_TYPE (ALU_SB_G0_NC,	REL)
+RELOC_TYPE (ALU_SB_G0,		REL)
+RELOC_TYPE (ALU_SB_G1_NC,	REL)
+RELOC_TYPE (ALU_SB_G1,		REL)
+RELOC_TYPE (ALU_SB_G2,		REL)
+RELOC_TYPE (LDR_SB_G0,		REL)
+RELOC_TYPE (LDR_SB_G1,		REL)
+RELOC_TYPE (LDR_SB_G2,		REL)
+RELOC_TYPE (LDRS_SB_G0,		REL)
+RELOC_TYPE (LDRS_SB_G1,		REL)
+RELOC_TYPE (LDRS_SB_G2,		REL)
+RELOC_TYPE (LDC_SB_G0,		REL)
+RELOC_TYPE (LDC_SB_G1,		REL)
+RELOC_TYPE (LDC_SB_G2,		REL)
+RELOC_TYPE (MOVW_BREL_NC,	REL)
+RELOC_TYPE (MOVT_BREL,		REL)
+RELOC_TYPE (MOVW_BREL,		REL)
+RELOC_TYPE (THM_MOVW_BREL_NC,	REL)
+RELOC_TYPE (THM_MOVT_BREL,	REL)
+RELOC_TYPE (THM_MOVW_BREL,	REL)
+RELOC_TYPE (TLS_GOTDESC,	REL)
+RELOC_TYPE (TLS_CALL,		REL)
+RELOC_TYPE (TLS_DESCSEQ,	REL)
+RELOC_TYPE (THM_TLS_CALL,	REL)
+RELOC_TYPE (PLT32_ABS,		REL)
+RELOC_TYPE (GOT_ABS,		REL)
+RELOC_TYPE (GOT_PREL,		REL)
+RELOC_TYPE (GOT_BREL12,		REL)
+RELOC_TYPE (GOTOFF12,		REL)
+RELOC_TYPE (GOTRELAX,		REL)
+RELOC_TYPE (GNU_VTENTRY,	REL)
+RELOC_TYPE (GNU_VTINHERIT,	REL)
+RELOC_TYPE (THM_PC11,		REL)
+RELOC_TYPE (THM_PC9,		REL)
+RELOC_TYPE (TLS_GD32,		REL)
+RELOC_TYPE (TLS_LDM32,		REL)
+RELOC_TYPE (TLS_LDO32,		REL)
+RELOC_TYPE (TLS_IE32,		REL)
+RELOC_TYPE (TLS_LE32,		REL)
+RELOC_TYPE (TLS_LDO12,		REL)
+RELOC_TYPE (TLS_LE12,		REL)
+RELOC_TYPE (TLS_IE12GP,		REL)
+
+RELOC_TYPE (ME_TOO,		REL)
+RELOC_TYPE (THM_TLS_DESCSEQ16,	REL)
+RELOC_TYPE (THM_TLS_DESCSEQ32,	REL)
+RELOC_TYPE (THM_GOT_BREL12,	REL)
+
+RELOC_TYPE (IRELATIVE,		EXEC|DYN)
+
+RELOC_TYPE (RXPC25,		REL)
+RELOC_TYPE (RSBREL32,		REL)
+RELOC_TYPE (THM_RPC22,		REL)
+RELOC_TYPE (RREL32,		REL)
+RELOC_TYPE (RABS22,		REL)
+RELOC_TYPE (RPC24,		REL)
+RELOC_TYPE (RBASE,		REL)
diff --git a/backends/arm_retval.c b/backends/arm_retval.c
new file mode 100644
index 0000000..1c28f01
--- /dev/null
+++ b/backends/arm_retval.c
@@ -0,0 +1,127 @@
+/* Function return value location for ARM EABI.
+   Copyright (C) 2009-2010, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND arm_
+#include "libebl_CPU.h"
+
+
+/* r0, or pair r0, r1, or aggregate up to r0-r3.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg0 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg1 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg2 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg3 }, { .atom = DW_OP_piece, .number = 4 },
+  };
+#define nloc_intreg	1
+#define nloc_intregs(n)	(2 * (n))
+
+/* The return value is a structure and is actually stored in stack space
+   passed in a hidden argument by the caller.  But, the compiler
+   helpfully returns the address of that space in r0.  */
+static const Dwarf_Op loc_aggregate[] =
+  {
+    { .atom = DW_OP_breg0, .number = 0 }
+  };
+#define nloc_aggregate 1
+
+
+int
+arm_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die die_mem, *typedie = &die_mem;
+  int tag = dwarf_peeled_die_type (functypedie, typedie);
+  if (tag <= 0)
+    return tag;
+
+  Dwarf_Word size;
+  switch (tag)
+    {
+    case -1:
+      return -1;
+
+    case DW_TAG_subrange_type:
+      if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
+	{
+	  Dwarf_Attribute attr_mem, *attr;
+	  attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+	  typedie = dwarf_formref_die (attr, &die_mem);
+	  tag = DWARF_TAG_OR_RETURN (typedie);
+	}
+      FALLTHROUGH;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    case DW_TAG_pointer_type:
+    case DW_TAG_ptr_to_member_type:
+      {
+	Dwarf_Attribute attr_mem;
+	if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+						   &attr_mem), &size) != 0)
+	  {
+	    if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+	      size = 4;
+	    else
+	      return -1;
+	  }
+	if (size <= 16)
+	  {
+	  intreg:
+	    *locp = loc_intreg;
+	    return size <= 4 ? nloc_intreg : nloc_intregs ((size + 3) / 4);
+	  }
+
+      aggregate:
+	*locp = loc_aggregate;
+	return nloc_aggregate;
+      }
+
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+    case DW_TAG_array_type:
+      if (dwarf_aggregate_size (typedie, &size) == 0
+	  && size > 0 && size <= 4)
+	goto intreg;
+      goto aggregate;
+    }
+
+  /* XXX We don't have a good way to return specific errors from ebl calls.
+     This value means we do not understand the type, but it is well-formed
+     DWARF and might be valid.  */
+  return -2;
+}
diff --git a/backends/arm_symbol.c b/backends/arm_symbol.c
new file mode 100644
index 0000000..3edda72
--- /dev/null
+++ b/backends/arm_symbol.c
@@ -0,0 +1,157 @@
+/* Arm specific symbolic name handling.
+   Copyright (C) 2002-2009, 2014, 2015, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <stddef.h>
+#include <string.h>
+
+#define BACKEND		arm_
+#include "libebl_CPU.h"
+
+
+const char *
+arm_segment_type_name (int segment, char *buf __attribute__ ((unused)),
+		       size_t len __attribute__ ((unused)))
+{
+  switch (segment)
+    {
+    case PT_ARM_EXIDX:
+      return "ARM_EXIDX";
+    }
+  return NULL;
+}
+
+/* Return symbolic representation of section type.  */
+const char *
+arm_section_type_name (int type,
+		       char *buf __attribute__ ((unused)),
+		       size_t len __attribute__ ((unused)))
+{
+  switch (type)
+    {
+    case SHT_ARM_EXIDX:
+      return "ARM_EXIDX";
+    case SHT_ARM_PREEMPTMAP:
+      return "ARM_PREEMPTMAP";
+    case SHT_ARM_ATTRIBUTES:
+      return "ARM_ATTRIBUTES";
+    }
+
+  return NULL;
+}
+
+/* Check whether machine flags are valid.  */
+bool
+arm_machine_flag_check (GElf_Word flags)
+{
+  switch (flags & EF_ARM_EABIMASK)
+    {
+    case EF_ARM_EABI_UNKNOWN:
+    case EF_ARM_EABI_VER1:
+    case EF_ARM_EABI_VER2:
+    case EF_ARM_EABI_VER3:
+    case EF_ARM_EABI_VER4:
+    case EF_ARM_EABI_VER5:
+      break;
+    default:
+      return false;
+    }
+
+  return ((flags &~ (EF_ARM_EABIMASK
+		     | EF_ARM_RELEXEC
+		     | EF_ARM_HASENTRY
+		     | EF_ARM_INTERWORK
+		     | EF_ARM_APCS_26
+		     | EF_ARM_APCS_FLOAT
+		     | EF_ARM_PIC
+		     | EF_ARM_ALIGN8
+		     | EF_ARM_NEW_ABI
+		     | EF_ARM_OLD_ABI
+		     | EF_ARM_SOFT_FLOAT
+		     | EF_ARM_VFP_FLOAT
+		     | EF_ARM_MAVERICK_FLOAT
+		     | EF_ARM_SYMSARESORTED
+		     | EF_ARM_DYNSYMSUSESEGIDX
+		     | EF_ARM_MAPSYMSFIRST
+		     | EF_ARM_EABIMASK
+		     | EF_ARM_BE8
+		     | EF_ARM_LE8)) == 0);
+}
+
+/* Check for the simple reloc types.  */
+Elf_Type
+arm_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+{
+  switch (type)
+    {
+    case R_ARM_ABS32:
+      return ELF_T_WORD;
+    case R_ARM_ABS16:
+      return ELF_T_HALF;
+    case R_ARM_ABS8:
+      return ELF_T_BYTE;
+    default:
+      return ELF_T_NUM;
+    }
+}
+
+/* The SHT_ARM_EXIDX section type is a valid target for relocation.  */
+bool
+arm_check_reloc_target_type (Ebl *ebl __attribute__ ((unused)), Elf64_Word sh_type)
+{
+  return sh_type == SHT_ARM_EXIDX;
+}
+
+const char *
+arm_symbol_type_name (int type,
+		      char *buf __attribute__ ((unused)),
+		      size_t len __attribute__ ((unused)))
+{
+  switch (type)
+    {
+    case STT_ARM_TFUNC:
+      return "ARM_TFUNC";
+    }
+  return NULL;
+}
+
+/* A data mapping symbol is a symbol with "$d" name or "$d.<any...>" name,
+ *    STT_NOTYPE, STB_LOCAL and st_size of zero. The indicate the stat of a
+ *       sequence of data items.  */
+bool
+arm_data_marker_symbol (const GElf_Sym *sym, const char *sname)
+{
+  return (sym != NULL && sname != NULL
+          && sym->st_size == 0 && GELF_ST_BIND (sym->st_info) == STB_LOCAL
+          && GELF_ST_TYPE (sym->st_info) == STT_NOTYPE
+          && (strcmp (sname, "$d") == 0 || strncmp (sname, "$d.", 3) == 0));
+}
diff --git a/backends/bpf_init.c b/backends/bpf_init.c
new file mode 100644
index 0000000..8ea1bc1
--- /dev/null
+++ b/backends/bpf_init.c
@@ -0,0 +1,58 @@
+/* Initialization of BPF specific backend library.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		bpf_
+#define RELOC_PREFIX	R_BPF_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on bpf_reloc.def.  */
+#define NO_RELATIVE_RELOC
+#define NO_COPY_RELOC
+#include "common-reloc.c"
+
+
+const char *
+bpf_init (Elf *elf __attribute__ ((unused)),
+	  GElf_Half machine __attribute__ ((unused)),
+	  Ebl *eh, size_t ehlen)
+{
+  /* Check whether the Elf_BH object has a sufficent size.  */
+  if (ehlen < sizeof (Ebl))
+    return NULL;
+
+  /* We handle it.  */
+  eh->name = "BPF";
+  bpf_init_reloc (eh);
+  HOOK (eh, register_info);
+  HOOK (eh, disasm);
+
+  return MODVERSION;
+}
diff --git a/backends/bpf_regs.c b/backends/bpf_regs.c
new file mode 100644
index 0000000..1863a16
--- /dev/null
+++ b/backends/bpf_regs.c
@@ -0,0 +1,60 @@
+/* Register names and numbers for BPF DWARF.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "bpf.h"
+
+#define BACKEND bpf_
+#include "libebl_CPU.h"
+
+ssize_t
+bpf_register_info (Ebl *ebl __attribute__ ((unused)),
+		   int regno, char *name, size_t namelen,
+		   const char **prefix, const char **setname,
+		   int *bits, int *type)
+{
+  ssize_t len;
+
+  if (name == NULL)
+    return MAX_BPF_REG;
+  if (regno < 0 || regno >= MAX_BPF_REG)
+    return -1;
+
+  *prefix = "";
+  *setname = "integer";
+  *bits = 64;
+  *type = DW_ATE_signed;
+
+  len = snprintf(name, namelen, "r%d", regno);
+  return ((size_t)len < namelen ? len : -1);
+}
diff --git a/backends/bpf_reloc.def b/backends/bpf_reloc.def
new file mode 100644
index 0000000..a410da9
--- /dev/null
+++ b/backends/bpf_reloc.def
@@ -0,0 +1,31 @@
+/* List the relocation types for BPF.  -*- C -*-
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,		EXEC|DYN)
+RELOC_TYPE (MAP_FD,		REL|EXEC|DYN)
diff --git a/backends/common-reloc.c b/backends/common-reloc.c
new file mode 100644
index 0000000..096ed1c
--- /dev/null
+++ b/backends/common-reloc.c
@@ -0,0 +1,162 @@
+/* Common code for ebl reloc functions.
+   Copyright (C) 2005, 2006 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include "libebl_CPU.h"
+#include <assert.h>
+
+#define R_TYPE(name)		PASTE (RELOC_PREFIX, name)
+#define PASTE(a, b)		PASTE_1 (a, b)
+#define PASTE_1(a, b)		a##b
+#define R_NAME(name)		R_NAME_1 (RELOC_PREFIX, name)
+#define R_NAME_1(prefix, type)	R_NAME_2 (prefix, type)
+#define R_NAME_2(prefix, type)	#prefix #type
+
+#define RELOC_TYPES		STRINGIFIED_PASTE (BACKEND, reloc.def)
+#define STRINGIFIED_PASTE(a, b)	STRINGIFY (PASTE (a, b))
+#define STRINGIFY(x)		STRINGIFY_1 (x)
+#define STRINGIFY_1(x)		#x
+
+/* Provide a table of reloc type names, in a PIC-friendly fashion.  */
+
+static const struct EBLHOOK(reloc_nametable)
+{
+  char zero;
+#define	RELOC_TYPE(type, uses) \
+  char name_##type[sizeof R_NAME (type)];
+#include RELOC_TYPES
+#undef RELOC_TYPE
+} EBLHOOK(reloc_nametable) =
+  {
+    '\0',
+#define	RELOC_TYPE(type, uses) R_NAME (type),
+#include RELOC_TYPES
+#undef RELOC_TYPE
+  };
+#define reloc_namestr (&EBLHOOK(reloc_nametable).zero)
+
+static const uint_fast16_t EBLHOOK(reloc_nameidx)[] =
+{
+#define	RELOC_TYPE(type, uses) \
+  [R_TYPE (type)] = offsetof (struct EBLHOOK(reloc_nametable), name_##type),
+#include RELOC_TYPES
+#undef RELOC_TYPE
+};
+#define nreloc \
+  ((int) (sizeof EBLHOOK(reloc_nameidx) / sizeof EBLHOOK(reloc_nameidx)[0]))
+
+#define REL	(1 << (ET_REL - 1))
+#define EXEC	(1 << (ET_EXEC - 1))
+#define DYN	(1 << (ET_DYN - 1))
+static const uint8_t EBLHOOK(reloc_valid)[] =
+{
+#define	RELOC_TYPE(type, uses) [R_TYPE (type)] = uses,
+#include RELOC_TYPES
+#undef RELOC_TYPE
+};
+#undef REL
+#undef EXEC
+#undef DYN
+
+const char *
+EBLHOOK(reloc_type_name) (int reloc,
+			  char *buf __attribute__ ((unused)),
+			  size_t len __attribute__ ((unused)))
+{
+#ifdef RELOC_TYPE_ID
+  reloc = RELOC_TYPE_ID (reloc);
+#endif
+
+  if (reloc >= 0 && reloc < nreloc && EBLHOOK(reloc_nameidx)[reloc] != 0)
+    return &reloc_namestr[EBLHOOK(reloc_nameidx)[reloc]];
+  return NULL;
+}
+
+bool
+EBLHOOK(reloc_type_check) (int reloc)
+{
+#ifdef RELOC_TYPE_ID
+  reloc = RELOC_TYPE_ID (reloc);
+#endif
+
+  return reloc >= 0 && reloc < nreloc && EBLHOOK(reloc_nameidx)[reloc] != 0;
+}
+
+bool
+EBLHOOK(reloc_valid_use) (Elf *elf, int reloc)
+{
+  uint8_t uses;
+
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
+  assert (ehdr != NULL);
+  uint8_t type = ehdr->e_type;
+
+#ifdef RELOC_TYPE_ID
+  reloc = RELOC_TYPE_ID (reloc);
+#endif
+
+  uses = EBLHOOK(reloc_valid)[reloc];
+  return type > ET_NONE && type < ET_CORE && (uses & (1 << (type - 1)));
+}
+
+#ifndef NO_COPY_RELOC
+bool
+EBLHOOK(copy_reloc_p) (int reloc)
+{
+  return reloc == R_TYPE (COPY);
+}
+#endif
+
+bool
+EBLHOOK(none_reloc_p) (int reloc)
+{
+  return reloc == R_TYPE (NONE);
+}
+
+#ifndef NO_RELATIVE_RELOC
+bool
+EBLHOOK(relative_reloc_p) (int reloc)
+{
+  return reloc == R_TYPE (RELATIVE);
+}
+#endif
+
+static void
+EBLHOOK(init_reloc) (Ebl *ebl)
+{
+  ebl->reloc_type_name = EBLHOOK(reloc_type_name);
+  ebl->reloc_type_check = EBLHOOK(reloc_type_check);
+  ebl->reloc_valid_use = EBLHOOK(reloc_valid_use);
+  ebl->none_reloc_p = EBLHOOK(none_reloc_p);
+#ifndef NO_COPY_RELOC
+  ebl->copy_reloc_p = EBLHOOK(copy_reloc_p);
+#endif
+#ifndef NO_RELATIVE_RELOC
+  ebl->relative_reloc_p = EBLHOOK(relative_reloc_p);
+#endif
+}
diff --git a/backends/i386_auxv.c b/backends/i386_auxv.c
new file mode 100644
index 0000000..dba63fe
--- /dev/null
+++ b/backends/i386_auxv.c
@@ -0,0 +1,52 @@
+/* i386 specific auxv handling.
+   Copyright (C) 2007 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND i386_
+#include "libebl_CPU.h"
+
+int
+EBLHOOK(auxv_info) (GElf_Xword a_type, const char **name, const char **format)
+{
+  if (a_type != AT_HWCAP)
+    return 0;
+
+  *name = "HWCAP";
+  *format = "b"
+    "fpu\0" "vme\0" "de\0" "pse\0" "tsc\0" "msr\0" "pae\0" "mce\0"
+    "cx8\0" "apic\0" "10\0" "sep\0" "mtrr\0" "pge\0" "mca\0" "cmov\0"
+    "pat\0" "pse36\0" "pn\0" "clflush\0" "20\0" "dts\0" "acpi\0" "mmx\0"
+    "fxsr\0" "sse\0" "sse2\0" "ss\0" "ht\0" "tm\0" "ia64\0" "pbe\0" "\0";
+  return 1;
+}
+
+__typeof (i386_auxv_info) x86_64_auxv_info
+			  __attribute__ ((alias ("i386_auxv_info")));
diff --git a/backends/i386_cfi.c b/backends/i386_cfi.c
new file mode 100644
index 0000000..31f85f7
--- /dev/null
+++ b/backends/i386_cfi.c
@@ -0,0 +1,68 @@
+/* i386 ABI-specified defaults for DWARF CFI.
+   Copyright (C) 2009 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#define BACKEND i386_
+#include "libebl_CPU.h"
+
+int
+i386_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info)
+{
+  static const uint8_t abi_cfi[] =
+    {
+      /* Call-saved regs.  */
+      DW_CFA_same_value, ULEB128_7 (3), /* %ebx */
+      DW_CFA_same_value, ULEB128_7 (5), /* %ebp */
+      DW_CFA_same_value, ULEB128_7 (6), /* %esi */
+      DW_CFA_same_value, ULEB128_7 (7), /* %edi */
+
+      /* The CFA is the SP.  */
+      DW_CFA_val_offset, ULEB128_7 (4), ULEB128_7 (0),
+
+      /* Segment registers are call-saved if ever used at all.  */
+      DW_CFA_same_value, ULEB128_7 (40), /* %es */
+      DW_CFA_same_value, ULEB128_7 (41), /* %cs */
+      DW_CFA_same_value, ULEB128_7 (42), /* %ss */
+      DW_CFA_same_value, ULEB128_7 (43), /* %ds */
+      DW_CFA_same_value, ULEB128_7 (44), /* %fs */
+      DW_CFA_same_value, ULEB128_7 (45), /* %gs */
+    };
+
+  abi_info->initial_instructions = abi_cfi;
+  abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
+  abi_info->data_alignment_factor = 4;
+
+  abi_info->return_address_register = 8; /* %eip */
+
+  return 0;
+}
diff --git a/backends/i386_corenote.c b/backends/i386_corenote.c
new file mode 100644
index 0000000..15cd66b
--- /dev/null
+++ b/backends/i386_corenote.c
@@ -0,0 +1,138 @@
+/* i386 specific core note handling.
+   Copyright (C) 2007-2010 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#define BACKEND i386_
+#include "libebl_CPU.h"
+
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+#define GR(at, n, dwreg)						\
+    { .offset = at * 4, .regno = dwreg, .count = n, .bits = 32 }
+#define SR(at, n, dwreg)						\
+    { .offset = at * 4, .regno = dwreg, .count = n, .bits = 16, .pad = 2 }
+
+    GR (0, 1, 3),		/* %ebx */
+    GR (1, 2, 1),		/* %ecx-%edx */
+    GR (3, 2, 6),		/* %esi-%edi */
+    GR (5, 1, 5),		/* %ebp */
+    GR (6, 1, 0),		/* %eax */
+    SR (7, 1, 43),		/* %ds */
+    SR (8, 1, 40),		/* %es */
+    SR (9, 1, 44),		/* %fs */
+    SR (10, 1, 45),		/* %gs */
+    /*  11, 1,			   orig_eax */
+    GR (12, 1, 8),		/* %eip */
+    SR (13, 1, 41),		/* %cs */
+    GR (14, 1, 9),		/* eflags */
+    GR (15, 1, 4),		/* %esp */
+    SR (16, 1, 42),		/* %ss */
+
+#undef	GR
+#undef	SR
+  };
+#define PRSTATUS_REGS_SIZE	(17 * 4)
+
+#define	ULONG			uint32_t
+#define PID_T			int32_t
+#define	UID_T			uint16_t
+#define	GID_T			uint16_t
+#define ALIGN_ULONG		4
+#define ALIGN_PID_T		4
+#define ALIGN_UID_T		2
+#define ALIGN_GID_T		2
+#define TYPE_ULONG		ELF_T_WORD
+#define TYPE_PID_T		ELF_T_SWORD
+#define TYPE_UID_T		ELF_T_HALF
+#define TYPE_GID_T		ELF_T_HALF
+
+#define PRSTATUS_REGSET_ITEMS						      \
+  {									      \
+    .name = "orig_eax", .type = ELF_T_SWORD, .format = 'd',		      \
+    .offset = offsetof (struct EBLHOOK(prstatus), pr_reg) + (4 * 11),	      \
+    .group = "register"	       			  	       	 	      \
+  }
+
+static const Ebl_Register_Location fpregset_regs[] =
+  {
+    { .offset = 0, .regno = 37, .count = 2, .bits = 32 }, /* fctrl-fstat */
+    { .offset = 7 * 4, .regno = 11, .count = 8, .bits = 80 }, /* stN */
+  };
+#define FPREGSET_SIZE	108
+
+static const Ebl_Register_Location prxfpreg_regs[] =
+  {
+    { .offset = 0, .regno = 37, .count = 2, .bits = 16 }, /* fctrl-fstat */
+    { .offset = 24, .regno = 39, .count = 1, .bits = 32 }, /* mxcsr */
+    { .offset = 32, .regno = 11, .count = 8, .bits = 80, .pad = 6 }, /* stN */
+    { .offset = 32 + 128, .regno = 21, .count = 8, .bits = 128 }, /* xmm */
+  };
+
+#define	EXTRA_NOTES \
+  EXTRA_REGSET (NT_PRXFPREG, 512, prxfpreg_regs) \
+  case NT_386_TLS: \
+    return tls_info (nhdr->n_descsz, regs_offset, nregloc, reglocs, \
+		     nitems, items);				    \
+  EXTRA_NOTES_IOPERM
+
+static const Ebl_Core_Item tls_items[] =
+  {
+    { .type = ELF_T_WORD, .offset = 0x0, .format = 'd', .name = "index" },
+    { .type = ELF_T_WORD, .offset = 0x4, .format = 'x', .name = "base" },
+    { .type = ELF_T_WORD, .offset = 0x8, .format = 'x', .name = "limit" },
+    { .type = ELF_T_WORD, .offset = 0xc, .format = 'x', .name = "flags" },
+  };
+
+static int
+tls_info (GElf_Word descsz, GElf_Word *regs_offset,
+	  size_t *nregloc, const Ebl_Register_Location **reglocs,
+	  size_t *nitems, const Ebl_Core_Item **items)
+{
+  if (descsz % 16 != 0)
+    return 0;
+
+  *regs_offset = 0;
+  *nregloc = 0;
+  *reglocs = NULL;
+  *nitems = sizeof tls_items / sizeof tls_items[0];
+  *items = tls_items;
+  return 1;
+}
+
+#include "x86_corenote.c"
+#include "linux-core-note.c"
diff --git a/backends/i386_init.c b/backends/i386_init.c
new file mode 100644
index 0000000..fc1587a
--- /dev/null
+++ b/backends/i386_init.c
@@ -0,0 +1,71 @@
+/* Initialization of i386 specific backend library.
+   Copyright (C) 2000-2009, 2013, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		i386_
+#define RELOC_PREFIX	R_386_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on i386_reloc.def.  */
+#include "common-reloc.c"
+
+const char *
+i386_init (Elf *elf __attribute__ ((unused)),
+	   GElf_Half machine __attribute__ ((unused)),
+	   Ebl *eh,
+	   size_t ehlen)
+{
+  /* Check whether the Elf_BH object has a sufficent size.  */
+  if (ehlen < sizeof (Ebl))
+    return NULL;
+
+  /* We handle it.  */
+  eh->name = "Intel 80386";
+  i386_init_reloc (eh);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, gotpc_reloc_check);
+  HOOK (eh, core_note);
+  generic_debugscn_p = eh->debugscn_p;
+  HOOK (eh, debugscn_p);
+  HOOK (eh, return_value_location);
+  HOOK (eh, register_info);
+  HOOK (eh, syscall_abi);
+  HOOK (eh, auxv_info);
+  HOOK (eh, disasm);
+  HOOK (eh, abi_cfi);
+  /* gcc/config/ #define DWARF_FRAME_REGISTERS.  For i386 it is 17, why?  */
+  eh->frame_nregs = 9;
+  HOOK (eh, set_initial_registers_tid);
+  HOOK (eh, unwind);
+
+  return MODVERSION;
+}
diff --git a/backends/i386_initreg.c b/backends/i386_initreg.c
new file mode 100644
index 0000000..c344282
--- /dev/null
+++ b/backends/i386_initreg.c
@@ -0,0 +1,79 @@
+/* Fetch live process registers from TID.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if (defined __i386__ || defined __x86_64__) && defined(__linux__)
+# include <sys/types.h>
+# include <sys/user.h>
+# include <sys/ptrace.h>
+#endif
+
+#define BACKEND i386_
+#include "libebl_CPU.h"
+
+bool
+i386_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
+			  ebl_tid_registers_t *setfunc __attribute__ ((unused)),
+				void *arg __attribute__ ((unused)))
+{
+#if (!defined __i386__ && !defined __x86_64__) || !defined(__linux__)
+  return false;
+#else /* __i386__ || __x86_64__ */
+  struct user_regs_struct user_regs;
+  if (ptrace (PTRACE_GETREGS, tid, NULL, &user_regs) != 0)
+    return false;
+  Dwarf_Word dwarf_regs[9];
+# if defined __i386__
+  dwarf_regs[0] = user_regs.eax;
+  dwarf_regs[1] = user_regs.ecx;
+  dwarf_regs[2] = user_regs.edx;
+  dwarf_regs[3] = user_regs.ebx;
+  dwarf_regs[4] = user_regs.esp;
+  dwarf_regs[5] = user_regs.ebp;
+  dwarf_regs[6] = user_regs.esi;
+  dwarf_regs[7] = user_regs.edi;
+  dwarf_regs[8] = user_regs.eip;
+# elif defined __x86_64__
+  dwarf_regs[0] = user_regs.rax;
+  dwarf_regs[1] = user_regs.rcx;
+  dwarf_regs[2] = user_regs.rdx;
+  dwarf_regs[3] = user_regs.rbx;
+  dwarf_regs[4] = user_regs.rsp;
+  dwarf_regs[5] = user_regs.rbp;
+  dwarf_regs[6] = user_regs.rsi;
+  dwarf_regs[7] = user_regs.rdi;
+  dwarf_regs[8] = user_regs.rip;
+# else /* (__i386__ || __x86_64__) && (!__i386__ && !__x86_64__) */
+#  error "source file error, it cannot happen"
+# endif /* (__i386__ || __x86_64__) && (!__i386__ && !__x86_64__) */
+  return setfunc (0, 9, dwarf_regs, arg);
+#endif /* __i386__ || __x86_64__ */
+}
diff --git a/backends/i386_regs.c b/backends/i386_regs.c
new file mode 100644
index 0000000..7ec93bb
--- /dev/null
+++ b/backends/i386_regs.c
@@ -0,0 +1,153 @@
+/* Register names and numbers for i386 DWARF.
+   Copyright (C) 2005, 2006, 2007 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND i386_
+#include "libebl_CPU.h"
+
+ssize_t
+i386_register_info (Ebl *ebl __attribute__ ((unused)),
+		    int regno, char *name, size_t namelen,
+		    const char **prefix, const char **setname,
+		    int *bits, int *type)
+{
+  if (name == NULL)
+    return 46;
+
+  if (regno < 0 || regno > 45 || namelen < 6)
+    return -1;
+
+  *prefix = "%";
+  *bits = 32;
+  *type = DW_ATE_unsigned;
+  if (regno < 11)
+    {
+      *setname = "integer";
+      if (regno < 9)
+	*type = DW_ATE_signed;
+    }
+  else if (regno < 19)
+    {
+      *setname = "x87";
+      *type = DW_ATE_float;
+      *bits = 80;
+    }
+  else if (regno < 29)
+    {
+      *setname = "SSE";
+      *bits = 128;
+    }
+  else if (regno < 37)
+    {
+      *setname = "MMX";
+      *bits = 64;
+    }
+  else if (regno < 40)
+    *setname = "FPU-control";
+  else
+    {
+      *setname = "segment";
+      *bits = 16;
+    }
+
+  switch (regno)
+    {
+      static const char baseregs[][2] =
+	{
+	  "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "ip"
+	};
+
+    case 4:
+    case 5:
+    case 8:
+      *type = DW_ATE_address;
+      FALLTHROUGH;
+    case 0 ... 3:
+    case 6 ... 7:
+      name[0] = 'e';
+      name[1] = baseregs[regno][0];
+      name[2] = baseregs[regno][1];
+      namelen = 3;
+      break;
+
+    case 9:
+      return stpcpy (name, "eflags") + 1 - name;
+    case 10:
+      return stpcpy (name, "trapno") + 1 - name;
+
+    case 11 ... 18:
+      name[0] = 's';
+      name[1] = 't';
+      name[2] = regno - 11 + '0';
+      namelen = 3;
+      break;
+
+    case 21 ... 28:
+      name[0] = 'x';
+      name[1] = 'm';
+      name[2] = 'm';
+      name[3] = regno - 21 + '0';
+      namelen = 4;
+      break;
+
+    case 29 ... 36:
+      name[0] = 'm';
+      name[1] = 'm';
+      name[2] = regno - 29 + '0';
+      namelen = 3;
+      break;
+
+    case 37:
+      *bits = 16;
+      return stpcpy (name, "fctrl") + 1 - name;
+    case 38:
+      *bits = 16;
+      return stpcpy (name, "fstat") + 1 - name;
+    case 39:
+      return stpcpy (name, "mxcsr") + 1 - name;
+
+    case 40 ... 45:
+      name[0] = "ecsdfg"[regno - 40];
+      name[1] = 's';
+      namelen = 2;
+      break;
+
+    default:
+      *setname = NULL;
+      return 0;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
diff --git a/backends/i386_reloc.def b/backends/i386_reloc.def
new file mode 100644
index 0000000..a6a03f3
--- /dev/null
+++ b/backends/i386_reloc.def
@@ -0,0 +1,71 @@
+/* List the relocation types for i386.	-*- C -*-
+   Copyright (C) 2000, 2001, 2002, 2003, 2005, 2009, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,		0)
+RELOC_TYPE (COPY,		EXEC|DYN)
+RELOC_TYPE (32,			REL|EXEC|DYN)
+RELOC_TYPE (PC32,		REL|EXEC|DYN)
+RELOC_TYPE (GOT32,		REL)
+RELOC_TYPE (PLT32,		REL)
+RELOC_TYPE (GLOB_DAT,		EXEC|DYN)
+RELOC_TYPE (JMP_SLOT,		EXEC|DYN)
+RELOC_TYPE (RELATIVE,		EXEC|DYN)
+RELOC_TYPE (GOTOFF,		REL)
+RELOC_TYPE (GOTPC,		REL)
+RELOC_TYPE (32PLT,		REL)
+RELOC_TYPE (TLS_TPOFF,		EXEC|DYN)
+RELOC_TYPE (TLS_IE,		REL)
+RELOC_TYPE (TLS_GOTIE,		REL)
+RELOC_TYPE (TLS_LE,		REL)
+RELOC_TYPE (TLS_GD,		REL)
+RELOC_TYPE (TLS_LDM,		REL)
+RELOC_TYPE (16,			REL)
+RELOC_TYPE (PC16,		REL)
+RELOC_TYPE (8,			REL)
+RELOC_TYPE (PC8,		REL)
+RELOC_TYPE (TLS_GD_32,		REL)
+RELOC_TYPE (TLS_GD_PUSH,	REL)
+RELOC_TYPE (TLS_GD_CALL,	REL)
+RELOC_TYPE (TLS_GD_POP,		REL)
+RELOC_TYPE (TLS_LDM_32,		REL)
+RELOC_TYPE (TLS_LDM_PUSH,	REL)
+RELOC_TYPE (TLS_LDM_CALL,	REL)
+RELOC_TYPE (TLS_LDM_POP,	REL)
+RELOC_TYPE (TLS_LDO_32,		REL)
+RELOC_TYPE (TLS_IE_32,		REL)
+RELOC_TYPE (TLS_LE_32,		REL)
+RELOC_TYPE (TLS_DTPMOD32,	EXEC|DYN)
+RELOC_TYPE (TLS_DTPOFF32,	EXEC|DYN)
+RELOC_TYPE (TLS_TPOFF32,	EXEC|DYN)
+RELOC_TYPE (TLS_GOTDESC,	REL)
+RELOC_TYPE (TLS_DESC_CALL,	REL)
+RELOC_TYPE (TLS_DESC,		EXEC)
+RELOC_TYPE (IRELATIVE,		EXEC|DYN)
+RELOC_TYPE (GOT32X,		REL)
diff --git a/backends/i386_retval.c b/backends/i386_retval.c
new file mode 100644
index 0000000..32fec72
--- /dev/null
+++ b/backends/i386_retval.c
@@ -0,0 +1,140 @@
+/* Function return value location for Linux/i386 ABI.
+   Copyright (C) 2005-2010, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND i386_
+#include "libebl_CPU.h"
+
+
+/* %eax, or pair %eax, %edx.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg0 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg2 }, { .atom = DW_OP_piece, .number = 4 },
+  };
+#define nloc_intreg	1
+#define nloc_intregpair	4
+
+/* %st(0).  */
+static const Dwarf_Op loc_fpreg[] =
+  {
+    { .atom = DW_OP_reg11 }
+  };
+#define nloc_fpreg	1
+
+/* The return value is a structure and is actually stored in stack space
+   passed in a hidden argument by the caller.  But, the compiler
+   helpfully returns the address of that space in %eax.  */
+static const Dwarf_Op loc_aggregate[] =
+  {
+    { .atom = DW_OP_breg0, .number = 0 }
+  };
+#define nloc_aggregate 1
+
+int
+i386_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die die_mem, *typedie = &die_mem;
+  int tag = dwarf_peeled_die_type (functypedie, typedie);
+  if (tag <= 0)
+    return tag;
+
+  switch (tag)
+    {
+    case -1:
+      return -1;
+
+    case DW_TAG_subrange_type:
+      if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
+	{
+	  Dwarf_Attribute attr_mem, *attr;
+	  attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+	  typedie = dwarf_formref_die (attr, &die_mem);
+	  tag = DWARF_TAG_OR_RETURN (typedie);
+	}
+      FALLTHROUGH;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    case DW_TAG_pointer_type:
+    case DW_TAG_ptr_to_member_type:
+      {
+	Dwarf_Word size;
+	Dwarf_Attribute attr_mem;
+	if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+						   &attr_mem), &size) != 0)
+	  {
+	    if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+	      size = 4;
+	    else
+	      return -1;
+	  }
+	if (tag == DW_TAG_base_type)
+	  {
+	    Dwarf_Word encoding;
+	    if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
+						       &attr_mem),
+				 &encoding) != 0)
+	      return -1;
+	    if (encoding == DW_ATE_float)
+	      {
+		if (size > 16)
+		  return -2;
+		*locp = loc_fpreg;
+		return nloc_fpreg;
+	      }
+	  }
+	*locp = loc_intreg;
+	if (size <= 4)
+	  return nloc_intreg;
+	if (size <= 8)
+	  return nloc_intregpair;
+      }
+    FALLTHROUGH;
+
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+    case DW_TAG_array_type:
+      *locp = loc_aggregate;
+      return nloc_aggregate;
+    }
+
+  /* XXX We don't have a good way to return specific errors from ebl calls.
+     This value means we do not understand the type, but it is well-formed
+     DWARF and might be valid.  */
+  return -2;
+}
diff --git a/backends/i386_symbol.c b/backends/i386_symbol.c
new file mode 100644
index 0000000..7dbf899
--- /dev/null
+++ b/backends/i386_symbol.c
@@ -0,0 +1,75 @@
+/* i386 specific symbolic name handling.
+   Copyright (C) 2000, 2001, 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <elf.h>
+#include <stddef.h>
+#include <string.h>
+
+#define BACKEND i386_
+#include "libebl_CPU.h"
+
+
+/* Return true if the symbol type is that referencing the GOT.  */
+bool
+i386_gotpc_reloc_check (Elf *elf __attribute__ ((unused)), int type)
+{
+  return type == R_386_GOTPC;
+}
+
+/* Check for the simple reloc types.  */
+Elf_Type
+i386_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+{
+  switch (type)
+    {
+    case R_386_32:
+      return ELF_T_SWORD;
+    case R_386_16:
+      return ELF_T_HALF;
+    case R_386_8:
+      return ELF_T_BYTE;
+    default:
+      return ELF_T_NUM;
+    }
+}
+
+/* Check section name for being that of a debug information section.  */
+bool (*generic_debugscn_p) (const char *);
+bool
+i386_debugscn_p (const char *name)
+{
+  return (generic_debugscn_p (name)
+	  || strcmp (name, ".stab") == 0
+	  || strcmp (name, ".stabstr") == 0);
+}
diff --git a/backends/i386_syscall.c b/backends/i386_syscall.c
new file mode 100644
index 0000000..535dcd8
--- /dev/null
+++ b/backends/i386_syscall.c
@@ -0,0 +1,50 @@
+/* Linux/i386 system call ABI in DWARF register numbers.
+   Copyright (C) 2008 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND i386_
+#include "libebl_CPU.h"
+
+int
+i386_syscall_abi (Ebl *ebl __attribute__ ((unused)),
+		  int *sp, int *pc, int *callno, int args[6])
+{
+  *sp = 4;			/* %esp */
+  *pc = 8;			/* %eip */
+  *callno = 0;			/* %eax */
+  args[0] = 3;			/* %ebx */
+  args[1] = 1;			/* %ecx */
+  args[2] = 2;			/* %edx */
+  args[3] = 6;			/* %esi */
+  args[4] = 7;			/* %edi */
+  args[5] = 5;			/* %ebp */
+  return 0;
+}
diff --git a/backends/i386_unwind.c b/backends/i386_unwind.c
new file mode 100644
index 0000000..5c9a5de
--- /dev/null
+++ b/backends/i386_unwind.c
@@ -0,0 +1,84 @@
+/* Get previous frame state for an existing frame state using frame pointers.
+   Copyright (C) 2017 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <assert.h>
+
+#define BACKEND i386_
+#include "libebl_CPU.h"
+
+/* Register numbers for frame and stack pointers.  We take advantage of
+   them being next to each other when calling getfunc and setfunc.  */
+#define ESP 4
+#define EBP (ESP + 1)
+
+/* Most basic frame pointer chasing with EBP as frame pointer.
+   PC = *(FP + 4), SP = FP + 8, FP = *FP.  */
+bool
+i386_unwind (Ebl *ebl __attribute__ ((unused)),
+	     Dwarf_Addr pc __attribute__ ((unused)),
+	     ebl_tid_registers_t *setfunc, ebl_tid_registers_get_t *getfunc,
+	     ebl_pid_memory_read_t *readfunc, void *arg,
+	     bool *signal_framep __attribute__ ((unused)))
+{
+  /* sp = 0, fp = 1 */
+  Dwarf_Word regs[2];
+
+  /* Get current stack and frame pointers.  */
+  if (! getfunc (ESP, 2, regs, arg))
+    return false;
+
+  Dwarf_Word sp = regs[0];
+  Dwarf_Word fp = regs[1];
+
+  /* Sanity check.  We only support traditional stack frames.  */
+  if (fp == 0 || sp == 0 || fp < sp)
+    return false;
+
+  /* Get the return address from the stack, it is our new pc.  */
+  Dwarf_Word ret_addr;
+  if (! readfunc (fp + 4, &ret_addr, arg) || ret_addr == 0)
+    return false;
+
+  /* Get new sp and fp.  Sanity check again.  */
+  sp = fp + 8;
+  if (! readfunc (fp, &fp, arg) || fp == 0 || sp >= fp)
+    return false;
+
+  /* Set new sp, fp and pc.  */
+  regs[0] = sp;
+  regs[1] = fp;
+  if (! setfunc (ESP, 2, regs, arg) || ! setfunc (-1, 1, &ret_addr, arg))
+    return false;
+
+  return true;
+}
diff --git a/backends/ia64_init.c b/backends/ia64_init.c
new file mode 100644
index 0000000..7241d7b
--- /dev/null
+++ b/backends/ia64_init.c
@@ -0,0 +1,66 @@
+/* Initialization of IA-64 specific backend library.
+   Copyright (C) 2002, 2003, 2005, 2006, 2007, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		ia64_
+#define RELOC_PREFIX	R_IA64_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on ia64_reloc.def.  */
+#include "common-reloc.c"
+
+const char *
+ia64_init (Elf *elf __attribute__ ((unused)),
+	   GElf_Half machine __attribute__ ((unused)),
+	   Ebl *eh,
+	   size_t ehlen)
+{
+  /* Check whether the Elf_BH object has a sufficent size.  */
+  if (ehlen < sizeof (Ebl))
+    return NULL;
+
+  /* We handle it.  */
+  eh->name = "Intel IA-64";
+  ia64_init_reloc (eh);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, segment_type_name);
+  HOOK (eh, section_type_name);
+  HOOK (eh, dynamic_tag_name);
+  HOOK (eh, dynamic_tag_check);
+  HOOK (eh, machine_flag_check);
+  HOOK (eh, machine_section_flag_check);
+  HOOK (eh, register_info);
+  HOOK (eh, return_value_location);
+  HOOK (eh, check_reloc_target_type);
+
+  return MODVERSION;
+}
diff --git a/backends/ia64_regs.c b/backends/ia64_regs.c
new file mode 100644
index 0000000..a27fe63
--- /dev/null
+++ b/backends/ia64_regs.c
@@ -0,0 +1,273 @@
+/* Register names and numbers for IA64 DWARF.
+   Copyright (C) 2006 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND i386_
+#include "libebl_CPU.h"
+
+ssize_t
+ia64_register_info (Ebl *ebl __attribute__ ((unused)),
+		    int regno, char *name, size_t namelen,
+		    const char **prefix, const char **setname,
+		    int *bits, int *type)
+{
+  if (name == NULL)
+    return 687 + 64;
+
+  if (regno < 0 || regno > 687 + 63 || namelen < 12)
+    return -1;
+
+  *prefix = "ar.";
+  *setname = "application";
+  *bits = 64;
+  *type = DW_ATE_signed;
+  switch (regno)
+    {
+    case 0 ... 9:
+      name[0] = 'r';
+      name[1] = (regno - 0) + '0';
+      namelen = 2;
+      *setname = "integer";
+      *prefix = "";
+      break;
+
+    case 10 ... 99:
+      name[0] = 'r';
+      name[1] = (regno - 0) / 10 + '0';
+      name[2] = (regno - 0) % 10 + '0';
+      namelen = 3;
+      *setname = "integer";
+      *prefix = "";
+      break;
+
+    case 100 ... 127:
+      name[0] = 'r';
+      name[1] = '1';
+      name[2] = (regno - 100) / 10 + '0';
+      name[3] = (regno - 0) % 10 + '0';
+      namelen = 4;
+      *setname = "integer";
+      *prefix = "";
+      break;
+
+    case 128 + 0 ... 128 + 9:
+      name[0] = 'f';
+      name[1] = (regno - 128) + '0';
+      namelen = 2;
+      *type = DW_ATE_float;
+      *bits = 128;
+      *setname = "FPU";
+      *prefix = "";
+      break;
+
+    case 128 + 10 ... 128 + 99:
+      name[0] = 'f';
+      name[1] = (regno - 128) / 10 + '0';
+      name[2] = (regno - 128) % 10 + '0';
+      namelen = 3;
+      *setname = "FPU";
+      *prefix = "";
+      break;
+
+    case 128 + 100 ... 128 + 127:
+      name[0] = 'f';
+      name[1] = '1';
+      name[2] = (regno - 128 - 100) / 10 + '0';
+      name[3] = (regno - 128) % 10 + '0';
+      namelen = 4;
+      *type = DW_ATE_float;
+      *bits = 128;
+      *setname = "FPU";
+      *prefix = "";
+      break;
+
+    case 320 + 0 ... 320 + 7:
+      name[0] = 'b';
+      name[1] = (regno - 320) + '0';
+      namelen = 2;
+      *type = DW_ATE_address;
+      *setname = "branch";
+      *prefix = "";
+      break;
+
+    case 328 ... 333:
+      {
+	static const char named_special[][5] =
+	  {
+	    "vfp", "vrap", "pr", "ip", "psr", "cfm"
+	  };
+	*setname = "special";
+	*prefix = "";
+	*type = regno == 331 ? DW_ATE_address : DW_ATE_unsigned;
+	return stpcpy (name, named_special[regno - 328]) + 1 - name;
+      }
+
+    case 590:
+      *setname = "special";
+      *prefix = "";
+      *type = DW_ATE_unsigned;
+      return stpcpy (name, "bof") + 1 - name;
+
+    case 334 + 0 ... 334 + 7:
+      name[0] = 'k';
+      name[1] = 'r';
+      name[2] = (regno - 334) + '0';
+      namelen = 3;
+      *prefix = "";
+      break;
+
+    case 334 + 8 ... 334 + 127:
+      {
+	static const char named_ar[][9] =
+	  {
+	    [16 - 8] = "rsc",
+	    [17 - 8] = "bsp",
+	    [18 - 8] = "bspstore",
+	    [19 - 8] = "rnat",
+	    [21 - 8] = "fcr",
+	    [24 - 8] = "eflag",
+	    [25 - 8] = "csd",
+	    [26 - 8] = "ssd",
+	    [27 - 8] = "cflg",
+	    [28 - 8] = "fsr",
+	    [29 - 8] = "fir",
+	    [30 - 8] = "fdr",
+	    [32 - 8] = "ccv",
+	    [36 - 8] = "unat",
+	    [40 - 8] = "fpsr",
+	    [44 - 8] = "itc",
+	    [64 - 8] = "pfs",
+	    [65 - 8] = "lc",
+	    [66 - 8] = "ec",
+	  };
+	const size_t idx = regno - (334 + 8);
+	*type = DW_ATE_unsigned;
+	if (idx == 1 || idx == 2)
+	  *type = DW_ATE_address;
+	if (idx < sizeof named_ar / sizeof named_ar[0]
+	    && named_ar[idx][0] != '\0')
+	  return stpcpy (name, named_ar[idx]) + 1 - name;
+
+	name[0] = 'a';
+	name[1] = 'r';
+	switch (regno - 334)
+	  {
+	  case 0 ... 9:
+	    name[2] = (regno - 334) + '0';
+	    namelen = 3;
+	    break;
+	  case 10 ... 99:
+	    name[2] = (regno - 334) / 10 + '0';
+	    name[3] = (regno - 334) % 10 + '0';
+	    namelen = 4;
+	    break;
+	  case 100 ... 127:
+	    name[2] = '1';
+	    name[3] = (regno - 334 - 100) / 10 + '0';
+	    name[4] = (regno - 334) % 10 + '0';
+	    namelen = 5;
+	    break;
+	  }
+	*prefix = "";
+	break;
+      }
+
+    case 462 + 0 ... 462 + 9:
+      name[0] = 'n';
+      name[1] = 'a';
+      name[2] = 't';
+      name[3] = (regno - 462) + '0';
+      namelen = 4;
+      *setname = "NAT";
+      *type = DW_ATE_boolean;
+      *bits = 1;
+      *prefix = "";
+      break;
+
+    case 462 + 10 ... 462 + 99:
+      name[0] = 'n';
+      name[1] = 'a';
+      name[2] = 't';
+      name[3] = (regno - 462) / 10 + '0';
+      name[4] = (regno - 462) % 10 + '0';
+      namelen = 5;
+      *setname = "NAT";
+      *type = DW_ATE_boolean;
+      *bits = 1;
+      *prefix = "";
+      break;
+
+    case 462 + 100 ... 462 + 127:
+      name[0] = 'n';
+      name[1] = 'a';
+      name[2] = 't';
+      name[3] = '1';
+      name[4] = (regno - 462 - 100) / 10 + '0';
+      name[5] = (regno - 462) % 10 + '0';
+      namelen = 6;
+      *setname = "NAT";
+      *type = DW_ATE_boolean;
+      *bits = 1;
+      *prefix = "";
+      break;
+
+    case 687 + 0 ... 687 + 9:
+      name[0] = 'p';
+      name[1] = (regno - 687) + '0';
+      namelen = 2;
+      *setname = "predicate";
+      *type = DW_ATE_boolean;
+      *bits = 1;
+      *prefix = "";
+      break;
+
+    case 687 + 10 ... 687 + 63:
+      name[0] = 'p';
+      name[1] = (regno - 687) / 10 + '0';
+      name[2] = (regno - 687) % 10 + '0';
+      namelen = 3;
+      *setname = "predicate";
+      *type = DW_ATE_boolean;
+      *bits = 1;
+      *prefix = "";
+      break;
+
+    default:
+      *setname = NULL;
+      return 0;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
diff --git a/backends/ia64_reloc.def b/backends/ia64_reloc.def
new file mode 100644
index 0000000..2428925
--- /dev/null
+++ b/backends/ia64_reloc.def
@@ -0,0 +1,113 @@
+/* List the relocation types for ia64.  -*- C -*-
+   Copyright (C) 2005, 2006, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,		0)
+RELOC_TYPE (IMM14,		REL)
+RELOC_TYPE (IMM22,		REL)
+RELOC_TYPE (IMM64,		REL)
+RELOC_TYPE (DIR32MSB,		REL|EXEC|DYN)
+RELOC_TYPE (DIR32LSB,		REL|EXEC|DYN)
+RELOC_TYPE (DIR64MSB,		REL|EXEC|DYN)
+RELOC_TYPE (DIR64LSB,		REL|EXEC|DYN)
+RELOC_TYPE (GPREL22,		REL)
+RELOC_TYPE (GPREL64I,		REL)
+RELOC_TYPE (GPREL32MSB,		REL)
+RELOC_TYPE (GPREL32LSB,		REL)
+RELOC_TYPE (GPREL64MSB,		REL)
+RELOC_TYPE (GPREL64LSB,		REL)
+RELOC_TYPE (LTOFF22,		REL)
+RELOC_TYPE (LTOFF64I,		REL)
+RELOC_TYPE (PLTOFF22,		REL)
+RELOC_TYPE (PLTOFF64I,		REL)
+RELOC_TYPE (PLTOFF64MSB,	REL)
+RELOC_TYPE (PLTOFF64LSB,	REL)
+RELOC_TYPE (FPTR64I,		REL)
+RELOC_TYPE (FPTR32MSB,		REL|EXEC|DYN)
+RELOC_TYPE (FPTR32LSB,		REL|EXEC|DYN)
+RELOC_TYPE (FPTR64MSB,		REL|EXEC|DYN)
+RELOC_TYPE (FPTR64LSB,		REL|EXEC|DYN)
+RELOC_TYPE (PCREL60B,		REL)
+RELOC_TYPE (PCREL21B,		REL)
+RELOC_TYPE (PCREL21M,		REL)
+RELOC_TYPE (PCREL21F,		REL)
+RELOC_TYPE (PCREL32MSB,		REL|EXEC|DYN)
+RELOC_TYPE (PCREL32LSB,		REL|EXEC|DYN)
+RELOC_TYPE (PCREL64MSB,		REL|EXEC|DYN)
+RELOC_TYPE (PCREL64LSB,		REL|EXEC|DYN)
+RELOC_TYPE (LTOFF_FPTR22,	REL)
+RELOC_TYPE (LTOFF_FPTR64I,	REL)
+RELOC_TYPE (LTOFF_FPTR32MSB,	REL)
+RELOC_TYPE (LTOFF_FPTR32LSB,	REL)
+RELOC_TYPE (LTOFF_FPTR64MSB,	REL)
+RELOC_TYPE (LTOFF_FPTR64LSB,	REL)
+RELOC_TYPE (SEGREL32MSB,	REL)
+RELOC_TYPE (SEGREL32LSB,	REL)
+RELOC_TYPE (SEGREL64MSB,	REL)
+RELOC_TYPE (SEGREL64LSB,	REL)
+RELOC_TYPE (SECREL32MSB,	REL)
+RELOC_TYPE (SECREL32LSB,	REL)
+RELOC_TYPE (SECREL64MSB,	REL)
+RELOC_TYPE (SECREL64LSB,	REL)
+RELOC_TYPE (REL32MSB,		EXEC|DYN)
+RELOC_TYPE (REL32LSB,		EXEC|DYN)
+RELOC_TYPE (REL64MSB,		EXEC|DYN)
+RELOC_TYPE (REL64LSB,		EXEC|DYN)
+RELOC_TYPE (LTV32MSB,		REL)
+RELOC_TYPE (LTV32LSB,		REL)
+RELOC_TYPE (LTV64MSB,		REL)
+RELOC_TYPE (LTV64LSB,		REL)
+RELOC_TYPE (PCREL21BI,		REL)
+RELOC_TYPE (PCREL22,		REL)
+RELOC_TYPE (PCREL64I,		REL)
+RELOC_TYPE (IPLTMSB,		REL|EXEC|DYN)
+RELOC_TYPE (IPLTLSB,		REL|EXEC|DYN)
+RELOC_TYPE (COPY,		EXEC|DYN)
+RELOC_TYPE (SUB,		0)
+RELOC_TYPE (LTOFF22X,		REL)
+RELOC_TYPE (LDXMOV,		REL)
+RELOC_TYPE (TPREL14,		REL)
+RELOC_TYPE (TPREL22,		REL)
+RELOC_TYPE (TPREL64I,		REL)
+RELOC_TYPE (TPREL64MSB,		REL|EXEC|DYN)
+RELOC_TYPE (TPREL64LSB,		REL|EXEC|DYN)
+RELOC_TYPE (LTOFF_TPREL22,	REL)
+RELOC_TYPE (DTPMOD64MSB,	REL|EXEC|DYN)
+RELOC_TYPE (DTPMOD64LSB,	REL|EXEC|DYN)
+RELOC_TYPE (LTOFF_DTPMOD22,	REL)
+RELOC_TYPE (DTPREL14,		REL)
+RELOC_TYPE (DTPREL22,		REL)
+RELOC_TYPE (DTPREL64I,		REL)
+RELOC_TYPE (DTPREL32MSB,	REL|EXEC|DYN)
+RELOC_TYPE (DTPREL32LSB,	REL|EXEC|DYN)
+RELOC_TYPE (DTPREL64MSB,	REL|EXEC|DYN)
+RELOC_TYPE (DTPREL64LSB,	REL|EXEC|DYN)
+RELOC_TYPE (LTOFF_DTPREL22,	REL)
+
+#define NO_RELATIVE_RELOC	1
diff --git a/backends/ia64_retval.c b/backends/ia64_retval.c
new file mode 100644
index 0000000..03ea4d8
--- /dev/null
+++ b/backends/ia64_retval.c
@@ -0,0 +1,366 @@
+/* Function return value location for IA64 ABI.
+   Copyright (C) 2006-2010, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND ia64_
+#include "libebl_CPU.h"
+
+
+/* r8, or pair r8, r9, or aggregate up to r8-r11.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg8 }, { .atom = DW_OP_piece, .number = 8 },
+    { .atom = DW_OP_reg9 }, { .atom = DW_OP_piece, .number = 8 },
+    { .atom = DW_OP_reg10 }, { .atom = DW_OP_piece, .number = 8 },
+    { .atom = DW_OP_reg11 }, { .atom = DW_OP_piece, .number = 8 },
+  };
+#define nloc_intreg	1
+#define nloc_intregs(n)	(2 * (n))
+
+/* f8, or aggregate up to f8-f15.  */
+#define DEFINE_FPREG(size) 						      \
+  static const Dwarf_Op loc_fpreg_##size[] =				      \
+    {									      \
+      { .atom = DW_OP_regx, .number = 128 + 8 },			      \
+      { .atom = DW_OP_piece, .number = size },				      \
+      { .atom = DW_OP_regx, .number = 128 + 9 },			      \
+      { .atom = DW_OP_piece, .number = size },				      \
+      { .atom = DW_OP_regx, .number = 128 + 10 },			      \
+      { .atom = DW_OP_piece, .number = size },				      \
+      { .atom = DW_OP_regx, .number = 128 + 11 },			      \
+      { .atom = DW_OP_piece, .number = size },				      \
+      { .atom = DW_OP_regx, .number = 128 + 12 },			      \
+      { .atom = DW_OP_piece, .number = size },				      \
+      { .atom = DW_OP_regx, .number = 128 + 13 },			      \
+      { .atom = DW_OP_piece, .number = size },				      \
+      { .atom = DW_OP_regx, .number = 128 + 14 },			      \
+      { .atom = DW_OP_piece, .number = size },				      \
+      { .atom = DW_OP_regx, .number = 128 + 15 },			      \
+      { .atom = DW_OP_piece, .number = size },				      \
+    }
+#define nloc_fpreg	1
+#define nloc_fpregs(n)	(2 * (n))
+
+DEFINE_FPREG (4);
+DEFINE_FPREG (8);
+DEFINE_FPREG (10);
+
+#undef DEFINE_FPREG
+
+
+/* The return value is a structure and is actually stored in stack space
+   passed in a hidden argument by the caller.  But, the compiler
+   helpfully returns the address of that space in r8.  */
+static const Dwarf_Op loc_aggregate[] =
+  {
+    { .atom = DW_OP_breg8, .number = 0 }
+  };
+#define nloc_aggregate 1
+
+
+static inline int
+compute_hfa (const Dwarf_Op *loc, int nregs,
+	     const Dwarf_Op **locp, int fpregs_used)
+{
+  if (fpregs_used == 0)
+    *locp = loc;
+  else if (*locp != loc)
+    return 9;
+  return fpregs_used + nregs;
+}
+
+/* If this type is an HFA small enough to be returned in FP registers,
+   return the number of registers to use.  Otherwise 9, or -1 for errors.  */
+static int
+hfa_type (Dwarf_Die *typedie, Dwarf_Word size,
+	  const Dwarf_Op **locp, int fpregs_used)
+{
+  /* Descend the type structure, counting elements and finding their types.
+     If we find a datum that's not an FP type (and not quad FP), punt.
+     If we find a datum that's not the same FP type as the first datum, punt.
+     If we count more than eight total homogeneous FP data, punt.  */
+
+  int tag = DWARF_TAG_OR_RETURN (typedie);
+  switch (tag)
+    {
+      Dwarf_Attribute attr_mem;
+
+    case -1:
+      return -1;
+
+    case DW_TAG_base_type:;
+      Dwarf_Word encoding;
+      if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
+						 &attr_mem), &encoding) != 0)
+	return -1;
+
+#define hfa(loc, nregs) compute_hfa(loc, nregs, locp, fpregs_used)
+      switch (encoding)
+	{
+	case DW_ATE_float:
+	  switch (size)
+	    {
+	    case 4:		/* float */
+	      return hfa (loc_fpreg_4, 1);
+	    case 8:		/* double */
+	      return hfa (loc_fpreg_8, 1);
+	    case 10:       /* x86-style long double, not really used */
+	      return hfa (loc_fpreg_10, 1);
+	    }
+	  break;
+
+	case DW_ATE_complex_float:
+	  switch (size)
+	    {
+	    case 4 * 2:	/* complex float */
+	      return hfa (loc_fpreg_4, 2);
+	    case 8 * 2:	/* complex double */
+	      return hfa (loc_fpreg_8, 2);
+	    case 10 * 2:	/* complex long double (x86-style) */
+	      return hfa (loc_fpreg_10, 2);
+	    }
+	  break;
+	}
+      break;
+
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:;
+      Dwarf_Die child_mem;
+      switch (dwarf_child (typedie, &child_mem))
+	{
+	default:
+	  return -1;
+
+	case 1:			/* No children: empty struct.  */
+	  break;
+
+	case 0:;		/* Look at each element.  */
+	  int max_used = fpregs_used;
+	  do
+	    switch (dwarf_tag (&child_mem))
+	      {
+	      case -1:
+		return -1;
+
+	      case DW_TAG_member:;
+		Dwarf_Die child_type_mem;
+		Dwarf_Die *child_typedie
+		  = dwarf_formref_die (dwarf_attr_integrate (&child_mem,
+							     DW_AT_type,
+							     &attr_mem),
+				       &child_type_mem);
+		Dwarf_Word child_size;
+		if (dwarf_aggregate_size (child_typedie, &child_size) != 0)
+		  return -1;
+		if (tag == DW_TAG_union_type)
+		  {
+		    int used = hfa_type (child_typedie, child_size,
+					 locp, fpregs_used);
+		    if (used < 0 || used > 8)
+		      return used;
+		    if (used > max_used)
+		      max_used = used;
+		  }
+		else
+		  {
+		    fpregs_used = hfa_type (child_typedie, child_size,
+					    locp, fpregs_used);
+		    if (fpregs_used < 0 || fpregs_used > 8)
+		      return fpregs_used;
+		  }
+	      }
+	  while (dwarf_siblingof (&child_mem, &child_mem) == 0);
+	  if (tag == DW_TAG_union_type)
+	    fpregs_used = max_used;
+	  break;
+	}
+      break;
+
+    case DW_TAG_array_type:
+      if (size == 0)
+	break;
+
+      Dwarf_Die base_type_mem;
+      Dwarf_Die *base_typedie
+	= dwarf_formref_die (dwarf_attr_integrate (typedie, DW_AT_type,
+						   &attr_mem),
+			     &base_type_mem);
+      Dwarf_Word base_size;
+      if (dwarf_aggregate_size (base_typedie, &base_size) != 0)
+	return -1;
+
+      int used = hfa_type (base_typedie, base_size, locp, 0);
+      if (used < 0 || used > 8)
+	return used;
+      if (size % (*locp)[1].number != 0)
+	return 0;
+      fpregs_used += used * (size / (*locp)[1].number);
+      break;
+
+    default:
+      return 9;
+    }
+
+  return fpregs_used;
+}
+
+int
+ia64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die die_mem, *typedie = &die_mem;
+  int tag = dwarf_peeled_die_type (functypedie, typedie);
+  if (tag <= 0)
+    return tag;
+
+  Dwarf_Word size;
+  switch (tag)
+    {
+    case -1:
+      return -1;
+
+    case DW_TAG_subrange_type:
+      if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
+	{
+	  Dwarf_Attribute attr_mem, *attr;
+	  attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+	  typedie = dwarf_formref_die (attr, &die_mem);
+	  tag = DWARF_TAG_OR_RETURN (typedie);
+	}
+      FALLTHROUGH;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    case DW_TAG_pointer_type:
+    case DW_TAG_ptr_to_member_type:
+      {
+	Dwarf_Attribute attr_mem;
+	if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+						   &attr_mem), &size) != 0)
+	  {
+	    if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+	      size = 8;
+	    else
+	      return -1;
+	  }
+      }
+
+      if (tag == DW_TAG_base_type)
+	{
+	  Dwarf_Attribute attr_mem;
+	  Dwarf_Word encoding;
+	  if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
+						     &attr_mem),
+			       &encoding) != 0)
+	    return -1;
+
+	  switch (encoding)
+	    {
+	    case DW_ATE_float:
+	      switch (size)
+		{
+		case 4:		/* float */
+		  *locp = loc_fpreg_4;
+		  return nloc_fpreg;
+		case 8:		/* double */
+		  *locp = loc_fpreg_8;
+		  return nloc_fpreg;
+		case 10:       /* x86-style long double, not really used */
+		  *locp = loc_fpreg_10;
+		  return nloc_fpreg;
+		case 16:	/* long double, IEEE quad format */
+		  *locp = loc_intreg;
+		  return nloc_intregs (2);
+		}
+	      return -2;
+
+	    case DW_ATE_complex_float:
+	      switch (size)
+		{
+		case 4 * 2:	/* complex float */
+		  *locp = loc_fpreg_4;
+		  return nloc_fpregs (2);
+		case 8 * 2:	/* complex double */
+		  *locp = loc_fpreg_8;
+		  return nloc_fpregs (2);
+		case 10 * 2:	/* complex long double (x86-style) */
+		  *locp = loc_fpreg_10;
+		  return nloc_fpregs (2);
+		case 16 * 2:	/* complex long double (IEEE quad) */
+		  *locp = loc_intreg;
+		  return nloc_intregs (4);
+		}
+	      return -2;
+	    }
+	}
+
+    intreg:
+      *locp = loc_intreg;
+      if (size <= 8)
+	return nloc_intreg;
+      if (size <= 32)
+	return nloc_intregs ((size + 7) / 8);
+
+    large:
+      *locp = loc_aggregate;
+      return nloc_aggregate;
+
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+    case DW_TAG_array_type:
+      if (dwarf_aggregate_size (typedie, &size) != 0)
+	return -1;
+
+      /* If this qualifies as an homogeneous floating-point aggregate
+	 (HFA), then it should be returned in FP regs. */
+      int nfpreg = hfa_type (typedie, size, locp, 0);
+      if (nfpreg < 0)
+	return nfpreg;
+      else if (nfpreg > 0 && nfpreg <= 8)
+	return nfpreg == 1 ? nloc_fpreg : nloc_fpregs (nfpreg);
+
+      if (size > 32)
+	goto large;
+
+      goto intreg;
+    }
+
+  /* XXX We don't have a good way to return specific errors from ebl calls.
+     This value means we do not understand the type, but it is well-formed
+     DWARF and might be valid.  */
+  return -2;
+}
diff --git a/backends/ia64_symbol.c b/backends/ia64_symbol.c
new file mode 100644
index 0000000..f928b0b
--- /dev/null
+++ b/backends/ia64_symbol.c
@@ -0,0 +1,157 @@
+/* IA-64 specific symbolic name handling.
+   Copyright (C) 2002-2009, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <stddef.h>
+#include <assert.h>
+
+#define BACKEND		ia64_
+#include "libebl_CPU.h"
+
+
+const char *
+ia64_segment_type_name (int segment, char *buf __attribute__ ((unused)),
+			size_t len __attribute__ ((unused)))
+{
+  switch (segment)
+    {
+    case PT_IA_64_ARCHEXT:
+      return "IA_64_ARCHEXT";
+    case PT_IA_64_UNWIND:
+      return "IA_64_UNWIND";
+    case PT_IA_64_HP_OPT_ANOT:
+      return "IA_64_HP_OPT_ANOT";
+    case PT_IA_64_HP_HSL_ANOT:
+      return "IA_64_HP_HSL_ANOT";
+    case PT_IA_64_HP_STACK:
+      return "IA_64_HP_STACK";
+    default:
+      break;
+    }
+  return NULL;
+}
+
+const char *
+ia64_dynamic_tag_name (int64_t tag, char *buf __attribute__ ((unused)),
+		       size_t len __attribute__ ((unused)))
+{
+  switch (tag)
+    {
+    case DT_IA_64_PLT_RESERVE:
+      return "IA_64_PLT_RESERVE";
+    default:
+      break;
+    }
+  return NULL;
+}
+
+/* Check dynamic tag.  */
+bool
+ia64_dynamic_tag_check (int64_t tag)
+{
+  return tag == DT_IA_64_PLT_RESERVE;
+}
+
+/* Check whether machine flags are valid.  */
+bool
+ia64_machine_flag_check (GElf_Word flags)
+{
+  return ((flags &~ EF_IA_64_ABI64) == 0);
+}
+
+/* Check whether SHF_MASKPROC flags are valid.  */
+bool
+ia64_machine_section_flag_check (GElf_Xword sh_flags)
+{
+  return (sh_flags &~ (SHF_IA_64_SHORT | SHF_IA_64_NORECOV)) == 0;
+}
+
+/* Return symbolic representation of section type.  */
+const char *
+ia64_section_type_name (int type,
+			char *buf __attribute__ ((unused)),
+			size_t len __attribute__ ((unused)))
+{
+  switch (type)
+    {
+    case SHT_IA_64_EXT:
+      return "IA_64_EXT";
+    case SHT_IA_64_UNWIND:
+      return "IA_64_UNWIND";
+    }
+
+  return NULL;
+}
+
+/* Check for the simple reloc types.  */
+Elf_Type
+ia64_reloc_simple_type (Ebl *ebl, int type)
+{
+  switch (type)
+    {
+      /* The SECREL types when used with non-allocated sections
+	 like .debug_* are the same as direct absolute relocs
+	 applied to those sections, since a 0 section address is assumed.
+	 So we treat them the same here.  */
+
+    case R_IA64_SECREL32MSB:
+    case R_IA64_DIR32MSB:
+      if (ebl->data == ELFDATA2MSB)
+	return ELF_T_WORD;
+      break;
+    case R_IA64_SECREL32LSB:
+    case R_IA64_DIR32LSB:
+      if (ebl->data == ELFDATA2LSB)
+	return ELF_T_WORD;
+      break;
+    case R_IA64_DIR64MSB:
+    case R_IA64_SECREL64MSB:
+      if (ebl->data == ELFDATA2MSB)
+	return ELF_T_XWORD;
+      break;
+    case R_IA64_SECREL64LSB:
+    case R_IA64_DIR64LSB:
+      if (ebl->data == ELFDATA2LSB)
+	return ELF_T_XWORD;
+      break;
+    }
+
+  return ELF_T_NUM;
+}
+
+/* The SHT_IA_64_UNWIND section type is a valid target for relocation.  */
+bool
+ia64_check_reloc_target_type (Ebl *ebl __attribute__ ((unused)), Elf64_Word sh_type)
+{
+  return sh_type == SHT_IA_64_UNWIND;
+}
diff --git a/backends/libebl_CPU.h b/backends/libebl_CPU.h
new file mode 100644
index 0000000..ef2b922
--- /dev/null
+++ b/backends/libebl_CPU.h
@@ -0,0 +1,76 @@
+/* Common interface for libebl modules.
+   Copyright (C) 2000, 2001, 2002, 2003, 2005, 2013, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LIBEBL_CPU_H
+#define _LIBEBL_CPU_H 1
+
+#include <dwarf.h>
+#include <libeblP.h>
+
+#define EBLHOOK(name)	EBLHOOK_1(BACKEND, name)
+#define EBLHOOK_1(a, b)	EBLHOOK_2(a, b)
+#define EBLHOOK_2(a, b)	a##b
+
+/* Constructor.  */
+extern const char *EBLHOOK(init) (Elf *elf, GElf_Half machine,
+				  Ebl *eh, size_t ehlen);
+
+#include "ebl-hooks.h"
+
+#define HOOK(eh, name)	eh->name = EBLHOOK(name)
+
+extern bool (*generic_debugscn_p) (const char *) attribute_hidden;
+
+/* Helper for retval.  Return dwarf_tag (die), but calls return -1
+   if there where previous errors that leave die NULL.  */
+#define DWARF_TAG_OR_RETURN(die)  \
+  ({ Dwarf_Die *_die = (die);	  \
+     if (_die == NULL) return -1; \
+     dwarf_tag (_die); })
+
+/* Get a type die corresponding to DIE.  Peel CV qualifiers off
+   it.  */
+static inline int
+dwarf_peeled_die_type (Dwarf_Die *die, Dwarf_Die *result)
+{
+  Dwarf_Attribute attr_mem;
+  Dwarf_Attribute *attr = dwarf_attr_integrate (die, DW_AT_type, &attr_mem);
+  if (attr == NULL)
+    /* The function has no return value, like a `void' function in C.  */
+    return 0;
+
+  if (dwarf_formref_die (attr, result) == NULL)
+    return -1;
+
+  if (dwarf_peel_type (result, result) != 0)
+    return -1;
+
+  return DWARF_TAG_OR_RETURN (result);
+}
+
+#endif	/* libebl_CPU.h */
diff --git a/backends/linux-core-note.c b/backends/linux-core-note.c
new file mode 100644
index 0000000..9faae4c
--- /dev/null
+++ b/backends/linux-core-note.c
@@ -0,0 +1,315 @@
+/* Common core note type descriptions for Linux.
+   Copyright (C) 2007-2010 Red Hat, Inc.
+   Copyright (C) H.J. Lu <hjl.tools@gmail.com>, 2015.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+
+/* The including CPU_corenote.c file provides prstatus_regs and
+   defines macros ULONG, [PUG]ID_T, and ALIGN_*, TYPE_*.
+
+   Here we describe the common layout used in <linux/elfcore.h>.  */
+
+#define	CHAR			int8_t
+#define	ALIGN_CHAR		1
+#define	TYPE_CHAR		ELF_T_BYTE
+#define	SHORT			uint16_t
+#define ALIGN_SHORT		2
+#define TYPE_SHORT		ELF_T_HALF
+#define	INT			int32_t
+#ifndef ALIGN_INT
+# define ALIGN_INT		4
+#endif
+#define TYPE_INT		ELF_T_SWORD
+#ifndef PR_REG
+# define PR_REG			ULONG
+#endif
+#ifndef ALIGN_PR_REG
+# define ALIGN_PR_REG		ALIGN_ULONG
+#endif
+#ifndef PRPSINFO_UID_T
+# define PRPSINFO_UID_T		UID_T
+# define ALIGN_PRPSINFO_UID_T	ALIGN_UID_T
+# define TYPE_PRPSINFO_UID_T	TYPE_UID_T
+#endif
+#ifndef PRPSINFO_GID_T
+# define PRPSINFO_GID_T		GID_T
+# define ALIGN_PRPSINFO_GID_T	ALIGN_GID_T
+# define TYPE_PRPSINFO_GID_T	TYPE_GID_T
+#endif
+
+#define FIELD(type, name) type name __attribute__ ((aligned (ALIGN_##type)))
+
+struct EBLHOOK(siginfo)
+{
+  FIELD (INT, si_signo);
+  FIELD (INT, si_code);
+  FIELD (INT, si_errno);
+};
+
+struct EBLHOOK(timeval)
+{
+  FIELD (ULONG, tv_sec);
+  FIELD (ULONG, tv_usec);
+};
+
+/* On sparc64, tv_usec (suseconds_t) is actually 32 bits with 32 bits padding.
+   The 'T'|0x80 value for .format indicates this as a special kludge.  */
+#if SUSECONDS_HALF
+# define TIMEVAL_FIELD(name)	FIELD (time, ULONG, name, 'T'|0x80, .count = 2)
+#else
+# define TIMEVAL_FIELD(name)	FIELD (time, ULONG, name, 'T', .count = 2)
+#endif
+
+
+struct EBLHOOK(prstatus)
+{
+  struct EBLHOOK(siginfo) pr_info;
+  FIELD (SHORT, pr_cursig);
+  FIELD (ULONG, pr_sigpend);
+  FIELD (ULONG, pr_sighold);
+  FIELD (PID_T, pr_pid);
+  FIELD (PID_T, pr_ppid);
+  FIELD (PID_T, pr_pgrp);
+  FIELD (PID_T, pr_sid);
+  struct EBLHOOK(timeval) pr_utime;
+  struct EBLHOOK(timeval) pr_stime;
+  struct EBLHOOK(timeval) pr_cutime;
+  struct EBLHOOK(timeval) pr_cstime;
+  struct
+  {
+    FIELD (PR_REG, pr_reg[PRSTATUS_REGS_SIZE / sizeof (PR_REG)]);
+  }
+#ifdef ALIGN_PR_REG
+    __attribute__ ((aligned (ALIGN_PR_REG)))
+#endif
+    ;
+  FIELD (INT, pr_fpvalid);
+}
+#ifdef ALIGN_PRSTATUS
+  attribute_packed __attribute__ ((aligned (ALIGN_PRSTATUS)))
+#endif
+;
+
+#define	FNAMESZ	16
+#define	PRARGSZ	80
+
+struct EBLHOOK(prpsinfo)
+{
+  FIELD (CHAR, pr_state);
+  FIELD (CHAR, pr_sname);
+  FIELD (CHAR, pr_zomb);
+  FIELD (CHAR, pr_nice);
+  FIELD (ULONG, pr_flag);
+  FIELD (PRPSINFO_UID_T, pr_uid);
+  FIELD (PRPSINFO_GID_T, pr_gid);
+  FIELD (PID_T, pr_pid);
+  FIELD (PID_T, pr_ppid);
+  FIELD (PID_T, pr_pgrp);
+  FIELD (PID_T, pr_sid);
+  FIELD (CHAR, pr_fname[FNAMESZ]);
+  FIELD (CHAR, pr_psargs[PRARGSZ]);
+};
+
+#undef	FIELD
+
+#define FIELD(igroup, itype, item, fmt, ...)			\
+    {								\
+      .name = #item,						\
+      .group = #igroup,					\
+      .offset = offsetof (struct EBLHOOK(prstatus), pr_##item),	\
+      .type = TYPE_##itype,					\
+      .format = fmt,						\
+      __VA_ARGS__						\
+    }
+
+static const Ebl_Core_Item prstatus_items[] =
+  {
+    FIELD (signal, INT, info.si_signo, 'd'),
+    FIELD (signal, INT, info.si_code, 'd'),
+    FIELD (signal, INT, info.si_errno, 'd'),
+    FIELD (signal, SHORT, cursig, 'd'),
+
+    /* Use different group name for a newline delimiter.  */
+    FIELD (signal2, ULONG, sigpend, 'B'),
+    FIELD (signal3, ULONG, sighold, 'B'),
+    FIELD (identity, PID_T, pid, 'd', .thread_identifier = true),
+    FIELD (identity, PID_T, ppid, 'd'),
+    FIELD (identity, PID_T, pgrp, 'd'),
+    FIELD (identity, PID_T, sid, 'd'),
+    TIMEVAL_FIELD (utime),
+    TIMEVAL_FIELD (stime),
+    TIMEVAL_FIELD (cutime),
+    TIMEVAL_FIELD (cstime),
+#ifdef PRSTATUS_REGSET_ITEMS
+    PRSTATUS_REGSET_ITEMS,
+#endif
+    FIELD (register, INT, fpvalid, 'd'),
+  };
+
+#undef	FIELD
+
+#define FIELD(igroup, itype, item, fmt, ...)			\
+    {								\
+      .name = #item,						\
+      .group = #igroup,					\
+      .offset = offsetof (struct EBLHOOK(prpsinfo), pr_##item),	\
+      .type = TYPE_##itype,					\
+      .format = fmt,						\
+      __VA_ARGS__						\
+    }
+
+static const Ebl_Core_Item prpsinfo_items[] =
+  {
+    FIELD (state, CHAR, state, 'd'),
+    FIELD (state, CHAR, sname, 'c'),
+    FIELD (state, CHAR, zomb, 'd'),
+    FIELD (state, CHAR, nice, 'd'),
+    FIELD (state, ULONG, flag, 'x'),
+    FIELD (identity, PRPSINFO_UID_T, uid, 'd'),
+    FIELD (identity, PRPSINFO_GID_T, gid, 'd'),
+    FIELD (identity, PID_T, pid, 'd'),
+    FIELD (identity, PID_T, ppid, 'd'),
+    FIELD (identity, PID_T, pgrp, 'd'),
+    FIELD (identity, PID_T, sid, 'd'),
+    FIELD (command, CHAR, fname, 's', .count = FNAMESZ),
+    FIELD (command, CHAR, psargs, 's', .count = PRARGSZ),
+  };
+
+static const Ebl_Core_Item vmcoreinfo_items[] =
+  {
+    {
+      .type = ELF_T_BYTE, .format = '\n'
+    }
+  };
+
+#undef	FIELD
+
+int
+EBLHOOK(core_note) (const GElf_Nhdr *nhdr, const char *name,
+		    GElf_Word *regs_offset, size_t *nregloc,
+		    const Ebl_Register_Location **reglocs,
+		    size_t *nitems, const Ebl_Core_Item **items)
+{
+  switch (nhdr->n_namesz)
+    {
+    case sizeof "CORE" - 1:	/* Buggy old Linux kernels.  */
+      if (memcmp (name, "CORE", nhdr->n_namesz) == 0)
+	break;
+      return 0;
+
+    case sizeof "CORE":
+      if (memcmp (name, "CORE", nhdr->n_namesz) == 0)
+	break;
+      /* Buggy old Linux kernels didn't terminate "LINUX".  */
+      FALLTHROUGH;
+
+    case sizeof "LINUX":
+      if (memcmp (name, "LINUX", nhdr->n_namesz) == 0)
+	break;
+      return 0;
+
+    case sizeof "VMCOREINFO":
+      if (nhdr->n_type != 0
+	  || memcmp (name, "VMCOREINFO", sizeof "VMCOREINFO") != 0)
+	return 0;
+      *regs_offset = 0;
+      *nregloc = 0;
+      *nitems = 1;
+      *items = vmcoreinfo_items;
+      return 1;
+
+    default:
+      return 0;
+    }
+
+  switch (nhdr->n_type)
+    {
+    case NT_PRSTATUS:
+      if (nhdr->n_descsz != sizeof (struct EBLHOOK(prstatus)))
+	return 0;
+      *regs_offset = offsetof (struct EBLHOOK(prstatus), pr_reg);
+      *nregloc = sizeof prstatus_regs / sizeof prstatus_regs[0];
+      *reglocs = prstatus_regs;
+      *nitems = sizeof prstatus_items / sizeof prstatus_items[0];
+      *items = prstatus_items;
+      return 1;
+
+    case NT_PRPSINFO:
+      if (nhdr->n_descsz != sizeof (struct EBLHOOK(prpsinfo)))
+	return 0;
+      *regs_offset = 0;
+      *nregloc = 0;
+      *reglocs = NULL;
+      *nitems = sizeof prpsinfo_items / sizeof prpsinfo_items[0];
+      *items = prpsinfo_items;
+      return 1;
+
+#define EXTRA_REGSET(type, size, table)					      \
+    case type:								      \
+      if (nhdr->n_descsz != size)					      \
+	return 0;							      \
+      *regs_offset = 0;							      \
+      *nregloc = sizeof table / sizeof table[0];			      \
+      *reglocs = table;							      \
+      *nitems = 0;							      \
+      *items = NULL;							      \
+      return 1;
+
+#define EXTRA_REGSET_ITEMS(type, size, table, extra_items)		      \
+    case type:								      \
+      if (nhdr->n_descsz != size)					      \
+	return 0;							      \
+      *regs_offset = 0;							      \
+      *nregloc = sizeof table / sizeof table[0];			      \
+      *reglocs = table;							      \
+      *nitems = sizeof extra_items / sizeof extra_items[0];		      \
+      *items = extra_items;						      \
+      return 1;
+
+#define EXTRA_ITEMS(type, size, extra_items)				      \
+    case type:								      \
+      if (nhdr->n_descsz != size)					      \
+	return 0;							      \
+      *regs_offset = 0;							      \
+      *nregloc = 0;							      \
+      *reglocs = NULL;							      \
+      *nitems = sizeof extra_items / sizeof extra_items[0];		      \
+      *items = extra_items;						      \
+      return 1;
+
+#ifdef FPREGSET_SIZE
+    EXTRA_REGSET (NT_FPREGSET, FPREGSET_SIZE, fpregset_regs)
+#endif
+
+#ifdef EXTRA_NOTES
+    EXTRA_NOTES
+#endif
+    }
+
+  return 0;
+}
diff --git a/backends/m68k_corenote.c b/backends/m68k_corenote.c
new file mode 100644
index 0000000..3c1d019
--- /dev/null
+++ b/backends/m68k_corenote.c
@@ -0,0 +1,72 @@
+/* M68K specific core note handling.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#define BACKEND	m68k_
+#include "libebl_CPU.h"
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+    { .offset = 0, .regno = 1, .count = 14, .bits = 32 }, /* d1-d7, a0-a6 */
+    { .offset = 14 * 4, .regno = 0, .count = 1, .bits = 32 }, /* d0 */
+    { .offset = 15 * 4, .regno = 15, .count = 1, .bits = 32 }, /* a7 */
+    { .offset = 18 * 4, .regno = 24, .count = 1, .bits = 32 } /* pc */
+  };
+#define PRSTATUS_REGS_SIZE	(20 * 4)
+
+#define ULONG			uint32_t
+#define PID_T			int32_t
+#define	UID_T			uint16_t
+#define	GID_T			uint16_t
+#define ALIGN_INT		2
+#define ALIGN_ULONG		2
+#define ALIGN_PID_T		2
+#define ALIGN_UID_T		2
+#define ALIGN_GID_T		2
+#define ALIGN_PRSTATUS		2
+#define TYPE_ULONG		ELF_T_WORD
+#define TYPE_PID_T		ELF_T_SWORD
+#define TYPE_UID_T		ELF_T_HALF
+#define TYPE_GID_T		ELF_T_HALF
+
+static const Ebl_Register_Location fpregset_regs[] =
+  {
+    { .offset = 0, .regno = 16, .count = 8, .bits = 96 }, /* fp0-fp7 */
+  };
+#define FPREGSET_SIZE	(27 * 4)
+
+#include "linux-core-note.c"
diff --git a/backends/m68k_init.c b/backends/m68k_init.c
new file mode 100644
index 0000000..943478f
--- /dev/null
+++ b/backends/m68k_init.c
@@ -0,0 +1,60 @@
+/* Initialization of M68K specific backend library.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		m68k_
+#define RELOC_PREFIX	R_68K_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on m68k_reloc.def.  */
+#include "common-reloc.c"
+
+
+const char *
+m68k_init (Elf *elf __attribute__ ((unused)),
+	   GElf_Half machine __attribute__ ((unused)),
+	   Ebl *eh,
+	   size_t ehlen)
+{
+  /* Check whether the Elf_BH object has a sufficent size.  */
+  if (ehlen < sizeof (Ebl))
+    return NULL;
+
+  /* We handle it.  */
+  eh->name = "M68K";
+  m68k_init_reloc (eh);
+  HOOK (eh, gotpc_reloc_check);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, return_value_location);
+  HOOK (eh, register_info);
+  HOOK (eh, core_note);
+
+  return MODVERSION;
+}
diff --git a/backends/m68k_regs.c b/backends/m68k_regs.c
new file mode 100644
index 0000000..cb99f55
--- /dev/null
+++ b/backends/m68k_regs.c
@@ -0,0 +1,96 @@
+/* Register names and numbers for M68K DWARF.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND m68k_
+#include "libebl_CPU.h"
+
+ssize_t
+m68k_register_info (Ebl *ebl __attribute__ ((unused)),
+		    int regno, char *name, size_t namelen,
+		    const char **prefix, const char **setname,
+		    int *bits, int *type)
+{
+  if (name == NULL)
+    return 25;
+
+  if (regno < 0 || regno > 24 || namelen < 5)
+    return -1;
+
+  *prefix = "%";
+  *setname = "integer";
+  *bits = 32;
+
+  switch (regno)
+    {
+    case 0 ... 7:
+      *type = DW_ATE_signed;
+      name[0] = 'd';
+      name[1] = regno + '0';
+      namelen = 2;
+      break;
+
+    case 8 ... 15:
+      *type = DW_ATE_address;
+      name[0] = 'a';
+      name[1] = regno - 8 + '0';
+      namelen = 2;
+      break;
+
+    case 16 ... 23:
+      *type = DW_ATE_float;
+      *setname = "FPU";
+      *bits = 96;
+      name[0] = 'f';
+      name[1] = 'p';
+      name[2] = regno - 16 + '0';
+      namelen = 3;
+      break;
+
+    case 24:
+      *type = DW_ATE_address;
+      name[0] = 'p';
+      name[1] = 'c';
+      namelen = 2;
+      break;
+
+    /* Can't happen.  */
+    default:
+      *setname = NULL;
+      return 0;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
diff --git a/backends/m68k_reloc.def b/backends/m68k_reloc.def
new file mode 100644
index 0000000..b7cc4df
--- /dev/null
+++ b/backends/m68k_reloc.def
@@ -0,0 +1,70 @@
+/* List the relocation types for m68k.  -*- C -*-
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,		EXEC|DYN)
+RELOC_TYPE (32,			REL|EXEC|DYN)
+RELOC_TYPE (16,			REL|EXEC|DYN)
+RELOC_TYPE (8,			REL|EXEC|DYN)
+RELOC_TYPE (PC32,		REL|EXEC|DYN)
+RELOC_TYPE (PC16,		REL|EXEC|DYN)
+RELOC_TYPE (PC8,		REL|EXEC|DYN)
+RELOC_TYPE (GOT32,		REL)
+RELOC_TYPE (GOT16,		REL)
+RELOC_TYPE (GOT8,		REL)
+RELOC_TYPE (GOT32O,		REL)
+RELOC_TYPE (GOT16O,		REL)
+RELOC_TYPE (GOT8O,		REL)
+RELOC_TYPE (PLT32,		REL)
+RELOC_TYPE (PLT16,		REL)
+RELOC_TYPE (PLT8,		REL)
+RELOC_TYPE (PLT32O,		REL)
+RELOC_TYPE (PLT16O,		REL)
+RELOC_TYPE (PLT8O,		REL)
+RELOC_TYPE (COPY,		EXEC|DYN)
+RELOC_TYPE (GLOB_DAT,		EXEC|DYN)
+RELOC_TYPE (JMP_SLOT,		EXEC|DYN)
+RELOC_TYPE (RELATIVE,		EXEC|DYN)
+RELOC_TYPE (TLS_GD32,		REL)
+RELOC_TYPE (TLS_GD16,		REL)
+RELOC_TYPE (TLS_GD8,		REL)
+RELOC_TYPE (TLS_LDM32,		REL)
+RELOC_TYPE (TLS_LDM16,		REL)
+RELOC_TYPE (TLS_LDM8,		REL)
+RELOC_TYPE (TLS_LDO32,		REL)
+RELOC_TYPE (TLS_LDO16,		REL)
+RELOC_TYPE (TLS_LDO8,		REL)
+RELOC_TYPE (TLS_IE32,		REL)
+RELOC_TYPE (TLS_IE16,		REL)
+RELOC_TYPE (TLS_IE8,		REL)
+RELOC_TYPE (TLS_LE32,		REL)
+RELOC_TYPE (TLS_LE16,		REL)
+RELOC_TYPE (TLS_LE8,		REL)
+RELOC_TYPE (TLS_DTPMOD32,	EXEC|DYN)
+RELOC_TYPE (TLS_DTPREL32,	EXEC|DYN)
+RELOC_TYPE (TLS_TPREL32,	EXEC|DYN)
diff --git a/backends/m68k_retval.c b/backends/m68k_retval.c
new file mode 100644
index 0000000..a653ba3
--- /dev/null
+++ b/backends/m68k_retval.c
@@ -0,0 +1,151 @@
+/* Function return value location for Linux/m68k ABI.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND m68k_
+#include "libebl_CPU.h"
+
+
+/* %d0, or pair %d0, %d1.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg0 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg1 }, { .atom = DW_OP_piece, .number = 4 },
+  };
+#define nloc_intreg	1
+#define nloc_intregpair	4
+
+/* %a0.  */
+static const Dwarf_Op loc_ptrreg[] =
+  {
+    { .atom = DW_OP_reg8 }
+  };
+#define nloc_ptrreg	1
+
+/* %fp0.  */
+static const Dwarf_Op loc_fpreg[] =
+  {
+    { .atom = DW_OP_reg16 }
+  };
+#define nloc_fpreg	1
+
+/* The return value is a structure and is actually stored in stack space
+   passed in a hidden argument by the caller.  But, the compiler
+   helpfully returns the address of that space in %a0.  */
+static const Dwarf_Op loc_aggregate[] =
+  {
+    { .atom = DW_OP_reg8 }
+  };
+#define nloc_aggregate 1
+
+int
+m68k_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die die_mem, *typedie = &die_mem;
+  int tag = dwarf_peeled_die_type (functypedie, typedie);
+  if (tag <= 0)
+    return tag;
+
+  switch (tag)
+    {
+    case -1:
+      return -1;
+
+    case DW_TAG_subrange_type:
+      if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
+	{
+	  Dwarf_Attribute attr_mem, *attr;
+	  attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+	  typedie = dwarf_formref_die (attr, &die_mem);
+	  tag = DWARF_TAG_OR_RETURN (typedie);
+	}
+      FALLTHROUGH;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    case DW_TAG_pointer_type:
+    case DW_TAG_ptr_to_member_type:
+      {
+	Dwarf_Word size;
+	Dwarf_Attribute attr_mem;
+	if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+						   &attr_mem), &size) != 0)
+	  {
+	    if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+	      size = 4;
+	    else
+	      return -1;
+	  }
+	if (tag == DW_TAG_base_type)
+	  {
+	    Dwarf_Word encoding;
+	    if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
+						       &attr_mem),
+				 &encoding) != 0)
+	      return -1;
+	    if (encoding == DW_ATE_float)
+	      {
+		if (size > 12)
+		  return -2;
+		*locp = loc_fpreg;
+		return nloc_fpreg;
+	      }
+	  }
+	if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+	  {
+	    *locp = loc_ptrreg;
+	    return nloc_ptrreg;
+	  }
+	*locp = loc_intreg;
+	if (size <= 4)
+	  return nloc_intreg;
+	if (size <= 8)
+	  return nloc_intregpair;
+      }
+      FALLTHROUGH;
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+    case DW_TAG_array_type:
+      *locp = loc_aggregate;
+      return nloc_aggregate;
+    }
+
+  /* XXX We don't have a good way to return specific errors from ebl calls.
+     This value means we do not understand the type, but it is well-formed
+     DWARF and might be valid.  */
+  return -2;
+}
diff --git a/backends/m68k_symbol.c b/backends/m68k_symbol.c
new file mode 100644
index 0000000..269d12e
--- /dev/null
+++ b/backends/m68k_symbol.c
@@ -0,0 +1,70 @@
+/* m68k specific symbolic name handling.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <elf.h>
+#include <stddef.h>
+#include <string.h>
+
+#define BACKEND m68k_
+#include "libebl_CPU.h"
+
+
+/* Return true if the symbol type is that referencing the GOT.  */
+bool
+m68k_gotpc_reloc_check (Elf *elf __attribute__ ((unused)), int type)
+{
+  switch (type)
+    {
+    case R_68K_GOT32:
+    case R_68K_GOT16:
+    case R_68K_GOT8:
+      return true;
+    }
+  return false;
+}
+
+/* Check for the simple reloc types.  */
+Elf_Type
+m68k_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+{
+  switch (type)
+    {
+    case R_68K_32:
+      return ELF_T_SWORD;
+    case R_68K_16:
+      return ELF_T_HALF;
+    case R_68K_8:
+      return ELF_T_BYTE;
+    default:
+      return ELF_T_NUM;
+    }
+}
diff --git a/backends/ppc64_corenote.c b/backends/ppc64_corenote.c
new file mode 100644
index 0000000..9d6a6a4
--- /dev/null
+++ b/backends/ppc64_corenote.c
@@ -0,0 +1,2 @@
+#define BITS 64
+#include "ppc_corenote.c"
diff --git a/backends/ppc64_init.c b/backends/ppc64_init.c
new file mode 100644
index 0000000..e567033
--- /dev/null
+++ b/backends/ppc64_init.c
@@ -0,0 +1,110 @@
+/* Initialization of PPC64 specific backend library.
+   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2013, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#define BACKEND		ppc64_
+#define RELOC_PREFIX	R_PPC64_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on ppc64_reloc.def.  */
+#include "common-reloc.c"
+
+
+const char *
+ppc64_init (Elf *elf __attribute__ ((unused)),
+	    GElf_Half machine __attribute__ ((unused)),
+	    Ebl *eh,
+	    size_t ehlen)
+{
+  /* Check whether the Elf_BH object has a sufficent size.  */
+  if (ehlen < sizeof (Ebl))
+    return NULL;
+
+  /* We handle it.  */
+  eh->name = "PowerPC 64-bit";
+  ppc64_init_reloc (eh);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, dynamic_tag_name);
+  HOOK (eh, dynamic_tag_check);
+  HOOK (eh, machine_flag_check);
+  HOOK (eh, copy_reloc_p);
+  HOOK (eh, check_special_symbol);
+  HOOK (eh, check_st_other_bits);
+  HOOK (eh, bss_plt_p);
+  HOOK (eh, return_value_location);
+  HOOK (eh, register_info);
+  HOOK (eh, syscall_abi);
+  HOOK (eh, core_note);
+  HOOK (eh, auxv_info);
+  HOOK (eh, check_object_attribute);
+  HOOK (eh, abi_cfi);
+  /* gcc/config/ #define DWARF_FRAME_REGISTERS.  */
+  eh->frame_nregs = (114 - 1) + 32;
+  HOOK (eh, set_initial_registers_tid);
+  HOOK (eh, dwarf_to_regno);
+  HOOK (eh, unwind);
+  HOOK (eh, resolve_sym_value);
+
+  /* Find the function descriptor .opd table for resolve_sym_value.  */
+  if (elf != NULL)
+    {
+      GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (elf, &ehdr_mem);
+      if (ehdr != NULL && ehdr->e_type != ET_REL)
+	{
+	  /* We could also try through DT_PPC64_OPD and DT_PPC64_OPDSZ. */
+	  GElf_Shdr opd_shdr_mem, *opd_shdr;
+	  Elf_Scn *scn = NULL;
+	  while ((scn = elf_nextscn (elf, scn)) != NULL)
+	    {
+	      opd_shdr = gelf_getshdr (scn, &opd_shdr_mem);
+	      if (opd_shdr != NULL
+		  && (opd_shdr->sh_flags & SHF_ALLOC) != 0
+		  && opd_shdr->sh_type == SHT_PROGBITS
+		  && opd_shdr->sh_size > 0)
+		{
+		  const char *name = elf_strptr (elf, ehdr->e_shstrndx,
+						 opd_shdr->sh_name);
+		  if (name != NULL && strcmp (name, ".opd") == 0)
+		    {
+		      eh->fd_addr = opd_shdr->sh_addr;
+		      eh->fd_data = elf_getdata (scn, NULL);
+		      break;
+		    }
+		}
+	    }
+	}
+    }
+
+  return MODVERSION;
+}
diff --git a/backends/ppc64_reloc.def b/backends/ppc64_reloc.def
new file mode 100644
index 0000000..15a73ba
--- /dev/null
+++ b/backends/ppc64_reloc.def
@@ -0,0 +1,161 @@
+/* List the relocation types for ppc64.  -*- C -*-
+   Copyright (C) 2005, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,		0)
+RELOC_TYPE (ADDR32,		REL|EXEC|DYN)
+RELOC_TYPE (ADDR24,		REL)
+RELOC_TYPE (ADDR16,		REL)		/* note 1 */
+RELOC_TYPE (ADDR16_LO,		REL)		/* note 1 */
+RELOC_TYPE (ADDR16_HI,		REL)		/* note 1 */
+RELOC_TYPE (ADDR16_HA,		REL)		/* note 1 */
+RELOC_TYPE (ADDR14,		REL)		/* note 1 */
+RELOC_TYPE (ADDR14_BRTAKEN,	REL)		/* note 1 */
+RELOC_TYPE (ADDR14_BRNTAKEN,	REL)		/* note 1 */
+RELOC_TYPE (REL24,		REL)
+RELOC_TYPE (REL14,		REL)
+RELOC_TYPE (REL14_BRTAKEN,	REL)
+RELOC_TYPE (REL14_BRNTAKEN,	REL)
+RELOC_TYPE (GOT16,		REL)
+RELOC_TYPE (GOT16_LO,		REL)
+RELOC_TYPE (GOT16_HI,		REL)
+RELOC_TYPE (GOT16_HA,		REL)
+RELOC_TYPE (COPY,		EXEC|DYN)
+RELOC_TYPE (GLOB_DAT,		EXEC|DYN)
+RELOC_TYPE (JMP_SLOT,		EXEC|DYN)
+RELOC_TYPE (RELATIVE,		EXEC|DYN)
+RELOC_TYPE (UADDR32,		REL|EXEC|DYN)
+RELOC_TYPE (UADDR16,		REL)
+RELOC_TYPE (REL32,		REL|EXEC|DYN)
+RELOC_TYPE (PLT32,		REL)
+RELOC_TYPE (PLTREL32,		REL)
+RELOC_TYPE (PLT16_LO,		REL)
+RELOC_TYPE (PLT16_HI,		REL)
+RELOC_TYPE (PLT16_HA,		REL)
+RELOC_TYPE (SECTOFF,		REL)
+RELOC_TYPE (SECTOFF_LO,		REL)
+RELOC_TYPE (SECTOFF_HI,		REL)
+RELOC_TYPE (SECTOFF_HA,		REL)
+RELOC_TYPE (ADDR30,		REL)		/* note 1 */
+RELOC_TYPE (ADDR64,		REL|EXEC|DYN)
+RELOC_TYPE (ADDR16_HIGHER,	REL)		/* note 1 */
+RELOC_TYPE (ADDR16_HIGHERA,	REL)		/* note 1 */
+RELOC_TYPE (ADDR16_HIGHEST,	REL)		/* note 1 */
+RELOC_TYPE (ADDR16_HIGHESTA,	REL)		/* note 1 */
+RELOC_TYPE (UADDR64,		REL|EXEC|DYN)
+RELOC_TYPE (REL64,		REL|EXEC|DYN)
+RELOC_TYPE (PLT64,		REL)
+RELOC_TYPE (PLTREL64,		REL)
+RELOC_TYPE (TOC16,		REL)
+RELOC_TYPE (TOC16_LO,		REL)
+RELOC_TYPE (TOC16_HI,		REL)
+RELOC_TYPE (TOC16_HA,		REL)
+RELOC_TYPE (TOC,		REL)
+RELOC_TYPE (PLTGOT16,		REL)
+RELOC_TYPE (PLTGOT16_LO,	REL)
+RELOC_TYPE (PLTGOT16_HI,	REL)
+RELOC_TYPE (PLTGOT16_HA,	REL)
+RELOC_TYPE (ADDR16_DS,		REL)		/* note 1 */
+RELOC_TYPE (ADDR16_LO_DS,	REL)		/* note 1 */
+RELOC_TYPE (GOT16_DS,		REL)
+RELOC_TYPE (GOT16_LO_DS,	REL)
+RELOC_TYPE (PLT16_LO_DS,	REL)
+RELOC_TYPE (SECTOFF_DS,		REL)
+RELOC_TYPE (SECTOFF_LO_DS,	REL)
+RELOC_TYPE (TOC16_DS,		REL)
+RELOC_TYPE (TOC16_LO_DS,	REL)
+RELOC_TYPE (PLTGOT16_DS,	REL)
+RELOC_TYPE (PLTGOT16_LO_DS,	REL)
+RELOC_TYPE (TLS,		REL)
+RELOC_TYPE (DTPMOD64,		REL|EXEC|DYN)	/* note 3 */
+RELOC_TYPE (TPREL16,		REL)		/* note 2 */
+RELOC_TYPE (TPREL16_LO,		REL)		/* note 2 */
+RELOC_TYPE (TPREL16_HI,		REL)		/* note 2 */
+RELOC_TYPE (TPREL16_HA,		REL)		/* note 2 */
+RELOC_TYPE (TPREL64,		REL|EXEC|DYN)	/* note 3 */
+RELOC_TYPE (DTPREL16,		REL)
+RELOC_TYPE (DTPREL16_LO,	REL)
+RELOC_TYPE (DTPREL16_HI,	REL)
+RELOC_TYPE (DTPREL16_HA,	REL)
+RELOC_TYPE (DTPREL64,		REL|EXEC|DYN)	/* note 3 */
+RELOC_TYPE (GOT_TLSGD16,	REL)
+RELOC_TYPE (GOT_TLSGD16_LO,	REL)
+RELOC_TYPE (GOT_TLSGD16_HI,	REL)
+RELOC_TYPE (GOT_TLSGD16_HA,	REL)
+RELOC_TYPE (GOT_TLSLD16,	REL)
+RELOC_TYPE (GOT_TLSLD16_LO,	REL)
+RELOC_TYPE (GOT_TLSLD16_HI,	REL)
+RELOC_TYPE (GOT_TLSLD16_HA,	REL)
+RELOC_TYPE (GOT_TPREL16_DS,	REL)
+RELOC_TYPE (GOT_TPREL16_LO_DS,	REL)
+RELOC_TYPE (GOT_TPREL16_HI,	REL)
+RELOC_TYPE (GOT_TPREL16_HA,	REL)
+RELOC_TYPE (GOT_DTPREL16_DS,	REL)
+RELOC_TYPE (GOT_DTPREL16_LO_DS, REL)
+RELOC_TYPE (GOT_DTPREL16_HI,	REL)
+RELOC_TYPE (GOT_DTPREL16_HA,	REL)
+RELOC_TYPE (TPREL16_DS,		REL)		/* note 2 */
+RELOC_TYPE (TPREL16_LO_DS,	REL)		/* note 2 */
+RELOC_TYPE (TPREL16_HIGHER,	REL)		/* note 2 */
+RELOC_TYPE (TPREL16_HIGHERA,	REL)		/* note 2 */
+RELOC_TYPE (TPREL16_HIGHEST,	REL)		/* note 2 */
+RELOC_TYPE (TPREL16_HIGHESTA,	REL)		/* note 2 */
+RELOC_TYPE (DTPREL16_DS,	REL)
+RELOC_TYPE (DTPREL16_LO_DS,	REL)
+RELOC_TYPE (DTPREL16_HIGHER,	REL)
+RELOC_TYPE (DTPREL16_HIGHERA,	REL)
+RELOC_TYPE (DTPREL16_HIGHEST,	REL)
+RELOC_TYPE (DTPREL16_HIGHESTA,	REL)
+RELOC_TYPE (TLSGD,		REL)
+RELOC_TYPE (TLSLD,		REL)
+RELOC_TYPE (TOCSAVE,		REL)
+RELOC_TYPE (ADDR16_HIGH,	REL)
+RELOC_TYPE (ADDR16_HIGHA,	REL)
+RELOC_TYPE (TPREL16_HIGH,	REL)
+RELOC_TYPE (TPREL16_HIGHA,	REL)
+RELOC_TYPE (DTPREL16_HIGH,	REL)
+RELOC_TYPE (DTPREL16_HIGHA,	REL)
+RELOC_TYPE (JMP_IREL,		REL)
+RELOC_TYPE (IRELATIVE,		REL)
+RELOC_TYPE (REL16,		REL)
+RELOC_TYPE (REL16_LO,		REL)
+RELOC_TYPE (REL16_HI,		REL)
+RELOC_TYPE (REL16_HA,		REL)
+
+/* Notes from Alan Modra:
+
+   1) These can appear in DYN and EXEC with improper assembly, but they
+   aren't really kosher.
+
+   2) These can appear in DYN with improper assembly (or silly gcc
+      attributes, I think).  Again, not kosher.
+
+   3) These are legal in REL for PowerOpen compatible assembler syntax,
+      ie. TOC managed by compiler.
+*/
diff --git a/backends/ppc64_resolve_sym.c b/backends/ppc64_resolve_sym.c
new file mode 100644
index 0000000..03f6558
--- /dev/null
+++ b/backends/ppc64_resolve_sym.c
@@ -0,0 +1,63 @@
+/* Resolve symbol values through .opd function descriptors.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND ppc64_
+#include "libebl_CPU.h"
+
+/* Resolve a function descriptor if addr points into the .opd section.
+   The .opd section contains function descriptors consisting of 3 addresses.
+   function, toc and chain. We are just interested in the first.
+   http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html#FUNC-DES
+
+   Returns true if the given address could be resolved, false otherwise.
+*/
+bool
+ppc64_resolve_sym_value (Ebl *ebl, GElf_Addr *addr)
+{
+  if (ebl->fd_data != NULL && *addr >= ebl->fd_addr
+      && *addr + sizeof (Elf64_Addr) <= ebl->fd_addr + ebl->fd_data->d_size)
+    {
+      GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (ebl->elf, &ehdr_mem);
+      if (ehdr != NULL)
+	{
+	  Elf_Data opd_in, opd_out;
+	  opd_in.d_buf = ebl->fd_data->d_buf + (*addr - ebl->fd_addr);
+	  opd_out.d_buf = addr;
+	  opd_out.d_size = opd_in.d_size = sizeof (Elf64_Addr);
+	  opd_out.d_type = opd_in.d_type = ELF_T_ADDR;
+	  if (elf64_xlatetom (&opd_out, &opd_in,
+			      ehdr->e_ident[EI_DATA]) != NULL)
+	    return true;
+	}
+    }
+  return false;
+}
diff --git a/backends/ppc64_retval.c b/backends/ppc64_retval.c
new file mode 100644
index 0000000..eb1c11e
--- /dev/null
+++ b/backends/ppc64_retval.c
@@ -0,0 +1,195 @@
+/* Function return value location for Linux/PPC64 ABI.
+   Copyright (C) 2005-2010, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND ppc64_
+#include "libebl_CPU.h"
+
+
+/* r3.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg3 }
+  };
+#define nloc_intreg	1
+
+/* f1, or f1:f2, or f1:f4.  */
+static const Dwarf_Op loc_fpreg[] =
+  {
+    { .atom = DW_OP_regx, .number = 33 }, { .atom = DW_OP_piece, .number = 8 },
+    { .atom = DW_OP_regx, .number = 34 }, { .atom = DW_OP_piece, .number = 8 },
+    { .atom = DW_OP_regx, .number = 35 }, { .atom = DW_OP_piece, .number = 8 },
+    { .atom = DW_OP_regx, .number = 36 }, { .atom = DW_OP_piece, .number = 8 },
+  };
+#define nloc_fpreg	1
+#define nloc_fp2regs	4
+#define nloc_fp4regs	8
+
+/* vr2.  */
+static const Dwarf_Op loc_vmxreg[] =
+  {
+    { .atom = DW_OP_regx, .number = 1124 + 2 }
+  };
+#define nloc_vmxreg	1
+
+/* The return value is a structure and is actually stored in stack space
+   passed in a hidden argument by the caller.  But, the compiler
+   helpfully returns the address of that space in r3.  */
+static const Dwarf_Op loc_aggregate[] =
+  {
+    { .atom = DW_OP_breg3, .number = 0 }
+  };
+#define nloc_aggregate 1
+
+int
+ppc64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die die_mem, *typedie = &die_mem;
+  int tag = dwarf_peeled_die_type (functypedie, typedie);
+  if (tag <= 0)
+    return tag;
+
+  Dwarf_Word size;
+  switch (tag)
+    {
+    case -1:
+      return -1;
+
+    case DW_TAG_subrange_type:
+      if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
+	{
+	  Dwarf_Attribute attr_mem, *attr;
+	  attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+	  typedie = dwarf_formref_die (attr, &die_mem);
+	  tag = DWARF_TAG_OR_RETURN (typedie);
+	}
+      FALLTHROUGH;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    case DW_TAG_pointer_type:
+    case DW_TAG_ptr_to_member_type:
+      {
+	Dwarf_Attribute attr_mem;
+	if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+						   &attr_mem), &size) != 0)
+	  {
+	    if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+	      size = 8;
+	    else
+	      return -1;
+	}
+      }
+
+      if (tag == DW_TAG_base_type)
+	{
+	  Dwarf_Attribute attr_mem;
+	  Dwarf_Word encoding;
+	  if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
+						     &attr_mem),
+			       &encoding) != 0)
+	    return -1;
+
+	  if (encoding == DW_ATE_float || encoding == DW_ATE_complex_float)
+	    {
+	      *locp = loc_fpreg;
+	      if (size <= 8)
+		return nloc_fpreg;
+	      if (size <= 16)
+		return nloc_fp2regs;
+	      if (size <= 32)
+		return nloc_fp4regs;
+	    }
+	}
+      if (size <= 8)
+	{
+	intreg:
+	  *locp = loc_intreg;
+	  return nloc_intreg;
+	}
+
+      FALLTHROUGH;
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+    aggregate:
+      *locp = loc_aggregate;
+      return nloc_aggregate;
+
+    case DW_TAG_array_type:
+      {
+	Dwarf_Attribute attr_mem;
+	bool is_vector;
+	if (dwarf_formflag (dwarf_attr_integrate (typedie, DW_AT_GNU_vector,
+						  &attr_mem), &is_vector) == 0
+	    && is_vector)
+	  {
+	    *locp = loc_vmxreg;
+	    return nloc_vmxreg;
+	  }
+      }
+      FALLTHROUGH;
+
+    case DW_TAG_string_type:
+      if (dwarf_aggregate_size (typedie, &size) == 0 && size <= 8)
+	{
+	  if (tag == DW_TAG_array_type)
+	    {
+	      /* Check if it's a character array.  */
+	      Dwarf_Attribute attr_mem, *attr;
+	      attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+	      typedie = dwarf_formref_die (attr, &die_mem);
+	      tag = DWARF_TAG_OR_RETURN (typedie);
+	      if (tag != DW_TAG_base_type)
+		goto aggregate;
+	      if (dwarf_formudata (dwarf_attr_integrate (typedie,
+							 DW_AT_byte_size,
+							 &attr_mem),
+				   &size) != 0)
+		return -1;
+	      if (size != 1)
+		goto aggregate;
+	    }
+	  goto intreg;
+	}
+      goto aggregate;
+    }
+
+  /* XXX We don't have a good way to return specific errors from ebl calls.
+     This value means we do not understand the type, but it is well-formed
+     DWARF and might be valid.  */
+  return -2;
+}
diff --git a/backends/ppc64_symbol.c b/backends/ppc64_symbol.c
new file mode 100644
index 0000000..0feddce
--- /dev/null
+++ b/backends/ppc64_symbol.c
@@ -0,0 +1,130 @@
+/* PPC64 specific symbolic name handling.
+   Copyright (C) 2004, 2005, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <elf.h>
+#include <stddef.h>
+#include <string.h>
+
+#define BACKEND		ppc64_
+#include "libebl_CPU.h"
+
+
+/* Check for the simple reloc types.  */
+Elf_Type
+ppc64_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+{
+  switch (type)
+    {
+    case R_PPC64_ADDR64:
+    case R_PPC64_UADDR64:
+      return ELF_T_XWORD;
+    case R_PPC64_ADDR32:
+    case R_PPC64_UADDR32:
+      return ELF_T_WORD;
+    case R_PPC64_UADDR16:
+      return ELF_T_HALF;
+    default:
+      return ELF_T_NUM;
+    }
+}
+
+
+const char *
+ppc64_dynamic_tag_name (int64_t tag, char *buf __attribute__ ((unused)),
+			size_t len __attribute__ ((unused)))
+{
+  switch (tag)
+    {
+    case DT_PPC64_GLINK:
+      return "PPC64_GLINK";
+    case DT_PPC64_OPD:
+      return "PPC64_OPD";
+    case DT_PPC64_OPDSZ:
+      return "PPC64_OPDSZ";
+    case DT_PPC64_OPT:
+      return "PPC64_OPT";
+    default:
+      break;
+    }
+  return NULL;
+}
+
+
+bool
+ppc64_dynamic_tag_check (int64_t tag)
+{
+  return (tag == DT_PPC64_GLINK
+	  || tag == DT_PPC64_OPD
+	  || tag == DT_PPC64_OPDSZ
+	  || tag == DT_PPC64_OPT);
+}
+
+
+/* Check whether given symbol's st_value and st_size are OK despite failing
+   normal checks.  */
+bool
+ppc64_check_special_symbol (Elf *elf, GElf_Ehdr *ehdr,
+			    const GElf_Sym *sym __attribute__ ((unused)),
+			    const char *name __attribute__ ((unused)),
+			    const GElf_Shdr *destshdr)
+{
+  const char *sname = elf_strptr (elf, ehdr->e_shstrndx, destshdr->sh_name);
+  if (sname == NULL)
+    return false;
+  return strcmp (sname, ".opd") == 0;
+}
+
+
+/* Check if backend uses a bss PLT in this file.  */
+bool
+ppc64_bss_plt_p (Elf *elf __attribute__ ((unused)))
+{
+  return true;
+}
+
+/* Check whether machine flags are valid.  PPC64 has three possible values:
+   0 - for unspecified ABI, or not using any specific ABI features.
+   1 - for the original ELF PPC64 ABI using function descriptors.
+   2 - for the revised ELFv2 PPC64 ABI without function descriptors.  */
+bool
+ppc64_machine_flag_check (GElf_Word flags)
+{
+  return flags == 0 || flags == 1 || flags == 2;
+}
+
+bool
+ppc64_check_st_other_bits (unsigned char st_other)
+{
+  return (PPC64_LOCAL_ENTRY_OFFSET (st_other) != 0);
+}
diff --git a/backends/ppc64_unwind.c b/backends/ppc64_unwind.c
new file mode 100644
index 0000000..4fa0b5a
--- /dev/null
+++ b/backends/ppc64_unwind.c
@@ -0,0 +1,76 @@
+/* Get previous frame state for an existing frame state.
+   Copyright (C) 2017 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND ppc64_
+
+#define LR_REG 65 /* Not 108, see ppc_dwarf_to_regno.  */
+#define SP_REG  1
+
+#define LR_OFFSET 16
+
+#include "libebl_CPU.h"
+
+/* Simplistic fallback frame unwinder. SP points to the backchain (contains
+   address of previous stack pointer). At SP offset 16 is the LR save area
+   (contains the value of the previous LR).  */
+
+bool
+EBLHOOK(unwind) (Ebl *ebl __attribute__ ((unused)),
+		 Dwarf_Addr pc __attribute__ ((unused)),
+                 ebl_tid_registers_t *setfunc, ebl_tid_registers_get_t *getfunc,
+                 ebl_pid_memory_read_t *readfunc, void *arg,
+                 bool *signal_framep __attribute__ ((unused)))
+{
+  Dwarf_Word sp, newSp, lr, newLr;
+
+  /* Stack pointer points to the backchain which contains the previous sp.  */
+  if (! getfunc (SP_REG, 1, &sp, arg))
+    sp = 0;
+
+  /* Link register contains previous program counter.  */
+  if (! getfunc (LR_REG, 1, &lr, arg)
+      || lr == 0
+      || ! setfunc (-1, 1, &lr, arg))
+    return false;
+
+  if (! readfunc(sp, &newSp, arg))
+    newSp = 0;
+
+  if (! readfunc(newSp + LR_OFFSET, &newLr, arg))
+    newLr = 0;
+
+  setfunc(SP_REG, 1, &newSp, arg);
+  setfunc(LR_REG, 1, &newLr, arg);
+
+  /* Sanity check the stack grows down.  */
+  return newSp > sp;
+}
diff --git a/backends/ppc_attrs.c b/backends/ppc_attrs.c
new file mode 100644
index 0000000..48d7129
--- /dev/null
+++ b/backends/ppc_attrs.c
@@ -0,0 +1,86 @@
+/* Object attribute tags for PowerPC.
+   Copyright (C) 2008, 2009 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND ppc_
+#include "libebl_CPU.h"
+
+bool
+ppc_check_object_attribute (Ebl *ebl __attribute__ ((unused)),
+			    const char *vendor, int tag, uint64_t value,
+			    const char **tag_name, const char **value_name)
+{
+  if (!strcmp (vendor, "gnu"))
+    switch (tag)
+      {
+      case 4:
+	*tag_name = "GNU_Power_ABI_FP";
+	static const char *fp_kinds[] =
+	  {
+	    "Hard or soft float",
+	    "Hard float",
+	    "Soft float",
+	    "Single-precision hard float",
+	  };
+	if (value < sizeof fp_kinds / sizeof fp_kinds[0])
+	  *value_name = fp_kinds[value];
+	return true;
+
+      case 8:
+	*tag_name = "GNU_Power_ABI_Vector";
+	static const char *vector_kinds[] =
+	  {
+	    "Any", "Generic", "AltiVec", "SPE"
+	  };
+	if (value < sizeof vector_kinds / sizeof vector_kinds[0])
+	  *value_name = vector_kinds[value];
+	return true;
+
+      case 12:
+	*tag_name = "GNU_Power_ABI_Struct_Return";
+	static const char *struct_return_kinds[] =
+	  {
+	    "Any", "r3/r4", "Memory"
+	  };
+	if (value < sizeof struct_return_kinds / sizeof struct_return_kinds[0])
+	  *value_name = struct_return_kinds[value];
+	return true;
+      }
+
+  return false;
+}
+
+__typeof (ppc_check_object_attribute)
+     ppc64_check_object_attribute
+     __attribute__ ((alias ("ppc_check_object_attribute")));
diff --git a/backends/ppc_auxv.c b/backends/ppc_auxv.c
new file mode 100644
index 0000000..a27a1da
--- /dev/null
+++ b/backends/ppc_auxv.c
@@ -0,0 +1,55 @@
+/* i386 specific auxv handling.
+   Copyright (C) 2007 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND ppc_
+#include "libebl_CPU.h"
+
+int
+EBLHOOK(auxv_info) (GElf_Xword a_type, const char **name, const char **format)
+{
+  if (a_type != AT_HWCAP)
+    return 0;
+
+  *name = "HWCAP";
+  *format = "b"
+    "ppcle\0" "truele\0" "3\0" "4\0" "5\0" "6\0" "7\0" "8\0" "9\0"
+    "power6x\0" "dfp\0" "pa6t\0" "arch_2_05\0"
+    "ic_snoop\0" "smt\0" "booke\0" "cellbe\0"
+    "power5+\0" "power5\0" "power4\0" "notb\0"
+    "efpdouble\0" "efpsingle\0" "spe\0" "ucache\0"
+    "4xxmac\0" "mmu\0" "fpu\0" "altivec\0"
+    "ppc601\0" "ppc64\0" "ppc32\0" "\0";
+  return 1;
+}
+
+__typeof (ppc_auxv_info) ppc64_auxv_info
+			 __attribute__ ((alias ("ppc_auxv_info")));
diff --git a/backends/ppc_cfi.c b/backends/ppc_cfi.c
new file mode 100644
index 0000000..55169ae
--- /dev/null
+++ b/backends/ppc_cfi.c
@@ -0,0 +1,77 @@
+/* ppc ABI-specified defaults for DWARF CFI.
+   Copyright (C) 2012, 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#define BACKEND ppc_
+#include "libebl_CPU.h"
+
+int
+ppc_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info)
+{
+  static const uint8_t abi_cfi[] =
+    {
+      /* This instruction is provided in every CIE.  It is not repeated here:
+	 DW_CFA_def_cfa, ULEB128_7 (1), ULEB128_7 (0)  */
+      /* r1 is assumed to be restored from cfa adress,
+	 r1 acts as a stack frame pointer.  */
+      DW_CFA_val_offset, ULEB128_7 (1), ULEB128_7 (0),
+      /* lr is not callee-saved but it needs to be preserved as it is pre-set
+	 by the caller.  */
+      DW_CFA_same_value, ULEB128_7 (65), /* lr */
+
+      /* Callee-saved regs.  */
+#define SV(n) DW_CFA_same_value, ULEB128_7 (n)
+      SV (2),			/* r2 is TOC pointer.  */
+      SV (13),			/* Reserved as system thread id (is it for CFI?).  */
+      /* r14-r31 are non-volatile registers.  */
+      SV (14), SV (15), SV (16), SV (17), SV (18), SV (19), SV (20), SV (21),
+      SV (22), SV (23), SV (24), SV (25), SV (26), SV (27), SV (28), SV (29),
+      SV (30), SV (31)
+      /* VMX registers v20-v31 and vrsave are non-volatile but they are
+	 assigned DWARF registers 1144-1156 (v20-v31) which is outside of the
+	 CFI supported range.  */
+#undef SV
+    };
+
+  abi_info->initial_instructions = abi_cfi;
+  abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
+  abi_info->data_alignment_factor = ebl->class == ELFCLASS64 ? 8 : 4;
+
+  abi_info->return_address_register = 65;
+
+  return 0;
+}
+
+__typeof (ppc_abi_cfi)
+     ppc64_abi_cfi
+     __attribute__ ((alias ("ppc_abi_cfi")));
diff --git a/backends/ppc_corenote.c b/backends/ppc_corenote.c
new file mode 100644
index 0000000..2b4ada7
--- /dev/null
+++ b/backends/ppc_corenote.c
@@ -0,0 +1,145 @@
+/* PowerPC specific core note handling.
+   Copyright (C) 2007, 2008 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#ifndef BITS
+# define BITS 		32
+# define BACKEND	ppc_
+#else
+# define BITS 		64
+# define BACKEND	ppc64_
+#endif
+#include "libebl_CPU.h"
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+#define GR(at, n, dwreg)						\
+    { .offset = at * BITS/8, .regno = dwreg, .count = n, .bits = BITS }
+
+    GR (0, 32, 0),		/* r0-r31 */
+    /*	32, 1,			   nip */
+    GR (33, 1, 66),		/* msr */
+    /*	34, 1,			   orig_gpr3 */
+    GR (35, 1, 109),		/* ctr */
+    GR (36, 1, 108),		/* lr */
+    GR (37, 1, 101),		/* xer */
+    GR (38, 1, 64),		/* cr */
+    GR (39, 1, 100),		/* mq */
+    /*  40, 1,			   trap */
+    GR (41, 1, 119),		/* dar */
+    GR (42, 1, 118),		/* dsisr */
+
+#undef	GR
+  };
+#define PRSTATUS_REGS_SIZE	(BITS / 8 * 48)
+
+static const Ebl_Register_Location fpregset_regs[] =
+  {
+    { .offset = 0, .regno = 32, .count = 32, .bits = 64 }, /* f0-f31 */
+    { .offset = 32 * 8 + 4, .regno = 65, .count = 1, .bits = 32 } /* fpscr */
+  };
+#define FPREGSET_SIZE		(33 * 8)
+
+static const Ebl_Register_Location altivec_regs[] =
+  {
+    /* vr0-vr31 */
+    { .offset = 0, .regno = 1124, .count = 32, .bits = 128 },
+    /* vscr XXX 67 is an unofficial assignment */
+    { .offset = 32 * 16, .regno = 67, .count = 1, .bits = 32, .pad = 12 },
+    /* vrsave */
+    { .offset = 33 * 16, .regno = 356, .count = 1, .bits = 32, .pad = 12 }
+  };
+
+static const Ebl_Register_Location spe_regs[] =
+  {
+    /* evr0-evr31
+    { .offset = 0, .regno = ???, .count = 32, .bits = 32 },
+     * acc *
+    { .offset = 32 * 4, .regno = ???, .count = 1, .bits = 64 }, */
+    /* spefscr */
+    { .offset = 34 * 4, .regno = 612, .count = 1, .bits = 32 }
+  };
+
+static const Ebl_Register_Location tm_spr_regs[] =
+  {
+    /* tfhar */
+    { .offset = 0, .regno = 114, .count = 1, .bits = 64 },
+    /* texasr */
+    { .offset = 8, .regno = 116, .count = 1, .bits = 64 },
+    /* tfiar */
+    { .offset = 16, .regno = 115, .count = 1, .bits = 64 }
+  };
+
+#define EXTRA_NOTES \
+  EXTRA_REGSET (NT_PPC_VMX, 34 * 16, altivec_regs) \
+  EXTRA_REGSET (NT_PPC_SPE, 35 * 4, spe_regs) \
+  EXTRA_REGSET (NT_PPC_TM_SPR, 3 * 8, tm_spr_regs)
+
+#if BITS == 32
+# define ULONG			uint32_t
+# define ALIGN_ULONG		4
+# define TYPE_ULONG		ELF_T_WORD
+# define TYPE_LONG		ELF_T_SWORD
+#else
+# define ULONG			uint64_t
+# define ALIGN_ULONG		8
+# define TYPE_ULONG		ELF_T_XWORD
+# define TYPE_LONG		ELF_T_SXWORD
+#endif
+#define PID_T			int32_t
+#define	UID_T			uint32_t
+#define	GID_T			uint32_t
+#define ALIGN_PID_T		4
+#define ALIGN_UID_T		4
+#define ALIGN_GID_T		4
+#define TYPE_PID_T		ELF_T_SWORD
+#define TYPE_UID_T		ELF_T_WORD
+#define TYPE_GID_T		ELF_T_WORD
+
+#define PRSTATUS_REGSET_ITEMS						      \
+  {									      \
+    .name = "nip", .type = ELF_T_ADDR, .format = 'x',			      \
+    .offset = offsetof (struct EBLHOOK(prstatus), pr_reg[32]),		      \
+    .group = "register", .pc_register = true				      \
+  },								      	      \
+  {									      \
+    .name = "orig_gpr3", .type = TYPE_LONG, .format = 'd',		      \
+    .offset = offsetof (struct EBLHOOK(prstatus), pr_reg[34]),		      \
+    .group = "register"	       			  	       	 	      \
+  }
+
+#include "linux-core-note.c"
diff --git a/backends/ppc_init.c b/backends/ppc_init.c
new file mode 100644
index 0000000..aea9f2d
--- /dev/null
+++ b/backends/ppc_init.c
@@ -0,0 +1,74 @@
+/* Initialization of PPC specific backend library.
+   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2013 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		ppc_
+#define RELOC_PREFIX	R_PPC_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on ppc_reloc.def.  */
+#include "common-reloc.c"
+
+
+const char *
+ppc_init (Elf *elf __attribute__ ((unused)),
+	  GElf_Half machine __attribute__ ((unused)),
+	  Ebl *eh,
+	  size_t ehlen)
+{
+  /* Check whether the Elf_BH object has a sufficent size.  */
+  if (ehlen < sizeof (Ebl))
+    return NULL;
+
+  /* We handle it.  */
+  eh->name = "PowerPC";
+  ppc_init_reloc (eh);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, machine_flag_check);
+  HOOK (eh, dynamic_tag_name);
+  HOOK (eh, dynamic_tag_check);
+  HOOK (eh, check_special_symbol);
+  HOOK (eh, bss_plt_p);
+  HOOK (eh, return_value_location);
+  HOOK (eh, register_info);
+  HOOK (eh, syscall_abi);
+  HOOK (eh, core_note);
+  HOOK (eh, auxv_info);
+  HOOK (eh, check_object_attribute);
+  HOOK (eh, abi_cfi);
+  /* gcc/config/ #define DWARF_FRAME_REGISTERS.  */
+  eh->frame_nregs = (114 - 1) + 32;
+  HOOK (eh, set_initial_registers_tid);
+  HOOK (eh, dwarf_to_regno);
+
+  return MODVERSION;
+}
diff --git a/backends/ppc_initreg.c b/backends/ppc_initreg.c
new file mode 100644
index 0000000..69d623b
--- /dev/null
+++ b/backends/ppc_initreg.c
@@ -0,0 +1,114 @@
+/* Fetch live process registers from TID.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "system.h"
+#include <stdlib.h>
+#if defined(__powerpc__) && defined(__linux__)
+# include <sys/user.h>
+# include <sys/ptrace.h>
+#endif
+
+#define BACKEND ppc_
+#include "libebl_CPU.h"
+
+bool
+ppc_dwarf_to_regno (Ebl *ebl __attribute__ ((unused)), unsigned *regno)
+{
+  switch (*regno)
+  {
+    case 108:
+      // LR uses both 65 and 108 numbers, there is no consistency for it.
+      *regno = 65;
+      return true;
+    case 0 ... 107:
+    case 109 ... (114 - 1) -1:
+      return true;
+    case 1200 ... 1231:
+      *regno = *regno - 1200 + (114 - 1);
+      return true;
+    default:
+      return false;
+  }
+  abort ();
+}
+
+__typeof (ppc_dwarf_to_regno)
+     ppc64_dwarf_to_regno
+     __attribute__ ((alias ("ppc_dwarf_to_regno")));
+
+bool
+ppc_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
+			  ebl_tid_registers_t *setfunc __attribute__ ((unused)),
+			       void *arg __attribute__ ((unused)))
+{
+#if !defined(__powerpc__) || !defined(__linux__)
+  return false;
+#else /* __powerpc__ */
+  union
+    {
+      struct pt_regs r;
+      long l[sizeof (struct pt_regs) / sizeof (long)];
+    }
+  user_regs;
+  eu_static_assert (sizeof (struct pt_regs) % sizeof (long) == 0);
+  /* PTRACE_GETREGS is EIO on kernel-2.6.18-308.el5.ppc64.  */
+  errno = 0;
+  for (unsigned regno = 0; regno < sizeof (user_regs) / sizeof (long);
+       regno++)
+    {
+      user_regs.l[regno] = ptrace (PTRACE_PEEKUSER, tid,
+				   (void *) (uintptr_t) (regno
+							 * sizeof (long)),
+				   NULL);
+      if (errno != 0)
+	return false;
+    }
+  const size_t gprs = sizeof (user_regs.r.gpr) / sizeof (*user_regs.r.gpr);
+  Dwarf_Word dwarf_regs[gprs];
+  for (unsigned gpr = 0; gpr < gprs; gpr++)
+    dwarf_regs[gpr] = user_regs.r.gpr[gpr];
+  if (! setfunc (0, gprs, dwarf_regs, arg))
+    return false;
+  dwarf_regs[0] = user_regs.r.link;
+  // LR uses both 65 and 108 numbers, there is no consistency for it.
+  if (! setfunc (65, 1, dwarf_regs, arg))
+    return false;
+  /* Registers like msr, ctr, xer, dar, dsisr etc. are probably irrelevant
+     for CFI.  */
+  dwarf_regs[0] = user_regs.r.nip;
+  return setfunc (-1, 1, dwarf_regs, arg);
+#endif /* __powerpc__ */
+}
+
+__typeof (ppc_set_initial_registers_tid)
+     ppc64_set_initial_registers_tid
+     __attribute__ ((alias ("ppc_set_initial_registers_tid")));
diff --git a/backends/ppc_regs.c b/backends/ppc_regs.c
new file mode 100644
index 0000000..43d2534
--- /dev/null
+++ b/backends/ppc_regs.c
@@ -0,0 +1,208 @@
+/* Register names and numbers for PowerPC DWARF.
+   Copyright (C) 2005, 2006, 2007 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND ppc_
+#include "libebl_CPU.h"
+
+ssize_t
+ppc_register_info (Ebl *ebl __attribute__ ((unused)),
+		   int regno, char *name, size_t namelen,
+		   const char **prefix, const char **setname,
+		   int *bits, int *type)
+{
+  if (name == NULL)
+    return 1156;
+
+  if (regno < 0 || regno > 1155 || namelen < 8)
+    return -1;
+
+  *prefix = "";
+  *bits = ebl->machine == EM_PPC64 ? 64 : 32;
+  *type = (regno < 32 ? DW_ATE_signed
+	   : regno < 64 ? DW_ATE_float : DW_ATE_unsigned);
+
+  if (regno < 32 || regno == 64 || regno == 66)
+    *setname = "integer";
+  else if (regno < 64 || regno == 65)
+    {
+      *setname = "FPU";
+      if (ebl->machine != EM_PPC64 && regno < 64)
+	*bits = 64;
+    }
+  else if (regno == 67 || regno == 356 || regno == 612 || regno >= 1124)
+    {
+      *setname = "vector";
+      *bits = regno >= 1124 ? 128 : 32;
+    }
+  else
+    *setname = "privileged";
+
+  switch (regno)
+    {
+    case 0 ... 9:
+      name[0] = 'r';
+      name[1] = regno + '0';
+      namelen = 2;
+      break;
+
+    case 10 ... 31:
+      name[0] = 'r';
+      name[1] = regno / 10 + '0';
+      name[2] = regno % 10 + '0';
+      namelen = 3;
+      break;
+
+    case 32 + 0 ... 32 + 9:
+      name[0] = 'f';
+      name[1] = (regno - 32) + '0';
+      namelen = 2;
+      break;
+
+    case 32 + 10 ... 32 + 31:
+      name[0] = 'f';
+      name[1] = (regno - 32) / 10 + '0';
+      name[2] = (regno - 32) % 10 + '0';
+      namelen = 3;
+      break;
+
+    case 64:
+      return stpcpy (name, "cr") + 1 - name;
+    case 65:
+      return stpcpy (name, "fpscr") + 1 - name;
+    case 66:
+      return stpcpy (name, "msr") + 1 - name;
+    case 67:			/* XXX unofficial assignment */
+      return stpcpy (name, "vscr") + 1 - name;
+
+    case 70 + 0 ... 70 + 9:
+      name[0] = 's';
+      name[1] = 'r';
+      name[2] = (regno - 70) + '0';
+      namelen = 3;
+      break;
+
+    case 70 + 10 ... 70 + 15:
+      name[0] = 's';
+      name[1] = 'r';
+      name[2] = (regno - 70) / 10 + '0';
+      name[3] = (regno - 70) % 10 + '0';
+      namelen = 4;
+      break;
+
+    case 101:
+      return stpcpy (name, "xer") + 1 - name;
+    case 108:
+      return stpcpy (name, "lr") + 1 - name;
+    case 109:
+      return stpcpy (name, "ctr") + 1 - name;
+    case 118:
+      return stpcpy (name, "dsisr") + 1 - name;
+    case 119:
+      return stpcpy (name, "dar") + 1 - name;
+    case 122:
+      return stpcpy (name, "dec") + 1 - name;
+    case 356:
+      return stpcpy (name, "vrsave") + 1 - name;
+    case 612:
+      return stpcpy (name, "spefscr") + 1 - name;
+    case 100:
+      if (*bits == 32)
+	return stpcpy (name, "mq") + 1 - name;
+      FALLTHROUGH;
+    case 102 ... 107:
+      name[0] = 's';
+      name[1] = 'p';
+      name[2] = 'r';
+      name[3] = (regno - 100) + '0';
+      namelen = 4;
+      break;
+
+    case 114:
+      return stpcpy (name, "tfhar") + 1 - name;
+    case 115:
+      return stpcpy (name, "tfiar") + 1 - name;
+    case 116:
+      return stpcpy (name, "texasr") + 1 - name;
+
+    case 110 ... 113:
+    case 117:
+    case 120 ... 121:
+    case 123 ... 199:
+      name[0] = 's';
+      name[1] = 'p';
+      name[2] = 'r';
+      name[3] = (regno - 100) / 10 + '0';
+      name[4] = (regno - 100) % 10 + '0';
+      namelen = 5;
+      break;
+
+    case 200 ... 355:
+    case 357 ... 611:
+    case 613 ... 999:
+      name[0] = 's';
+      name[1] = 'p';
+      name[2] = 'r';
+      name[3] = (regno - 100) / 100 + '0';
+      name[4] = ((regno - 100) % 100 / 10) + '0';
+      name[5] = (regno - 100) % 10 + '0';
+      namelen = 6;
+      break;
+
+    case 1124 + 0 ... 1124 + 9:
+      name[0] = 'v';
+      name[1] = 'r';
+      name[2] = (regno - 1124) + '0';
+      namelen = 3;
+      break;
+
+    case 1124 + 10 ... 1124 + 31:
+      name[0] = 'v';
+      name[1] = 'r';
+      name[2] = (regno - 1124) / 10 + '0';
+      name[3] = (regno - 1124) % 10 + '0';
+      namelen = 4;
+      break;
+
+    default:
+      *setname = NULL;
+      return 0;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
+
+__typeof (ppc_register_info)
+     ppc64_register_info __attribute__ ((alias ("ppc_register_info")));
diff --git a/backends/ppc_reloc.def b/backends/ppc_reloc.def
new file mode 100644
index 0000000..3723a9c
--- /dev/null
+++ b/backends/ppc_reloc.def
@@ -0,0 +1,137 @@
+/* List the relocation types for ppc.  -*- C -*-
+   Copyright (C) 2005, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,		0)
+RELOC_TYPE (ADDR32,		REL|EXEC|DYN)
+RELOC_TYPE (ADDR24,		REL)
+RELOC_TYPE (ADDR16,		REL|EXEC|DYN)	/* note 1 */
+RELOC_TYPE (ADDR16_LO,		REL|EXEC|DYN)	/* note 1 */
+RELOC_TYPE (ADDR16_HI,		REL|EXEC|DYN)	/* note 1 */
+RELOC_TYPE (ADDR16_HA,		REL|EXEC|DYN)	/* note 1 */
+RELOC_TYPE (ADDR14,		REL|EXEC|DYN)	/* note 1 */
+RELOC_TYPE (ADDR14_BRTAKEN,	REL|EXEC|DYN)	/* note 1 */
+RELOC_TYPE (ADDR14_BRNTAKEN,	REL|EXEC|DYN)	/* note 1 */
+RELOC_TYPE (REL24,		REL|EXEC|DYN)	/* note 1 */
+RELOC_TYPE (REL14,		REL|EXEC|DYN)	/* note 1 */
+RELOC_TYPE (REL14_BRTAKEN,	REL|EXEC|DYN)	/* note 1 */
+RELOC_TYPE (REL14_BRNTAKEN,	REL|EXEC|DYN)	/* note 1 */
+RELOC_TYPE (GOT16,		REL)
+RELOC_TYPE (GOT16_LO,		REL)
+RELOC_TYPE (GOT16_HI,		REL)
+RELOC_TYPE (GOT16_HA,		REL)
+RELOC_TYPE (PLTREL24,		REL)
+RELOC_TYPE (COPY,		EXEC|DYN)
+RELOC_TYPE (GLOB_DAT,		EXEC|DYN)
+RELOC_TYPE (JMP_SLOT,		EXEC|DYN)
+RELOC_TYPE (RELATIVE,		EXEC|DYN)
+RELOC_TYPE (LOCAL24PC,		REL)
+RELOC_TYPE (UADDR32,		REL|EXEC|DYN)
+RELOC_TYPE (UADDR16,		REL)		/* note 2 */
+RELOC_TYPE (REL32,		REL|EXEC|DYN)
+RELOC_TYPE (PLT32,		REL)
+RELOC_TYPE (PLTREL32,		REL)
+RELOC_TYPE (PLT16_LO,		REL)
+RELOC_TYPE (PLT16_HI,		REL)
+RELOC_TYPE (PLT16_HA,		REL)
+RELOC_TYPE (SDAREL16,		REL)
+RELOC_TYPE (SECTOFF,		REL)
+RELOC_TYPE (SECTOFF_LO,		REL)
+RELOC_TYPE (SECTOFF_HI,		REL)
+RELOC_TYPE (SECTOFF_HA,		REL)
+RELOC_TYPE (TLS,		REL)
+RELOC_TYPE (DTPMOD32,		EXEC|DYN)	/* note 2 */
+RELOC_TYPE (TPREL16,		REL)		/* note 2 */
+RELOC_TYPE (TPREL16_LO,		REL)		/* note 2 */
+RELOC_TYPE (TPREL16_HI,		REL)		/* note 2 */
+RELOC_TYPE (TPREL16_HA,		REL)		/* note 2 */
+RELOC_TYPE (TPREL32,		EXEC|DYN)	/* note 2 */
+RELOC_TYPE (DTPREL16,		REL)
+RELOC_TYPE (DTPREL16_LO,	REL)
+RELOC_TYPE (DTPREL16_HI,	REL)
+RELOC_TYPE (DTPREL16_HA,	REL)
+RELOC_TYPE (DTPREL32,		EXEC|DYN)	/* note 2 */
+RELOC_TYPE (GOT_TLSGD16,	REL)
+RELOC_TYPE (GOT_TLSGD16_LO,	REL)
+RELOC_TYPE (GOT_TLSGD16_HI,	REL)
+RELOC_TYPE (GOT_TLSGD16_HA,	REL)
+RELOC_TYPE (GOT_TLSLD16,	REL)
+RELOC_TYPE (GOT_TLSLD16_LO,	REL)
+RELOC_TYPE (GOT_TLSLD16_HI,	REL)
+RELOC_TYPE (GOT_TLSLD16_HA,	REL)
+RELOC_TYPE (GOT_TPREL16,	REL)
+RELOC_TYPE (GOT_TPREL16_LO,	REL)
+RELOC_TYPE (GOT_TPREL16_HI,	REL)
+RELOC_TYPE (GOT_TPREL16_HA,	REL)
+RELOC_TYPE (GOT_DTPREL16,	REL)
+RELOC_TYPE (GOT_DTPREL16_LO,	REL)
+RELOC_TYPE (GOT_DTPREL16_HI,	REL)
+RELOC_TYPE (GOT_DTPREL16_HA,	REL)
+RELOC_TYPE (EMB_NADDR32,	REL)		/* note 3 */
+RELOC_TYPE (EMB_NADDR16,	REL)		/* note 3 */
+RELOC_TYPE (EMB_NADDR16_LO,	REL)		/* note 3 */
+RELOC_TYPE (EMB_NADDR16_HI,	REL)		/* note 3 */
+RELOC_TYPE (EMB_NADDR16_HA,	REL)		/* note 3 */
+RELOC_TYPE (EMB_SDAI16,		REL)		/* note 3 */
+RELOC_TYPE (EMB_SDA2I16,	REL)		/* note 3 */
+RELOC_TYPE (EMB_SDA2REL,	REL)		/* note 3 */
+RELOC_TYPE (EMB_SDA21,		REL)		/* note 3 */
+RELOC_TYPE (EMB_MRKREF,		REL)		/* note 3 */
+RELOC_TYPE (EMB_RELSEC16,	REL)		/* note 3 */
+RELOC_TYPE (EMB_RELST_LO,	REL)		/* note 3 */
+RELOC_TYPE (EMB_RELST_HI,	REL)		/* note 3 */
+RELOC_TYPE (EMB_RELST_HA,	REL)		/* note 3 */
+RELOC_TYPE (EMB_BIT_FLD,	REL)		/* note 3 */
+RELOC_TYPE (EMB_RELSDA,		REL)		/* note 3 */
+RELOC_TYPE (DIAB_SDA21_LO,	REL)		/* note 3 */
+RELOC_TYPE (DIAB_SDA21_HI,	REL)		/* note 3 */
+RELOC_TYPE (DIAB_SDA21_HA,	REL)		/* note 3 */
+RELOC_TYPE (DIAB_RELSDA_LO,	REL)		/* note 3 */
+RELOC_TYPE (DIAB_RELSDA_HI,	REL)		/* note 3 */
+RELOC_TYPE (DIAB_RELSDA_HA,	REL)		/* note 3 */
+RELOC_TYPE (REL16,		REL)		/* note 2 */
+RELOC_TYPE (REL16_LO,		REL)		/* note 2 */
+RELOC_TYPE (REL16_HI,		REL)		/* note 2 */
+RELOC_TYPE (REL16_HA,		REL)		/* note 2 */
+RELOC_TYPE (TOC16,		REL)		/* note 2 */
+
+/* Notes from Alan Modra:
+
+   1) These relocs should not really appear in EXEC or DYN, but they do,
+   primarily due to improper assembly or non-pic shared objects.  They
+   will cause TEXTREL to be set.  I marked them in the table, because
+   numerous people seem to think non-pic shared libs are a good idea.
+
+   2) As for (1), these relocs can appear anywhere with improper
+   assembler.  I should probably make ld reject anything other than the
+   cases allowed in this table.	 Not seen in the wild, so I haven't
+   added the other cases.
+
+   3) Not used in SYSV4
+*/
diff --git a/backends/ppc_retval.c b/backends/ppc_retval.c
new file mode 100644
index 0000000..39b42da
--- /dev/null
+++ b/backends/ppc_retval.c
@@ -0,0 +1,191 @@
+/* Function return value location for Linux/PPC ABI.
+   Copyright (C) 2005, 2006, 2007, 2010, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND ppc_
+#include "libebl_CPU.h"
+
+
+/* This is the SVR4 ELF ABI convention, but AIX and Linux do not use it.  */
+#define SVR4_STRUCT_RETURN 0
+
+
+/* r3, or pair r3, r4, or quad r3-r6.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg3 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg4 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg5 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg6 }, { .atom = DW_OP_piece, .number = 4 },
+  };
+#define nloc_intreg	1
+#define nloc_intregpair	4
+#define nloc_intregquad	8
+
+/* f1.  */
+static const Dwarf_Op loc_fpreg[] =
+  {
+    { .atom = DW_OP_regx, .number = 33 }
+  };
+#define nloc_fpreg	1
+
+/* vr2.  */
+static const Dwarf_Op loc_vmxreg[] =
+  {
+    { .atom = DW_OP_regx, .number = 1124 + 2 }
+  };
+#define nloc_vmxreg	1
+
+/* The return value is a structure and is actually stored in stack space
+   passed in a hidden argument by the caller.  But, the compiler
+   helpfully returns the address of that space in r3.  */
+static const Dwarf_Op loc_aggregate[] =
+  {
+    { .atom = DW_OP_breg3, .number = 0 }
+  };
+#define nloc_aggregate 1
+
+
+/* XXX We should check the SHT_GNU_ATTRIBUTES bits here (or in ppc_init).  */
+static bool
+ppc_altivec_abi (void)
+{
+  return true;
+}
+
+int
+ppc_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die die_mem, *typedie = &die_mem;
+  int tag = dwarf_peeled_die_type (functypedie, typedie);
+  if (tag <= 0)
+    return tag;
+
+  Dwarf_Word size;
+  switch (tag)
+    {
+    case -1:
+      return -1;
+
+    case DW_TAG_subrange_type:
+      if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
+	{
+	  Dwarf_Attribute attr_mem, *attr;
+	  attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+	  typedie = dwarf_formref_die (attr, &die_mem);
+	  tag = DWARF_TAG_OR_RETURN (typedie);
+	}
+      FALLTHROUGH;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    case DW_TAG_pointer_type:
+    case DW_TAG_ptr_to_member_type:
+      {
+	Dwarf_Attribute attr_mem;
+	if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+						   &attr_mem), &size) != 0)
+	  {
+	    if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+	      size = 4;
+	    else
+	      return -1;
+	  }
+      }
+
+      if (size <= 8)
+	{
+	  if (tag == DW_TAG_base_type)
+	    {
+	      Dwarf_Attribute attr_mem;
+	      Dwarf_Word encoding;
+	      if (dwarf_formudata (dwarf_attr_integrate (typedie,
+							 DW_AT_encoding,
+							 &attr_mem),
+				   &encoding) != 0)
+		return -1;
+	      if (encoding == DW_ATE_float)
+		{
+		  *locp = loc_fpreg;
+		  return nloc_fpreg;
+		}
+	    }
+	intreg:
+	  *locp = loc_intreg;
+	  return size <= 4 ? nloc_intreg : nloc_intregpair;
+	}
+
+    aggregate:
+      *locp = loc_aggregate;
+      return nloc_aggregate;
+
+    case DW_TAG_array_type:
+      {
+	Dwarf_Attribute attr_mem;
+	bool is_vector;
+	if (dwarf_formflag (dwarf_attr_integrate (typedie, DW_AT_GNU_vector,
+						  &attr_mem), &is_vector) == 0
+	    && is_vector
+	    && dwarf_aggregate_size (typedie, &size) == 0)
+	  switch (size)
+	    {
+	    case 16:
+	      if (ppc_altivec_abi ())
+		{
+		  *locp = loc_vmxreg;
+		  return nloc_vmxreg;
+		}
+	      *locp = loc_intreg;
+	      return nloc_intregquad;
+	    }
+      }
+      FALLTHROUGH;
+
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+      if (SVR4_STRUCT_RETURN
+	  && dwarf_aggregate_size (typedie, &size) == 0
+	  && size > 0 && size <= 8)
+	goto intreg;
+      goto aggregate;
+    }
+
+  /* XXX We don't have a good way to return specific errors from ebl calls.
+     This value means we do not understand the type, but it is well-formed
+     DWARF and might be valid.  */
+  return -2;
+}
diff --git a/backends/ppc_symbol.c b/backends/ppc_symbol.c
new file mode 100644
index 0000000..4b32003
--- /dev/null
+++ b/backends/ppc_symbol.c
@@ -0,0 +1,184 @@
+/* PPC specific symbolic name handling.
+   Copyright (C) 2004, 2005, 2007, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <elf.h>
+#include <stddef.h>
+#include <string.h>
+
+#define BACKEND		ppc_
+#include "libebl_CPU.h"
+
+
+/* Check for the simple reloc types.  */
+Elf_Type
+ppc_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+{
+  switch (type)
+    {
+    case R_PPC_ADDR32:
+    case R_PPC_UADDR32:
+      return ELF_T_WORD;
+    case R_PPC_UADDR16:
+      return ELF_T_HALF;
+    default:
+      return ELF_T_NUM;
+    }
+}
+
+
+/* Check whether machine flags are valid.  */
+bool
+ppc_machine_flag_check (GElf_Word flags)
+{
+  return ((flags &~ (EF_PPC_EMB
+		     | EF_PPC_RELOCATABLE
+		     | EF_PPC_RELOCATABLE_LIB)) == 0);
+}
+
+
+const char *
+ppc_dynamic_tag_name (int64_t tag, char *buf __attribute__ ((unused)),
+		      size_t len __attribute__ ((unused)))
+{
+  switch (tag)
+    {
+    case DT_PPC_GOT:
+      return "PPC_GOT";
+    case DT_PPC_OPT:
+      return "PPC_OPT";
+    default:
+      break;
+    }
+  return NULL;
+}
+
+
+bool
+ppc_dynamic_tag_check (int64_t tag)
+{
+  return (tag == DT_PPC_GOT
+	  || tag == DT_PPC_OPT);
+}
+
+
+/* Look for DT_PPC_GOT.  */
+static bool
+find_dyn_got (Elf *elf, GElf_Addr *addr)
+{
+  size_t phnum;
+  if (elf_getphdrnum (elf, &phnum) != 0)
+    return false;
+
+  for (size_t i = 0; i < phnum; ++i)
+    {
+      GElf_Phdr phdr_mem;
+      GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
+      if (phdr == NULL || phdr->p_type != PT_DYNAMIC)
+	continue;
+
+      Elf_Scn *scn = gelf_offscn (elf, phdr->p_offset);
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      Elf_Data *data = elf_getdata (scn, NULL);
+      if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC && data != NULL
+	  && shdr->sh_entsize != 0)
+	for (unsigned int j = 0; j < shdr->sh_size / shdr->sh_entsize; ++j)
+	  {
+	    GElf_Dyn dyn_mem;
+	    GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
+	    if (dyn != NULL && dyn->d_tag == DT_PPC_GOT)
+	      {
+		*addr = dyn->d_un.d_ptr;
+		return true;
+	      }
+	  }
+
+      /* There is only one PT_DYNAMIC entry.  */
+      break;
+    }
+
+  return false;
+}
+
+
+/* Check whether given symbol's st_value and st_size are OK despite failing
+   normal checks.  */
+bool
+ppc_check_special_symbol (Elf *elf, GElf_Ehdr *ehdr, const GElf_Sym *sym,
+			  const char *name, const GElf_Shdr *destshdr)
+{
+  if (name == NULL)
+    return false;
+
+  if (strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
+    {
+      /* In -msecure-plt mode, DT_PPC_GOT is present and must match.  */
+      GElf_Addr gotaddr;
+      if (find_dyn_got (elf, &gotaddr))
+	return sym->st_value == gotaddr;
+
+      /* In -mbss-plt mode, any place in the section is valid.  */
+      return true;
+    }
+
+  const char *sname = elf_strptr (elf, ehdr->e_shstrndx, destshdr->sh_name);
+  if (sname == NULL)
+    return false;
+
+  /* Small data area.  Normally points to .sdata, in which case we
+     check it is at an offset of 0x8000.  It might however fall in the
+     .data section, in which case we cannot check the offset.  The
+     size always should be zero.  */
+  if (strcmp (name, "_SDA_BASE_") == 0)
+    return (((strcmp (sname, ".sdata") == 0
+	      && sym->st_value == destshdr->sh_addr + 0x8000)
+	     || strcmp (sname, ".data") == 0)
+	    && sym->st_size == 0);
+
+  if (strcmp (name, "_SDA2_BASE_") == 0)
+    return (strcmp (sname, ".sdata2") == 0
+	    && sym->st_value == destshdr->sh_addr + 0x8000
+	    && sym->st_size == 0);
+
+  return false;
+}
+
+
+/* Check if backend uses a bss PLT in this file.  */
+bool
+ppc_bss_plt_p (Elf *elf)
+{
+  GElf_Addr addr;
+  return ! find_dyn_got (elf, &addr);
+}
diff --git a/backends/ppc_syscall.c b/backends/ppc_syscall.c
new file mode 100644
index 0000000..b1b9c52
--- /dev/null
+++ b/backends/ppc_syscall.c
@@ -0,0 +1,53 @@
+/* Linux/PPC system call ABI in DWARF register numbers.
+   Copyright (C) 2008 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND ppc_
+#include "libebl_CPU.h"
+
+int
+ppc_syscall_abi (Ebl *ebl __attribute__ ((unused)),
+		 int *sp, int *pc, int *callno, int args[6])
+{
+  *sp = 1;
+  *pc = -1;
+  *callno = 0;
+  args[0] = 3;
+  args[1] = 4;
+  args[2] = 5;
+  args[3] = 6;
+  args[4] = 7;
+  args[5] = 8;
+  return 0;
+}
+
+__typeof (ppc_syscall_abi)
+ppc64_syscall_abi __attribute__ ((alias ("ppc_syscall_abi")));
diff --git a/backends/s390_cfi.c b/backends/s390_cfi.c
new file mode 100644
index 0000000..cb49486
--- /dev/null
+++ b/backends/s390_cfi.c
@@ -0,0 +1,65 @@
+/* s390 ABI-specified defaults for DWARF CFI.
+   Copyright (C) 2012, 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#define BACKEND s390_
+#include "libebl_CPU.h"
+
+int
+s390_abi_cfi (Ebl *ebl, Dwarf_CIE *abi_info)
+{
+  static const uint8_t abi_cfi[] =
+    {
+      /* This instruction is provided in every CIE.  It is not repeated here:
+	 DW_CFA_def_cfa, ULEB128_7 (15), ULEB128_7 (96)  */
+      /* r14 is not callee-saved but it needs to be preserved as it is pre-set
+	 by the caller.  */
+      DW_CFA_same_value, ULEB128_7 (14), /* r14 */
+
+      /* Callee-saved regs.  */
+#define SV(n) DW_CFA_same_value, ULEB128_7 (n)
+      SV (6), SV (7), SV (8), SV (9), SV (10),		       /* r6-r13, r15 */
+      SV (11), SV (12), SV (13), SV (15),
+      SV (16 + 8), SV (16 + 9), SV (16 + 10), SV (16 + 11),    /* f8-f15 */
+      SV (16 + 12), SV (16 + 13), SV (16 + 14), SV (16 + 15)
+#undef SV
+    };
+
+  abi_info->initial_instructions = abi_cfi;
+  abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
+  abi_info->data_alignment_factor = ebl->class == ELFCLASS64 ? 8 : 4;
+
+  abi_info->return_address_register = 14;
+
+  return 0;
+}
diff --git a/backends/s390_corenote.c b/backends/s390_corenote.c
new file mode 100644
index 0000000..7ca3516
--- /dev/null
+++ b/backends/s390_corenote.c
@@ -0,0 +1,189 @@
+/* S390-specific core note handling.
+   Copyright (C) 2012 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#ifndef BITS
+# define BITS 		32
+# define BACKEND	s390_
+#else
+# define BITS 		64
+# define BACKEND	s390x_
+#endif
+#include "libebl_CPU.h"
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+#define GR(at, n, dwreg, b...)						\
+    { .offset = at * BITS/8, .regno = dwreg, .count = n, .bits = b }
+
+    GR ( 0,  1, 64, BITS),				/* pswm */
+    GR ( 1,  1, 65, BITS, .pc_register = true ),	/* pswa */
+    GR ( 2, 16,  0, BITS),				/* r0-r15 */
+    GR (18, 16, 48,   32),				/* ar0-ar15 */
+
+#undef	GR
+  };
+
+  /* orig_r2 is at offset (BITS == 32 ? 34 * 4 : 26 * 8).  */
+#define PRSTATUS_REGS_SIZE	(BITS / 8 * (BITS == 32 ? 35 : 27))
+
+static const Ebl_Register_Location fpregset_regs[] =
+  {
+#define FPR(at, n, dwreg)						\
+    { .offset = at * 64/8, .regno = dwreg, .count = n, .bits = 64 }
+
+    /* fpc is at offset 0, see fpregset_items, it has no assigned DWARF regno.
+       Bytes at offsets 4 to 7 are unused.  */
+    FPR (1 +  0, 1, 16),	/* f0 */
+    FPR (1 +  1, 1, 20),	/* f1 */
+    FPR (1 +  2, 1, 17),	/* f2 */
+    FPR (1 +  3, 1, 21),	/* f3 */
+    FPR (1 +  4, 1, 18),	/* f4 */
+    FPR (1 +  5, 1, 22),	/* f5 */
+    FPR (1 +  6, 1, 19),	/* f6 */
+    FPR (1 +  7, 1, 23),	/* f7 */
+    FPR (1 +  8, 1, 24),	/* f8 */
+    FPR (1 +  9, 1, 28),	/* f9 */
+    FPR (1 + 10, 1, 25),	/* f10 */
+    FPR (1 + 11, 1, 29),	/* f11 */
+    FPR (1 + 12, 1, 26),	/* f12 */
+    FPR (1 + 13, 1, 30),	/* f13 */
+    FPR (1 + 14, 1, 27),	/* f14 */
+    FPR (1 + 15, 1, 31),	/* f15 */
+
+#undef	FPR
+  };
+
+static const Ebl_Core_Item fpregset_items[] =
+  {
+    {
+      .name = "fpc", .group = "register", .offset = 0, .type = ELF_T_WORD,
+      .format = 'x',
+    },
+  };
+
+/* Do not set FPREGSET_SIZE so that we can supply fpregset_items.  */
+#define EXTRA_NOTES_FPREGSET \
+    EXTRA_REGSET_ITEMS (NT_FPREGSET, 17 * 8, fpregset_regs, fpregset_items)
+
+#if BITS == 32
+# define ULONG			uint32_t
+# define ALIGN_ULONG		4
+# define TYPE_ULONG		ELF_T_WORD
+# define TYPE_LONG		ELF_T_SWORD
+# define UID_T			uint16_t
+# define GID_T			uint16_t
+# define ALIGN_UID_T		2
+# define ALIGN_GID_T		2
+# define TYPE_UID_T		ELF_T_HALF
+# define TYPE_GID_T		ELF_T_HALF
+#else
+# define ULONG			uint64_t
+# define ALIGN_ULONG		8
+# define TYPE_ULONG		ELF_T_XWORD
+# define TYPE_LONG		ELF_T_SXWORD
+# define UID_T			uint32_t
+# define GID_T			uint32_t
+# define ALIGN_UID_T		4
+# define ALIGN_GID_T		4
+# define TYPE_UID_T		ELF_T_WORD
+# define TYPE_GID_T		ELF_T_WORD
+#endif
+#define PID_T			int32_t
+#define ALIGN_PID_T		4
+#define TYPE_PID_T		ELF_T_SWORD
+/* s390 psw_compat_t has alignment 8 bytes where it is inherited from.  */
+#define ALIGN_PR_REG		8
+
+#define PRSTATUS_REGSET_ITEMS					\
+  {								\
+    .name = "orig_r2", .type = TYPE_LONG, .format = 'd',	\
+    .offset = offsetof (struct EBLHOOK(prstatus),		\
+			pr_reg[BITS == 32 ? 34 : 26]),		\
+    .group = "register"						\
+  }
+
+#if BITS == 32
+
+static const Ebl_Core_Item high_regs_items[] =
+  {
+#define HR(n)								\
+    {									\
+      .name = "high_r" #n , .group = "register", .offset = (n) * 4,	\
+      .type = ELF_T_WORD, .format = 'x',				\
+    }
+
+    /* Upper halves of r0-r15 are stored here.
+       FIXME: They are currently not combined with the r0-r15 lower halves.  */
+    HR (0), HR (1), HR (2), HR (3), HR (4), HR (5), HR (6), HR (7),
+    HR (8), HR (9), HR (10), HR (11), HR (12), HR (13), HR (14), HR (15)
+
+#undef HR
+  };
+
+#define EXTRA_NOTES_HIGH_GPRS \
+  EXTRA_ITEMS (NT_S390_HIGH_GPRS, 16 * 4, high_regs_items)
+
+#else /* BITS == 64 */
+
+#define EXTRA_NOTES_HIGH_GPRS
+
+#endif /* BITS == 64 */
+
+static const Ebl_Core_Item last_break_items[] =
+  {
+    {
+      .name = "last_break", .group = "system", .offset = BITS == 32 ? 4 : 0,
+      .type = BITS == 32 ? ELF_T_WORD : ELF_T_XWORD, .format = 'x',
+    },
+  };
+
+static const Ebl_Core_Item system_call_items[] =
+  {
+    {
+      .name = "system_call", .group = "system", .offset = 0, .type = ELF_T_WORD,
+      .format = 'd',
+    },
+  };
+
+#define	EXTRA_NOTES							  \
+  EXTRA_NOTES_FPREGSET							  \
+  EXTRA_NOTES_HIGH_GPRS							  \
+  EXTRA_ITEMS (NT_S390_LAST_BREAK, 8, last_break_items)	  \
+  EXTRA_ITEMS (NT_S390_SYSTEM_CALL, 4, system_call_items)
+
+#include "linux-core-note.c"
diff --git a/backends/s390_init.c b/backends/s390_init.c
new file mode 100644
index 0000000..ba8df45
--- /dev/null
+++ b/backends/s390_init.c
@@ -0,0 +1,79 @@
+/* Initialization of S/390 specific backend library.
+   Copyright (C) 2005, 2006, 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		s390_
+#define RELOC_PREFIX	R_390_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on arm_reloc.def.  */
+#include "common-reloc.c"
+
+extern __typeof (s390_core_note) s390x_core_note;
+
+
+const char *
+s390_init (Elf *elf __attribute__ ((unused)),
+	   GElf_Half machine __attribute__ ((unused)),
+	   Ebl *eh,
+	   size_t ehlen)
+{
+  /* Check whether the Elf_BH object has a sufficent size.  */
+  if (ehlen < sizeof (Ebl))
+    return NULL;
+
+  /* We handle it.  */
+  eh->name = "IBM S/390";
+  s390_init_reloc (eh);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, register_info);
+  HOOK (eh, return_value_location);
+  if (eh->class == ELFCLASS64)
+    eh->core_note = s390x_core_note;
+  else
+    HOOK (eh, core_note);
+  HOOK (eh, abi_cfi);
+  /* gcc/config/ #define DWARF_FRAME_REGISTERS 34.
+     But from the gcc/config/s390/s390.h "Register usage." comment it looks as
+     if #32 (Argument pointer) and #33 (Condition code) are not used for
+     unwinding.  */
+  eh->frame_nregs = 32;
+  HOOK (eh, set_initial_registers_tid);
+  if (eh->class == ELFCLASS32)
+    HOOK (eh, normalize_pc);
+  HOOK (eh, unwind);
+
+  /* Only the 64-bit format uses the incorrect hash table entry size.  */
+  if (eh->class == ELFCLASS64)
+    eh->sysvhash_entrysize = sizeof (Elf64_Xword);
+
+  return MODVERSION;
+}
diff --git a/backends/s390_initreg.c b/backends/s390_initreg.c
new file mode 100644
index 0000000..23bf8ed
--- /dev/null
+++ b/backends/s390_initreg.c
@@ -0,0 +1,95 @@
+/* Fetch live process registers from TID.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "system.h"
+#include <assert.h>
+#if defined(__s390__) && defined(__linux__)
+# include <sys/user.h>
+# include <sys/ptrace.h>
+# include <asm/ptrace.h>
+#endif
+
+#define BACKEND s390_
+#include "libebl_CPU.h"
+
+bool
+s390_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
+			  ebl_tid_registers_t *setfunc __attribute__ ((unused)),
+				void *arg __attribute__ ((unused)))
+{
+#if !defined(__s390__) || !defined(__linux__)
+  return false;
+#else /* __s390__ */
+  struct user user_regs;
+  ptrace_area parea;
+  parea.process_addr = (uintptr_t) &user_regs;
+  parea.kernel_addr = 0;
+  parea.len = sizeof (user_regs);
+  if (ptrace (PTRACE_PEEKUSR_AREA, tid, &parea, NULL) != 0)
+    return false;
+  /* If we run as s390x we get the 64-bit registers of tid.
+     But -m31 executable seems to use only the 32-bit parts of its
+     registers so we ignore the upper half.  */
+  Dwarf_Word dwarf_regs[16];
+  for (unsigned u = 0; u < 16; u++)
+    dwarf_regs[u] = user_regs.regs.gprs[u];
+  if (! setfunc (0, 16, dwarf_regs, arg))
+    return false;
+  /* Avoid conversion double -> integer.  */
+  eu_static_assert (sizeof user_regs.regs.fp_regs.fprs[0]
+		    == sizeof dwarf_regs[0]);
+  for (unsigned u = 0; u < 16; u++)
+    {
+      // Store the double bits as is in the Dwarf_Word without conversion.
+      union
+	{
+	  double d;
+	  Dwarf_Word w;
+	} fpr = { .d = user_regs.regs.fp_regs.fprs[u] };
+      dwarf_regs[u] = fpr.w;
+    }
+
+  if (! setfunc (16, 16, dwarf_regs, arg))
+    return false;
+  dwarf_regs[0] = user_regs.regs.psw.addr;
+  return setfunc (-1, 1, dwarf_regs, arg);
+#endif /* __s390__ */
+}
+
+void
+s390_normalize_pc (Ebl *ebl __attribute__ ((unused)), Dwarf_Addr *pc)
+{
+  assert (ebl->class == ELFCLASS32);
+
+  /* Clear S390 bit 31.  */
+  *pc &= (1U << 31) - 1;
+}
diff --git a/backends/s390_regs.c b/backends/s390_regs.c
new file mode 100644
index 0000000..ba6178a
--- /dev/null
+++ b/backends/s390_regs.c
@@ -0,0 +1,146 @@
+/* Register names and numbers for S/390 DWARF.
+   Copyright (C) 2006 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND s390_
+#include "libebl_CPU.h"
+
+
+/*
+zseries (64)
+
+0-15	gpr0-gpr15	x
+16-19	fpr[0246]
+20-24	fpr[13578]
+25-27	fpr1[024]
+28	fpr9
+29-31	fpr1[135]
+32-47	cr0-cr15	x
+48-63	ar0-ar15	x
+64	psw_mask
+65	psw_address
+*/
+
+
+ssize_t
+s390_register_info (Ebl *ebl __attribute__ ((unused)),
+		    int regno, char *name, size_t namelen,
+		    const char **prefix, const char **setname,
+		    int *bits, int *type)
+{
+  if (name == NULL)
+    return 66;
+
+  if (regno < 0 || regno > 65 || namelen < 7)
+    return -1;
+
+  *prefix = "%";
+
+  *bits = ebl->class == ELFCLASS64 ? 64 : 32;
+  *type = DW_ATE_unsigned;
+  if (regno < 16)
+    {
+      *setname = "integer";
+      *type = DW_ATE_signed;
+    }
+  else if (regno < 32)
+    {
+      *setname = "FPU";
+      *type = DW_ATE_float;
+      *bits = 64;
+    }
+  else if (regno < 48 || regno > 63)
+    *setname = "control";
+  else
+    {
+      *setname = "access";
+      *bits = 32;
+    }
+
+  switch (regno)
+    {
+    case 0 ... 9:
+      name[0] = 'r';
+      name[1] = regno + '0';
+      namelen = 2;
+      break;
+
+    case 10 ... 15:
+      name[0] = 'r';
+      name[1] = '1';
+      name[2] = regno - 10 + '0';
+      namelen = 3;
+      break;
+
+    case 16 ... 31:
+      name[0] = 'f';
+      regno = (regno & 8) | ((regno & 4) >> 2) | ((regno & 3) << 1);
+      namelen = 1;
+      if (regno >= 10)
+	{
+	  regno -= 10;
+	  name[namelen++] = '1';
+	}
+      name[namelen++] = regno + '0';
+      break;
+
+    case 32 + 0 ... 32 + 9:
+    case 48 + 0 ... 48 + 9:
+      name[0] = regno < 48 ? 'c' : 'a';
+      name[1] = (regno & 15) + '0';
+      namelen = 2;
+      break;
+
+    case 32 + 10 ... 32 + 15:
+    case 48 + 10 ... 48 + 15:
+      name[0] = regno < 48 ? 'c' : 'a';
+      name[1] = '1';
+      name[2] = (regno & 15) - 10 + '0';
+      namelen = 3;
+      break;
+
+    case 64:
+      return stpcpy (name, "pswm") + 1 - name;
+    case 65:
+      *type = DW_ATE_address;
+      return stpcpy (name, "pswa") + 1 - name;
+
+    default:
+      *setname = NULL;
+      return 0;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
diff --git a/backends/s390_reloc.def b/backends/s390_reloc.def
new file mode 100644
index 0000000..cdef9eb
--- /dev/null
+++ b/backends/s390_reloc.def
@@ -0,0 +1,91 @@
+/* List the relocation types for s390.  -*- C -*-
+   Copyright (C) 2005, 2006, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/* 	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,               0)
+RELOC_TYPE (8,                  REL|EXEC|DYN)
+RELOC_TYPE (12,                 REL|EXEC|DYN)
+RELOC_TYPE (16,                 REL|EXEC|DYN)
+RELOC_TYPE (32,                 REL|EXEC|DYN)
+RELOC_TYPE (PC32,               REL|EXEC|DYN)
+RELOC_TYPE (GOT12,              REL)
+RELOC_TYPE (GOT32,              REL)
+RELOC_TYPE (PLT32,              REL)
+RELOC_TYPE (COPY,               EXEC|DYN)
+RELOC_TYPE (GLOB_DAT,           EXEC|DYN)
+RELOC_TYPE (JMP_SLOT,           EXEC|DYN)
+RELOC_TYPE (RELATIVE,           EXEC|DYN)
+RELOC_TYPE (GOTOFF32,           REL)
+RELOC_TYPE (GOTPC,              REL)
+RELOC_TYPE (GOT16,              REL)
+RELOC_TYPE (PC16,               REL|EXEC|DYN)
+RELOC_TYPE (PC16DBL,            REL|EXEC|DYN)
+RELOC_TYPE (PLT16DBL,           REL)
+RELOC_TYPE (PC32DBL,            REL|EXEC|DYN)
+RELOC_TYPE (PLT32DBL,           REL)
+RELOC_TYPE (GOTPCDBL,           REL)
+RELOC_TYPE (64,                 REL|EXEC|DYN)
+RELOC_TYPE (PC64,               REL|EXEC|DYN)
+RELOC_TYPE (GOT64,              REL)
+RELOC_TYPE (PLT64,              REL)
+RELOC_TYPE (GOTENT,             REL)
+RELOC_TYPE (GOTOFF16,           REL)
+RELOC_TYPE (GOTOFF64,           REL)
+RELOC_TYPE (GOTPLT12,           REL)
+RELOC_TYPE (GOTPLT16,           REL)
+RELOC_TYPE (GOTPLT32,           REL)
+RELOC_TYPE (GOTPLT64,           REL)
+RELOC_TYPE (GOTPLTENT,          REL)
+RELOC_TYPE (PLTOFF16,           REL)
+RELOC_TYPE (PLTOFF32,           REL)
+RELOC_TYPE (PLTOFF64,           REL)
+RELOC_TYPE (TLS_LOAD,           REL)
+RELOC_TYPE (TLS_GDCALL,         REL)
+RELOC_TYPE (TLS_LDCALL,         REL)
+RELOC_TYPE (TLS_GD32,           REL)
+RELOC_TYPE (TLS_GD64,           REL)
+RELOC_TYPE (TLS_GOTIE12,        REL)
+RELOC_TYPE (TLS_GOTIE32,        REL)
+RELOC_TYPE (TLS_GOTIE64,        REL)
+RELOC_TYPE (TLS_LDM32,          REL)
+RELOC_TYPE (TLS_LDM64,          REL)
+RELOC_TYPE (TLS_IE32,           REL)
+RELOC_TYPE (TLS_IE64,           REL)
+RELOC_TYPE (TLS_IEENT,          REL)
+RELOC_TYPE (TLS_LE32,           REL)
+RELOC_TYPE (TLS_LE64,           REL)
+RELOC_TYPE (TLS_LDO32,          REL)
+RELOC_TYPE (TLS_LDO64,          REL)
+RELOC_TYPE (TLS_DTPMOD,         DYN)
+RELOC_TYPE (TLS_DTPOFF,         DYN)
+RELOC_TYPE (TLS_TPOFF,          DYN)
+RELOC_TYPE (20,                 REL|EXEC|DYN)
+RELOC_TYPE (GOT20,              REL)
+RELOC_TYPE (GOTPLT20,           REL)
+RELOC_TYPE (TLS_GOTIE20,        REL)
diff --git a/backends/s390_retval.c b/backends/s390_retval.c
new file mode 100644
index 0000000..2043f98
--- /dev/null
+++ b/backends/s390_retval.c
@@ -0,0 +1,144 @@
+/* Function return value location for S/390 ABI.
+   Copyright (C) 2006, 2007, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND s390_
+#include "libebl_CPU.h"
+
+
+/* %r2, or pair %r2, %r3.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg2 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg3 }, { .atom = DW_OP_piece, .number = 4 },
+  };
+#define nloc_intreg	1
+#define nloc_intregpair	4
+
+/* %f0.  */
+static const Dwarf_Op loc_fpreg[] =
+  {
+    { .atom = DW_OP_reg16 },
+  };
+#define nloc_fpreg	1
+
+/* The return value is a structure and is actually stored in stack space
+   passed in a hidden argument by the caller.  But, the compiler
+   helpfully returns the address of that space in %r2.  */
+static const Dwarf_Op loc_aggregate[] =
+  {
+    { .atom = DW_OP_breg2, .number = 0 }
+  };
+#define nloc_aggregate 1
+
+
+int
+s390_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die die_mem, *typedie = &die_mem;
+  int tag = dwarf_peeled_die_type (functypedie, typedie);
+  if (tag <= 0)
+    return tag;
+
+  Dwarf_Word size;
+  switch (tag)
+    {
+    case -1:
+      return -1;
+
+    case DW_TAG_subrange_type:
+      if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
+	{
+	  Dwarf_Attribute attr_mem, *attr;
+	  attr = dwarf_attr (typedie, DW_AT_type, &attr_mem);
+	  typedie = dwarf_formref_die (attr, &die_mem);
+	  tag = DWARF_TAG_OR_RETURN (typedie);
+	}
+      FALLTHROUGH;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    case DW_TAG_pointer_type:
+    case DW_TAG_ptr_to_member_type:
+      {
+	Dwarf_Die cudie;
+	uint8_t asize;
+	if (dwarf_diecu (typedie, &cudie, &asize, NULL) == NULL)
+	  return -1;
+
+	Dwarf_Attribute attr_mem;
+	if (dwarf_formudata (dwarf_attr (typedie, DW_AT_byte_size,
+					 &attr_mem), &size) != 0)
+	  {
+	    if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+	      size = asize;
+	    else
+	      return -1;
+	  }
+	if (tag == DW_TAG_base_type)
+	  {
+	    Dwarf_Word encoding;
+	    if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
+						       &attr_mem),
+				 &encoding) != 0)
+	      return -1;
+	    if (encoding == DW_ATE_float && size <= 8)
+	      {
+		*locp = loc_fpreg;
+		return nloc_fpreg;
+	      }
+	  }
+	if (size <= 8)
+	  {
+	    *locp = loc_intreg;
+	    return size <= asize ? nloc_intreg : nloc_intregpair;
+	  }
+      }
+      FALLTHROUGH;
+
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+    case DW_TAG_array_type:
+      *locp = loc_aggregate;
+      return nloc_aggregate;
+    }
+
+  /* XXX We don't have a good way to return specific errors from ebl calls.
+     This value means we do not understand the type, but it is well-formed
+     DWARF and might be valid.  */
+  return -2;
+}
diff --git a/backends/s390_symbol.c b/backends/s390_symbol.c
new file mode 100644
index 0000000..a0a4faf
--- /dev/null
+++ b/backends/s390_symbol.c
@@ -0,0 +1,56 @@
+/* S/390-specific symbolic name handling.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <stddef.h>
+
+#define BACKEND		s390_
+#include "libebl_CPU.h"
+
+/* Check for the simple reloc types.  */
+Elf_Type
+s390_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+{
+  switch (type)
+    {
+    case R_390_64:
+      return ELF_T_SXWORD;
+    case R_390_32:
+      return ELF_T_SWORD;
+    case R_390_16:
+      return ELF_T_HALF;
+    case R_390_8:
+      return ELF_T_BYTE;
+    default:
+      return ELF_T_NUM;
+    }
+}
diff --git a/backends/s390_unwind.c b/backends/s390_unwind.c
new file mode 100644
index 0000000..752bc28
--- /dev/null
+++ b/backends/s390_unwind.c
@@ -0,0 +1,139 @@
+/* Get previous frame state for an existing frame state.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <assert.h>
+
+#define BACKEND s390_
+#include "libebl_CPU.h"
+
+/* s390/s390x do not annotate signal handler frame by CFI.  It would be also
+   difficult as PC points into a stub built on stack.  Function below is called
+   only if unwinder could not find CFI.  Function then verifies the register
+   state for this frame really belongs to a signal frame.  In such case it
+   fetches original registers saved by the signal frame.  */
+
+bool
+s390_unwind (Ebl *ebl, Dwarf_Addr pc, ebl_tid_registers_t *setfunc,
+	     ebl_tid_registers_get_t *getfunc, ebl_pid_memory_read_t *readfunc,
+	     void *arg, bool *signal_framep)
+{
+  /* Caller already assumed caller adjustment but S390 instructions are 4 bytes
+     long.  Undo it.  */
+  if ((pc & 0x3) != 0x3)
+    return false;
+  pc++;
+  /* We can assume big-endian read here.  */
+  Dwarf_Word instr;
+  if (! readfunc (pc, &instr, arg))
+    return false;
+  /* Fetch only the very first two bytes.  */
+  instr = (instr >> (ebl->class == ELFCLASS64 ? 48 : 16)) & 0xffff;
+  /* See GDB s390_sigtramp_frame_sniffer.  */
+  /* Check for 'svc' as the first instruction.  */
+  if (((instr >> 8) & 0xff) != 0x0a)
+    return false;
+  /* Check for 'sigreturn' or 'rt_sigreturn' as the second instruction.  */
+  if ((instr & 0xff) != 119 && (instr & 0xff) != 173)
+    return false;
+  /* See GDB s390_sigtramp_frame_unwind_cache.  */
+  Dwarf_Word this_sp;
+  if (! getfunc (0 + 15, 1, &this_sp, arg))
+    return false;
+  unsigned word_size = ebl->class == ELFCLASS64 ? 8 : 4;
+  Dwarf_Addr next_cfa = this_sp + 16 * word_size + 32;
+  /* "New-style RT frame" is not supported,
+     assuming "Old-style RT frame and all non-RT frames".
+     Pointer to the array of saved registers is at NEXT_CFA + 8.  */
+  Dwarf_Word sigreg_ptr;
+  if (! readfunc (next_cfa + 8, &sigreg_ptr, arg))
+    return false;
+  /* Skip PSW mask.  */
+  sigreg_ptr += word_size;
+  /* Read PSW address.  */
+  Dwarf_Word val;
+  if (! readfunc (sigreg_ptr, &val, arg))
+    return false;
+  if (! setfunc (-1, 1, &val, arg))
+    return false;
+  sigreg_ptr += word_size;
+  /* Then the GPRs.  */
+  Dwarf_Word gprs[16];
+  for (int i = 0; i < 16; i++)
+    {
+      if (! readfunc (sigreg_ptr, &gprs[i], arg))
+	return false;
+      sigreg_ptr += word_size;
+    }
+  /* Then the ACRs.  Skip them, they are not used in CFI.  */
+  for (int i = 0; i < 16; i++)
+    sigreg_ptr += 4;
+  /* The floating-point control word.  */
+  sigreg_ptr += 8;
+  /* And finally the FPRs.  */
+  Dwarf_Word fprs[16];
+  for (int i = 0; i < 16; i++)
+    {
+      if (! readfunc (sigreg_ptr, &val, arg))
+	return false;
+      if (ebl->class == ELFCLASS32)
+	{
+	  Dwarf_Addr val_low;
+	  if (! readfunc (sigreg_ptr + 4, &val_low, arg))
+	    return false;
+	  val = (val << 32) | val_low;
+	}
+      fprs[i] = val;
+      sigreg_ptr += 8;
+    }
+  /* If we have them, the GPR upper halves are appended at the end.  */
+  if (ebl->class == ELFCLASS32)
+    {
+      /* Skip signal number.  */
+      sigreg_ptr += 4;
+      for (int i = 0; i < 16; i++)
+	{
+	  if (! readfunc (sigreg_ptr, &val, arg))
+	    return false;
+	  Dwarf_Word val_low = gprs[i];
+	  val = (val << 32) | val_low;
+	  gprs[i] = val;
+	  sigreg_ptr += 4;
+	}
+    }
+  if (! setfunc (0, 16, gprs, arg))
+    return false;
+  if (! setfunc (16, 16, fprs, arg))
+    return false;
+  *signal_framep = true;
+  return true;
+}
diff --git a/backends/s390x_corenote.c b/backends/s390x_corenote.c
new file mode 100644
index 0000000..427bf7d
--- /dev/null
+++ b/backends/s390x_corenote.c
@@ -0,0 +1,2 @@
+#define BITS 64
+#include "s390_corenote.c"
diff --git a/backends/sh_corenote.c b/backends/sh_corenote.c
new file mode 100644
index 0000000..9268f56
--- /dev/null
+++ b/backends/sh_corenote.c
@@ -0,0 +1,88 @@
+/* SH specific core note handling.
+   Copyright (C) 2010 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed Matt Fleming <matt@console-pimps.org>.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#define BACKEND		sh_
+#include "libebl_CPU.h"
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+#define GR(at, n, dwreg)						\
+    { .offset = at * 4, .regno = dwreg, .count = n, .bits = 32 }
+    GR (0, 16, 0),		/* r0-r15 */
+    GR (16, 1, 16),		/* pc */
+    GR (17, 1, 17),		/* pr */
+    GR (18, 1, 22),		/* sr */
+    GR (19, 1, 18),		/* gbr */
+    GR (20, 1, 20),		/* mach */
+    GR (21, 1, 21),		/* macl */
+    /*  22, 1,			   tra */
+#undef GR
+  };
+#define PRSTATUS_REGS_SIZE	(23 * 4)
+
+#define	ULONG			uint32_t
+#define PID_T			int32_t
+#define	UID_T			uint16_t
+#define	GID_T			uint16_t
+#define ALIGN_ULONG		4
+#define ALIGN_PID_T		4
+#define ALIGN_UID_T		2
+#define ALIGN_GID_T		2
+#define TYPE_ULONG		ELF_T_WORD
+#define TYPE_PID_T		ELF_T_SWORD
+#define TYPE_UID_T		ELF_T_HALF
+#define TYPE_GID_T		ELF_T_HALF
+
+#define PRSTATUS_REGSET_ITEMS						      \
+  {									      \
+    .name = "tra", .type = ELF_T_ADDR, .format = 'x',			      \
+    .offset = offsetof (struct EBLHOOK(prstatus), pr_reg[22]),		      \
+    .group = "register"	       			  	       	 	      \
+  }
+
+static const Ebl_Register_Location fpregset_regs[] =
+  {
+    { .offset = 0, .regno = 25, .count = 16, .bits = 32 }, /* fr0-fr15 */
+    { .offset = 16, .regno = 87, .count = 16, .bits = 32 }, /* xf0-xf15 */
+    { .offset = 32, .regno = 24, .count = 1, .bits = 32 }, /* fpscr */
+    { .offset = 33, .regno = 23, .count = 1, .bits = 32 }  /* fpul */
+  };
+#define FPREGSET_SIZE		(50 * 4)
+
+#include "linux-core-note.c"
diff --git a/backends/sh_init.c b/backends/sh_init.c
new file mode 100644
index 0000000..5526aca
--- /dev/null
+++ b/backends/sh_init.c
@@ -0,0 +1,63 @@
+/* Initialization of SH specific backend library.
+   Copyright (C) 2000, 2001, 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		sh_
+#define RELOC_PREFIX	R_SH_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on sh_reloc.def.  */
+#include "common-reloc.c"
+
+
+const char *
+sh_init (Elf *elf __attribute__ ((unused)),
+	 GElf_Half machine __attribute__ ((unused)),
+	 Ebl *eh,
+	 size_t ehlen)
+{
+  /* Check whether the Elf_BH object has a sufficent size.  */
+  if (ehlen < sizeof (Ebl))
+    return NULL;
+
+  /* We handle it.  */
+  eh->name = "Hitachi SH";
+  sh_init_reloc (eh);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, gotpc_reloc_check);
+  HOOK (eh, machine_flag_check);
+  HOOK (eh, core_note);
+  HOOK (eh, register_info);
+  HOOK (eh, return_value_location);
+
+  return MODVERSION;
+}
diff --git a/backends/sh_regs.c b/backends/sh_regs.c
new file mode 100644
index 0000000..d433236
--- /dev/null
+++ b/backends/sh_regs.c
@@ -0,0 +1,191 @@
+/* Register names and numbers for SH DWARF.
+   Copyright (C) 2010 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Matt Fleming <matt@console-pimps.org>.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+#include <string.h>
+
+#define BACKEND sh_
+#include "libebl_CPU.h"
+
+ssize_t
+sh_register_info (Ebl *ebl __attribute__ ((unused)),
+		  int regno, char *name, size_t namelen,
+		  const char **prefix, const char **setname,
+		  int *bits, int *type)
+{
+  if (name == NULL)
+    return 104;
+
+  if (regno < 0 || regno > 103 || namelen < 6)
+    return -1;
+
+  *prefix = "";
+  *bits = 32;
+  *type = DW_ATE_signed;
+
+  switch (regno)
+    {
+    case 0 ... 9:
+      *setname = "integer";
+      name[0] = 'r';
+      name[1] = regno + '0';
+      namelen = 2;
+      break;
+
+    case 10 ... 15:
+      *setname = "integer";
+      name[0] = 'r';
+      name[1] = '1';
+      name[2] = regno - 10 + '0';
+      namelen = 3;
+      break;
+
+    case 16:
+      *setname = "system";
+      *type = DW_ATE_address;
+      name[0] = 'p';
+      name[1] = 'c';
+      namelen = 2;
+      break;
+
+    case 17:
+      *setname = "system";
+      *type = DW_ATE_address;
+      name[0] = 'p';
+      name[1] = 'r';
+      namelen = 2;
+      break;
+
+    case 18:
+      *setname = "control";
+      *type = DW_ATE_unsigned;
+      name[0] = 's';
+      name[1] = 'r';
+      namelen = 2;
+      break;
+
+    case 19:
+      *setname = "control";
+      *type = DW_ATE_unsigned;
+      name[0] = 'g';
+      name[1] = 'b';
+      name[2] = 'r';
+      namelen = 3;
+      break;
+
+    case 20:
+      *setname = "system";
+      name[0] = 'm';
+      name[1] = 'a';
+      name[2] = 'c';
+      name[3] = 'h';
+      namelen = 4;
+      break;
+
+    case 21:
+      *setname = "system";
+      name[0] = 'm';
+      name[1] = 'a';
+      name[2] = 'c';
+      name[3] = 'l';
+      namelen = 4;
+
+      break;
+
+    case 23:
+      *setname = "system";
+      *type = DW_ATE_unsigned;
+      name[0] = 'f';
+      name[1] = 'p';
+      name[2] = 'u';
+      name[3] = 'l';
+      namelen = 4;
+      break;
+
+    case 24:
+      *setname = "system";
+      *type = DW_ATE_unsigned;
+      name[0] = 'f';
+      name[1] = 'p';
+      name[2] = 's';
+      name[3] = 'c';
+      name[4] = 'r';
+      namelen = 5;
+      break;
+
+    case 25 ... 34:
+      *setname = "fpu";
+      *type = DW_ATE_float;
+      name[0] = 'f';
+      name[1] = 'r';
+      name[2] = regno - 25 + '0';
+      namelen = 3;
+      break;
+
+    case 35 ... 40:
+      *setname = "fpu";
+      *type = DW_ATE_float;
+      name[0] = 'f';
+      name[1] = 'r';
+      name[2] = '1';
+      name[3] = regno - 35 + '0';
+      namelen = 4;
+      break;
+
+    case 87 ... 96:
+      *type = DW_ATE_float;
+      *setname = "fpu";
+      name[0] = 'x';
+      name[1] = 'f';
+      name[2] = regno - 87 + '0';
+      namelen = 3;
+      break;
+
+    case 97 ... 103:
+      *type = DW_ATE_float;
+      *setname = "fpu";
+      name[0] = 'x';
+      name[1] = 'f';
+      name[2] = '1';
+      name[3] = regno - 97 + '0';
+      namelen = 4;
+      break;
+
+    default:
+      return 0;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
diff --git a/backends/sh_reloc.def b/backends/sh_reloc.def
new file mode 100644
index 0000000..aded361
--- /dev/null
+++ b/backends/sh_reloc.def
@@ -0,0 +1,67 @@
+/* List the relocation types for SH.  -*- C -*-
+   Copyright (C) 2005, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,		0)
+RELOC_TYPE (DIR32,		REL|DYN)
+RELOC_TYPE (REL32,		REL|DYN)
+RELOC_TYPE (DIR8WPN,		REL)
+RELOC_TYPE (IND12W,		REL)
+RELOC_TYPE (DIR8WPL,		REL)
+RELOC_TYPE (DIR8WPZ,		REL)
+RELOC_TYPE (DIR8BP,		REL)
+RELOC_TYPE (DIR8W,		REL)
+RELOC_TYPE (DIR8L,		REL)
+RELOC_TYPE (SWITCH16,		REL)
+RELOC_TYPE (SWITCH32,		REL)
+RELOC_TYPE (USES,		REL)
+RELOC_TYPE (COUNT,		REL)
+RELOC_TYPE (ALIGN,		REL)
+RELOC_TYPE (CODE,		REL)
+RELOC_TYPE (DATA,		REL)
+RELOC_TYPE (LABEL,		REL)
+RELOC_TYPE (SWITCH8,		REL)
+RELOC_TYPE (GNU_VTINHERIT,	REL)
+RELOC_TYPE (GNU_VTENTRY,	REL)
+RELOC_TYPE (TLS_GD_32,		REL)
+RELOC_TYPE (TLS_LD_32,		REL)
+RELOC_TYPE (TLS_LDO_32,		REL)
+RELOC_TYPE (TLS_IE_32,		REL)
+RELOC_TYPE (TLS_LE_32,		REL)
+RELOC_TYPE (TLS_DTPMOD32,	DYN)
+RELOC_TYPE (TLS_DTPOFF32,	DYN)
+RELOC_TYPE (TLS_TPOFF32,	DYN)
+RELOC_TYPE (GOT32,		REL)
+RELOC_TYPE (PLT32,		REL)
+RELOC_TYPE (COPY,		EXEC|DYN)
+RELOC_TYPE (GLOB_DAT,		EXEC|DYN)
+RELOC_TYPE (JMP_SLOT,		EXEC|DYN)
+RELOC_TYPE (RELATIVE,		EXEC|DYN)
+RELOC_TYPE (GOTOFF,		REL)
+RELOC_TYPE (GOTPC,		REL)
diff --git a/backends/sh_retval.c b/backends/sh_retval.c
new file mode 100644
index 0000000..33d7d96
--- /dev/null
+++ b/backends/sh_retval.c
@@ -0,0 +1,131 @@
+/* Function return value location for Linux/SH ABI.
+   Copyright (C) 2010, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Matt Fleming <matt@console-pimps.org>.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND sh_
+#include "libebl_CPU.h"
+
+
+/* This is the SVR4 ELF ABI convention, but AIX and Linux do not use it.  */
+#define SVR4_STRUCT_RETURN 0
+
+
+/* r0, or pair r0, r1.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg0 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg1 }, { .atom = DW_OP_piece, .number = 4 },
+  };
+#define nloc_intreg	1
+#define nloc_intregpair	4
+
+/* fr0 or fr1.  */
+static const Dwarf_Op loc_fpreg[] =
+  {
+    { .atom = DW_OP_reg25 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg26 }, { .atom = DW_OP_piece, .number = 4 },
+  };
+#define nloc_fpreg	1
+#define nloc_fpregpair	2
+
+int
+sh_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die die_mem, *typedie = &die_mem;
+  int tag = dwarf_peeled_die_type (functypedie, typedie);
+  if (tag <= 0)
+    return tag;
+
+  Dwarf_Word size;
+  switch (tag)
+    {
+    case -1:
+      return -1;
+
+    case DW_TAG_subrange_type:
+      if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
+	{
+	  Dwarf_Attribute attr_mem, *attr;
+	  attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+	  typedie = dwarf_formref_die (attr, &die_mem);
+	  tag = DWARF_TAG_OR_RETURN (typedie);
+	}
+      FALLTHROUGH;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    case DW_TAG_pointer_type:
+    case DW_TAG_ptr_to_member_type:
+      {
+	Dwarf_Attribute attr_mem;
+	if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+						   &attr_mem), &size) != 0)
+	  {
+	    if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+	      size = 4;
+	    else
+	      return -1;
+	  }
+      }
+
+      if (size <= 8)
+	{
+	  if (tag == DW_TAG_base_type)
+	    {
+	      Dwarf_Attribute attr_mem;
+	      Dwarf_Word encoding;
+	      if (dwarf_formudata (dwarf_attr_integrate (typedie,
+							 DW_AT_encoding,
+							 &attr_mem),
+				   &encoding) != 0)
+		return -1;
+	      if (encoding == DW_ATE_float)
+		{
+		  *locp = loc_fpreg;
+		  return size <= 4 ? nloc_fpreg : nloc_fpregpair;
+		}
+	    }
+	  *locp = loc_intreg;
+	  return size <= 4 ? nloc_intreg : nloc_intregpair;
+	}
+    }
+
+  /* XXX We don't have a good way to return specific errors from ebl calls.
+     This value means we do not understand the type, but it is well-formed
+     DWARF and might be valid.  */
+  return -2;
+}
diff --git a/backends/sh_symbol.c b/backends/sh_symbol.c
new file mode 100644
index 0000000..8101e96
--- /dev/null
+++ b/backends/sh_symbol.c
@@ -0,0 +1,94 @@
+/* SH specific relocation handling.
+   Copyright (C) 2000, 2001, 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <stddef.h>
+
+#define BACKEND sh_
+#include "libebl_CPU.h"
+
+
+/* Return true if the symbol type is that referencing the GOT.  */
+bool
+sh_gotpc_reloc_check (Elf *elf __attribute__ ((unused)), int type)
+{
+  return type == R_SH_GOTPC;
+}
+
+/* Check for the simple reloc types.  */
+Elf_Type
+sh_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+{
+  switch (type)
+    {
+    case R_SH_DIR32:
+      return ELF_T_WORD;
+    default:
+      return ELF_T_NUM;
+    }
+}
+
+/* Check whether machine flags are valid.  */
+bool
+sh_machine_flag_check (GElf_Word flags)
+{
+  switch (flags & EF_SH_MACH_MASK)
+    {
+    case EF_SH_UNKNOWN:
+    case EF_SH1:
+    case EF_SH2:
+    case EF_SH3:
+    case EF_SH_DSP:
+    case EF_SH3_DSP:
+    case EF_SH4AL_DSP:
+    case EF_SH3E:
+    case EF_SH4:
+    case EF_SH2E:
+    case EF_SH4A:
+    case EF_SH2A:
+    case EF_SH4_NOFPU:
+    case EF_SH4A_NOFPU:
+    case EF_SH4_NOMMU_NOFPU:
+    case EF_SH2A_NOFPU:
+    case EF_SH3_NOMMU:
+    case EF_SH2A_SH4_NOFPU:
+    case EF_SH2A_SH3_NOFPU:
+    case EF_SH2A_SH4:
+    case EF_SH2A_SH3E:
+      break;
+    default:
+      return false;
+    }
+
+  return ((flags &~ (EF_SH_MACH_MASK)) == 0);
+}
diff --git a/backends/sparc64_corenote.c b/backends/sparc64_corenote.c
new file mode 100644
index 0000000..cef6431
--- /dev/null
+++ b/backends/sparc64_corenote.c
@@ -0,0 +1,2 @@
+#define BITS 64
+#include "sparc_corenote.c"
diff --git a/backends/sparc_attrs.c b/backends/sparc_attrs.c
new file mode 100644
index 0000000..974e8fb
--- /dev/null
+++ b/backends/sparc_attrs.c
@@ -0,0 +1,105 @@
+/* Object attribute tags for SPARC.
+   Copyright (C) 2015 Oracle, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND sparc_
+#include "libebl_CPU.h"
+
+bool
+sparc_check_object_attribute (Ebl *ebl __attribute__ ((unused)),
+			      const char *vendor, int tag, uint64_t value,
+			      const char **tag_name, const char **value_name)
+{
+  static const char *hwcaps[32] =
+    {
+      "mul32", "div32", "fsmuld", "v8plus", "popc", "vis", "vis2",
+      "asi_blk_init", "fmaf", "vis3", "hpc", "random", "trans",
+      "fjfmau", "ima", "asi_cache_sparing", "aes", "des", "kasumi",
+      "camellia", "md5", "sha1", "sha256", "sha512", "mpmul", "mont",
+      "pause", "cbcond", "crc32c", "resv30", "resv31"
+    };
+
+  
+  static const char *hwcaps2[32] =
+    {
+      "fjathplus", "vis3b", "adp", "sparc5", "mwait", "xmpmul", "xmont",
+      "nsec", "resv8", "resv9" , "resv10", "resv11", "fjathhpc", "fjdes",
+      "fjaes", "resv15", "resv16", "resv17", "resv18", "resv19", "resv20",
+      "resv21", "resv22", "resv23", "resv24", "resv25", "resv26", "resv27",
+      "resv28", "resv29", "resv30", "resv31",
+    };
+
+  /* NAME should be big enough to hold any possible comma-separated
+     list (no repetitions allowed) of attribute names from one of the
+     arrays above.  */
+  static char name[32*17+32+1];
+  name[0] = '\0';
+
+  if (!strcmp (vendor, "gnu"))
+    switch (tag)
+      {
+      case 4:
+      case 8:
+        {
+          const char **caps;
+          int cap;
+          
+          if (tag == 4)
+            {
+              *tag_name = "GNU_Sparc_HWCAPS";
+              caps = hwcaps;
+            }
+          else
+            {
+              *tag_name = "GNU_Sparc_HWCAPS2";
+              caps = hwcaps2;
+            }
+          
+          char *s = name;
+          for (cap = 0; cap < 32; cap++)
+            if (value & (1U << cap))
+              {
+                if (*s != '\0')
+                  s = strcat (s, ",");
+                s = strcat (s, caps[cap]);
+              }
+          
+          *value_name = s;
+          return true;
+        }
+      }
+
+  return false;
+}
+
diff --git a/backends/sparc_auxv.c b/backends/sparc_auxv.c
new file mode 100644
index 0000000..2da349c
--- /dev/null
+++ b/backends/sparc_auxv.c
@@ -0,0 +1,46 @@
+/* SPARC-specific auxv handling.
+   Copyright (C) 2007 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND sparc_
+#include "libebl_CPU.h"
+
+int
+EBLHOOK(auxv_info) (GElf_Xword a_type, const char **name, const char **format)
+{
+  if (a_type != AT_HWCAP)
+    return 0;
+
+  *name = "HWCAP";
+  *format = "b"
+    "flush\0" "stbar\0" "swap\0" "muldiv\0" "v9\0" "ultra3\0" "v9v\0" "\0";
+  return 1;
+}
diff --git a/backends/sparc_cfi.c b/backends/sparc_cfi.c
new file mode 100644
index 0000000..dcc17bd
--- /dev/null
+++ b/backends/sparc_cfi.c
@@ -0,0 +1,83 @@
+/* SPARC defaults for DWARF CFI.
+   Copyright (C) 2015 Oracle Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#define BACKEND sparc_
+#include "libebl_CPU.h"
+
+int
+sparc_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info)
+{
+  static const uint8_t abi_cfi[] =
+    {
+#define SV(n) DW_CFA_same_value, ULEB128_7 (n)
+      /* %g0 .. %g7 */
+      SV (0), SV (1), SV (2), SV (3), SV (4), SV (5), SV (6), SV (7),
+      /* %o0 .. %o7 */
+      SV (8), SV (9), SV (10), SV (11), SV (12), SV (13), SV (14), SV (15),
+      /* %l0 .. %l7 */
+      SV (16), SV (17), SV (18), SV (19), SV (20), SV (21), SV (22), SV (23),
+      /* %i0 .. %i7 */
+      SV (24), SV (25), SV (26), SV (27), SV (28), SV (29), SV (30), SV (31),
+      /* %f0 .. %f32 */
+      SV (32), SV (33), SV (34), SV (35), SV (36), SV (37), SV (38), SV (39),
+      SV (40), SV (41), SV (42), SV (43), SV (44), SV (45), SV (46), SV (47),
+      SV (48), SV (49), SV (50), SV (51), SV (52), SV (53), SV (54), SV (55),
+      SV (56), SV (57), SV (58), SV (59), SV (60), SV (61), SV (52), SV (63),
+      /* %f33 .. %63
+         Note that there are DWARF columns for the odd registers, even
+         if they don't exist in hardware) */
+      SV (64), SV (65), SV (66), SV (67), SV (68), SV (69), SV (70), SV (71),
+      SV (72), SV (73), SV (74), SV (75), SV (76), SV (77), SV (78), SV (79),
+      SV (80), SV (81), SV (82), SV (83), SV (84), SV (85), SV (86), SV (87),
+      SV (88), SV (89), SV (90), SV (91), SV (92), SV (93), SV (94), SV (95),
+      /* %fcc[0123] */
+      SV (96), SV (97), SV (98), SV (99),
+      /* %icc/%xcc */
+      SV (100),
+      /* Soft frame-pointer */
+      SV (101),
+      /* %gsr */
+      SV (102)
+#undef SV
+    };
+
+  abi_info->initial_instructions = abi_cfi;
+  abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
+  abi_info->data_alignment_factor = 4;
+
+  abi_info->return_address_register = 31; /* %i7 */
+
+  return 0;
+}
+
diff --git a/backends/sparc_corenote.c b/backends/sparc_corenote.c
new file mode 100644
index 0000000..c9b6ff3
--- /dev/null
+++ b/backends/sparc_corenote.c
@@ -0,0 +1,120 @@
+/* SPARC specific core note handling.
+   Copyright (C) 2007 Red Hat, Inc.
+   Copyright (C) 2015 Oracle, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#ifndef BITS
+# define BITS 		32
+# define BACKEND	sparc_
+#else
+# define BITS 		64
+# define BACKEND	sparc64_
+#endif
+#include "libebl_CPU.h"
+
+#define GR(at, n, dwreg)						\
+    { .offset = at * BITS/8, .regno = dwreg, .count = n, .bits = BITS }
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+    GR (0, 32, 0),		/* %g0-%g7, %o0-%o7, %i0-%i7 */
+#if BITS == 32
+    GR (32, 1, 65),		/* %psr */
+    GR (33, 2, 68),		/* %pc, %npc */
+    GR (35, 1, 64),		/* %y */
+    GR (36, 1, 66),		/* %wim, %tbr */
+#else
+    GR (32, 1, 82),		/* %state */
+    GR (33, 2, 80),		/* %pc, %npc */
+    GR (35, 1, 85),		/* %y */
+#endif
+  };
+#define PRSTATUS_REGS_SIZE	(BITS / 8 * (32 + (BITS == 32 ? 6 : 4)))
+
+static const Ebl_Register_Location fpregset_regs[] =
+  {
+#if BITS == 32
+    GR (0, 32, 32),		/* %f0-%f31 */
+    /* 				   padding word */
+    GR (33, 1, 70),		/* %fsr */
+    /* 	       			   qcnt, q_entrysize, en, q, padding */
+# define FPREGSET_SIZE		(34 * 4 + 4 + 64 * 4 + 4)
+#else
+    GR (0, 32, 32),		/* %f0-%f31 */
+    GR (32, 1, 83),		/* %fsr */
+    /*  33, 1, 			   %gsr */
+    GR (34, 1, 84),		/* %fprs */
+# define FPREGSET_SIZE		(35 * 8)
+#endif
+  };
+
+#if BITS == 32
+# define ULONG			uint32_t
+# define ALIGN_ULONG		4
+# define TYPE_ULONG		ELF_T_WORD
+# define TYPE_LONG		ELF_T_SWORD
+# define UID_T			uint16_t
+# define GID_T			uint16_t
+# define ALIGN_UID_T		2
+# define ALIGN_GID_T		2
+# define TYPE_UID_T		ELF_T_HALF
+# define TYPE_GID_T		ELF_T_HALF
+#else
+# define ULONG			uint64_t
+# define ALIGN_ULONG		8
+# define TYPE_ULONG		ELF_T_XWORD
+# define TYPE_LONG		ELF_T_SXWORD
+# define UID_T			uint32_t
+# define GID_T			uint32_t
+# define ALIGN_UID_T		4
+# define ALIGN_GID_T		4
+# define TYPE_UID_T		ELF_T_WORD
+# define TYPE_GID_T		ELF_T_WORD
+# define SUSECONDS_HALF		1
+#endif
+#define PID_T			int32_t
+#define ALIGN_PID_T		4
+#define TYPE_PID_T		ELF_T_SWORD
+
+#define PRSTATUS_REGSET_ITEMS						      \
+  {									      \
+    .name = "pc", .type = ELF_T_ADDR, .format = 'x',			      \
+    .offset = offsetof (struct EBLHOOK(prstatus), pr_reg[33]),		      \
+    .group = "register", .pc_register = true				      \
+  }
+
+#include "linux-core-note.c"
diff --git a/backends/sparc_init.c b/backends/sparc_init.c
new file mode 100644
index 0000000..8e946fb
--- /dev/null
+++ b/backends/sparc_init.c
@@ -0,0 +1,89 @@
+/* Initialization of SPARC specific backend library.
+   Copyright (C) 2002, 2005, 2006, 2007, 2008 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		sparc_
+#define RELOC_PREFIX	R_SPARC_
+#include "libebl_CPU.h"
+
+/* In SPARC some relocations use the most significative 24 bits of the
+   r_type field to encode a secondary addend.  Make sure the routines
+   in common-reloc.c acknowledge this.  */
+#define RELOC_TYPE_ID(type) ((type) & 0xff)
+
+/* This defines the common reloc hooks based on sparc_reloc.def.  */
+#include "common-reloc.c"
+
+extern __typeof (EBLHOOK (core_note)) sparc64_core_note attribute_hidden;
+
+const char *
+sparc_init (Elf *elf __attribute__ ((unused)),
+	    GElf_Half machine __attribute__ ((unused)),
+	    Ebl *eh,
+	    size_t ehlen)
+{
+  /* Check whether the Elf_BH object has a sufficent size.  */
+  if (ehlen < sizeof (Ebl))
+    return NULL;
+
+  /* We handle it.  */
+  if (machine == EM_SPARCV9)
+    eh->name = "SPARC v9";
+  else if (machine == EM_SPARC32PLUS)
+    eh->name = "SPARC v8+";
+  else
+    eh->name = "SPARC";
+  sparc_init_reloc (eh);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, machine_flag_check);
+  HOOK (eh, check_special_section);
+  HOOK (eh, symbol_type_name);
+  HOOK (eh, dynamic_tag_name);
+  HOOK (eh, dynamic_tag_check);
+  if (eh->class == ELFCLASS64)
+    eh->core_note = sparc64_core_note;
+  else
+    HOOK (eh, core_note);
+  HOOK (eh, auxv_info);
+  HOOK (eh, register_info);
+  HOOK (eh, return_value_location);
+  HOOK (eh, check_object_attribute);
+  HOOK (eh, abi_cfi);
+  /* gcc/config/sparc.h define FIRST_PSEUDO_REGISTER  */
+  eh->frame_nregs = 103;
+  /* The CFI Dwarf register with the "return address" in sparc
+     actually contains the call address.  The return address is
+     located 8 bytes after it.  */
+  eh->ra_offset = 8;
+  HOOK (eh, set_initial_registers_tid);
+
+  return MODVERSION;
+}
diff --git a/backends/sparc_initreg.c b/backends/sparc_initreg.c
new file mode 100644
index 0000000..c4b321c
--- /dev/null
+++ b/backends/sparc_initreg.c
@@ -0,0 +1,129 @@
+/* Fetch live process registers from TID.
+   Copyright (C) 2015 Oracle, In
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "system.h"
+#include <stdlib.h>
+#ifdef __sparc__
+# include <asm/ptrace.h>
+# include <sys/ptrace.h>
+#endif
+
+#define BACKEND sparc_
+#include "libebl_CPU.h"
+
+bool
+EBLHOOK (set_initial_registers_tid) (pid_t tid __attribute__ ((unused)),
+                                     ebl_tid_registers_t *setfunc __attribute__ ((unused)),
+                                     void *arg __attribute__ ((unused)))
+{
+#if !defined(__sparc__) || !defined( __arch64__)
+  return false;
+#else /* __sparc__ */
+
+
+  /* The pt_regs structure filled in by PTRACE_GETREGS provides the
+     PC, the global registers and the output registers.  Note how the
+     %g0 register is not explicitly provided in the structure (it's
+     value is always 0) and the resulting weird packing in the u_regs
+     array: the last element is not used.  */
+  
+  struct pt_regs regs;
+  if (ptrace (PTRACE_GETREGS, tid, &regs, 0) == -1)
+    return false;
+
+  /* PC: no DWARF number  */
+  if (!setfunc (-1, 1, (Dwarf_Word *) &regs.tpc, arg))
+    return false;
+  
+  /* Global registers: DWARF 0 .. 7  */
+  Dwarf_Word zero = 0;
+  if (!setfunc (0, 1, &zero, arg))
+    return false;
+  if (!setfunc (1, 7, (Dwarf_Word *) &regs.u_regs[0], arg))
+    return false;
+
+  /* Output registers: DWARF  8 .. 15  */
+  if (!setfunc (8, 8, (Dwarf_Word *) &regs.u_regs[7], arg))
+    return false;
+
+  /* Local and input registers must be read from the stack.  They are
+     saved in the previous stack frame.  The stack pointer is %o6,
+     read above.  */
+
+  Dwarf_Word locals_outs[16];
+  Dwarf_Word sp = regs.u_regs[13];
+
+  if (sp & 1)
+    {
+      /* Registers are 64 bits, and we need to apply the 2047 stack
+         bias in order to get the real stack pointer.  */
+
+      sp += 2047;
+
+      for (unsigned i = 0; i < 16; i++)
+        {
+          locals_outs[i] = ptrace (PTRACE_PEEKDATA, tid,
+                                   (void *) (uintptr_t) (sp + (i * 8)),
+                                   NULL);
+          if (errno != 0)
+            return false;
+        }
+    }
+  else
+    {
+      /* Registers are 32 bits.  */
+
+      for (unsigned i = 0; i < 8; i++)
+        {
+          Dwarf_Word tuple = ptrace (PTRACE_PEEKDATA, tid,
+                                     (void *) (uintptr_t) (sp + (i * 8)),
+                                     NULL);
+          if (errno != 0)
+            return false;
+
+          locals_outs[2*i] = (tuple >> 32) & 0xffffffff;
+          locals_outs[2*i+1] = tuple & 0xffffffff;
+        }
+    }
+
+  
+  /* Local registers:  DWARF 16 .. 23 */
+  if (!setfunc (16, 8, &locals_outs[0], arg))
+    return false;
+  
+  /* Input registers: DWARF 24 .. 31 */
+  if (!setfunc (24, 8, &locals_outs[8], arg))
+    return false;
+
+  return true;
+#endif
+}
diff --git a/backends/sparc_regs.c b/backends/sparc_regs.c
new file mode 100644
index 0000000..2bddcf4
--- /dev/null
+++ b/backends/sparc_regs.c
@@ -0,0 +1,111 @@
+/* Register names and numbers for SPARC DWARF.
+   Copyright (C) 2005, 2006, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND sparc_
+#include "libebl_CPU.h"
+
+ssize_t
+sparc_register_info (Ebl *ebl,
+		     int regno, char *name, size_t namelen,
+		     const char **prefix, const char **setname,
+		     int *bits, int *type)
+{
+  const int nfp = 32 + (ebl->class == ELFCLASS32 ? 0 : 16);
+  const int nspec = ebl->class == ELFCLASS32 ? 8 : 6;
+
+  if (name == NULL)
+    return 32 + nfp + nspec;
+
+  if (regno < 0 || regno >= 32 + nfp + nspec || namelen < 6)
+    return -1;
+
+  *bits = ebl->class == ELFCLASS32 ? 32 : 64;
+  *type = DW_ATE_signed;
+
+  *prefix = "%";
+
+  if (regno >= 32 + nfp)
+    {
+      regno -= 32 + nfp;
+      static const char names[2][8][6] =
+	{
+	  { "y", "psr", "wim", "tbr", "pc", "npc", "fsr", "csr" }, /* v8 */
+	  { "pc", "npc", "state", "fsr", "fprs", "y" } /* v9 */
+	};
+      *setname = "control";
+      *type = DW_ATE_unsigned;
+      if ((ebl->class == ELFCLASS64 ? 0 : 4) + 1 - (unsigned int) regno <= 1)
+	*type = DW_ATE_address;
+      return stpncpy (name, names[ebl->class == ELFCLASS64][regno],
+		      namelen) + 1 - name;
+    }
+
+  if (regno < 32)
+    {
+      *setname = "integer";
+      name[0] = "goli"[regno >> 3];
+      name[1] = (regno & 7) + '0';
+      namelen = 2;
+      if ((regno & 8) && (regno & 7) == 6)
+	*type = DW_ATE_address;
+    }
+  else
+    {
+      *setname = "FPU";
+      *type = DW_ATE_float;
+
+      regno -= 32;
+      if (regno >= 32)
+	regno = 32 + 2 * (regno - 32);
+      else
+	*bits = 32;
+
+      name[0] = 'f';
+      if (regno < 10)
+	{
+	  name[1] = regno + '0';
+	  namelen = 2;
+	}
+      else
+	{
+	  name[1] = regno / 10 + '0';
+	  name[2] = regno % 10 + '0';
+	  namelen = 3;
+	}
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
diff --git a/backends/sparc_reloc.def b/backends/sparc_reloc.def
new file mode 100644
index 0000000..7cd5ce9
--- /dev/null
+++ b/backends/sparc_reloc.def
@@ -0,0 +1,124 @@
+/* List the relocation types for sparc.  -*- C -*-
+   Copyright (C) 2009, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/* 	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,               REL)
+RELOC_TYPE (8,                  REL)
+RELOC_TYPE (16,                 REL)
+RELOC_TYPE (32,                 REL|DYN)
+RELOC_TYPE (DISP8,              REL)
+RELOC_TYPE (DISP16,             REL)
+RELOC_TYPE (DISP32,             REL)
+RELOC_TYPE (WDISP30,            REL)
+RELOC_TYPE (WDISP22,            REL)
+RELOC_TYPE (HI22,               REL)
+RELOC_TYPE (22,                 REL)
+RELOC_TYPE (13,                 REL)
+RELOC_TYPE (LO10,               REL)
+RELOC_TYPE (GOT10,              REL)
+RELOC_TYPE (GOT13,              REL)
+RELOC_TYPE (GOT22,              REL)
+RELOC_TYPE (PC10,               REL)
+RELOC_TYPE (PC22,               REL)
+RELOC_TYPE (WPLT30,             REL)
+RELOC_TYPE (COPY,               EXEC|DYN)
+RELOC_TYPE (GLOB_DAT,           EXEC|DYN)
+RELOC_TYPE (JMP_SLOT,           EXEC|DYN)
+RELOC_TYPE (RELATIVE,           EXEC|DYN)
+RELOC_TYPE (UA32,               REL)
+RELOC_TYPE (PLT32,              REL)
+RELOC_TYPE (HIPLT22,            REL)
+RELOC_TYPE (LOPLT10,            REL)
+RELOC_TYPE (PCPLT32,            REL)
+RELOC_TYPE (PCPLT22,            REL)
+RELOC_TYPE (PCPLT10,            REL)
+RELOC_TYPE (10,                 REL)
+RELOC_TYPE (11,                 REL)
+RELOC_TYPE (64,                 REL|DYN)
+RELOC_TYPE (OLO10,              REL)
+RELOC_TYPE (HH22,               REL)
+RELOC_TYPE (HM10,               REL)
+RELOC_TYPE (LM22,               REL)
+RELOC_TYPE (PC_HH22,            REL)
+RELOC_TYPE (PC_HM10,            REL)
+RELOC_TYPE (PC_LM22,            REL)
+RELOC_TYPE (WDISP16,            REL)
+RELOC_TYPE (WDISP19,            REL)
+RELOC_TYPE (GLOB_JMP,		EXEC|DYN)
+RELOC_TYPE (7,                  REL)
+RELOC_TYPE (5,                  REL)
+RELOC_TYPE (6,                  REL)
+RELOC_TYPE (DISP64,             REL)
+RELOC_TYPE (PLT64,              REL)
+RELOC_TYPE (HIX22,              REL)
+RELOC_TYPE (LOX10,              REL)
+RELOC_TYPE (H44,                REL)
+RELOC_TYPE (M44,                REL)
+RELOC_TYPE (L44,                REL)
+RELOC_TYPE (REGISTER,           REL)
+RELOC_TYPE (UA64,               REL)
+RELOC_TYPE (UA16,               REL)
+RELOC_TYPE (TLS_GD_HI22,        REL)
+RELOC_TYPE (TLS_GD_LO10,        REL)
+RELOC_TYPE (TLS_GD_ADD,         REL)
+RELOC_TYPE (TLS_GD_CALL,        REL)
+RELOC_TYPE (TLS_LDM_HI22,       REL)
+RELOC_TYPE (TLS_LDM_LO10,       REL)
+RELOC_TYPE (TLS_LDM_ADD,        REL)
+RELOC_TYPE (TLS_LDM_CALL,       REL)
+RELOC_TYPE (TLS_LDO_HIX22,      REL)
+RELOC_TYPE (TLS_LDO_LOX10,      REL)
+RELOC_TYPE (TLS_LDO_ADD,        REL)
+RELOC_TYPE (TLS_IE_HI22,        REL)
+RELOC_TYPE (TLS_IE_LO10,        REL)
+RELOC_TYPE (TLS_IE_LD,          REL)
+RELOC_TYPE (TLS_IE_LDX,         REL)
+RELOC_TYPE (TLS_IE_ADD,         REL)
+RELOC_TYPE (TLS_LE_HIX22,       REL)
+RELOC_TYPE (TLS_LE_LOX10,       REL)
+RELOC_TYPE (TLS_DTPMOD32,       DYN)
+RELOC_TYPE (TLS_DTPMOD64,       DYN)
+RELOC_TYPE (TLS_DTPOFF32,       DYN)
+RELOC_TYPE (TLS_DTPOFF64,       DYN)
+RELOC_TYPE (TLS_TPOFF32,        DYN)
+RELOC_TYPE (TLS_TPOFF64,        DYN)
+RELOC_TYPE (GOTDATA_HIX22,	REL)
+RELOC_TYPE (GOTDATA_LOX10,	REL)
+RELOC_TYPE (GOTDATA_OP_HIX22,	REL|DYN)
+RELOC_TYPE (GOTDATA_OP_LOX10,	REL|DYN)
+RELOC_TYPE (GOTDATA_OP,		REL|DYN)
+RELOC_TYPE (H34,		REL)
+RELOC_TYPE (SIZE32,		REL)
+RELOC_TYPE (SIZE64,		REL)
+RELOC_TYPE (WDISP10,		REL)
+RELOC_TYPE (JMP_IREL,		REL)
+RELOC_TYPE (IRELATIVE,		REL)
+RELOC_TYPE (GNU_VTINHERIT,	REL)
+RELOC_TYPE (GNU_VTENTRY,	REL)
+RELOC_TYPE (REV32,		REL)
diff --git a/backends/sparc_retval.c b/backends/sparc_retval.c
new file mode 100644
index 0000000..fb81cdc
--- /dev/null
+++ b/backends/sparc_retval.c
@@ -0,0 +1,159 @@
+/* Function return value location for SPARC.
+   Copyright (C) 2006-2010, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND sparc_
+#include "libebl_CPU.h"
+
+
+/* %o0, or pair %o0, %o1.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg8 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg9 }, { .atom = DW_OP_piece, .number = 4 },
+  };
+#define nloc_intreg	1
+#define nloc_intregpair	4
+
+/* %f0 or pair %f0, %f1, or quad %f0..%f3.  */
+static const Dwarf_Op loc_fpreg[] =
+  {
+    { .atom = DW_OP_regx, .number = 32 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_regx, .number = 33 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_regx, .number = 34 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_regx, .number = 35 }, { .atom = DW_OP_piece, .number = 4 },
+  };
+#define nloc_fpreg	1
+#define nloc_fpregpair	4
+#define nloc_fpregquad	8
+
+/* The return value is a structure and is actually stored in stack space
+   passed in a hidden argument by the caller.  But, the compiler
+   helpfully returns the address of that space in %o0.  */
+static const Dwarf_Op loc_aggregate[] =
+  {
+    { .atom = DW_OP_breg8, .number = 0 }
+  };
+#define nloc_aggregate 1
+
+int
+sparc_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die die_mem, *typedie = &die_mem;
+  int tag = dwarf_peeled_die_type (functypedie, typedie);
+  if (tag <= 0)
+    return tag;
+
+  Dwarf_Word size;
+  switch (tag)
+    {
+    case -1:
+      return -1;
+
+    case DW_TAG_subrange_type:
+      if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
+	{
+	  Dwarf_Attribute attr_mem, *attr;
+	  attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+	  typedie = dwarf_formref_die (attr, &die_mem);
+	  tag = DWARF_TAG_OR_RETURN (typedie);
+	}
+      FALLTHROUGH;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    case DW_TAG_pointer_type:
+    case DW_TAG_ptr_to_member_type:
+      {
+	Dwarf_Attribute attr_mem;
+	if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+						   &attr_mem), &size) != 0)
+	  {
+	    uint8_t asize;
+	    Dwarf_Die cudie;
+	    if ((tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+		&& dwarf_diecu (typedie, &cudie, &asize, NULL) != NULL)
+	      size = asize;
+	    else
+	      return -1;
+	  }
+      }
+
+      if (tag == DW_TAG_base_type)
+	{
+	  Dwarf_Attribute attr_mem;
+	  Dwarf_Word encoding;
+	  if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
+						     &attr_mem),
+			       &encoding) != 0)
+	    return -1;
+	  if (encoding == DW_ATE_float)
+	    {
+	      *locp = loc_fpreg;
+	      if (size <= 4)
+		return nloc_fpreg;
+	      if (size <= 8)
+		return nloc_fpregpair;
+	      if (size <= 16)
+		return nloc_fpregquad;
+	    }
+	}
+      if (size <= 8)
+	{
+	intreg:
+	  *locp = loc_intreg;
+	  return size <= 4 ? nloc_intreg : nloc_intregpair;
+	}
+
+    aggregate:
+      *locp = loc_aggregate;
+      return nloc_aggregate;
+
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+    case DW_TAG_array_type:
+      if (dwarf_aggregate_size (typedie, &size) == 0
+	  && size > 0 && size <= 8)
+	goto intreg;
+      goto aggregate;
+    }
+
+  /* XXX We don't have a good way to return specific errors from ebl calls.
+     This value means we do not understand the type, but it is well-formed
+     DWARF and might be valid.  */
+  return -2;
+}
diff --git a/backends/sparc_symbol.c b/backends/sparc_symbol.c
new file mode 100644
index 0000000..ec11dc9
--- /dev/null
+++ b/backends/sparc_symbol.c
@@ -0,0 +1,148 @@
+/* SPARC specific symbolic name handling.
+   Copyright (C) 2002, 2003, 2005, 2007, 2008 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Jakub Jelinek <jakub@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <stddef.h>
+
+#define BACKEND		sparc_
+#include "libebl_CPU.h"
+
+/* Check for the simple reloc types.  */
+Elf_Type
+sparc_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+{
+  switch (type)
+    {
+    case R_SPARC_8:
+      return ELF_T_BYTE;
+    case R_SPARC_16:
+    case R_SPARC_UA16:
+      return ELF_T_HALF;
+    case R_SPARC_32:
+    case R_SPARC_UA32:
+      return ELF_T_WORD;
+    case R_SPARC_64:
+    case R_SPARC_UA64:
+      return ELF_T_XWORD;
+    default:
+      return ELF_T_NUM;
+    }
+}
+
+/* Check whether machine flags are valid.  */
+bool
+sparc_machine_flag_check (GElf_Word flags)
+{
+  return ((flags &~ (EF_SPARCV9_MM
+		     | EF_SPARC_LEDATA
+		     | EF_SPARC_32PLUS
+		     | EF_SPARC_SUN_US1
+		     | EF_SPARC_SUN_US3)) == 0);
+}
+
+bool
+sparc_check_special_section (Ebl *ebl,
+			     int ndx __attribute__ ((unused)),
+			     const GElf_Shdr *shdr,
+			     const char *sname __attribute__ ((unused)))
+{
+  if ((shdr->sh_flags & (SHF_WRITE | SHF_EXECINSTR))
+      == (SHF_WRITE | SHF_EXECINSTR))
+    {
+      /* This is ordinarily flagged, but is valid for a PLT on SPARC.
+
+	 Look for the SHT_DYNAMIC section and the DT_PLTGOT tag in it.
+	 Its d_ptr should match the .plt section's sh_addr.  */
+
+      Elf_Scn *scn = NULL;
+      while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+	{
+	  GElf_Shdr scn_shdr;
+	  if (likely (gelf_getshdr (scn, &scn_shdr) != NULL)
+	      && scn_shdr.sh_type == SHT_DYNAMIC
+	      && scn_shdr.sh_entsize != 0)
+	    {
+	      Elf_Data *data = elf_getdata (scn, NULL);
+	      if (data != NULL)
+		for (size_t i = 0; i < data->d_size / scn_shdr.sh_entsize; ++i)
+		  {
+		    GElf_Dyn dyn;
+		    if (unlikely (gelf_getdyn (data, i, &dyn) == NULL))
+		      break;
+		    if (dyn.d_tag == DT_PLTGOT)
+		      return dyn.d_un.d_ptr == shdr->sh_addr;
+		  }
+	      break;
+	    }
+	}
+    }
+
+  return false;
+}
+
+const char *
+sparc_symbol_type_name (int type,
+			char *buf __attribute__ ((unused)),
+			size_t len __attribute__ ((unused)))
+{
+  switch (type)
+    {
+    case STT_SPARC_REGISTER:
+      return "SPARC_REGISTER";
+    }
+  return NULL;
+}
+
+const char *
+sparc_dynamic_tag_name (int64_t tag,
+			char *buf __attribute__ ((unused)),
+			size_t len __attribute__ ((unused)))
+{
+  switch (tag)
+    {
+    case DT_SPARC_REGISTER:
+      return "SPARC_REGISTER";
+    }
+  return NULL;
+}
+
+bool
+sparc_dynamic_tag_check (int64_t tag)
+{
+  switch (tag)
+    {
+    case DT_SPARC_REGISTER:
+      return true;
+    }
+  return false;
+}
diff --git a/backends/tilegx_corenote.c b/backends/tilegx_corenote.c
new file mode 100644
index 0000000..be3e7db
--- /dev/null
+++ b/backends/tilegx_corenote.c
@@ -0,0 +1,64 @@
+/* TILE-Gx specific core note handling.
+   Copyright (C) 2012 Tilera Corporation
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#define BACKEND	tilegx_
+#include "libebl_CPU.h"
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+    { .offset = 0, .regno = 0, .count = 56, .bits = 64 }, /* r0-r55 */
+    { .offset = 56 * 8, .regno = 64, .count = 1, .bits = 64 } /* pc */
+  };
+#define PRSTATUS_REGS_SIZE	(57 * 8)
+
+#define ULONG			uint64_t
+#define ALIGN_ULONG		8
+#define TYPE_ULONG		ELF_T_XWORD
+#define TYPE_LONG		ELF_T_SXWORD
+#define PID_T			int32_t
+#define	UID_T			uint32_t
+#define	GID_T			uint32_t
+#define ALIGN_PID_T		4
+#define ALIGN_UID_T		4
+#define ALIGN_GID_T		4
+#define TYPE_PID_T		ELF_T_SWORD
+#define TYPE_UID_T		ELF_T_WORD
+#define TYPE_GID_T		ELF_T_WORD
+
+#include "linux-core-note.c"
diff --git a/backends/tilegx_init.c b/backends/tilegx_init.c
new file mode 100644
index 0000000..162ed36
--- /dev/null
+++ b/backends/tilegx_init.c
@@ -0,0 +1,59 @@
+/* Initialization of TILE-Gx specific backend library.
+   Copyright (C) 2012 Tilera Corporation
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		tilegx_
+#define RELOC_PREFIX	R_TILEGX_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on tilegx_reloc.def.  */
+#include "common-reloc.c"
+
+const char *
+tilegx_init (Elf *elf __attribute__ ((unused)),
+	     GElf_Half machine __attribute__ ((unused)),
+	     Ebl *eh,
+	     size_t ehlen)
+{
+  /* Check whether the Elf_BH object has a sufficent size.  */
+  if (ehlen < sizeof (Ebl))
+    return NULL;
+
+  /* We handle it.  */
+  eh->name = "TILE-Gx";
+  tilegx_init_reloc (eh);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, return_value_location);
+  HOOK (eh, register_info);
+  HOOK (eh, core_note);
+
+  return MODVERSION;
+}
diff --git a/backends/tilegx_regs.c b/backends/tilegx_regs.c
new file mode 100644
index 0000000..b1e1743
--- /dev/null
+++ b/backends/tilegx_regs.c
@@ -0,0 +1,129 @@
+/* Register names and numbers for TILE-Gx DWARF.
+   Copyright (C) 2012 Tilera Corporation
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND tilegx_
+#include "libebl_CPU.h"
+
+ssize_t
+tilegx_register_info (Ebl *ebl __attribute__ ((unused)),
+		    int regno, char *name, size_t namelen,
+		    const char **prefix, const char **setname,
+		    int *bits, int *type)
+{
+  if (name == NULL)
+    return 65;
+
+  if (regno < 0 || regno > 64 || namelen < 5)
+    return -1;
+
+  *prefix = "";
+  *setname = "integer";
+  *bits = 64;
+
+  switch (regno)
+    {
+    case 0 ... 9:
+      *type = DW_ATE_signed;
+      name[0] = 'r';
+      name[1] = regno + '0';
+      namelen = 2;
+      break;
+
+    case 10 ... 52:
+      *type = DW_ATE_signed;
+      name[0] = 'r';
+      name[1] = regno / 10 + '0';
+      name[2] = regno % 10 + '0';
+      namelen = 3;
+      break;
+
+    case 53:
+      *type = DW_ATE_address;
+      return stpcpy (name, "tp") + 1 - name;
+
+    case 54:
+      *type = DW_ATE_address;
+      return stpcpy (name, "sp") + 1 - name;
+
+    case 55:
+      *type = DW_ATE_address;
+      return stpcpy (name, "lr") + 1 - name;
+
+    case 56:
+      *type = DW_ATE_unsigned;
+      return stpcpy (name, "sn") + 1 - name;
+
+    case 57:
+      *type = DW_ATE_unsigned;
+      return stpcpy (name, "idn0") + 1 - name;
+
+    case 58:
+      *type = DW_ATE_unsigned;
+      return stpcpy (name, "idn1") + 1 - name;
+
+    case 59:
+      *type = DW_ATE_unsigned;
+      return stpcpy (name, "udn0") + 1 - name;
+
+    case 60:
+      *type = DW_ATE_unsigned;
+      return stpcpy (name, "udn1") + 1 - name;
+
+    case 61:
+      *type = DW_ATE_unsigned;
+      return stpcpy (name, "udn2") + 1 - name;
+
+    case 62:
+      *type = DW_ATE_unsigned;
+      return stpcpy (name, "udn3") + 1 - name;
+
+    case 63:
+      *type = DW_ATE_unsigned;
+      return stpcpy (name, "zero") + 1 - name;
+
+    case 64:
+      *type = DW_ATE_address;
+      return stpcpy (name, "pc") + 1 - name;
+
+    /* Can't happen.  */
+    default:
+      *setname = NULL;
+      return 0;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
diff --git a/backends/tilegx_reloc.def b/backends/tilegx_reloc.def
new file mode 100644
index 0000000..1018110
--- /dev/null
+++ b/backends/tilegx_reloc.def
@@ -0,0 +1,121 @@
+/* List the relocation types for tilegx.  -*- C -*-
+   Copyright (C) 2012 Tilera Corporation
+   Copyright (C) 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,			REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,			0)
+RELOC_TYPE (64,				REL|EXEC|DYN)
+RELOC_TYPE (32,				REL|EXEC|DYN)
+RELOC_TYPE (16,				REL|EXEC|DYN)
+RELOC_TYPE (8,				REL|EXEC|DYN)
+RELOC_TYPE (64_PCREL,			REL)
+RELOC_TYPE (32_PCREL,			REL)
+RELOC_TYPE (16_PCREL,			REL)
+RELOC_TYPE (8_PCREL,			REL)
+RELOC_TYPE (HW0,			REL)
+RELOC_TYPE (HW1,			REL)
+RELOC_TYPE (HW2,			REL)
+RELOC_TYPE (HW3,			REL)
+RELOC_TYPE (HW0_LAST,			REL)
+RELOC_TYPE (HW1_LAST,			REL)
+RELOC_TYPE (HW2_LAST,			REL)
+RELOC_TYPE (COPY,			EXEC|DYN)
+RELOC_TYPE (GLOB_DAT,			EXEC|DYN)
+RELOC_TYPE (JMP_SLOT,			EXEC|DYN)
+RELOC_TYPE (RELATIVE,			EXEC|DYN)
+RELOC_TYPE (BROFF_X1,			REL)
+RELOC_TYPE (JUMPOFF_X1,			REL)
+RELOC_TYPE (JUMPOFF_X1_PLT,		REL)
+RELOC_TYPE (IMM8_X0,			REL)
+RELOC_TYPE (IMM8_Y0,			REL)
+RELOC_TYPE (IMM8_X1,			REL)
+RELOC_TYPE (IMM8_Y1,			REL)
+RELOC_TYPE (DEST_IMM8_X1,		REL)
+RELOC_TYPE (MT_IMM14_X1,		REL)
+RELOC_TYPE (MF_IMM14_X1,		REL)
+RELOC_TYPE (MMSTART_X0,			REL)
+RELOC_TYPE (MMEND_X0,			REL)
+RELOC_TYPE (SHAMT_X0,			REL)
+RELOC_TYPE (SHAMT_X1,			REL)
+RELOC_TYPE (SHAMT_Y0,			REL)
+RELOC_TYPE (SHAMT_Y1,			REL)
+RELOC_TYPE (IMM16_X0_HW0,		REL)
+RELOC_TYPE (IMM16_X1_HW0,		REL)
+RELOC_TYPE (IMM16_X0_HW1,		REL)
+RELOC_TYPE (IMM16_X1_HW1,		REL)
+RELOC_TYPE (IMM16_X0_HW2,		REL)
+RELOC_TYPE (IMM16_X1_HW2,		REL)
+RELOC_TYPE (IMM16_X0_HW3,		REL)
+RELOC_TYPE (IMM16_X1_HW3,		REL)
+RELOC_TYPE (IMM16_X0_HW0_LAST,		REL)
+RELOC_TYPE (IMM16_X1_HW0_LAST,		REL)
+RELOC_TYPE (IMM16_X0_HW1_LAST,		REL)
+RELOC_TYPE (IMM16_X1_HW1_LAST,		REL)
+RELOC_TYPE (IMM16_X0_HW2_LAST,		REL)
+RELOC_TYPE (IMM16_X1_HW2_LAST,		REL)
+RELOC_TYPE (IMM16_X0_HW0_PCREL,		REL)
+RELOC_TYPE (IMM16_X1_HW0_PCREL,		REL)
+RELOC_TYPE (IMM16_X0_HW1_PCREL,		REL)
+RELOC_TYPE (IMM16_X1_HW1_PCREL,		REL)
+RELOC_TYPE (IMM16_X0_HW2_PCREL,		REL)
+RELOC_TYPE (IMM16_X1_HW2_PCREL,		REL)
+RELOC_TYPE (IMM16_X0_HW3_PCREL,		REL)
+RELOC_TYPE (IMM16_X1_HW3_PCREL,		REL)
+RELOC_TYPE (IMM16_X0_HW0_LAST_PCREL,	REL)
+RELOC_TYPE (IMM16_X1_HW0_LAST_PCREL,	REL)
+RELOC_TYPE (IMM16_X0_HW1_LAST_PCREL,	REL)
+RELOC_TYPE (IMM16_X1_HW1_LAST_PCREL,	REL)
+RELOC_TYPE (IMM16_X0_HW2_LAST_PCREL,	REL)
+RELOC_TYPE (IMM16_X1_HW2_LAST_PCREL,	REL)
+RELOC_TYPE (IMM16_X0_HW0_GOT,		REL)
+RELOC_TYPE (IMM16_X1_HW0_GOT,		REL)
+RELOC_TYPE (IMM16_X0_HW0_LAST_GOT,	REL)
+RELOC_TYPE (IMM16_X1_HW0_LAST_GOT,	REL)
+RELOC_TYPE (IMM16_X0_HW1_LAST_GOT,	REL)
+RELOC_TYPE (IMM16_X1_HW1_LAST_GOT,	REL)
+RELOC_TYPE (IMM16_X0_HW0_TLS_GD,	REL)
+RELOC_TYPE (IMM16_X1_HW0_TLS_GD,	REL)
+RELOC_TYPE (IMM16_X0_HW0_LAST_TLS_GD,	REL)
+RELOC_TYPE (IMM16_X1_HW0_LAST_TLS_GD,	REL)
+RELOC_TYPE (IMM16_X0_HW1_LAST_TLS_GD,	REL)
+RELOC_TYPE (IMM16_X1_HW1_LAST_TLS_GD,	REL)
+RELOC_TYPE (IMM16_X0_HW0_TLS_IE,	REL)
+RELOC_TYPE (IMM16_X1_HW0_TLS_IE,	REL)
+RELOC_TYPE (IMM16_X0_HW0_LAST_TLS_IE,	REL)
+RELOC_TYPE (IMM16_X1_HW0_LAST_TLS_IE,	REL)
+RELOC_TYPE (IMM16_X0_HW1_LAST_TLS_IE,	REL)
+RELOC_TYPE (IMM16_X1_HW1_LAST_TLS_IE,	REL)
+RELOC_TYPE (TLS_DTPMOD64,		EXEC|DYN)
+RELOC_TYPE (TLS_DTPOFF64,		EXEC|DYN)
+RELOC_TYPE (TLS_TPOFF64,		EXEC|DYN)
+RELOC_TYPE (TLS_DTPMOD32,		EXEC|DYN)
+RELOC_TYPE (TLS_DTPOFF32,		EXEC|DYN)
+RELOC_TYPE (TLS_TPOFF32,		EXEC|DYN)
+RELOC_TYPE (GNU_VTINHERIT,		REL)
+RELOC_TYPE (GNU_VTENTRY,		REL)
diff --git a/backends/tilegx_retval.c b/backends/tilegx_retval.c
new file mode 100644
index 0000000..7f7d24b
--- /dev/null
+++ b/backends/tilegx_retval.c
@@ -0,0 +1,154 @@
+/* Function return value location for Linux/TILE-Gx ABI.
+   Copyright (C) 2012 Tilera Corporation
+   Copyright (C) 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND tilegx_
+#include "libebl_CPU.h"
+
+
+/* r0.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg0 }
+  };
+#define nloc_intreg	1
+
+/* The return value is a structure and is actually stored in stack space
+   passed in a hidden argument by the caller.  But, the compiler
+   helpfully returns the address of that space in r0.  */
+static const Dwarf_Op loc_aggregate[] =
+  {
+    { .atom = DW_OP_breg0, .number = 0 }
+  };
+#define nloc_aggregate 1
+
+int
+tilegx_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die die_mem, *typedie = &die_mem;
+  int tag = dwarf_peeled_die_type (functypedie, typedie);
+  if (tag <= 0)
+    return tag;
+
+  Dwarf_Word size;
+  switch (tag)
+    {
+    case -1:
+      return -1;
+
+    case DW_TAG_subrange_type:
+      if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
+	{
+	  Dwarf_Attribute attr_mem, *attr;
+	  attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+	  typedie = dwarf_formref_die (attr, &die_mem);
+	  tag = DWARF_TAG_OR_RETURN (typedie);
+	}
+      FALLTHROUGH;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    case DW_TAG_pointer_type:
+    case DW_TAG_ptr_to_member_type:
+      {
+	Dwarf_Attribute attr_mem;
+	if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+						   &attr_mem), &size) != 0)
+	  {
+	    if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+	      size = 8;
+	    else
+	      return -1;
+	  }
+	if (tag == DW_TAG_base_type)
+	  {
+	    Dwarf_Word encoding;
+	    if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
+						       &attr_mem),
+				 &encoding) != 0)
+	      return -1;
+	  }
+      }
+
+      /* Small enough structs are passed directly in registers R0 ... R7.  */
+      if (size <= 8)
+	{
+	intreg:
+	  *locp = loc_intreg;
+	  return nloc_intreg;
+	}
+
+      FALLTHROUGH;
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+    aggregate:
+      *locp = loc_aggregate;
+      return nloc_aggregate;
+
+    case DW_TAG_array_type:
+    case DW_TAG_string_type:
+      if (dwarf_aggregate_size (typedie, &size) == 0 && size <= 8)
+	{
+	  if (tag == DW_TAG_array_type)
+	    {
+	      Dwarf_Attribute attr_mem, *attr;
+	      /* Check if it's a character array.  */
+	      attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+	      typedie = dwarf_formref_die (attr, &die_mem);
+	      tag = DWARF_TAG_OR_RETURN (typedie);
+	      if (tag != DW_TAG_base_type)
+		goto aggregate;
+	      if (dwarf_formudata (dwarf_attr_integrate (typedie,
+							 DW_AT_byte_size,
+							 &attr_mem),
+				   &size) != 0)
+		return -1;
+	      if (size != 1)
+		goto aggregate;
+	    }
+	  goto intreg;
+	}
+      goto aggregate;
+    }
+
+  /* XXX We don't have a good way to return specific errors from ebl calls.
+     This value means we do not understand the type, but it is well-formed
+     DWARF and might be valid.  */
+  return -2;
+}
diff --git a/backends/tilegx_symbol.c b/backends/tilegx_symbol.c
new file mode 100644
index 0000000..b653326
--- /dev/null
+++ b/backends/tilegx_symbol.c
@@ -0,0 +1,57 @@
+/* TILEGX-specific symbolic name handling.
+   Copyright (C) 2012 Tilera Corporation
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <stddef.h>
+
+#define BACKEND		tilegx_
+#include "libebl_CPU.h"
+
+/* Check for the simple reloc types.  */
+Elf_Type
+tilegx_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+{
+  switch (type)
+    {
+    case R_TILEGX_64:
+      return ELF_T_SXWORD;
+    case R_TILEGX_32:
+      return ELF_T_SWORD;
+    case R_TILEGX_16:
+      return ELF_T_HALF;
+    case R_TILEGX_8:
+      return ELF_T_BYTE;
+    default:
+      return ELF_T_NUM;
+    }
+}
diff --git a/backends/x32_corenote.c b/backends/x32_corenote.c
new file mode 100644
index 0000000..bd6560d
--- /dev/null
+++ b/backends/x32_corenote.c
@@ -0,0 +1,2 @@
+#define BITS 32
+#include "x86_64_corenote.c"
diff --git a/backends/x86_64_cfi.c b/backends/x86_64_cfi.c
new file mode 100644
index 0000000..6db8ac4
--- /dev/null
+++ b/backends/x86_64_cfi.c
@@ -0,0 +1,63 @@
+/* x86-64 ABI-specified defaults for DWARF CFI.
+   Copyright (C) 2009 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#define BACKEND x86_64_
+#include "libebl_CPU.h"
+
+int
+x86_64_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info)
+{
+  static const uint8_t abi_cfi[] =
+    {
+      /* Call-saved regs.  */
+      DW_CFA_same_value, ULEB128_7 (0), /* %rbx */
+      DW_CFA_same_value, ULEB128_7 (6), /* %rbp */
+      DW_CFA_same_value, ULEB128_7 (12), /* %r12 */
+      DW_CFA_same_value, ULEB128_7 (13), /* %r13 */
+      DW_CFA_same_value, ULEB128_7 (14), /* %r14 */
+      DW_CFA_same_value, ULEB128_7 (15), /* %r15 */
+      DW_CFA_same_value, ULEB128_7 (16), /* %r16 */
+
+      /* The CFA is the SP.  */
+      DW_CFA_val_offset, ULEB128_7 (7), ULEB128_7 (0),
+    };
+
+  abi_info->initial_instructions = abi_cfi;
+  abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
+  abi_info->data_alignment_factor = 8;
+
+  abi_info->return_address_register = 16; /* %rip */
+
+  return 0;
+}
diff --git a/backends/x86_64_corenote.c b/backends/x86_64_corenote.c
new file mode 100644
index 0000000..1bacc60
--- /dev/null
+++ b/backends/x86_64_corenote.c
@@ -0,0 +1,139 @@
+/* x86-64 specific core note handling.
+   Copyright (C) 2005, 2007, 2008 Red Hat, Inc.
+   Copyright (C) H.J. Lu <hjl.tools@gmail.com>, 2015.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#ifndef BITS
+# define BITS 		64
+# define BACKEND	x86_64_
+#else
+# define BITS 		32
+# define BACKEND	x32_
+#endif
+#include "libebl_CPU.h"
+
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+#define GR(at, n, dwreg)						\
+    { .offset = at * 8, .regno = dwreg, .count = n, .bits = 64 }
+#define SR(at, n, dwreg)						\
+    { .offset = at * 8, .regno = dwreg, .count = n, .bits = 16, .pad = 6 }
+
+    GR (0, 1, 15),		/* %r15 */
+    GR (1, 1, 14),		/* %r14 */
+    GR (2, 1, 13),		/* %r13 */
+    GR (3, 1, 12),		/* %r12 */
+    GR (4, 1, 6),		/* %rbp */
+    GR (5, 1, 3),		/* %rbx */
+    GR (6, 1, 11),		/* %r11 */
+    GR (7, 1, 10),		/* %r10 */
+    GR (8, 1, 9),		/* %r9 */
+    GR (9, 1, 8),		/* %r8 */
+    GR (10,1, 0),		/* %rax */
+    GR (11,1, 2),		/* %rcx */
+    GR (12,1, 1),		/* %rdx */
+    GR (13,2, 4),		/* %rsi-%rdi */
+    /*  15,1,			    orig_rax */
+    GR (16,1, 16),		/* %rip */
+    SR (17,1, 51),		/* %cs */
+    GR (18,1, 49),		/* %rFLAGS */
+    GR (19,1, 7),		/* %rsp */
+    SR (20,1, 52),		/* %ss */
+    GR (21,2, 58),		/* %fs.base-%gs.base */
+    SR (23,1, 53),		/* %ds */
+    SR (24,1, 50),		/* %es */
+    SR (25,2, 54),		/* %fs-%gs */
+
+#undef	GR
+#undef	SR
+  };
+#define PRSTATUS_REGS_SIZE	(27 * 8)
+
+#if BITS == 32
+# define ULONG			uint32_t
+# define ALIGN_ULONG		4
+# define TYPE_ULONG		ELF_T_WORD
+# define PRPSINFO_UID_T		uint16_t
+# define ALIGN_PRPSINFO_UID_T	2
+# define TYPE_PRPSINFO_UID_T	ELF_T_HALF
+# define PRPSINFO_GID_T		uint16_t
+# define ALIGN_PRPSINFO_GID_T	2
+# define TYPE_PRPSINFO_GID_T	ELF_T_HALF
+#else
+# define ULONG			uint64_t
+# define ALIGN_ULONG		8
+# define TYPE_ULONG		ELF_T_XWORD
+# define PRPSINFO_UID_T		uint32_t
+# define ALIGN_PRPSINFO_UID_T	4
+# define TYPE_PRPSINFO_UID_T	TYPE_UID_T
+# define PRPSINFO_GID_T		uint32_t
+# define ALIGN_PRPSINFO_GID_T	4
+# define TYPE_PRPSINFO_GID_T	TYPE_GID_T
+#endif
+#define PR_REG			uint64_t
+#define ALIGN_PR_REG		8
+#define PID_T			int32_t
+#define	UID_T			uint32_t
+#define	GID_T			uint32_t
+#define ALIGN_PID_T		4
+#define ALIGN_UID_T		4
+#define ALIGN_GID_T		4
+#define TYPE_PID_T		ELF_T_SWORD
+#define TYPE_UID_T		ELF_T_SWORD
+#define TYPE_GID_T		ELF_T_SWORD
+
+#define PRSTATUS_REGSET_ITEMS						      \
+  {									      \
+    .name = "orig_rax", .type = ELF_T_SXWORD, .format = 'd',		      \
+    .offset = offsetof (struct EBLHOOK(prstatus), pr_reg) + (8 * 15),	      \
+    .group = "register"	       			  	       	 	      \
+  }
+
+static const Ebl_Register_Location fpregset_regs[] =
+  {
+    { .offset = 0, .regno = 65, .count = 2, .bits = 16 }, /* fcw-fsw */
+    { .offset = 24, .regno = 64, .count = 1, .bits = 32 }, /* mxcsr */
+    { .offset = 32, .regno = 33, .count = 8, .bits = 80, .pad = 6 }, /* stN */
+    { .offset = 32 + 128, .regno = 17, .count = 16, .bits = 128 }, /* xmm */
+  };
+#define FPREGSET_SIZE	512
+
+#define	EXTRA_NOTES	EXTRA_NOTES_IOPERM
+
+#include "x86_corenote.c"
+#include "linux-core-note.c"
diff --git a/backends/x86_64_init.c b/backends/x86_64_init.c
new file mode 100644
index 0000000..adfa479
--- /dev/null
+++ b/backends/x86_64_init.c
@@ -0,0 +1,74 @@
+/* Initialization of x86-64 specific backend library.
+   Copyright (C) 2002-2009, 2013 Red Hat, Inc.
+   Copyright (C) H.J. Lu <hjl.tools@gmail.com>, 2015.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		x86_64_
+#define RELOC_PREFIX	R_X86_64_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on x86_64_reloc.def.  */
+#include "common-reloc.c"
+
+extern __typeof (EBLHOOK (core_note)) x32_core_note attribute_hidden;
+
+const char *
+x86_64_init (Elf *elf __attribute__ ((unused)),
+	     GElf_Half machine __attribute__ ((unused)),
+	     Ebl *eh,
+	     size_t ehlen)
+{
+  /* Check whether the Elf_BH object has a sufficent size.  */
+  if (ehlen < sizeof (Ebl))
+    return NULL;
+
+  /* We handle it.  */
+  eh->name = "AMD x86-64";
+  x86_64_init_reloc (eh);
+  HOOK (eh, reloc_simple_type);
+  if (eh->class == ELFCLASS32)
+    eh->core_note = x32_core_note;
+  else
+    HOOK (eh, core_note);
+  HOOK (eh, return_value_location);
+  HOOK (eh, register_info);
+  HOOK (eh, syscall_abi);
+  HOOK (eh, auxv_info);
+  HOOK (eh, disasm);
+  HOOK (eh, abi_cfi);
+  /* gcc/config/ #define DWARF_FRAME_REGISTERS.  */
+  eh->frame_nregs = 17;
+  HOOK (eh, set_initial_registers_tid);
+  HOOK (eh, unwind);
+
+  return MODVERSION;
+}
diff --git a/backends/x86_64_initreg.c b/backends/x86_64_initreg.c
new file mode 100644
index 0000000..50e9002
--- /dev/null
+++ b/backends/x86_64_initreg.c
@@ -0,0 +1,73 @@
+/* Fetch live process registers from TID.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#if defined(__x86_64__) && defined(__linux__)
+# include <sys/user.h>
+# include <sys/ptrace.h>
+#endif
+
+#define BACKEND x86_64_
+#include "libebl_CPU.h"
+
+bool
+x86_64_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
+			  ebl_tid_registers_t *setfunc __attribute__ ((unused)),
+				  void *arg __attribute__ ((unused)))
+{
+#if !defined(__x86_64__) || !defined(__linux__)
+  return false;
+#else /* __x86_64__ */
+  struct user_regs_struct user_regs;
+  if (ptrace (PTRACE_GETREGS, tid, NULL, &user_regs) != 0)
+    return false;
+  Dwarf_Word dwarf_regs[17];
+  dwarf_regs[0] = user_regs.rax;
+  dwarf_regs[1] = user_regs.rdx;
+  dwarf_regs[2] = user_regs.rcx;
+  dwarf_regs[3] = user_regs.rbx;
+  dwarf_regs[4] = user_regs.rsi;
+  dwarf_regs[5] = user_regs.rdi;
+  dwarf_regs[6] = user_regs.rbp;
+  dwarf_regs[7] = user_regs.rsp;
+  dwarf_regs[8] = user_regs.r8;
+  dwarf_regs[9] = user_regs.r9;
+  dwarf_regs[10] = user_regs.r10;
+  dwarf_regs[11] = user_regs.r11;
+  dwarf_regs[12] = user_regs.r12;
+  dwarf_regs[13] = user_regs.r13;
+  dwarf_regs[14] = user_regs.r14;
+  dwarf_regs[15] = user_regs.r15;
+  dwarf_regs[16] = user_regs.rip;
+  return setfunc (0, 17, dwarf_regs, arg);
+#endif /* __x86_64__ */
+}
diff --git a/backends/x86_64_regs.c b/backends/x86_64_regs.c
new file mode 100644
index 0000000..ef987da
--- /dev/null
+++ b/backends/x86_64_regs.c
@@ -0,0 +1,186 @@
+/* Register names and numbers for x86-64 DWARF.
+   Copyright (C) 2005, 2006, 2007 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+#include <string.h>
+
+#define BACKEND x86_64_
+#include "libebl_CPU.h"
+
+ssize_t
+x86_64_register_info (Ebl *ebl __attribute__ ((unused)),
+		      int regno, char *name, size_t namelen,
+		      const char **prefix, const char **setname,
+		      int *bits, int *type)
+{
+  if (name == NULL)
+    return 67;
+
+  if (regno < 0 || regno > 66 || namelen < 7)
+    return -1;
+
+  *prefix = "%";
+  *bits = 64;
+  *type = DW_ATE_unsigned;
+  if (regno < 17)
+    {
+      *setname = "integer";
+      *type = DW_ATE_signed;
+    }
+  else if (regno < 33)
+    {
+      *setname = "SSE";
+      *bits = 128;
+    }
+  else if (regno < 41)
+    {
+      *setname = "x87";
+      *type = DW_ATE_float;
+      *bits = 80;
+    }
+  else if (regno < 49)
+    *setname = "MMX";
+  else if (regno > 49 && regno < 60)
+    {
+      *setname = "segment";
+      *bits = 16;
+    }
+  else
+    *setname = "control";
+
+  switch (regno)
+    {
+      static const char baseregs[][2] =
+	{
+	  "ax", "dx", "cx", "bx", "si", "di", "bp", "sp"
+	};
+
+    case 6 ... 7:
+      *type = DW_ATE_address;
+      FALLTHROUGH;
+    case 0 ... 5:
+      name[0] = 'r';
+      name[1] = baseregs[regno][0];
+      name[2] = baseregs[regno][1];
+      namelen = 3;
+      break;
+
+    case 8 ... 9:
+      name[0] = 'r';
+      name[1] = regno - 8 + '8';
+      namelen = 2;
+      break;
+
+    case 10 ... 15:
+      name[0] = 'r';
+      name[1] = '1';
+      name[2] = regno - 10 + '0';
+      namelen = 3;
+      break;
+
+    case 16:
+      *type = DW_ATE_address;
+      name[0] = 'r';
+      name[1] = 'i';
+      name[2] = 'p';
+      namelen = 3;
+      break;
+
+    case 17 ... 26:
+      name[0] = 'x';
+      name[1] = 'm';
+      name[2] = 'm';
+      name[3] = regno - 17 + '0';
+      namelen = 4;
+      break;
+
+    case 27 ... 32:
+      name[0] = 'x';
+      name[1] = 'm';
+      name[2] = 'm';
+      name[3] = '1';
+      name[4] = regno - 27 + '0';
+      namelen = 5;
+      break;
+
+    case 33 ... 40:
+      name[0] = 's';
+      name[1] = 't';
+      name[2] = regno - 33 + '0';
+      namelen = 3;
+      break;
+
+    case 41 ... 48:
+      name[0] = 'm';
+      name[1] = 'm';
+      name[2] = regno - 41 + '0';
+      namelen = 3;
+      break;
+
+    case 50 ... 55:
+      name[0] = "ecsdfg"[regno - 50];
+      name[1] = 's';
+      namelen = 2;
+      break;
+
+    case 58 ... 59:
+      *type = DW_ATE_address;
+      *bits = 64;
+      name[0] = regno - 58 + 'f';
+      return stpcpy (&name[1], "s.base") + 1 - name;
+
+    case 49:
+      *setname = "integer";
+      return stpcpy (name, "rflags") + 1 - name;
+    case 62:
+      return stpcpy (name, "tr") + 1 - name;
+    case 63:
+      return stpcpy (name, "ldtr") + 1 - name;
+    case 64:
+      return stpcpy (name, "mxcsr") + 1 - name;
+
+    case 65 ... 66:
+      *bits = 16;
+      name[0] = 'f';
+      name[1] = "cs"[regno - 65];
+      name[2] = 'w';
+      namelen = 3;
+      break;
+
+    default:
+      return 0;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
diff --git a/backends/x86_64_reloc.def b/backends/x86_64_reloc.def
new file mode 100644
index 0000000..07a7c3d
--- /dev/null
+++ b/backends/x86_64_reloc.def
@@ -0,0 +1,65 @@
+/* List the relocation types for x86-64.  -*- C -*-
+   Copyright (C) 2000, 2001, 2002, 2003, 2005, 2009, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,	REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,	0)
+RELOC_TYPE (64,		REL|EXEC|DYN)
+RELOC_TYPE (PC32,	REL|EXEC|DYN)
+RELOC_TYPE (GOT32,	REL)
+RELOC_TYPE (PLT32,	REL)
+RELOC_TYPE (COPY,	EXEC|DYN)
+RELOC_TYPE (GLOB_DAT,	EXEC|DYN)
+RELOC_TYPE (JUMP_SLOT,	EXEC|DYN)
+RELOC_TYPE (RELATIVE,	EXEC|DYN)
+RELOC_TYPE (GOTPCREL,	REL)
+RELOC_TYPE (32,		REL|EXEC|DYN)
+RELOC_TYPE (32S,	REL)
+RELOC_TYPE (16,		REL)
+RELOC_TYPE (PC16,	REL)
+RELOC_TYPE (8,		REL)
+RELOC_TYPE (PC8,	REL)
+RELOC_TYPE (DTPMOD64,	EXEC|DYN)
+RELOC_TYPE (DTPOFF64,	EXEC|DYN)
+RELOC_TYPE (TPOFF64,	EXEC|DYN)
+RELOC_TYPE (TLSGD,	REL)
+RELOC_TYPE (TLSLD,	REL)
+RELOC_TYPE (DTPOFF32,	REL)
+RELOC_TYPE (GOTTPOFF,	REL)
+RELOC_TYPE (TPOFF32,	REL)
+RELOC_TYPE (PC64,	REL|EXEC|DYN)
+RELOC_TYPE (GOTOFF64,	REL)
+RELOC_TYPE (GOTPC32,	REL)
+RELOC_TYPE (SIZE32,	REL|EXEC|DYN)
+RELOC_TYPE (SIZE64,	REL|EXEC|DYN)
+RELOC_TYPE (GOTPC32_TLSDESC, REL)
+RELOC_TYPE (TLSDESC_CALL, REL)
+RELOC_TYPE (TLSDESC,	REL|EXEC|DYN)
+RELOC_TYPE (IRELATIVE,	EXEC|DYN)
+RELOC_TYPE (GOTPCRELX,	REL)
+RELOC_TYPE (REX_GOTPCRELX, REL)
diff --git a/backends/x86_64_retval.c b/backends/x86_64_retval.c
new file mode 100644
index 0000000..f9114cb
--- /dev/null
+++ b/backends/x86_64_retval.c
@@ -0,0 +1,194 @@
+/* Function return value location for Linux/x86-64 ABI.
+   Copyright (C) 2005-2010, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND x86_64_
+#include "libebl_CPU.h"
+
+
+/* %rax, or pair %rax, %rdx.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg0 }, { .atom = DW_OP_piece, .number = 8 },
+    { .atom = DW_OP_reg1 }, { .atom = DW_OP_piece, .number = 8 },
+  };
+#define nloc_intreg	1
+#define nloc_intregpair	4
+
+/* %st(0), or pair %st(0), %st(1).  */
+static const Dwarf_Op loc_x87reg[] =
+  {
+    { .atom = DW_OP_regx, .number = 33 },
+    { .atom = DW_OP_piece, .number = 10 },
+    { .atom = DW_OP_regx, .number = 34 },
+    { .atom = DW_OP_piece, .number = 10 },
+  };
+#define nloc_x87reg	1
+#define nloc_x87regpair	4
+
+/* %xmm0, or pair %xmm0, %xmm1.  */
+static const Dwarf_Op loc_ssereg[] =
+  {
+    { .atom = DW_OP_reg17 }, { .atom = DW_OP_piece, .number = 16 },
+    { .atom = DW_OP_reg18 }, { .atom = DW_OP_piece, .number = 16 },
+  };
+#define nloc_ssereg	1
+#define nloc_sseregpair	4
+
+/* The return value is a structure and is actually stored in stack space
+   passed in a hidden argument by the caller.  But, the compiler
+   helpfully returns the address of that space in %rax.  */
+static const Dwarf_Op loc_aggregate[] =
+  {
+    { .atom = DW_OP_breg0, .number = 0 }
+  };
+#define nloc_aggregate 1
+
+
+int
+x86_64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die die_mem, *typedie = &die_mem;
+  int tag = dwarf_peeled_die_type (functypedie, typedie);
+  if (tag <= 0)
+    return tag;
+
+  Dwarf_Word size;
+  switch (tag)
+    {
+    case -1:
+      return -1;
+
+    case DW_TAG_subrange_type:
+      if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
+	{
+	  Dwarf_Attribute attr_mem, *attr;
+	  attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+	  typedie = dwarf_formref_die (attr, &die_mem);
+	  tag = DWARF_TAG_OR_RETURN (typedie);
+	}
+      FALLTHROUGH;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    case DW_TAG_pointer_type:
+    case DW_TAG_ptr_to_member_type:
+      {
+	Dwarf_Attribute attr_mem;
+	if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+						   &attr_mem), &size) != 0)
+	  {
+	    if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+	      size = 8;
+	    else
+	      return -1;
+	  }
+      }
+
+      if (tag == DW_TAG_base_type)
+	{
+	  Dwarf_Attribute attr_mem;
+	  Dwarf_Word encoding;
+	  if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
+						     &attr_mem),
+			       &encoding) != 0)
+	    return -1;
+
+	  switch (encoding)
+	    {
+	    case DW_ATE_complex_float:
+	      switch (size)
+		{
+		case 4 * 2:	/* complex float */
+		case 8 * 2:	/* complex double */
+		  *locp = loc_ssereg;
+		  return nloc_sseregpair;
+		case 16 * 2:	/* complex long double */
+		  *locp = loc_x87reg;
+		  return nloc_x87regpair;
+		}
+	      return -2;
+
+	    case DW_ATE_float:
+	      switch (size)
+		{
+		case 4:	/* float */
+		case 8:	/* double */
+		  *locp = loc_ssereg;
+		  return nloc_ssereg;
+		case 16:	/* long double */
+		  /* XXX distinguish __float128, which is sseregpair?? */
+		  *locp = loc_x87reg;
+		  return nloc_x87reg;
+		}
+	      return -2;
+	    }
+	}
+
+    intreg:
+      *locp = loc_intreg;
+      if (size <= 8)
+	return nloc_intreg;
+      if (size <= 16)
+	return nloc_intregpair;
+
+    large:
+      *locp = loc_aggregate;
+      return nloc_aggregate;
+
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+    case DW_TAG_array_type:
+      if (dwarf_aggregate_size (typedie, &size) != 0)
+	goto large;
+      if (size > 16)
+	goto large;
+
+      /* XXX
+	 Must examine the fields in picayune ways to determine the
+	 actual answer.  This will be right for small C structs
+	 containing integer types and similarly simple cases.
+      */
+
+      goto intreg;
+    }
+
+  /* XXX We don't have a good way to return specific errors from ebl calls.
+     This value means we do not understand the type, but it is well-formed
+     DWARF and might be valid.  */
+  return -2;
+}
diff --git a/backends/x86_64_symbol.c b/backends/x86_64_symbol.c
new file mode 100644
index 0000000..1622461
--- /dev/null
+++ b/backends/x86_64_symbol.c
@@ -0,0 +1,60 @@
+/* x86_64 specific symbolic name handling.
+   Copyright (C) 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <elf.h>
+#include <stddef.h>
+
+#define BACKEND		x86_64_
+#include "libebl_CPU.h"
+
+/* Check for the simple reloc types.  */
+Elf_Type
+x86_64_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type)
+{
+  switch (type)
+    {
+    case R_X86_64_64:
+      return ELF_T_XWORD;
+    case R_X86_64_32:
+      return ELF_T_WORD;
+    case R_X86_64_32S:
+      return ELF_T_SWORD;
+    case R_X86_64_16:
+      return ELF_T_HALF;
+    case R_X86_64_8:
+      return ELF_T_BYTE;
+    default:
+      return ELF_T_NUM;
+    }
+}
diff --git a/backends/x86_64_syscall.c b/backends/x86_64_syscall.c
new file mode 100644
index 0000000..0deb8ba
--- /dev/null
+++ b/backends/x86_64_syscall.c
@@ -0,0 +1,50 @@
+/* Linux/x86-64 system call ABI in DWARF register numbers.
+   Copyright (C) 2008 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND x86_64_
+#include "libebl_CPU.h"
+
+int
+x86_64_syscall_abi (Ebl *ebl __attribute__ ((unused)),
+		    int *sp, int *pc, int *callno, int args[6])
+{
+  *sp = 7;			/* %rsp */
+  *pc = 16;			/* %rip */
+  *callno = 0;			/* %rax */
+  args[0] = 5;			/* %rdi */
+  args[1] = 4;			/* %rsi */
+  args[2] = 1;			/* %rdx */
+  args[3] = 10;			/* %r10 */
+  args[4] = 8;			/* %r8 */
+  args[5] = 9;			/* %r9 */
+  return 0;
+}
diff --git a/backends/x86_64_unwind.c b/backends/x86_64_unwind.c
new file mode 100644
index 0000000..ade64c0
--- /dev/null
+++ b/backends/x86_64_unwind.c
@@ -0,0 +1,86 @@
+/* Get previous frame state for an existing frame state.
+   Copyright (C) 2016 The Qt Company Ltd.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <assert.h>
+
+#define BACKEND x86_64_
+#include "libebl_CPU.h"
+
+/* There was no CFI. Maybe we happen to have a frame pointer and can unwind from that?  */
+
+bool
+x86_64_unwind (Ebl *ebl __attribute__ ((unused)),
+               Dwarf_Addr pc __attribute__ ((unused)),
+               ebl_tid_registers_t *setfunc, ebl_tid_registers_get_t *getfunc,
+               ebl_pid_memory_read_t *readfunc, void *arg,
+               bool *signal_framep __attribute__ ((unused)))
+{
+  // Register 6 is supposed to be rbp, thus the conventional frame pointer
+  const int fpReg = 6;
+  const int spReg = 7;
+
+  Dwarf_Word fp;
+  if (!getfunc(fpReg, 1, &fp, arg) || fp == 0)
+    return false;
+
+  // Try to read old sp, so that we can avoid infinite loops below
+  Dwarf_Word sp;
+  if (!getfunc(spReg, 1, &sp, arg))
+    sp = 0;
+
+  Dwarf_Word prev_fp;
+  if (!readfunc(fp, &prev_fp, arg))
+    prev_fp = 0;
+
+  Dwarf_Word ret;
+  if (!readfunc(fp + 8, &ret, arg))
+    return false;
+
+  if (!setfunc(fpReg, 1, &prev_fp, arg))
+    return false;
+
+  fp += 16; // Pop fp and return address and write result to sp
+  if (!setfunc(spReg, 1, &fp, arg))
+    return false;
+
+  if (!setfunc(-1, 1, &ret, arg))
+    return false;
+
+  // If the sp didn't move up we don't actually have a new stack
+  // frame but rather some random data that doesn't include frame
+  // pointers. Break the unwinding then.
+  if (sp >= fp)
+    return false;
+
+  return true;
+}
diff --git a/backends/x86_corenote.c b/backends/x86_corenote.c
new file mode 100644
index 0000000..629462c
--- /dev/null
+++ b/backends/x86_corenote.c
@@ -0,0 +1,51 @@
+/* x86-specific core note handling, pieces common to x86-64 and i386.
+   Copyright (C) 2005-2010 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * 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
+
+   or both in parallel, as here.
+
+   elfutils 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#define	EXTRA_NOTES_IOPERM \
+  case NT_386_IOPERM: \
+    return ioperm_info (nhdr->n_descsz, \
+			regs_offset, nregloc, reglocs, nitems, items);
+
+static int
+ioperm_info (GElf_Word descsz, GElf_Word *regs_offset,
+	     size_t *nregloc, const Ebl_Register_Location **reglocs,
+	     size_t *nitems, const Ebl_Core_Item **items)
+{
+  static const Ebl_Core_Item ioperm_item =
+    { .type = ELF_T_WORD, .format = 'b', .name = "ioperm" };
+
+  if (descsz % 4 != 0)
+    return 0;
+
+  *regs_offset = 0;
+  *nregloc = 0;
+  *reglocs = NULL;
+  *nitems = 1;
+  *items = &ioperm_item;
+  return 1;
+}